1#![allow(unused_braces)] use 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 TapCode, VarInt, VarIntBytes, WitnessVer, LIB_NAME_BITCOIN,
44};
45
46const MIDSTATE_TAPLEAF: [u8; 7] = *b"TapLeaf";
48const MIDSTATE_TAPBRANCH: [u8; 9] = *b"TapBranch";
52const MIDSTATE_TAPTWEAK: [u8; 8] = *b"TapTweak";
56pub const MIDSTATE_TAPSIGHASH: [u8; 10] = *b"TapSighash";
60impl<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#[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#[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 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#[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 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#[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 #[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 #[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
411pub const TAPROOT_ANNEX_PREFIX: u8 = 0x50;
413
414pub const TAPROOT_LEAF_TAPSCRIPT: u8 = 0xc0;
417
418pub const TAPROOT_LEAF_MASK: u8 = 0xfe;
421
422#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Display, Error)]
423#[display(doc_comments)]
424pub struct InvalidLeafVer(u8);
426
427#[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 #[default]
433 TapScript,
434
435 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 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 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#[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 #[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
553impl 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(Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
585#[wrapper(Deref, AsSlice, Hex)]
586#[wrapper_mut(DerefMut, AsSliceMut)]
587#[derive(StrictType, StrictEncode, StrictDecode)]
588#[strict_type(lib = LIB_NAME_BITCOIN)]
589#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
590pub struct TapScript(ScriptBytes);
591impl TryFrom<Vec<u8>> for TapScript {
594 type Error = confinement::Error;
595 fn try_from(script_bytes: Vec<u8>) -> Result<Self, Self::Error> {
596 ScriptBytes::try_from(script_bytes).map(Self)
597 }
598}
599
600impl TapScript {
601 #[inline]
602 pub fn new() -> Self { Self::default() }
603
604 #[inline]
605 pub fn with_capacity(capacity: usize) -> Self {
606 Self(ScriptBytes::from(Confined::with_capacity(capacity)))
607 }
608
609 #[inline]
612 pub fn from_checked(script_bytes: Vec<u8>) -> Self {
613 Self(ScriptBytes::from_checked(script_bytes))
614 }
615
616 #[inline]
617 pub fn tap_leaf_hash(&self) -> TapLeafHash { TapLeafHash::with_tap_script(self) }
618
619 #[inline]
621 pub fn push_opcode(&mut self, op_code: TapCode) { self.0.push(op_code as u8); }
622
623 #[inline]
624 pub fn as_script_bytes(&self) -> &ScriptBytes { &self.0 }
625}
626
627impl ScriptPubkey {
628 pub fn p2tr(internal_key: InternalPk, merkle_root: Option<TapNodeHash>) -> Self {
629 let (output_key, _) = internal_key.to_output_pk(merkle_root);
630 Self::p2tr_tweaked(output_key)
631 }
632
633 pub fn p2tr_key_only(internal_key: InternalPk) -> Self {
634 let (output_key, _) = internal_key.to_output_pk(None);
635 Self::p2tr_tweaked(output_key)
636 }
637
638 pub fn p2tr_scripted(internal_key: InternalPk, merkle_root: impl IntoTapHash) -> Self {
639 let (output_key, _) = internal_key.to_output_pk(Some(merkle_root.into_tap_hash()));
640 Self::p2tr_tweaked(output_key)
641 }
642
643 pub fn p2tr_tweaked(output_key: OutputPk) -> Self {
644 Self::with_witness_program_unchecked(WitnessVer::V1, &output_key.serialize())
647 }
648
649 pub fn is_p2tr(&self) -> bool {
650 self.len() == 34 && self[0] == WitnessVer::V1.op_code() as u8 && self[1] == OP_PUSHBYTES_32
651 }
652}
653
654#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Error)]
656#[display(doc_comments)]
657pub struct InvalidParityValue(pub u8);
658
659#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
661#[display(lowercase)]
662#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
663#[strict_type(lib = LIB_NAME_BITCOIN, tags = repr, into_u8, try_from_u8)]
664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
665#[repr(u8)]
666pub enum Parity {
667 #[strict_type(dumb)]
669 Even = 0,
670 Odd = 1,
672}
673
674impl From<secp256k1::Parity> for Parity {
675 fn from(parity: secp256k1::Parity) -> Self {
676 match parity {
677 secp256k1::Parity::Even => Parity::Even,
678 secp256k1::Parity::Odd => Parity::Odd,
679 }
680 }
681}
682
683impl Parity {
684 pub fn to_consensus_u8(self) -> u8 { self as u8 }
688
689 pub fn from_consensus_u8(parity: u8) -> Result<Parity, InvalidParityValue> {
694 match parity {
695 0 => Ok(Parity::Even),
696 1 => Ok(Parity::Odd),
697 invalid => Err(InvalidParityValue(invalid)),
698 }
699 }
700}
701
702impl BitXor for Parity {
704 type Output = Parity;
705
706 fn bitxor(self, rhs: Parity) -> Self::Output {
707 if self == rhs {
710 Parity::Even } else {
712 Parity::Odd }
714 }
715}
716
717#[derive(Clone, Eq, PartialEq, Hash, Debug)]
718#[derive(StrictType, StrictEncode, StrictDecode, StrictDumb)]
719#[strict_type(lib = LIB_NAME_BITCOIN)]
720#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
721pub struct ControlBlock {
722 pub leaf_version: LeafVer,
724 pub output_key_parity: Parity,
727 pub internal_pk: InternalPk,
729 pub merkle_branch: TapMerklePath,
731}
732
733impl ControlBlock {
734 #[inline]
735 pub fn with(
736 leaf_version: LeafVer,
737 internal_pk: InternalPk,
738 output_key_parity: Parity,
739 merkle_branch: TapMerklePath,
740 ) -> Self {
741 ControlBlock {
742 leaf_version,
743 output_key_parity,
744 internal_pk,
745 merkle_branch,
746 }
747 }
748}
749
750#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
751#[display(doc_comments)]
752pub enum AnnexError {
753 WrongFirstByte(u8),
755
756 #[from]
757 #[display(inner)]
758 Size(confinement::Error),
759}
760
761#[derive(Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
763#[wrapper(Deref, AsSlice, Hex)]
764#[wrapper_mut(DerefMut, AsSliceMut)]
765#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
766#[strict_type(lib = LIB_NAME_BITCOIN, dumb = { Self(VarIntBytes::with(0x50)) })]
767pub struct Annex(VarIntBytes<1>);
768
769impl TryFrom<Vec<u8>> for Annex {
770 type Error = confinement::Error;
771 fn try_from(script_bytes: Vec<u8>) -> Result<Self, Self::Error> {
772 Confined::try_from(script_bytes).map(Self)
773 }
774}
775
776impl Annex {
777 #[inline]
781 pub fn new(annex_bytes: Vec<u8>) -> Result<Self, AnnexError> {
782 let annex = Confined::try_from(annex_bytes).map(Self)?;
783 if annex[0] != TAPROOT_ANNEX_PREFIX {
784 return Err(AnnexError::WrongFirstByte(annex[0]));
785 }
786 Ok(annex)
787 }
788
789 pub fn len_var_int(&self) -> VarInt { VarInt(self.len() as u64) }
790
791 pub fn into_vec(self) -> Vec<u8> { self.0.release() }
792
793 pub fn as_slice(&self) -> &[u8] { self.0.as_slice() }
795
796 pub(crate) fn as_var_int_bytes(&self) -> &VarIntBytes<1> { &self.0 }
797}
798
799#[cfg(feature = "serde")]
800mod _serde {
801 use amplify::hex::{FromHex, ToHex};
802 use serde::de::Error;
803 use serde::{Deserialize, Deserializer, Serialize, Serializer};
804
805 use super::*;
806
807 impl Serialize for Annex {
808 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
809 where S: Serializer {
810 if serializer.is_human_readable() {
811 serializer.serialize_str(&self.to_hex())
812 } else {
813 serializer.serialize_bytes(self.as_slice())
814 }
815 }
816 }
817
818 impl<'de> Deserialize<'de> for Annex {
819 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
820 where D: Deserializer<'de> {
821 if deserializer.is_human_readable() {
822 String::deserialize(deserializer).and_then(|string| {
823 Self::from_hex(&string).map_err(|_| D::Error::custom("wrong hex data"))
824 })
825 } else {
826 let bytes = Vec::<u8>::deserialize(deserializer)?;
827 Self::new(bytes).map_err(|_| D::Error::custom("invalid annex data"))
828 }
829 }
830 }
831}