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