bc/
taproot.rs

1// Bitcoin protocol consensus library.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved.
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22#![allow(unused_braces)] // required due to strict dumb derivation and compiler bug
23
24use std::borrow::Borrow;
25use std::fmt::{self, Formatter, LowerHex, UpperHex};
26use std::ops::BitXor;
27use std::str::FromStr;
28use std::{cmp, io, slice, vec};
29
30use amplify::confinement::Confined;
31use amplify::hex::FromHex;
32use amplify::{confinement, ByteArray, Bytes32, Wrapper};
33use commit_verify::{DigestExt, Sha256};
34use secp256k1::{Keypair, PublicKey, Scalar, XOnlyPublicKey};
35use strict_encoding::{
36    DecodeError, ReadTuple, StrictDecode, StrictEncode, StrictProduct, StrictTuple, StrictType,
37    TypeName, TypedRead, TypedWrite, WriteTuple,
38};
39
40use crate::opcodes::*;
41use crate::{
42    CompressedPk, ConsensusEncode, InvalidPubkey, PubkeyParseError, ScriptBytes, ScriptPubkey,
43    VarInt, VarIntBytes, WitnessVer, LIB_NAME_BITCOIN,
44};
45
46/// The SHA-256 midstate value for the TapLeaf hash.
47const MIDSTATE_TAPLEAF: [u8; 7] = *b"TapLeaf";
48// 9ce0e4e67c116c3938b3caf2c30f5089d3f3936c47636e607db33eeaddc6f0c9
49
50/// The SHA-256 midstate value for the TapBranch hash.
51const MIDSTATE_TAPBRANCH: [u8; 9] = *b"TapBranch";
52// 23a865a9b8a40da7977c1e04c49e246fb5be13769d24c9b7b583b5d4a8d226d2
53
54/// The SHA-256 midstate value for the TapTweak hash.
55const MIDSTATE_TAPTWEAK: [u8; 8] = *b"TapTweak";
56// d129a2f3701c655d6583b6c3b941972795f4e23294fd54f4a2ae8d8547ca590b
57
58/// The SHA-256 midstate value for the TapSig hash.
59pub const MIDSTATE_TAPSIGHASH: [u8; 10] = *b"TapSighash";
60// f504a425d7f8783b1363868ae3e556586eee945dbc7888dd02a6e2c31873fe9f
61
62impl<const LEN: usize> From<InvalidPubkey<LEN>> for DecodeError {
63    fn from(e: InvalidPubkey<LEN>) -> Self {
64        DecodeError::DataIntegrityError(format!("invalid x-only public key value '{e}'"))
65    }
66}
67
68/// Generic taproot x-only (BIP-340) public key - a wrapper around
69/// [`XOnlyPublicKey`] providing APIs compatible with the rest of the library.
70/// Should be used everywhere when [`InternalPk`] and [`OutputPk`] do not apply:
71/// as an output of BIP32 key derivation functions, inside tapscripts/
72/// leafscripts etc.
73#[derive(Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
74#[wrapper(Deref, LowerHex, Display)]
75#[wrapper_mut(DerefMut)]
76#[derive(StrictType, StrictDumb)]
77#[strict_type(lib = LIB_NAME_BITCOIN, dumb = Self::dumb())]
78#[cfg_attr(
79    feature = "serde",
80    derive(Serialize, Deserialize),
81    serde(crate = "serde_crate", transparent)
82)]
83pub struct XOnlyPk(XOnlyPublicKey);
84
85impl XOnlyPk {
86    fn dumb() -> Self { Self(XOnlyPublicKey::from_slice(&[1u8; 32]).unwrap()) }
87
88    pub fn from_byte_array(data: [u8; 32]) -> Result<Self, InvalidPubkey<32>> {
89        XOnlyPublicKey::from_slice(data.as_ref())
90            .map(Self)
91            .map_err(|_| InvalidPubkey::Specified(data.into()))
92    }
93
94    pub fn to_byte_array(&self) -> [u8; 32] { self.0.serialize() }
95
96    pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, InvalidPubkey<33>> {
97        Ok(XOnlyPk(XOnlyPublicKey::from_slice(bytes.as_ref())?))
98    }
99}
100
101impl From<CompressedPk> for XOnlyPk {
102    fn from(pubkey: CompressedPk) -> Self { XOnlyPk(pubkey.x_only_public_key().0) }
103}
104
105impl From<PublicKey> for XOnlyPk {
106    fn from(pubkey: PublicKey) -> Self { XOnlyPk(pubkey.x_only_public_key().0) }
107}
108
109impl From<XOnlyPk> for [u8; 32] {
110    fn from(pk: XOnlyPk) -> [u8; 32] { pk.to_byte_array() }
111}
112
113impl StrictEncode for XOnlyPk {
114    fn strict_encode<W: TypedWrite>(&self, writer: W) -> io::Result<W> {
115        let bytes = Bytes32::from(self.0.serialize());
116        writer.write_newtype::<Self>(&bytes)
117    }
118}
119
120impl StrictDecode for XOnlyPk {
121    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
122        reader.read_tuple(|r| {
123            let bytes: Bytes32 = r.read_field()?;
124            XOnlyPublicKey::from_slice(bytes.as_slice())
125                .map(Self)
126                .map_err(|_| InvalidPubkey::Specified(bytes).into())
127        })
128    }
129}
130
131impl FromStr for XOnlyPk {
132    type Err = PubkeyParseError<32>;
133
134    fn from_str(s: &str) -> Result<Self, Self::Err> {
135        let data = <[u8; 32]>::from_hex(s)?;
136        let pk = Self::from_byte_array(data)?;
137        Ok(pk)
138    }
139}
140
141/// Internal taproot public key, which can be present only in key fragment
142/// inside taproot descriptors.
143#[derive(Eq, PartialEq, From)]
144pub struct InternalKeypair(#[from] Keypair);
145
146impl InternalKeypair {
147    pub fn to_output_keypair(&self, merkle_root: Option<TapNodeHash>) -> (Keypair, Parity) {
148        let internal_pk = self.0.x_only_public_key().0;
149        let mut engine = Sha256::from_tag(MIDSTATE_TAPTWEAK);
150        // always hash the key
151        engine.input_raw(&internal_pk.serialize());
152        if let Some(merkle_root) = merkle_root {
153            engine.input_raw(merkle_root.into_tap_hash().as_ref());
154        }
155        let tweak =
156            Scalar::from_be_bytes(engine.finish()).expect("hash value greater than curve order");
157        let pair = self.0.add_xonly_tweak(secp256k1::SECP256K1, &tweak).expect("hash collision");
158        let (outpput_key, tweaked_parity) = pair.x_only_public_key();
159        debug_assert!(internal_pk.tweak_add_check(
160            secp256k1::SECP256K1,
161            &outpput_key,
162            tweaked_parity,
163            tweak
164        ));
165        (pair, tweaked_parity.into())
166    }
167}
168
169/// Internal taproot public key, which can be present only in key fragment
170/// inside taproot descriptors.
171#[derive(Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
172#[wrapper(Deref, LowerHex, Display, FromStr)]
173#[wrapper_mut(DerefMut)]
174#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
175#[strict_type(lib = LIB_NAME_BITCOIN)]
176#[cfg_attr(
177    feature = "serde",
178    derive(Serialize, Deserialize),
179    serde(crate = "serde_crate", transparent)
180)]
181pub struct InternalPk(
182    #[from]
183    #[from(XOnlyPublicKey)]
184    XOnlyPk,
185);
186
187impl InternalPk {
188    #[inline]
189    pub fn from_unchecked(pk: XOnlyPk) -> Self { Self(pk) }
190
191    #[inline]
192    pub fn from_byte_array(data: [u8; 32]) -> Result<Self, InvalidPubkey<32>> {
193        XOnlyPk::from_byte_array(data).map(Self)
194    }
195
196    #[inline]
197    pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, InvalidPubkey<33>> {
198        XOnlyPk::from_bytes(bytes).map(Self)
199    }
200
201    #[inline]
202    pub fn to_byte_array(&self) -> [u8; 32] { self.0.to_byte_array() }
203
204    #[inline]
205    pub fn to_xonly_pk(&self) -> XOnlyPk { self.0 }
206
207    pub fn to_output_pk(&self, merkle_root: Option<TapNodeHash>) -> (OutputPk, Parity) {
208        let mut engine = Sha256::from_tag(MIDSTATE_TAPTWEAK);
209        // always hash the key
210        engine.input_raw(&self.0.serialize());
211        if let Some(merkle_root) = merkle_root {
212            engine.input_raw(merkle_root.into_tap_hash().as_ref());
213        }
214        let tweak =
215            Scalar::from_be_bytes(engine.finish()).expect("hash value greater than curve order");
216        let (output_key, tweaked_parity) =
217            self.0.add_tweak(secp256k1::SECP256K1, &tweak).expect("hash collision");
218        debug_assert!(self.tweak_add_check(
219            secp256k1::SECP256K1,
220            &output_key,
221            tweaked_parity,
222            tweak
223        ));
224        (OutputPk(XOnlyPk(output_key)), tweaked_parity.into())
225    }
226}
227
228impl From<InternalPk> for [u8; 32] {
229    fn from(pk: InternalPk) -> [u8; 32] { pk.to_byte_array() }
230}
231
232/// Output taproot key - an [`InternalPk`] tweaked with merkle root of the
233/// script tree - or its own hash. Used only inside addresses and raw taproot
234/// descriptors.
235#[derive(Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
236#[wrapper(Deref, LowerHex, Display, FromStr)]
237#[wrapper_mut(DerefMut)]
238#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
239#[strict_type(lib = LIB_NAME_BITCOIN)]
240#[cfg_attr(
241    feature = "serde",
242    derive(Serialize, Deserialize),
243    serde(crate = "serde_crate", transparent)
244)]
245pub struct OutputPk(XOnlyPk);
246
247impl OutputPk {
248    #[inline]
249    pub fn from_unchecked(pk: XOnlyPk) -> Self { Self(pk) }
250
251    #[inline]
252    pub fn from_byte_array(data: [u8; 32]) -> Result<Self, InvalidPubkey<32>> {
253        XOnlyPk::from_byte_array(data).map(Self)
254    }
255
256    #[inline]
257    pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, InvalidPubkey<33>> {
258        XOnlyPk::from_bytes(bytes).map(Self)
259    }
260
261    #[inline]
262    pub fn to_xonly_pk(&self) -> XOnlyPk { self.0 }
263
264    #[inline]
265    pub fn to_script_pubkey(&self) -> ScriptPubkey { ScriptPubkey::p2tr_tweaked(*self) }
266
267    #[inline]
268    pub fn to_byte_array(&self) -> [u8; 32] { self.0.to_byte_array() }
269}
270
271impl From<OutputPk> for [u8; 32] {
272    fn from(pk: OutputPk) -> [u8; 32] { pk.to_byte_array() }
273}
274
275pub trait IntoTapHash {
276    fn into_tap_hash(self) -> TapNodeHash;
277}
278
279#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
280#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
281#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
282#[strict_type(lib = LIB_NAME_BITCOIN)]
283#[cfg_attr(
284    feature = "serde",
285    derive(Serialize, Deserialize),
286    serde(crate = "serde_crate", transparent)
287)]
288pub struct TapSighash(
289    #[from]
290    #[from([u8; 32])]
291    pub Bytes32,
292);
293
294impl From<TapSighash> for [u8; 32] {
295    fn from(value: TapSighash) -> Self { value.0.into_inner() }
296}
297
298impl From<TapSighash> for secp256k1::Message {
299    fn from(sighash: TapSighash) -> Self {
300        secp256k1::Message::from_digest(sighash.to_byte_array())
301    }
302}
303
304impl TapSighash {
305    pub fn engine() -> Sha256 { Sha256::from_tag(MIDSTATE_TAPSIGHASH) }
306
307    pub fn from_engine(engine: Sha256) -> Self { Self(engine.finish().into()) }
308}
309
310#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
311#[wrapper(Index, RangeOps, BorrowSlice, Hex, Display, FromStr)]
312#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
313#[strict_type(lib = LIB_NAME_BITCOIN)]
314#[cfg_attr(
315    feature = "serde",
316    derive(Serialize, Deserialize),
317    serde(crate = "serde_crate", transparent)
318)]
319pub struct TapLeafHash(
320    #[from]
321    #[from([u8; 32])]
322    Bytes32,
323);
324
325impl TapLeafHash {
326    pub fn with_leaf_script(leaf_script: &LeafScript) -> Self {
327        Self::with_raw_script(leaf_script.version, leaf_script.as_script_bytes())
328    }
329
330    pub fn with_tap_script(tap_script: &TapScript) -> Self {
331        Self::with_raw_script(LeafVer::TapScript, tap_script.as_script_bytes())
332    }
333
334    fn with_raw_script(version: LeafVer, script: &ScriptBytes) -> Self {
335        let mut engine = Sha256::from_tag(MIDSTATE_TAPLEAF);
336        engine.input_raw(&[version.to_consensus_u8()]);
337        script.len_var_int().consensus_encode(&mut engine).ok();
338        engine.input_raw(script.as_slice());
339        Self(engine.finish().into())
340    }
341}
342
343impl IntoTapHash for TapLeafHash {
344    fn into_tap_hash(self) -> TapNodeHash { TapNodeHash(self.0) }
345}
346
347#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
348#[wrapper(Index, RangeOps, BorrowSlice, Hex, Display, FromStr)]
349#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
350#[strict_type(lib = LIB_NAME_BITCOIN)]
351#[cfg_attr(
352    feature = "serde",
353    derive(Serialize, Deserialize),
354    serde(crate = "serde_crate", transparent)
355)]
356pub struct TapBranchHash(
357    #[from]
358    #[from([u8; 32])]
359    Bytes32,
360);
361
362impl TapBranchHash {
363    pub fn with_nodes(node1: TapNodeHash, node2: TapNodeHash) -> Self {
364        let mut engine = Sha256::from_tag(MIDSTATE_TAPBRANCH);
365        engine.input_raw(cmp::min(&node1, &node2).borrow());
366        engine.input_raw(cmp::max(&node1, &node2).borrow());
367        Self(engine.finish().into())
368    }
369}
370
371impl IntoTapHash for TapBranchHash {
372    fn into_tap_hash(self) -> TapNodeHash { TapNodeHash(self.0) }
373}
374
375#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
376#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
377#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
378#[strict_type(lib = LIB_NAME_BITCOIN)]
379#[cfg_attr(
380    feature = "serde",
381    derive(Serialize, Deserialize),
382    serde(crate = "serde_crate", transparent)
383)]
384pub struct TapNodeHash(
385    #[from]
386    #[from([u8; 32])]
387    #[from(TapLeafHash)]
388    #[from(TapBranchHash)]
389    Bytes32,
390);
391
392impl IntoTapHash for TapNodeHash {
393    fn into_tap_hash(self) -> TapNodeHash { self }
394}
395
396#[derive(Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
397#[wrapper(Deref)]
398#[wrapper_mut(DerefMut)]
399#[derive(StrictType, StrictEncode, StrictDecode)]
400#[strict_type(lib = LIB_NAME_BITCOIN)]
401#[cfg_attr(
402    feature = "serde",
403    derive(Serialize, Deserialize),
404    serde(crate = "serde_crate", transparent)
405)]
406pub struct TapMerklePath(Confined<Vec<TapBranchHash>, 0, 128>);
407
408impl IntoIterator for TapMerklePath {
409    type Item = TapBranchHash;
410    type IntoIter = vec::IntoIter<TapBranchHash>;
411
412    fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
413}
414
415impl<'a> IntoIterator for &'a TapMerklePath {
416    type Item = &'a TapBranchHash;
417    type IntoIter = slice::Iter<'a, TapBranchHash>;
418
419    fn into_iter(self) -> Self::IntoIter { self.0.iter() }
420}
421
422impl TapMerklePath {
423    /// Tries to construct a confinement over a collection. Fails if the number
424    /// of items in the collection exceeds one of the confinement bounds.
425    // We can't use `impl TryFrom` due to the conflict with core library blanked
426    // implementation
427    #[inline]
428    pub fn try_from(path: Vec<TapBranchHash>) -> Result<Self, confinement::Error> {
429        Confined::try_from(path).map(Self::from_inner)
430    }
431
432    /// Tries to construct a confinement with a collection of elements taken
433    /// from an iterator. Fails if the number of items in the collection
434    /// exceeds one of the confinement bounds.
435    #[inline]
436    pub fn try_from_iter<I: IntoIterator<Item = TapBranchHash>>(
437        iter: I,
438    ) -> Result<Self, confinement::Error> {
439        Confined::try_from_iter(iter).map(Self::from_inner)
440    }
441}
442
443/// Taproot annex prefix.
444pub const TAPROOT_ANNEX_PREFIX: u8 = 0x50;
445
446/// Tapscript leaf version.
447// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L226
448pub const TAPROOT_LEAF_TAPSCRIPT: u8 = 0xc0;
449
450/// Tapleaf mask for getting the leaf version from first byte of control block.
451// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L225
452pub const TAPROOT_LEAF_MASK: u8 = 0xfe;
453
454#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Display, Error)]
455#[display(doc_comments)]
456/// invalid taproot leaf version {0}.
457pub struct InvalidLeafVer(u8);
458
459/// The leaf version for tapleafs.
460#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
461#[cfg_attr(
462    feature = "serde",
463    derive(Serialize, Deserialize),
464    serde(crate = "serde_crate", rename_all = "camelCase")
465)]
466pub enum LeafVer {
467    /// BIP-342 tapscript.
468    #[default]
469    TapScript,
470
471    /// Future leaf version.
472    Future(FutureLeafVer),
473}
474
475impl StrictType for LeafVer {
476    const STRICT_LIB_NAME: &'static str = LIB_NAME_BITCOIN;
477    fn strict_name() -> Option<TypeName> { Some(tn!("LeafVer")) }
478}
479impl StrictProduct for LeafVer {}
480impl StrictTuple for LeafVer {
481    const FIELD_COUNT: u8 = 1;
482}
483impl StrictEncode for LeafVer {
484    fn strict_encode<W: TypedWrite>(&self, writer: W) -> std::io::Result<W> {
485        writer.write_tuple::<Self>(|w| Ok(w.write_field(&self.to_consensus_u8())?.complete()))
486    }
487}
488impl StrictDecode for LeafVer {
489    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
490        reader.read_tuple(|r| {
491            let version = r.read_field()?;
492            Self::from_consensus_u8(version)
493                .map_err(|err| DecodeError::DataIntegrityError(err.to_string()))
494        })
495    }
496}
497
498impl LeafVer {
499    #[doc(hidden)]
500    #[deprecated(since = "0.10.9", note = "use from_consensus_u8")]
501    pub fn from_consensus(version: u8) -> Result<Self, InvalidLeafVer> {
502        Self::from_consensus_u8(version)
503    }
504
505    /// Creates a [`LeafVer`] from consensus byte representation.
506    ///
507    /// # Errors
508    ///
509    /// - If the last bit of the `version` is odd.
510    /// - If the `version` is 0x50 ([`TAPROOT_ANNEX_PREFIX`]).
511    pub fn from_consensus_u8(version: u8) -> Result<Self, InvalidLeafVer> {
512        match version {
513            TAPROOT_LEAF_TAPSCRIPT => Ok(LeafVer::TapScript),
514            TAPROOT_ANNEX_PREFIX => Err(InvalidLeafVer(TAPROOT_ANNEX_PREFIX)),
515            future => FutureLeafVer::from_consensus(future).map(LeafVer::Future),
516        }
517    }
518
519    #[doc(hidden)]
520    #[deprecated(since = "0.10.9", note = "use to_consensus_u8")]
521    pub fn to_consensus(self) -> u8 { self.to_consensus_u8() }
522
523    /// Returns the consensus representation of this [`LeafVer`].
524    pub fn to_consensus_u8(self) -> u8 {
525        match self {
526            LeafVer::TapScript => TAPROOT_LEAF_TAPSCRIPT,
527            LeafVer::Future(version) => version.to_consensus(),
528        }
529    }
530}
531
532impl LowerHex for LeafVer {
533    fn fmt(&self, f: &mut Formatter) -> fmt::Result { LowerHex::fmt(&self.to_consensus_u8(), f) }
534}
535
536impl UpperHex for LeafVer {
537    fn fmt(&self, f: &mut Formatter) -> fmt::Result { UpperHex::fmt(&self.to_consensus_u8(), f) }
538}
539
540/// Inner type representing future (non-tapscript) leaf versions. See
541/// [`LeafVer::Future`].
542///
543/// NB: NO PUBLIC CONSTRUCTOR!
544/// The only way to construct this is by converting `u8` to [`LeafVer`] and then
545/// extracting it.
546#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
547#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
548#[strict_type(lib = LIB_NAME_BITCOIN, dumb = { Self(0x51) })]
549#[cfg_attr(
550    feature = "serde",
551    derive(Serialize, Deserialize),
552    serde(crate = "serde_crate", transparent)
553)]
554pub struct FutureLeafVer(u8);
555
556impl FutureLeafVer {
557    pub(self) fn from_consensus(version: u8) -> Result<FutureLeafVer, InvalidLeafVer> {
558        match version {
559            TAPROOT_LEAF_TAPSCRIPT => unreachable!(
560                "FutureLeafVersion::from_consensus should be never called for 0xC0 value"
561            ),
562            TAPROOT_ANNEX_PREFIX => Err(InvalidLeafVer(TAPROOT_ANNEX_PREFIX)),
563            odd if odd & 0xFE != odd => Err(InvalidLeafVer(odd)),
564            even => Ok(FutureLeafVer(even)),
565        }
566    }
567
568    /// Returns the consensus representation of this [`FutureLeafVer`].
569    #[inline]
570    pub fn to_consensus(self) -> u8 { self.0 }
571}
572
573impl LowerHex for FutureLeafVer {
574    #[inline]
575    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { LowerHex::fmt(&self.0, f) }
576}
577
578impl UpperHex for FutureLeafVer {
579    #[inline]
580    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { UpperHex::fmt(&self.0, f) }
581}
582
583#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, Display)]
584#[derive(StrictType, StrictEncode, StrictDecode)]
585#[strict_type(lib = LIB_NAME_BITCOIN)]
586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
587#[display("{version:04x} {script:x}")]
588pub struct LeafScript {
589    pub version: LeafVer,
590    pub script: ScriptBytes,
591}
592
593// TODO: Impl Hex and FromStr for LeafScript
594
595impl From<TapScript> for LeafScript {
596    fn from(tap_script: TapScript) -> Self {
597        LeafScript {
598            version: LeafVer::TapScript,
599            script: tap_script.into_inner(),
600        }
601    }
602}
603
604impl LeafScript {
605    #[inline]
606    pub fn new(version: LeafVer, script: ScriptBytes) -> Self { LeafScript { version, script } }
607    #[inline]
608    pub fn with_bytes(version: LeafVer, script: Vec<u8>) -> Result<Self, confinement::Error> {
609        Ok(LeafScript {
610            version,
611            script: ScriptBytes::try_from(script)?,
612        })
613    }
614    #[inline]
615    pub fn from_tap_script(tap_script: TapScript) -> Self { Self::from(tap_script) }
616
617    #[inline]
618    pub fn as_script_bytes(&self) -> &ScriptBytes { &self.script }
619
620    #[inline]
621    pub fn tap_leaf_hash(&self) -> TapLeafHash { TapLeafHash::with_leaf_script(self) }
622}
623
624#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
625#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
626#[strict_type(lib = LIB_NAME_BITCOIN, tags = repr, into_u8, try_from_u8)]
627#[repr(u8)]
628#[non_exhaustive]
629pub enum TapCode {
630    /// Push the next 32 bytes as an array onto the stack.
631    #[display("OP_PUSH_BYTES32")]
632    PushBytes32 = OP_PUSHBYTES_32,
633
634    /// Synonym for OP_RETURN.
635    Reserved = OP_RESERVED,
636
637    /// Fail the script immediately.
638    #[display("OP_RETURN")]
639    #[strict_type(dumb)]
640    Return = OP_RETURN,
641
642    /// Read the next byte as N; push the next N bytes as an array onto the
643    /// stack.
644    #[display("OP_PUSH_DATA1")]
645    PushData1 = OP_PUSHDATA1,
646    /// Read the next 2 bytes as N; push the next N bytes as an array onto the
647    /// stack.
648    #[display("OP_PUSH_DATA2")]
649    PushData2 = OP_PUSHDATA2,
650    /// Read the next 4 bytes as N; push the next N bytes as an array onto the
651    /// stack.
652    #[display("OP_PUSH_DATA3")]
653    PushData4 = OP_PUSHDATA4,
654}
655
656#[derive(Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
657#[wrapper(Deref, AsSlice, Hex)]
658#[wrapper_mut(DerefMut, AsSliceMut)]
659#[derive(StrictType, StrictEncode, StrictDecode)]
660#[strict_type(lib = LIB_NAME_BITCOIN)]
661#[cfg_attr(
662    feature = "serde",
663    derive(Serialize, Deserialize),
664    serde(crate = "serde_crate", transparent)
665)]
666pub struct TapScript(ScriptBytes);
667// TODO: impl Display/FromStr for TapScript providing correct opcodes
668
669impl TryFrom<Vec<u8>> for TapScript {
670    type Error = confinement::Error;
671    fn try_from(script_bytes: Vec<u8>) -> Result<Self, Self::Error> {
672        ScriptBytes::try_from(script_bytes).map(Self)
673    }
674}
675
676impl TapScript {
677    #[inline]
678    pub fn new() -> Self { Self::default() }
679
680    #[inline]
681    pub fn with_capacity(capacity: usize) -> Self {
682        Self(ScriptBytes::from(Confined::with_capacity(capacity)))
683    }
684
685    /// Constructs script object assuming the script length is less than 4GB.
686    /// Panics otherwise.
687    #[inline]
688    pub fn from_unsafe(script_bytes: Vec<u8>) -> Self {
689        Self(ScriptBytes::from_unsafe(script_bytes))
690    }
691
692    #[inline]
693    pub fn tap_leaf_hash(&self) -> TapLeafHash { TapLeafHash::with_tap_script(self) }
694
695    /// Adds a single opcode to the script.
696    #[inline]
697    pub fn push_opcode(&mut self, op_code: TapCode) { self.0.push(op_code as u8); }
698
699    #[inline]
700    pub fn as_script_bytes(&self) -> &ScriptBytes { &self.0 }
701}
702
703impl ScriptPubkey {
704    pub fn p2tr(internal_key: InternalPk, merkle_root: Option<TapNodeHash>) -> Self {
705        let (output_key, _) = internal_key.to_output_pk(merkle_root);
706        Self::p2tr_tweaked(output_key)
707    }
708
709    pub fn p2tr_key_only(internal_key: InternalPk) -> Self {
710        let (output_key, _) = internal_key.to_output_pk(None);
711        Self::p2tr_tweaked(output_key)
712    }
713
714    pub fn p2tr_scripted(internal_key: InternalPk, merkle_root: impl IntoTapHash) -> Self {
715        let (output_key, _) = internal_key.to_output_pk(Some(merkle_root.into_tap_hash()));
716        Self::p2tr_tweaked(output_key)
717    }
718
719    pub fn p2tr_tweaked(output_key: OutputPk) -> Self {
720        // output key is 32 bytes long, so it's safe to use
721        // `new_witness_program_unchecked` (Segwitv1)
722        Self::with_witness_program_unchecked(WitnessVer::V1, &output_key.serialize())
723    }
724
725    pub fn is_p2tr(&self) -> bool {
726        self.len() == 34 && self[0] == WitnessVer::V1.op_code() as u8 && self[1] == OP_PUSHBYTES_32
727    }
728}
729
730/// invalid parity value {0} - must be 0 or 1
731#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Error)]
732#[display(doc_comments)]
733pub struct InvalidParityValue(pub u8);
734
735/// Represents the parity passed between FFI function calls.
736#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
737#[display(lowercase)]
738#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
739#[strict_type(lib = LIB_NAME_BITCOIN, tags = repr, into_u8, try_from_u8)]
740#[cfg_attr(
741    feature = "serde",
742    derive(Serialize, Deserialize),
743    serde(crate = "serde_crate", rename_all = "camelCase")
744)]
745#[repr(u8)]
746pub enum Parity {
747    /// Even parity.
748    #[strict_type(dumb)]
749    Even = 0,
750    /// Odd parity.
751    Odd = 1,
752}
753
754impl From<secp256k1::Parity> for Parity {
755    fn from(parity: secp256k1::Parity) -> Self {
756        match parity {
757            secp256k1::Parity::Even => Parity::Even,
758            secp256k1::Parity::Odd => Parity::Odd,
759        }
760    }
761}
762
763impl Parity {
764    /// Converts parity into an integer (byte) value.
765    ///
766    /// This returns `0` for even parity and `1` for odd parity.
767    pub fn to_consensus_u8(self) -> u8 { self as u8 }
768
769    /// Constructs a [`Parity`] from a byte.
770    ///
771    /// The only allowed values are `0` meaning even parity and `1` meaning odd.
772    /// Other values result in error being returned.
773    pub fn from_consensus_u8(parity: u8) -> Result<Parity, InvalidParityValue> {
774        match parity {
775            0 => Ok(Parity::Even),
776            1 => Ok(Parity::Odd),
777            invalid => Err(InvalidParityValue(invalid)),
778        }
779    }
780}
781
782/// Returns even parity if the operands are equal, odd otherwise.
783impl BitXor for Parity {
784    type Output = Parity;
785
786    fn bitxor(self, rhs: Parity) -> Self::Output {
787        // This works because Parity has only two values (i.e. only 1 bit of
788        // information).
789        if self == rhs {
790            Parity::Even // 1^1==0 and 0^0==0
791        } else {
792            Parity::Odd // 1^0==1 and 0^1==1
793        }
794    }
795}
796
797#[derive(Clone, Eq, PartialEq, Hash, Debug)]
798#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
799#[strict_type(lib = LIB_NAME_BITCOIN)]
800#[cfg_attr(
801    feature = "serde",
802    derive(Serialize, Deserialize),
803    serde(crate = "serde_crate", rename_all = "camelCase")
804)]
805pub struct ControlBlock {
806    /// The tapleaf version.
807    pub leaf_version: LeafVer,
808    /// The parity of the output key (NOT THE INTERNAL KEY WHICH IS ALWAYS
809    /// XONLY).
810    pub output_key_parity: Parity,
811    /// The internal key.
812    pub internal_pk: InternalPk,
813    /// The merkle proof of a script associated with this leaf.
814    pub merkle_branch: TapMerklePath,
815}
816
817impl ControlBlock {
818    #[inline]
819    pub fn with(
820        leaf_version: LeafVer,
821        internal_pk: InternalPk,
822        output_key_parity: Parity,
823        merkle_branch: TapMerklePath,
824    ) -> Self {
825        ControlBlock {
826            leaf_version,
827            output_key_parity,
828            internal_pk,
829            merkle_branch,
830        }
831    }
832}
833
834#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
835#[display(doc_comments)]
836pub enum AnnexError {
837    /// invalid first annex byte `{0:#02x}`, which must be `0x50`.
838    WrongFirstByte(u8),
839
840    #[from]
841    #[display(inner)]
842    Size(confinement::Error),
843}
844
845/// The `Annex` struct enforces first byte to be `0x50`.
846#[derive(Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
847#[wrapper(Deref, AsSlice, Hex)]
848#[wrapper_mut(DerefMut, AsSliceMut)]
849#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
850#[strict_type(lib = LIB_NAME_BITCOIN, dumb = { Self(VarIntBytes::with(0x50)) })]
851pub struct Annex(VarIntBytes<1>);
852
853impl TryFrom<Vec<u8>> for Annex {
854    type Error = confinement::Error;
855    fn try_from(script_bytes: Vec<u8>) -> Result<Self, Self::Error> {
856        Confined::try_from(script_bytes).map(Self)
857    }
858}
859
860impl Annex {
861    /// Creates a new `Annex` struct checking the first byte is `0x50`.
862    /// Constructs script object assuming the script length is less than 4GB.
863    /// Panics otherwise.
864    #[inline]
865    pub fn new(annex_bytes: Vec<u8>) -> Result<Self, AnnexError> {
866        let annex = Confined::try_from(annex_bytes).map(Self)?;
867        if annex[0] != TAPROOT_ANNEX_PREFIX {
868            return Err(AnnexError::WrongFirstByte(annex[0]));
869        }
870        Ok(annex)
871    }
872
873    pub fn len_var_int(&self) -> VarInt { VarInt(self.len() as u64) }
874
875    pub fn into_vec(self) -> Vec<u8> { self.0.release() }
876
877    /// Returns the Annex bytes data (including first byte `0x50`).
878    pub fn as_slice(&self) -> &[u8] { self.0.as_slice() }
879
880    pub(crate) fn as_var_int_bytes(&self) -> &VarIntBytes<1> { &self.0 }
881}
882
883#[cfg(feature = "serde")]
884mod _serde {
885    use amplify::hex::{FromHex, ToHex};
886    use serde::{Deserialize, Serialize};
887    use serde_crate::de::Error;
888    use serde_crate::{Deserializer, Serializer};
889
890    use super::*;
891
892    impl Serialize for Annex {
893        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
894        where S: Serializer {
895            if serializer.is_human_readable() {
896                serializer.serialize_str(&self.to_hex())
897            } else {
898                serializer.serialize_bytes(self.as_slice())
899            }
900        }
901    }
902
903    impl<'de> Deserialize<'de> for Annex {
904        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
905        where D: Deserializer<'de> {
906            if deserializer.is_human_readable() {
907                String::deserialize(deserializer).and_then(|string| {
908                    Self::from_hex(&string).map_err(|_| D::Error::custom("wrong hex data"))
909                })
910            } else {
911                let bytes = Vec::<u8>::deserialize(deserializer)?;
912                Self::new(bytes).map_err(|_| D::Error::custom("invalid annex data"))
913            }
914        }
915    }
916}