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 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(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 #[display("OP_PUSH_BYTES32")]
592 PushBytes32 = OP_PUSHBYTES_32,
593
594 Reserved = OP_RESERVED,
596
597 #[display("OP_RETURN")]
599 #[strict_type(dumb)]
600 Return = OP_RETURN,
601
602 #[display("OP_PUSH_DATA1")]
605 PushData1 = OP_PUSHDATA1,
606 #[display("OP_PUSH_DATA2")]
609 PushData2 = OP_PUSHDATA2,
610 #[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);
623impl 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 #[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 #[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 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#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Error)]
688#[display(doc_comments)]
689pub struct InvalidParityValue(pub u8);
690
691#[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 #[strict_type(dumb)]
701 Even = 0,
702 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 pub fn to_consensus_u8(self) -> u8 { self as u8 }
720
721 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
734impl BitXor for Parity {
736 type Output = Parity;
737
738 fn bitxor(self, rhs: Parity) -> Self::Output {
739 if self == rhs {
742 Parity::Even } else {
744 Parity::Odd }
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 pub leaf_version: LeafVer,
756 pub output_key_parity: Parity,
759 pub internal_pk: InternalPk,
761 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 WrongFirstByte(u8),
787
788 #[from]
789 #[display(inner)]
790 Size(confinement::Error),
791}
792
793#[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 #[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 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}