1use serde::{Deserialize, Serialize};
26use thiserror::Error;
27
28#[derive(Error, Debug, Clone, PartialEq, Eq)]
34pub enum TaprootPsbtError {
35 #[error("invalid key path: {0}")]
37 InvalidKeyPath(String),
38
39 #[error("invalid leaf script: {0}")]
41 InvalidLeafScript(String),
42
43 #[error("invalid control block: {0}")]
45 InvalidControlBlock(String),
46
47 #[error("invalid Taproot signature: {0}")]
49 InvalidSignature(String),
50
51 #[error("invalid internal key: {0}")]
53 InvalidInternalKey(String),
54
55 #[error("invalid Merkle root: {0}")]
57 InvalidMerkleRoot(String),
58
59 #[error("invalid derivation path: {0}")]
61 InvalidDerivationPath(String),
62
63 #[error("input index {0} out of range")]
65 InputIndexOutOfRange(usize),
66
67 #[error("output index {0} out of range")]
69 OutputIndexOutOfRange(usize),
70}
71
72fn validate_hex_length(
78 hex_str: &str,
79 expected_bytes: usize,
80 field: &str,
81) -> Result<(), TaprootPsbtError> {
82 let expected_chars = expected_bytes * 2;
83 if hex_str.len() != expected_chars {
84 return Err(TaprootPsbtError::InvalidInternalKey(format!(
85 "{field}: expected {expected_bytes} bytes ({expected_chars} hex chars), got {} chars",
86 hex_str.len()
87 )));
88 }
89 if !hex_str.chars().all(|c| c.is_ascii_hexdigit()) {
90 return Err(TaprootPsbtError::InvalidInternalKey(format!(
91 "{field}: contains non-hex characters"
92 )));
93 }
94 Ok(())
95}
96
97fn validate_hex_with<E, F>(hex_str: &str, expected_bytes: usize, make_err: F) -> Result<(), E>
100where
101 F: FnOnce(String) -> E,
102{
103 let expected_chars = expected_bytes * 2;
104 if hex_str.len() != expected_chars {
105 return Err(make_err(format!(
106 "expected {expected_bytes} bytes ({expected_chars} hex chars), got {} chars",
107 hex_str.len()
108 )));
109 }
110 if !hex_str.chars().all(|c| c.is_ascii_hexdigit()) {
111 return Err(make_err("contains non-hex characters".to_string()));
112 }
113 Ok(())
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
127pub enum LeafVersion {
128 #[default]
130 TapScript,
131 Future(u8),
133}
134
135impl LeafVersion {
136 pub fn to_byte(&self) -> u8 {
138 match self {
139 Self::TapScript => 0xC0,
140 Self::Future(b) => *b,
141 }
142 }
143
144 pub fn from_byte(b: u8) -> Self {
146 if b == 0xC0 {
147 Self::TapScript
148 } else {
149 Self::Future(b)
150 }
151 }
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct TapLeafScript {
164 pub leaf_version: LeafVersion,
166
167 pub script: Vec<u8>,
169
170 pub control_block: Vec<u8>,
175}
176
177impl TapLeafScript {
178 pub fn new(script: Vec<u8>, version: LeafVersion) -> Self {
180 Self {
181 leaf_version: version,
182 script,
183 control_block: Vec::new(),
184 }
185 }
186
187 pub fn script_hex(&self) -> String {
189 self.script
190 .iter()
191 .map(|b| format!("{b:02x}"))
192 .collect::<String>()
193 }
194
195 pub fn control_block_hex(&self) -> String {
197 self.control_block
198 .iter()
199 .map(|b| format!("{b:02x}"))
200 .collect::<String>()
201 }
202
203 pub fn proof_len(&self) -> usize {
209 if self.control_block.len() < 33 {
210 return 0;
211 }
212 (self.control_block.len() - 33) / 32
213 }
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct TapBip32Derivation {
224 pub x_only_pubkey: String,
226
227 pub master_fingerprint: String,
229
230 pub derivation_path: String,
232
233 pub leaf_hashes: Vec<String>,
236}
237
238impl TapBip32Derivation {
239 pub fn new(x_only_pubkey: String, master_fingerprint: String, derivation_path: String) -> Self {
241 Self {
242 x_only_pubkey,
243 master_fingerprint,
244 derivation_path,
245 leaf_hashes: Vec::new(),
246 }
247 }
248
249 pub fn is_key_path(&self) -> bool {
252 self.leaf_hashes.is_empty()
253 }
254
255 pub fn validate(&self) -> Result<(), TaprootPsbtError> {
257 validate_hex_with(&self.x_only_pubkey, 32, |msg| {
259 TaprootPsbtError::InvalidKeyPath(format!("x_only_pubkey: {msg}"))
260 })?;
261
262 validate_hex_with(&self.master_fingerprint, 4, |msg| {
264 TaprootPsbtError::InvalidDerivationPath(format!("master_fingerprint: {msg}"))
265 })?;
266
267 if self.derivation_path.is_empty() {
268 return Err(TaprootPsbtError::InvalidDerivationPath(
269 "derivation path is empty".to_string(),
270 ));
271 }
272
273 for hash in &self.leaf_hashes {
275 validate_hex_with(hash, 32, |msg| {
276 TaprootPsbtError::InvalidKeyPath(format!("leaf_hash: {msg}"))
277 })?;
278 }
279
280 Ok(())
281 }
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct TaprootInputFields {
291 pub tap_key_sig: Option<String>,
295
296 pub tap_script_sigs: Vec<(String, String)>,
299
300 pub tap_leaf_scripts: Vec<TapLeafScript>,
302
303 pub tap_bip32_derivations: Vec<TapBip32Derivation>,
306
307 pub tap_internal_key: Option<String>,
309
310 pub tap_merkle_root: Option<String>,
314}
315
316impl TaprootInputFields {
317 pub fn new() -> Self {
319 Self {
320 tap_key_sig: None,
321 tap_script_sigs: Vec::new(),
322 tap_leaf_scripts: Vec::new(),
323 tap_bip32_derivations: Vec::new(),
324 tap_internal_key: None,
325 tap_merkle_root: None,
326 }
327 }
328
329 pub fn with_key_sig(mut self, sig: String) -> Result<Self, TaprootPsbtError> {
334 let is_valid = sig.len() == 128 || sig.len() == 130 ;
335 if !is_valid || !sig.chars().all(|c| c.is_ascii_hexdigit()) {
336 return Err(TaprootPsbtError::InvalidSignature(format!(
337 "tap_key_sig must be 64 or 65 bytes (128 or 130 hex chars), got {} chars",
338 sig.len()
339 )));
340 }
341 self.tap_key_sig = Some(sig);
342 Ok(self)
343 }
344
345 pub fn with_internal_key(mut self, key: String) -> Result<Self, TaprootPsbtError> {
349 validate_hex_length(&key, 32, "tap_internal_key").map_err(|_| {
350 TaprootPsbtError::InvalidInternalKey(format!(
351 "tap_internal_key must be 32 bytes (64 hex chars), got {} chars",
352 key.len()
353 ))
354 })?;
355 self.tap_internal_key = Some(key);
356 Ok(self)
357 }
358
359 pub fn with_merkle_root(mut self, root: String) -> Result<Self, TaprootPsbtError> {
363 validate_hex_with(&root, 32, TaprootPsbtError::InvalidMerkleRoot)?;
364 self.tap_merkle_root = Some(root);
365 Ok(self)
366 }
367
368 pub fn add_leaf_script(&mut self, leaf: TapLeafScript) {
370 self.tap_leaf_scripts.push(leaf);
371 }
372
373 pub fn add_bip32_derivation(&mut self, deriv: TapBip32Derivation) {
375 self.tap_bip32_derivations.push(deriv);
376 }
377
378 pub fn is_key_path_signed(&self) -> bool {
380 self.tap_key_sig.is_some()
381 }
382
383 pub fn is_script_path_signed(&self) -> bool {
385 !self.tap_script_sigs.is_empty()
386 }
387
388 pub fn is_finalized(&self) -> bool {
391 self.is_key_path_signed() || self.is_script_path_signed()
392 }
393
394 pub fn validate(&self) -> Result<(), TaprootPsbtError> {
396 if let Some(ref sig) = self.tap_key_sig {
397 let valid = (sig.len() == 128 || sig.len() == 130)
398 && sig.chars().all(|c| c.is_ascii_hexdigit());
399 if !valid {
400 return Err(TaprootPsbtError::InvalidSignature(format!(
401 "tap_key_sig: expected 64 or 65 bytes, got {} hex chars",
402 sig.len()
403 )));
404 }
405 }
406
407 if let Some(ref key) = self.tap_internal_key {
408 validate_hex_length(key, 32, "tap_internal_key").map_err(|_| {
409 TaprootPsbtError::InvalidInternalKey(format!(
410 "tap_internal_key must be 32 bytes (64 hex chars), got {} chars",
411 key.len()
412 ))
413 })?;
414 }
415
416 if let Some(ref root) = self.tap_merkle_root {
417 validate_hex_with(root, 32, TaprootPsbtError::InvalidMerkleRoot)?;
418 }
419
420 for (cb, sig) in &self.tap_script_sigs {
421 if cb.len() < 66 || cb.len() % 2 != 0 || !cb.chars().all(|c| c.is_ascii_hexdigit()) {
423 return Err(TaprootPsbtError::InvalidControlBlock(format!(
424 "script sig control block is malformed (len {})",
425 cb.len()
426 )));
427 }
428 let sig_valid = (sig.len() == 128 || sig.len() == 130)
429 && sig.chars().all(|c| c.is_ascii_hexdigit());
430 if !sig_valid {
431 return Err(TaprootPsbtError::InvalidSignature(format!(
432 "script-path sig must be 64 or 65 bytes, got {} hex chars",
433 sig.len()
434 )));
435 }
436 }
437
438 for deriv in &self.tap_bip32_derivations {
439 deriv.validate()?;
440 }
441
442 Ok(())
443 }
444}
445
446impl Default for TaprootInputFields {
447 fn default() -> Self {
448 Self::new()
449 }
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
458pub struct TaprootOutputFields {
459 pub tap_internal_key: Option<String>,
461
462 pub tap_tree: Vec<TapLeafScript>,
464
465 pub tap_bip32_derivations: Vec<TapBip32Derivation>,
468}
469
470impl TaprootOutputFields {
471 pub fn new() -> Self {
473 Self {
474 tap_internal_key: None,
475 tap_tree: Vec::new(),
476 tap_bip32_derivations: Vec::new(),
477 }
478 }
479
480 pub fn with_internal_key(mut self, key: String) -> Result<Self, TaprootPsbtError> {
484 validate_hex_with(&key, 32, |msg| {
485 TaprootPsbtError::InvalidInternalKey(format!("tap_internal_key: {msg}"))
486 })?;
487 self.tap_internal_key = Some(key);
488 Ok(self)
489 }
490
491 pub fn add_tree_leaf(&mut self, leaf: TapLeafScript) {
493 self.tap_tree.push(leaf);
494 }
495
496 pub fn is_taproot_output(&self) -> bool {
499 self.tap_internal_key.is_some()
500 }
501
502 pub fn validate(&self) -> Result<(), TaprootPsbtError> {
504 if let Some(ref key) = self.tap_internal_key {
505 validate_hex_with(key, 32, |msg| {
506 TaprootPsbtError::InvalidInternalKey(format!("tap_internal_key: {msg}"))
507 })?;
508 }
509
510 for deriv in &self.tap_bip32_derivations {
511 deriv.validate()?;
512 }
513
514 Ok(())
515 }
516}
517
518impl Default for TaprootOutputFields {
519 fn default() -> Self {
520 Self::new()
521 }
522}
523
524#[derive(Debug, Clone, Serialize, Deserialize)]
534pub struct TaprootPsbt {
535 pub base_psbt_hex: String,
537
538 pub input_fields: Vec<TaprootInputFields>,
540
541 pub output_fields: Vec<TaprootOutputFields>,
543}
544
545impl TaprootPsbt {
546 pub fn new(psbt_hex: String) -> Self {
548 Self {
549 base_psbt_hex: psbt_hex,
550 input_fields: Vec::new(),
551 output_fields: Vec::new(),
552 }
553 }
554
555 pub fn input_count(&self) -> usize {
557 self.input_fields.len()
558 }
559
560 pub fn output_count(&self) -> usize {
562 self.output_fields.len()
563 }
564
565 pub fn is_complete(&self) -> bool {
569 if self.input_fields.is_empty() {
570 return false;
571 }
572 self.input_fields.iter().all(|f| f.is_finalized())
573 }
574
575 pub fn get_input_fields(&self, index: usize) -> Option<&TaprootInputFields> {
578 self.input_fields.get(index)
579 }
580
581 pub fn get_output_fields(&self, index: usize) -> Option<&TaprootOutputFields> {
584 self.output_fields.get(index)
585 }
586
587 pub fn add_input_taproot_fields(
592 &mut self,
593 index: usize,
594 fields: TaprootInputFields,
595 ) -> Result<(), TaprootPsbtError> {
596 while self.input_fields.len() <= index {
598 self.input_fields.push(TaprootInputFields::new());
599 }
600 self.input_fields[index] = fields;
601 Ok(())
602 }
603
604 pub fn add_output_taproot_fields(
609 &mut self,
610 index: usize,
611 fields: TaprootOutputFields,
612 ) -> Result<(), TaprootPsbtError> {
613 while self.output_fields.len() <= index {
614 self.output_fields.push(TaprootOutputFields::new());
615 }
616 self.output_fields[index] = fields;
617 Ok(())
618 }
619
620 pub fn validate_all(&self) -> Result<(), TaprootPsbtError> {
622 for fields in &self.input_fields {
623 fields.validate()?;
624 }
625 for fields in &self.output_fields {
626 fields.validate()?;
627 }
628 Ok(())
629 }
630}
631
632#[derive(Debug)]
654pub struct TaprootPsbtBuilder {
655 psbt_hex: String,
656 input_fields: Vec<TaprootInputFields>,
657 output_fields: Vec<TaprootOutputFields>,
658}
659
660impl TaprootPsbtBuilder {
661 pub fn new(psbt_hex: String) -> Self {
663 Self {
664 psbt_hex,
665 input_fields: Vec::new(),
666 output_fields: Vec::new(),
667 }
668 }
669
670 #[must_use]
672 pub fn add_input_fields(mut self, fields: TaprootInputFields) -> Self {
673 self.input_fields.push(fields);
674 self
675 }
676
677 #[must_use]
679 pub fn add_output_fields(mut self, fields: TaprootOutputFields) -> Self {
680 self.output_fields.push(fields);
681 self
682 }
683
684 pub fn build(self) -> TaprootPsbt {
686 TaprootPsbt {
687 base_psbt_hex: self.psbt_hex,
688 input_fields: self.input_fields,
689 output_fields: self.output_fields,
690 }
691 }
692}
693
694#[cfg(test)]
699mod tests {
700 use super::*;
701
702 fn xonly_key() -> String {
704 "b2c9c8b6a5d3e1f0b2c9c8b6a5d3e1f0b2c9c8b6a5d3e1f0b2c9c8b6a5d3e1f0".to_string()
705 }
706
707 fn schnorr_sig_64() -> String {
709 "aa".repeat(64)
710 }
711
712 fn schnorr_sig_65() -> String {
714 format!("{}01", "bb".repeat(64))
715 }
716
717 fn minimal_control_block() -> String {
719 "c0".to_string() + &"ab".repeat(32)
720 }
721
722 #[test]
723 fn test_leaf_version_tapscript() {
724 let v = LeafVersion::TapScript;
725 assert_eq!(v.to_byte(), 0xC0);
726 assert_eq!(LeafVersion::from_byte(0xC0), LeafVersion::TapScript);
727 }
728
729 #[test]
730 fn test_leaf_version_future() {
731 let v = LeafVersion::Future(0xC2);
732 assert_eq!(v.to_byte(), 0xC2);
733 assert_eq!(LeafVersion::from_byte(0xC2), LeafVersion::Future(0xC2));
734 }
735
736 #[test]
737 fn test_tap_leaf_script_new() {
738 let script = vec![0x51, 0x20]; let leaf = TapLeafScript::new(script.clone(), LeafVersion::TapScript);
740 assert_eq!(leaf.leaf_version, LeafVersion::TapScript);
741 assert_eq!(leaf.script, script);
742 assert!(leaf.control_block.is_empty());
743 assert_eq!(leaf.script_hex(), "5120");
744 }
745
746 #[test]
747 fn test_tap_leaf_script_proof_len() {
748 let mut leaf = TapLeafScript::new(vec![], LeafVersion::TapScript);
749
750 assert_eq!(leaf.proof_len(), 0);
752
753 leaf.control_block = vec![0xc0; 33];
755 assert_eq!(leaf.proof_len(), 0);
756
757 leaf.control_block = vec![0xc0; 65];
759 assert_eq!(leaf.proof_len(), 1);
760
761 leaf.control_block = vec![0xc0; 97];
763 assert_eq!(leaf.proof_len(), 2);
764 }
765
766 #[test]
767 fn test_taproot_input_fields_default() {
768 let fields = TaprootInputFields::default();
769 assert!(fields.tap_key_sig.is_none());
770 assert!(fields.tap_internal_key.is_none());
771 assert!(fields.tap_merkle_root.is_none());
772 assert!(fields.tap_script_sigs.is_empty());
773 assert!(fields.tap_leaf_scripts.is_empty());
774 assert!(fields.tap_bip32_derivations.is_empty());
775 assert!(!fields.is_finalized());
776 }
777
778 #[test]
779 fn test_taproot_input_key_path_signed() {
780 let fields = TaprootInputFields::new()
781 .with_key_sig(schnorr_sig_64())
782 .expect("64-byte sig should be accepted");
783
784 assert!(fields.is_key_path_signed());
785 assert!(!fields.is_script_path_signed());
786 assert!(fields.is_finalized());
787 assert!(fields.validate().is_ok());
788 }
789
790 #[test]
791 fn test_taproot_input_key_sig_65_bytes() {
792 let fields = TaprootInputFields::new()
793 .with_key_sig(schnorr_sig_65())
794 .expect("65-byte sig should be accepted");
795
796 assert!(fields.is_key_path_signed());
797 assert!(fields.validate().is_ok());
798 }
799
800 #[test]
801 fn test_taproot_input_key_sig_invalid_length() {
802 let bad_sig = "cc".repeat(63);
804 let result = TaprootInputFields::new().with_key_sig(bad_sig);
805 assert!(
806 matches!(result, Err(TaprootPsbtError::InvalidSignature(_))),
807 "expected InvalidSignature"
808 );
809 }
810
811 #[test]
812 fn test_taproot_input_internal_key_valid() {
813 let fields = TaprootInputFields::new()
814 .with_internal_key(xonly_key())
815 .expect("valid 32-byte key");
816
817 assert!(fields.tap_internal_key.is_some());
818 assert!(fields.validate().is_ok());
819 }
820
821 #[test]
822 fn test_taproot_input_internal_key_invalid() {
823 let short_key = "aabb".to_string(); let result = TaprootInputFields::new().with_internal_key(short_key);
825 assert!(
826 matches!(result, Err(TaprootPsbtError::InvalidInternalKey(_))),
827 "expected InvalidInternalKey"
828 );
829 }
830
831 #[test]
832 fn test_taproot_output_fields() {
833 let fields = TaprootOutputFields::new()
834 .with_internal_key(xonly_key())
835 .expect("valid key");
836
837 assert!(fields.is_taproot_output());
838 assert!(fields.validate().is_ok());
839 }
840
841 #[test]
842 fn test_taproot_output_fields_default_not_taproot() {
843 let fields = TaprootOutputFields::default();
844 assert!(!fields.is_taproot_output());
845 assert!(fields.validate().is_ok());
846 }
847
848 #[test]
849 fn test_taproot_psbt_new() {
850 let psbt = TaprootPsbt::new("deadbeef".to_string());
851 assert_eq!(psbt.base_psbt_hex, "deadbeef");
852 assert_eq!(psbt.input_count(), 0);
853 assert_eq!(psbt.output_count(), 0);
854 assert!(!psbt.is_complete());
855 }
856
857 #[test]
858 fn test_taproot_psbt_add_input_fields() {
859 let mut psbt = TaprootPsbt::new("deadbeef".to_string());
860
861 let fields = TaprootInputFields::new()
862 .with_key_sig(schnorr_sig_64())
863 .expect("valid sig");
864
865 psbt.add_input_taproot_fields(0, fields).unwrap();
866 assert_eq!(psbt.input_count(), 1);
867
868 assert!(psbt.is_complete());
870
871 let retrieved = psbt.get_input_fields(0);
873 assert!(retrieved.is_some());
874 assert!(retrieved.unwrap().is_key_path_signed());
875
876 assert!(psbt.get_input_fields(99).is_none());
878 }
879
880 #[test]
881 fn test_taproot_psbt_add_output_fields_sparse() {
882 let mut psbt = TaprootPsbt::new("cafebabe".to_string());
883
884 let fields = TaprootOutputFields::new()
886 .with_internal_key(xonly_key())
887 .expect("valid key");
888
889 psbt.add_output_taproot_fields(2, fields).unwrap();
890 assert_eq!(psbt.output_count(), 3); assert!(psbt.get_output_fields(2).unwrap().is_taproot_output());
892 assert!(!psbt.get_output_fields(0).unwrap().is_taproot_output());
893 }
894
895 #[test]
896 fn test_bip32_derivation() {
897 let deriv = TapBip32Derivation::new(
898 xonly_key(),
899 "deadbeef".to_string(), "m/86'/0'/0'/0/0".to_string(),
901 );
902
903 assert!(deriv.is_key_path());
904 assert!(deriv.validate().is_ok());
905 }
906
907 #[test]
908 fn test_bip32_derivation_invalid_fingerprint() {
909 let deriv = TapBip32Derivation::new(
910 xonly_key(),
911 "dead".to_string(), "m/86'/0'/0'/0/0".to_string(),
913 );
914 let result = deriv.validate();
915 assert!(
916 matches!(result, Err(TaprootPsbtError::InvalidDerivationPath(_))),
917 "expected InvalidDerivationPath for bad fingerprint, got {result:?}"
918 );
919 }
920
921 #[test]
922 fn test_taproot_psbt_builder() {
923 let input_fields = TaprootInputFields::new()
924 .with_key_sig(schnorr_sig_64())
925 .expect("valid sig");
926
927 let output_fields = TaprootOutputFields::new()
928 .with_internal_key(xonly_key())
929 .expect("valid key");
930
931 let psbt = TaprootPsbtBuilder::new("aabbccdd".to_string())
932 .add_input_fields(input_fields)
933 .add_output_fields(output_fields)
934 .build();
935
936 assert_eq!(psbt.base_psbt_hex, "aabbccdd");
937 assert_eq!(psbt.input_count(), 1);
938 assert_eq!(psbt.output_count(), 1);
939 assert!(psbt.is_complete());
940 assert!(psbt.validate_all().is_ok());
941 }
942
943 #[test]
944 fn test_validate_all_with_script_path_sigs() {
945 let mut input_fields = TaprootInputFields::new();
946 input_fields
948 .tap_script_sigs
949 .push((minimal_control_block(), schnorr_sig_64()));
950
951 let psbt = TaprootPsbtBuilder::new("ff".to_string())
952 .add_input_fields(input_fields)
953 .build();
954
955 assert!(psbt.is_complete());
956 assert!(psbt.validate_all().is_ok());
957 }
958
959 #[test]
960 fn test_merkle_root_validation() {
961 let valid_root = "ab".repeat(32);
963 let fields = TaprootInputFields::new()
964 .with_merkle_root(valid_root)
965 .expect("valid 32-byte merkle root");
966
967 assert!(fields.tap_merkle_root.is_some());
968 assert!(fields.validate().is_ok());
969
970 let result = TaprootInputFields::new().with_merkle_root("deadbeef".to_string()); assert!(
973 matches!(result, Err(TaprootPsbtError::InvalidMerkleRoot(_))),
974 "expected InvalidMerkleRoot for short value"
975 );
976 }
977
978 #[test]
979 fn test_tap_leaf_script_add_and_retrieve() {
980 let mut input_fields = TaprootInputFields::new();
981
982 let leaf1 = TapLeafScript::new(vec![0x51], LeafVersion::TapScript);
983 let leaf2 = TapLeafScript::new(vec![0x52], LeafVersion::Future(0xC2));
984
985 input_fields.add_leaf_script(leaf1);
986 input_fields.add_leaf_script(leaf2);
987
988 assert_eq!(input_fields.tap_leaf_scripts.len(), 2);
989 assert_eq!(input_fields.tap_leaf_scripts[0].script_hex(), "51");
990 assert_eq!(
991 input_fields.tap_leaf_scripts[1].leaf_version,
992 LeafVersion::Future(0xC2)
993 );
994 }
995}