1#![deny(unsafe_code)]
35#![deny(non_upper_case_globals)]
36#![deny(non_camel_case_types)]
37#![deny(non_snake_case)]
38#![deny(unused_mut)]
39#![deny(dead_code)]
40#![deny(unused_imports)]
41#![deny(missing_docs)]
42
43#[cfg(not(any(feature = "std")))]
44compile_error!("`std` must be enabled");
45
46use bitcoin::{
47    Address, Network, ScriptBuf, TapNodeHash, TapSighashType, TapTweakHash, Transaction, TxOut,
48    Witness, XOnlyPublicKey,
49    hashes::Hash,
50    key::Secp256k1,
51    secp256k1,
52    secp256k1::{Keypair, Message, PublicKey, Scalar, SecretKey, constants::CURVE_ORDER},
53    sighash::{Annex, Prevouts, SighashCache},
54    taproot::{ControlBlock, Signature},
55};
56use hmac::{Hmac, Mac};
57use num_bigint::BigUint;
58use sha2::{Digest, Sha256, Sha512};
59use std::collections::HashMap;
60use std::fmt;
61
62pub const TAPROOT_ANNEX_DATA_CARRYING_TAG: u8 = 0;
64
65#[derive(Debug)]
67pub enum Error {
68    VerificationFailed(String),
70    Secp256k1(secp256k1::Error),
72    InvalidControlBlock,
74    InvalidSighash,
76    MissingSpentOutputs,
78    UnexpectedInput,
80}
81
82pub trait Verifier {
85    fn verify(
95        &self,
96        script_pubkeys: &HashMap<usize, ScriptBuf>,
97        tx_to: &Transaction,
98        spent_outputs: &[TxOut],
99    ) -> Result<(), Error>;
100}
101
102#[cfg(feature = "bitcoinkernel")]
104pub struct DefaultVerifier;
105
106#[cfg(feature = "bitcoinkernel")]
107impl Verifier for DefaultVerifier {
108    fn verify(
109        &self,
110        script_pubkeys: &HashMap<usize, ScriptBuf>,
111        tx_to: &Transaction,
112        spent_outputs: &[TxOut],
113    ) -> Result<(), Error> {
114        let mut amounts = Vec::new();
115        let mut outputs = Vec::new();
116        for txout in spent_outputs {
117            let amount = txout
118                .value
119                .to_signed()
120                .map_err(|_| Error::VerificationFailed("invalid amount".to_string()))?
121                .to_sat();
122            let script = bitcoinkernel::ScriptPubkey::try_from(txout.script_pubkey.as_bytes())
123                .map_err(|e| Error::VerificationFailed(e.to_string()))?;
124
125            amounts.push(amount);
126            outputs.push(bitcoinkernel::TxOut::new(&script, amount));
127        }
128
129        let tx_bytes = bitcoin::consensus::serialize(tx_to);
130        let tx_to = &bitcoinkernel::Transaction::try_from(tx_bytes.as_slice())
131            .map_err(|e| Error::VerificationFailed(e.to_string()))?;
132
133        for (&i, script_pubkey) in script_pubkeys {
134            let amount = amounts.get(i).cloned();
135            let script_pubkey = &bitcoinkernel::ScriptPubkey::try_from(script_pubkey.as_bytes())
136                .map_err(|e| Error::VerificationFailed(e.to_string()))?;
137
138            bitcoinkernel::verify(script_pubkey, amount, tx_to, i, None, &outputs)
139                .map_err(|e| Error::VerificationFailed(e.to_string()))?;
140        }
141
142        Ok(())
143    }
144}
145
146pub fn verify_and_sign<V: Verifier>(
176    verifier: &V,
177    emulated_tx_to: &Transaction,
178    actual_spent_outputs: &[TxOut],
179    aux_rand: &[u8; 32],
180    parent_key: SecretKey,
181    backup_merkle_roots: HashMap<usize, TapNodeHash>,
182) -> Result<Transaction, Error> {
183    let mut emulated_script_pubkeys: HashMap<usize, ScriptBuf> = HashMap::new();
185
186    let mut child_keys_by_index: HashMap<usize, SecretKey> = HashMap::new();
188
189    if actual_spent_outputs.len() < emulated_tx_to.input.len() {
191        return Err(Error::MissingSpentOutputs);
192    }
193
194    let secp = Secp256k1::new();
196    for (i, input) in emulated_tx_to.input.clone().into_iter().enumerate() {
197        let (Some(true), Some(control_block), Some(tapleaf)) = (
199            actual_spent_outputs[i]
200                .script_pubkey
201                .is_p2tr()
202                .then_some(true),
203            input.witness.taproot_control_block(),
204            input.witness.taproot_leaf_script(),
205        ) else {
206            continue;
207        };
208
209        let Ok(control_block) = ControlBlock::decode(control_block) else {
211            return Err(Error::InvalidControlBlock);
212        };
213
214        let mut merkle_root = TapNodeHash::from_script(tapleaf.script, tapleaf.version);
216        for elem in &control_block.merkle_branch {
217            merkle_root = TapNodeHash::from_node_hashes(merkle_root, *elem);
218        }
219
220        let emulated_address = Address::p2tr(
222            &secp,
223            control_block.internal_key,
224            Some(merkle_root),
225            Network::Bitcoin,
226        );
227
228        if actual_spent_outputs[i].script_pubkey == emulated_address.script_pubkey() {
230            continue;
231        }
232
233        let child_key = derive_child_secret_key(parent_key, merkle_root.to_byte_array())?;
235        let (internal_key, _) = child_key.public_key(&secp).x_only_public_key();
236        child_keys_by_index.insert(i, child_key);
237
238        let backup_merkle_root = backup_merkle_roots.get(&i).cloned();
240        let actual_address =
241            Address::p2tr(&secp, internal_key, backup_merkle_root, Network::Bitcoin);
242        if actual_spent_outputs[i].script_pubkey != actual_address.script_pubkey() {
243            return Err(Error::UnexpectedInput);
244        }
245
246        emulated_script_pubkeys.insert(i, emulated_address.script_pubkey());
248    }
249
250    verifier.verify(
252        &emulated_script_pubkeys,
253        emulated_tx_to,
254        actual_spent_outputs,
255    )?;
256
257    let mut tx = emulated_tx_to.clone();
258    for &i in emulated_script_pubkeys.keys() {
259        let annex = tx.input[i]
261            .witness
262            .taproot_annex()
263            .filter(|bytes| bytes.len() > 1 && bytes[1] == TAPROOT_ANNEX_DATA_CARRYING_TAG)
264            .and_then(|bytes| Annex::new(bytes).ok());
265
266        let mut sighash_cache = SighashCache::new(&tx);
268        let sighash_bytes = sighash_cache
269            .taproot_signature_hash(
270                i,
271                &Prevouts::All(actual_spent_outputs),
272                annex.clone(),
273                None,
274                TapSighashType::Default,
275            )
276            .map_err(|_| Error::InvalidSighash)?;
277        let mut sighash = [0u8; 32];
278        sighash.copy_from_slice(sighash_bytes.as_byte_array());
279
280        let child_key = child_keys_by_index.get(&i).unwrap();
282        let (internal_key, parity) = child_key.public_key(&secp).x_only_public_key();
283        let child_key_for_tweak = if parity == secp256k1::Parity::Odd {
284            child_key.negate()
285        } else {
286            *child_key
287        };
288
289        let backup_merkle_root = backup_merkle_roots.get(&i).cloned();
291        let tweak = TapTweakHash::from_key_and_tweak(internal_key, backup_merkle_root);
292        let tweaked_secret_key = child_key_for_tweak.add_tweak(&tweak.to_scalar())?;
293        let tweaked_keypair = Keypair::from_secret_key(&secp, &tweaked_secret_key);
294
295        let mut hasher = Sha256::new();
297        hasher.update(aux_rand);
298        hasher.update((i as u64).to_le_bytes());
299        let aux_rand: [u8; 32] = hasher.finalize().into();
300
301        let message = Message::from_digest(sighash);
303        let signature = secp.sign_schnorr_with_aux_rand(&message, &tweaked_keypair, &aux_rand);
304
305        let tap_signature = Signature {
307            signature,
308            sighash_type: TapSighashType::Default,
309        };
310
311        let mut witness = Witness::new();
313        witness.push(tap_signature.to_vec());
314        if let Some(annex) = annex {
315            witness.push(annex.as_bytes());
316        }
317        tx.input[i].witness = witness;
318    }
319
320    Ok(tx)
321}
322
323pub fn generate_address(
335    parent_key: PublicKey,
336    emulated_merkle_root: TapNodeHash,
337    backup_merkle_root: Option<TapNodeHash>,
338    network: Network,
339) -> Result<Address, secp256k1::Error> {
340    let secp = Secp256k1::new();
341    let child_key = derive_child_public_key(parent_key, emulated_merkle_root.to_byte_array())?;
342    let internal_key = XOnlyPublicKey::from(child_key);
343    let address = Address::p2tr(&secp, internal_key, backup_merkle_root, network);
344
345    Ok(address)
346}
347
348fn derive_child_secret_key(
351    parent_key: SecretKey,
352    emulated_merkle_root: [u8; 32],
353) -> Result<SecretKey, secp256k1::Error> {
354    let secp = Secp256k1::new();
355
356    let parent_public = parent_key.public_key(&secp);
358
359    let mut mac = Hmac::<Sha512>::new_from_slice(&parent_public.serialize())
361        .expect("PublicKey serialization should always be non-empty");
362    mac.update(&emulated_merkle_root);
363    let hmac_result = mac.finalize().into_bytes();
364
365    let mut key_material = [0u8; 32];
367    key_material.copy_from_slice(&hmac_result[..32]);
368    let scalar = reduce_mod_order(&key_material);
369
370    parent_key.add_tweak(&scalar)
372}
373
374fn derive_child_public_key(
377    parent_public: PublicKey,
378    emulated_merkle_root: [u8; 32],
379) -> Result<PublicKey, secp256k1::Error> {
380    let secp = Secp256k1::new();
381
382    let mut mac = Hmac::<Sha512>::new_from_slice(&parent_public.serialize())
384        .expect("PublicKey serialization should always be non-empty");
385    mac.update(&emulated_merkle_root);
386    let hmac_result = mac.finalize().into_bytes();
387
388    let mut key_material = [0u8; 32];
390    key_material.copy_from_slice(&hmac_result[..32]);
391    let scalar = reduce_mod_order(&key_material);
392
393    parent_public.add_exp_tweak(&secp, &scalar)
395}
396
397fn reduce_mod_order(bytes: &[u8; 32]) -> Scalar {
399    let mut attempt = *bytes;
402    loop {
403        match Scalar::from_be_bytes(attempt) {
404            Ok(scalar) => return scalar,
405            Err(_) => {
406                attempt = subtract_curve_order(&attempt);
409            }
410        }
411    }
412}
413
414fn subtract_curve_order(bytes: &[u8; 32]) -> [u8; 32] {
416    let value = BigUint::from_bytes_be(bytes);
417    let order = BigUint::from_bytes_be(&CURVE_ORDER);
418    let reduced = value % order;
419
420    let mut result = [0u8; 32];
421    let reduced_bytes = reduced.to_bytes_be();
422    let offset = 32 - reduced_bytes.len();
423    result[offset..].copy_from_slice(&reduced_bytes);
424    result
425}
426
427impl fmt::Display for Error {
428    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429        match self {
430            Error::VerificationFailed(e) => {
431                write!(f, "Verification failed: {e}")
432            }
433            Error::Secp256k1(e) => {
434                write!(f, "Secp256k1 cryptographic operation failed: {e}")
435            }
436            Error::InvalidControlBlock => {
437                write!(f, "Input has invalid control block")
438            }
439            Error::InvalidSighash => {
440                write!(f, "Unable to calculate sighash for input")
441            }
442            Error::MissingSpentOutputs => {
443                write!(f, "Missing spent outputs")
444            }
445            Error::UnexpectedInput => {
446                write!(f, "Unexpected input scriptPubKey")
447            }
448        }
449    }
450}
451
452impl From<secp256k1::Error> for Error {
453    fn from(error: secp256k1::Error) -> Self {
454        Error::Secp256k1(error)
455    }
456}
457
458#[cfg(test)]
459#[cfg(feature = "bitcoinkernel")]
460mod kernel_tests {
461    use super::*;
462    use bitcoin::{
463        Address, Amount, Network, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut, Txid,
464        Witness,
465        consensus::encode::serialize,
466        hashes::Hash,
467        key::UntweakedPublicKey,
468        taproot::{LeafVersion, TaprootBuilder},
469    };
470
471    fn create_test_transaction_single_input() -> Transaction {
472        Transaction {
473            version: bitcoin::transaction::Version::TWO,
474            lock_time: bitcoin::locktime::absolute::LockTime::ZERO,
475            input: vec![TxIn {
476                previous_output: OutPoint::null(),
477                script_sig: ScriptBuf::new(),
478                sequence: bitcoin::Sequence::ENABLE_RBF_NO_LOCKTIME,
479                witness: Witness::new(),
480            }],
481            output: vec![TxOut {
482                value: Amount::from_sat(100000),
483                script_pubkey: ScriptBuf::new_op_return([]),
484            }],
485        }
486    }
487
488    fn create_test_transaction_multi_input() -> Transaction {
489        Transaction {
490            version: bitcoin::transaction::Version::TWO,
491            lock_time: bitcoin::locktime::absolute::LockTime::ZERO,
492            input: vec![
493                TxIn {
494                    previous_output: OutPoint::null(),
495                    script_sig: ScriptBuf::new(),
496                    sequence: bitcoin::Sequence::ENABLE_RBF_NO_LOCKTIME,
497                    witness: Witness::new(),
498                },
499                TxIn {
500                    previous_output: OutPoint::new(Txid::all_zeros(), 1),
501                    script_sig: ScriptBuf::new(),
502                    sequence: bitcoin::Sequence::ENABLE_RBF_NO_LOCKTIME,
503                    witness: Witness::new(),
504                },
505            ],
506            output: vec![TxOut {
507                value: Amount::from_sat(100000),
508                script_pubkey: ScriptBuf::new_op_return([]),
509            }],
510        }
511    }
512
513    #[test]
514    fn test_missing_spent_outputs() {
515        let result = verify_and_sign(
516            &DefaultVerifier,
517            &create_test_transaction_single_input(),
518            &[],
519            &[1u8; 32],
520            SecretKey::from_slice(&[1u8; 32]).unwrap(),
521            HashMap::new(),
522        );
523
524        assert!(matches!(result, Err(Error::MissingSpentOutputs)));
525    }
526
527    #[test]
528    fn test_unexpected_input_script_pubkey() {
529        let secp = Secp256k1::new();
530
531        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
533        let internal_key = UntweakedPublicKey::from(internal_secret.public_key(&secp));
534
535        let op_true_script = Script::builder()
537            .push_opcode(bitcoin::opcodes::OP_TRUE)
538            .into_script();
539
540        let taproot_builder = TaprootBuilder::new()
542            .add_leaf(0, op_true_script.clone())
543            .unwrap();
544        let taproot_spend_info = taproot_builder.finalize(&secp, internal_key).unwrap();
545
546        let control_block = taproot_spend_info
548            .control_block(&(op_true_script.clone(), LeafVersion::TapScript))
549            .unwrap();
550
551        let mut witness = Witness::new();
553        witness.push(op_true_script.as_bytes());
554        witness.push(control_block.serialize());
555
556        let mut emulated_tx = create_test_transaction_single_input();
558        emulated_tx.input[0].witness = witness;
559
560        let dummy_p2tr_address = Address::p2tr(&secp, internal_key, None, Network::Bitcoin);
562        let txout = TxOut {
563            value: Amount::from_sat(100000),
564            script_pubkey: dummy_p2tr_address.script_pubkey(),
565        };
566
567        let result = verify_and_sign(
568            &DefaultVerifier,
569            &emulated_tx,
570            std::slice::from_ref(&txout),
571            &[1u8; 32],
572            SecretKey::from_slice(&[1u8; 32]).unwrap(),
573            HashMap::new(),
574        );
575
576        assert!(matches!(result, Err(Error::UnexpectedInput)));
577    }
578
579    #[test]
580    fn test_verify_and_sign_single_input_single_leaf() {
581        let secp = Secp256k1::new();
582
583        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
585        let internal_key = UntweakedPublicKey::from(internal_secret.public_key(&secp));
586
587        let op_true_script = Script::builder()
589            .push_opcode(bitcoin::opcodes::OP_TRUE)
590            .into_script();
591
592        let taproot_builder = TaprootBuilder::new()
594            .add_leaf(0, op_true_script.clone())
595            .unwrap();
596        let taproot_spend_info = taproot_builder.finalize(&secp, internal_key).unwrap();
597
598        let control_block = taproot_spend_info
600            .control_block(&(op_true_script.clone(), LeafVersion::TapScript))
601            .unwrap();
602
603        let mut witness = Witness::new();
605        witness.push(op_true_script.as_bytes());
606        witness.push(control_block.serialize());
607
608        let mut emulated_tx = create_test_transaction_single_input();
610        emulated_tx.input[0].witness = witness;
611
612        let aux_rand = [1u8; 32];
614        let parent_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
615        let child_secret = derive_child_secret_key(
616            parent_secret,
617            taproot_spend_info.merkle_root().unwrap().to_byte_array(),
618        )
619        .unwrap();
620
621        let actual_internal_key = XOnlyPublicKey::from(child_secret.public_key(&secp));
623        let actual_address = Address::p2tr(&secp, actual_internal_key, None, Network::Bitcoin);
624        let actual_spent_outputs = [TxOut {
625            value: Amount::from_sat(100_000),
626            script_pubkey: actual_address.script_pubkey(),
627        }];
628
629        let actual_tx = verify_and_sign(
631            &DefaultVerifier,
632            &emulated_tx,
633            &actual_spent_outputs,
634            &aux_rand,
635            parent_secret,
636            HashMap::new(),
637        )
638        .unwrap();
639
640        let mut actual_outputs = Vec::new();
641        for txout in actual_spent_outputs {
642            let amount = txout.value.to_signed().unwrap().to_sat();
643            let script =
644                bitcoinkernel::ScriptPubkey::try_from(txout.script_pubkey.as_bytes()).unwrap();
645            actual_outputs.push(bitcoinkernel::TxOut::new(&script, amount));
646        }
647
648        let verify_result = bitcoinkernel::verify(
650            &bitcoinkernel::ScriptPubkey::try_from(actual_address.script_pubkey().as_bytes())
651                .unwrap(),
652            Some(100_000),
653            &bitcoinkernel::Transaction::try_from(serialize(&actual_tx).as_slice()).unwrap(),
654            0,
655            None,
656            &actual_outputs,
657        );
658
659        assert!(verify_result.is_ok());
660        assert_eq!(actual_tx.input[0].witness.len(), 1);
661    }
662
663    #[test]
664    fn test_verify_and_sign_single_input_multiple_leaves() {
665        let secp = Secp256k1::new();
666
667        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
669        let internal_key = UntweakedPublicKey::from(internal_secret.public_key(&secp));
670
671        let op_true_script = Script::builder()
673            .push_opcode(bitcoin::opcodes::OP_TRUE)
674            .into_script();
675        let op_false_script = Script::builder()
676            .push_opcode(bitcoin::opcodes::OP_FALSE)
677            .into_script();
678
679        let taproot_builder = TaprootBuilder::new()
681            .add_leaf(1, op_true_script.clone())
682            .unwrap()
683            .add_leaf(1, op_false_script.clone())
684            .unwrap();
685        let taproot_spend_info = taproot_builder.finalize(&secp, internal_key).unwrap();
686
687        let control_block = taproot_spend_info
689            .control_block(&(op_true_script.clone(), LeafVersion::TapScript))
690            .unwrap();
691
692        let mut witness = Witness::new();
694        witness.push(op_true_script.as_bytes());
695        witness.push(control_block.serialize());
696
697        let mut emulated_tx = create_test_transaction_single_input();
699        emulated_tx.input[0].witness = witness;
700
701        let aux_rand = [1u8; 32];
703        let parent_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
704        let child_secret = derive_child_secret_key(
705            parent_secret,
706            taproot_spend_info.merkle_root().unwrap().to_byte_array(),
707        )
708        .unwrap();
709
710        let actual_internal_key = XOnlyPublicKey::from(child_secret.public_key(&secp));
712        let actual_address = Address::p2tr(&secp, actual_internal_key, None, Network::Bitcoin);
713        let actual_spent_outputs = [TxOut {
714            value: Amount::from_sat(100_000),
715            script_pubkey: actual_address.script_pubkey(),
716        }];
717
718        let actual_tx = verify_and_sign(
720            &DefaultVerifier,
721            &emulated_tx,
722            &actual_spent_outputs,
723            &aux_rand,
724            parent_secret,
725            HashMap::new(),
726        )
727        .unwrap();
728
729        let mut actual_outputs = Vec::new();
730        for txout in actual_spent_outputs {
731            let amount = txout.value.to_signed().unwrap().to_sat();
732            let script =
733                bitcoinkernel::ScriptPubkey::try_from(txout.script_pubkey.as_bytes()).unwrap();
734            actual_outputs.push(bitcoinkernel::TxOut::new(&script, amount));
735        }
736
737        let verify_result = bitcoinkernel::verify(
739            &bitcoinkernel::ScriptPubkey::try_from(actual_address.script_pubkey().as_bytes())
740                .unwrap(),
741            Some(100_000),
742            &bitcoinkernel::Transaction::try_from(serialize(&actual_tx).as_slice()).unwrap(),
743            0,
744            None,
745            &actual_outputs,
746        );
747
748        assert!(verify_result.is_ok());
749        assert_eq!(actual_tx.input[0].witness.len(), 1);
750    }
751
752    #[test]
753    fn test_verify_and_sign_single_input_with_backup() {
754        let secp = Secp256k1::new();
755
756        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
758        let internal_key = UntweakedPublicKey::from(internal_secret.public_key(&secp));
759
760        let op_true_script = Script::builder()
762            .push_opcode(bitcoin::opcodes::OP_TRUE)
763            .into_script();
764
765        let taproot_builder = TaprootBuilder::new()
767            .add_leaf(0, op_true_script.clone())
768            .unwrap();
769        let taproot_spend_info = taproot_builder.finalize(&secp, internal_key).unwrap();
770
771        let control_block = taproot_spend_info
773            .control_block(&(op_true_script.clone(), LeafVersion::TapScript))
774            .unwrap();
775
776        let mut witness = Witness::new();
778        witness.push(op_true_script.as_bytes());
779        witness.push(control_block.serialize());
780
781        let mut emulated_tx = create_test_transaction_single_input();
783        emulated_tx.input[0].witness = witness;
784
785        let aux_rand = [1u8; 32];
787        let parent_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
788        let child_secret = derive_child_secret_key(
789            parent_secret,
790            taproot_spend_info.merkle_root().unwrap().to_byte_array(),
791        )
792        .unwrap();
793
794        let actual_backup_merkle_root = taproot_spend_info.merkle_root();
796        let actual_internal_key = XOnlyPublicKey::from(child_secret.public_key(&secp));
797        let actual_address = Address::p2tr(
798            &secp,
799            actual_internal_key,
800            actual_backup_merkle_root,
801            Network::Bitcoin,
802        );
803        let actual_spent_outputs = [TxOut {
804            value: Amount::from_sat(100_000),
805            script_pubkey: actual_address.script_pubkey(),
806        }];
807
808        let actual_tx = verify_and_sign(
810            &DefaultVerifier,
811            &emulated_tx,
812            &actual_spent_outputs,
813            &aux_rand,
814            parent_secret,
815            HashMap::from([(0, actual_backup_merkle_root.unwrap())]),
816        )
817        .unwrap();
818
819        let mut actual_outputs = Vec::new();
820        for txout in actual_spent_outputs {
821            let amount = txout.value.to_signed().unwrap().to_sat();
822            let script =
823                bitcoinkernel::ScriptPubkey::try_from(txout.script_pubkey.as_bytes()).unwrap();
824            actual_outputs.push(bitcoinkernel::TxOut::new(&script, amount));
825        }
826
827        let verify_result = bitcoinkernel::verify(
829            &bitcoinkernel::ScriptPubkey::try_from(actual_address.script_pubkey().as_bytes())
830                .unwrap(),
831            Some(100_000),
832            &bitcoinkernel::Transaction::try_from(serialize(&actual_tx).as_slice()).unwrap(),
833            0,
834            None,
835            &actual_outputs,
836        );
837
838        assert!(verify_result.is_ok());
839        assert_eq!(actual_tx.input[0].witness.len(), 1);
840    }
841
842    #[test]
843    fn test_verify_and_sign_single_input_single_leaf_with_data_carrying_annex() {
844        let secp = Secp256k1::new();
845
846        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
848        let internal_key = UntweakedPublicKey::from(internal_secret.public_key(&secp));
849
850        let op_true_script = Script::builder()
852            .push_opcode(bitcoin::opcodes::OP_TRUE)
853            .into_script();
854
855        let taproot_builder = TaprootBuilder::new()
857            .add_leaf(0, op_true_script.clone())
858            .unwrap();
859        let taproot_spend_info = taproot_builder.finalize(&secp, internal_key).unwrap();
860
861        let control_block = taproot_spend_info
863            .control_block(&(op_true_script.clone(), LeafVersion::TapScript))
864            .unwrap();
865
866        let annex: &[u8] = &[0x50, TAPROOT_ANNEX_DATA_CARRYING_TAG, 0x01, 0x02, 0x03];
868
869        let mut witness = Witness::new();
871        witness.push(op_true_script.as_bytes());
872        witness.push(control_block.serialize());
873        witness.push(annex);
874
875        let mut emulated_tx = create_test_transaction_single_input();
877        emulated_tx.input[0].witness = witness;
878
879        let aux_rand = [1u8; 32];
881        let parent_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
882        let child_secret = derive_child_secret_key(
883            parent_secret,
884            taproot_spend_info.merkle_root().unwrap().to_byte_array(),
885        )
886        .unwrap();
887
888        let actual_internal_key = XOnlyPublicKey::from(child_secret.public_key(&secp));
890        let actual_address = Address::p2tr(&secp, actual_internal_key, None, Network::Bitcoin);
891        let actual_spent_outputs = [TxOut {
892            value: Amount::from_sat(100_000),
893            script_pubkey: actual_address.script_pubkey(),
894        }];
895
896        let actual_tx = verify_and_sign(
898            &DefaultVerifier,
899            &emulated_tx,
900            &actual_spent_outputs,
901            &aux_rand,
902            parent_secret,
903            HashMap::new(),
904        )
905        .unwrap();
906
907        let mut actual_outputs = Vec::new();
908        for txout in actual_spent_outputs {
909            let amount = txout.value.to_signed().unwrap().to_sat();
910            let script =
911                bitcoinkernel::ScriptPubkey::try_from(txout.script_pubkey.as_bytes()).unwrap();
912            actual_outputs.push(bitcoinkernel::TxOut::new(&script, amount));
913        }
914
915        let verify_result = bitcoinkernel::verify(
917            &bitcoinkernel::ScriptPubkey::try_from(actual_address.script_pubkey().as_bytes())
918                .unwrap(),
919            Some(100_000),
920            &bitcoinkernel::Transaction::try_from(serialize(&actual_tx).as_slice()).unwrap(),
921            0,
922            None,
923            &actual_outputs,
924        );
925
926        assert!(verify_result.is_ok());
927        assert_eq!(actual_tx.input[0].witness.len(), 2);
928        assert_eq!(&actual_tx.input[0].witness[1], annex);
929    }
930
931    #[test]
932    fn test_verify_and_sign_single_input_single_leaf_with_non_data_carrying_annex() {
933        let secp = Secp256k1::new();
934
935        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
937        let internal_key = UntweakedPublicKey::from(internal_secret.public_key(&secp));
938
939        let op_true_script = Script::builder()
941            .push_opcode(bitcoin::opcodes::OP_TRUE)
942            .into_script();
943
944        let taproot_builder = TaprootBuilder::new()
946            .add_leaf(0, op_true_script.clone())
947            .unwrap();
948        let taproot_spend_info = taproot_builder.finalize(&secp, internal_key).unwrap();
949
950        let control_block = taproot_spend_info
952            .control_block(&(op_true_script.clone(), LeafVersion::TapScript))
953            .unwrap();
954
955        let annex: &[u8] = &[0x50, 0x01, 0x02, 0x03];
957
958        let mut witness = Witness::new();
960        witness.push(op_true_script.as_bytes());
961        witness.push(control_block.serialize());
962        witness.push(annex);
963
964        let mut emulated_tx = create_test_transaction_single_input();
966        emulated_tx.input[0].witness = witness;
967
968        let aux_rand = [1u8; 32];
970        let parent_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
971        let child_secret = derive_child_secret_key(
972            parent_secret,
973            taproot_spend_info.merkle_root().unwrap().to_byte_array(),
974        )
975        .unwrap();
976
977        let actual_internal_key = XOnlyPublicKey::from(child_secret.public_key(&secp));
979        let actual_address = Address::p2tr(&secp, actual_internal_key, None, Network::Bitcoin);
980        let actual_spent_outputs = [TxOut {
981            value: Amount::from_sat(100_000),
982            script_pubkey: actual_address.script_pubkey(),
983        }];
984
985        let actual_tx = verify_and_sign(
987            &DefaultVerifier,
988            &emulated_tx,
989            &actual_spent_outputs,
990            &aux_rand,
991            parent_secret,
992            HashMap::new(),
993        )
994        .unwrap();
995
996        let mut actual_outputs = Vec::new();
997        for txout in actual_spent_outputs {
998            let amount = txout.value.to_signed().unwrap().to_sat();
999            let script =
1000                bitcoinkernel::ScriptPubkey::try_from(txout.script_pubkey.as_bytes()).unwrap();
1001            actual_outputs.push(bitcoinkernel::TxOut::new(&script, amount));
1002        }
1003
1004        let verify_result = bitcoinkernel::verify(
1006            &bitcoinkernel::ScriptPubkey::try_from(actual_address.script_pubkey().as_bytes())
1007                .unwrap(),
1008            Some(100_000),
1009            &bitcoinkernel::Transaction::try_from(serialize(&actual_tx).as_slice()).unwrap(),
1010            0,
1011            None,
1012            &actual_outputs,
1013        );
1014
1015        assert!(verify_result.is_ok());
1016        assert_eq!(actual_tx.input[0].witness.len(), 1);
1017    }
1018
1019    #[test]
1020    fn test_verify_and_sign_multi_input_tx() {
1021        let secp = Secp256k1::new();
1022
1023        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
1025        let internal_key = UntweakedPublicKey::from(internal_secret.public_key(&secp));
1026
1027        let op_true_script = Script::builder()
1029            .push_opcode(bitcoin::opcodes::OP_TRUE)
1030            .into_script();
1031
1032        let taproot_builder = TaprootBuilder::new()
1034            .add_leaf(0, op_true_script.clone())
1035            .unwrap();
1036        let taproot_spend_info = taproot_builder.finalize(&secp, internal_key).unwrap();
1037
1038        let control_block = taproot_spend_info
1040            .control_block(&(op_true_script.clone(), LeafVersion::TapScript))
1041            .unwrap();
1042
1043        let mut witness = Witness::new();
1045        witness.push(op_true_script.as_bytes());
1046        witness.push(control_block.serialize());
1047
1048        let mut emulated_tx = create_test_transaction_multi_input();
1050        emulated_tx.input[1].witness = witness;
1051
1052        let aux_rand = [1u8; 32];
1054        let parent_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
1055        let child_secret = derive_child_secret_key(
1056            parent_secret,
1057            taproot_spend_info.merkle_root().unwrap().to_byte_array(),
1058        )
1059        .unwrap();
1060
1061        let actual_internal_key = XOnlyPublicKey::from(child_secret.public_key(&secp));
1063        let actual_address = Address::p2tr(&secp, actual_internal_key, None, Network::Bitcoin);
1064        let actual_spent_outputs = [
1065            TxOut {
1066                value: Amount::from_sat(200_000),
1067                script_pubkey: actual_address.script_pubkey(),
1068            },
1069            TxOut {
1070                value: Amount::from_sat(100_000),
1071                script_pubkey: actual_address.script_pubkey(),
1072            },
1073        ];
1074
1075        let actual_tx = verify_and_sign(
1077            &DefaultVerifier,
1078            &emulated_tx,
1079            &actual_spent_outputs,
1080            &aux_rand,
1081            parent_secret,
1082            HashMap::new(),
1083        )
1084        .unwrap();
1085
1086        let mut actual_outputs = Vec::new();
1087        for txout in actual_spent_outputs {
1088            let amount = txout.value.to_signed().unwrap().to_sat();
1089            let script =
1090                bitcoinkernel::ScriptPubkey::try_from(txout.script_pubkey.as_bytes()).unwrap();
1091            actual_outputs.push(bitcoinkernel::TxOut::new(&script, amount));
1092        }
1093
1094        let verify_result = bitcoinkernel::verify(
1096            &bitcoinkernel::ScriptPubkey::try_from(actual_address.script_pubkey().as_bytes())
1097                .unwrap(),
1098            Some(100_000),
1099            &bitcoinkernel::Transaction::try_from(serialize(&actual_tx).as_slice()).unwrap(),
1100            1,
1101            None,
1102            &actual_outputs,
1103        );
1104
1105        assert!(verify_result.is_ok());
1106        assert_eq!(actual_tx.input[1].witness.len(), 1);
1107    }
1108}
1109
1110#[cfg(test)]
1111mod non_kernel_tests {
1112    use super::*;
1113    use bitcoin::{
1114        Script,
1115        key::{Secp256k1, UntweakedPublicKey},
1116        taproot::TaprootBuilder,
1117    };
1118
1119    #[test]
1120    fn test_generate_address() {
1121        let secp = Secp256k1::new();
1122
1123        let emulated_script = Script::builder()
1125            .push_opcode(bitcoin::opcodes::OP_TRUE)
1126            .into_script();
1127
1128        let taproot_builder = TaprootBuilder::new()
1130            .add_leaf(0, emulated_script.clone())
1131            .unwrap();
1132        let dummy_internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
1133        let dummy_internal_key = UntweakedPublicKey::from(dummy_internal_secret.public_key(&secp));
1134        let taproot_spend_info = taproot_builder.finalize(&secp, dummy_internal_key).unwrap();
1135        let emulated_merkle_root = taproot_spend_info.merkle_root().unwrap();
1136
1137        let backup_merkle_root = emulated_merkle_root;
1139
1140        let internal_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
1142        let master_public_key: PublicKey = internal_secret.public_key(&secp);
1143        let onchain_address = generate_address(
1144            master_public_key,
1145            emulated_merkle_root,
1146            Some(backup_merkle_root),
1147            Network::Bitcoin,
1148        );
1149
1150        assert!(onchain_address.is_ok());
1151    }
1152
1153    #[test]
1154    fn test_public_private_key_derivation_consistency() {
1155        let parent_secret = SecretKey::from_slice(&[1u8; 32]).unwrap();
1156        let parent_public = parent_secret.public_key(&Secp256k1::new());
1157        let merkle_root = [42u8; 32];
1158
1159        let child_secret = derive_child_secret_key(parent_secret, merkle_root).unwrap();
1160        let child_public_from_secret = child_secret.public_key(&Secp256k1::new());
1161        let child_public_direct = derive_child_public_key(parent_public, merkle_root).unwrap();
1162
1163        assert_eq!(child_public_from_secret, child_public_direct);
1164    }
1165
1166    #[test]
1167    fn test_curve_order_reduction() {
1168        let max_bytes = [0xFF; 32];
1169        let reduced = reduce_mod_order(&max_bytes);
1170        #[allow(clippy::useless_conversion)]
1172        let _ = Scalar::from(reduced);
1173    }
1174}