@@ -24,13 +24,14 @@ use std::sync::Arc;
24
24
use bitcoin:: secp256k1:: Secp256k1 ;
25
25
26
26
use bitcoin:: consensus:: encode:: serialize;
27
- use bitcoin:: util:: psbt;
27
+ use bitcoin:: util:: { psbt, taproot } ;
28
28
use bitcoin:: {
29
29
Address , EcdsaSighashType , Network , OutPoint , Script , Transaction , TxOut , Txid , Witness ,
30
30
} ;
31
31
32
32
use miniscript:: descriptor:: DescriptorTrait ;
33
33
use miniscript:: psbt:: PsbtInputSatisfier ;
34
+ use miniscript:: ToPublicKey ;
34
35
35
36
#[ allow( unused_imports) ]
36
37
use log:: { debug, error, info, trace} ;
@@ -1432,8 +1433,10 @@ where
1432
1433
psbt_input : foreign_psbt_input,
1433
1434
outpoint,
1434
1435
} => {
1435
- // TODO: do not require non_witness_utxo for taproot utxos
1436
- if !params. only_witness_utxo && foreign_psbt_input. non_witness_utxo . is_none ( ) {
1436
+ if foreign_psbt_input. tap_internal_key . is_none ( )
1437
+ && !params. only_witness_utxo
1438
+ && foreign_psbt_input. non_witness_utxo . is_none ( )
1439
+ {
1437
1440
return Err ( Error :: Generic ( format ! (
1438
1441
"Missing non_witness_utxo on foreign utxo {}" ,
1439
1442
outpoint
@@ -1458,10 +1461,27 @@ where
1458
1461
let ( desc, _) = self . _get_descriptor_for_keychain ( keychain) ;
1459
1462
let derived_descriptor = desc. as_derived ( child, & self . secp ) ;
1460
1463
1461
- if desc. is_taproot ( ) {
1464
+ if let miniscript:: Descriptor :: Tr ( tr) = & derived_descriptor {
1465
+ let tap_tree = if tr. taptree ( ) . is_some ( ) {
1466
+ let mut builder = taproot:: TaprootBuilder :: new ( ) ;
1467
+ for ( depth, ms) in tr. iter_scripts ( ) {
1468
+ let script = ms. encode ( ) ;
1469
+ builder = builder. add_leaf ( depth, script) . expect (
1470
+ "Computing spend data on a valid Tree should always succeed" ,
1471
+ ) ;
1472
+ }
1473
+ Some (
1474
+ psbt:: TapTree :: from_builder ( builder)
1475
+ . expect ( "The tree should always be valid" ) ,
1476
+ )
1477
+ } else {
1478
+ None
1479
+ } ;
1480
+ psbt_output. tap_tree = tap_tree;
1462
1481
psbt_output
1463
1482
. tap_key_origins
1464
1483
. append ( & mut derived_descriptor. get_tap_key_origins ( & self . secp ) ) ;
1484
+ psbt_output. tap_internal_key = Some ( tr. internal_key ( ) . to_x_only_pubkey ( ) ) ;
1465
1485
} else {
1466
1486
psbt_output
1467
1487
. bip32_derivation
@@ -1499,8 +1519,22 @@ where
1499
1519
1500
1520
let desc = self . get_descriptor_for_keychain ( keychain) ;
1501
1521
let derived_descriptor = desc. as_derived ( child, & self . secp ) ;
1502
- if desc. is_taproot ( ) {
1522
+
1523
+ if let miniscript:: Descriptor :: Tr ( tr) = & derived_descriptor {
1503
1524
psbt_input. tap_key_origins = derived_descriptor. get_tap_key_origins ( & self . secp ) ;
1525
+ psbt_input. tap_internal_key = Some ( tr. internal_key ( ) . to_x_only_pubkey ( ) ) ;
1526
+
1527
+ let spend_info = tr. spend_info ( ) ;
1528
+ psbt_input. tap_merkle_root = spend_info. merkle_root ( ) ;
1529
+ psbt_input. tap_scripts = spend_info
1530
+ . as_script_map ( )
1531
+ . keys ( )
1532
+ . filter_map ( |script_ver| {
1533
+ spend_info
1534
+ . control_block ( script_ver)
1535
+ . map ( |cb| ( cb, script_ver. clone ( ) ) )
1536
+ } )
1537
+ . collect ( ) ;
1504
1538
} else {
1505
1539
psbt_input. bip32_derivation = derived_descriptor. get_hd_keypaths ( & self . secp ) ;
1506
1540
}
@@ -1783,6 +1817,10 @@ pub(crate) mod test {
1783
1817
"tr(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*)"
1784
1818
}
1785
1819
1820
+ pub ( crate ) fn get_test_tr_with_taptree ( ) -> & ' static str {
1821
+ "tr(cPZzKuNmpuUjD1e8jUU4PVzy2b5LngbSip8mBsxf4e7rSFZVb4Uh,{pk(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
1822
+ }
1823
+
1786
1824
macro_rules! assert_fee_rate {
1787
1825
( $tx: expr, $fees: expr, $fee_rate: expr $( , @dust_change $( $dust_change: expr ) * ) * $( , @add_signature $( $add_signature: expr ) * ) * ) => ( {
1788
1826
let mut tx = $tx. clone( ) ;
@@ -4098,8 +4136,32 @@ pub(crate) mod test {
4098
4136
builder. add_recipient ( addr. script_pubkey ( ) , 25_000 ) ;
4099
4137
let ( psbt, _) = builder. finish ( ) . unwrap ( ) ;
4100
4138
4101
- assert_eq ! ( psbt. inputs[ 0 ] . tap_key_origins. len( ) , 1 , "Empty input tap_key_origins" ) ;
4102
- assert_eq ! ( psbt. outputs[ 0 ] . tap_key_origins. len( ) , 1 , "Empty output tap_key_origins" ) ;
4139
+ assert_eq ! (
4140
+ psbt. inputs[ 0 ] . tap_key_origins. len( ) ,
4141
+ 1 ,
4142
+ "Empty input tap_key_origins"
4143
+ ) ;
4144
+ assert_eq ! (
4145
+ psbt. outputs[ 0 ] . tap_key_origins. len( ) ,
4146
+ 1 ,
4147
+ "Empty output tap_key_origins"
4148
+ ) ;
4149
+ }
4150
+
4151
+ #[ test]
4152
+ fn test_taproot_psbt_input_tap_tree ( ) {
4153
+ let ( wallet, _, _) = get_funded_wallet ( get_test_tr_with_taptree ( ) ) ;
4154
+ let addr = wallet. get_address ( AddressIndex :: New ) . unwrap ( ) ;
4155
+
4156
+ let mut builder = wallet. build_tx ( ) ;
4157
+ builder. add_recipient ( addr. script_pubkey ( ) , 25_000 ) ;
4158
+ let ( psbt, _) = builder. finish ( ) . unwrap ( ) ;
4159
+
4160
+ assert ! (
4161
+ psbt. inputs[ 0 ] . tap_merkle_root. is_some( ) ,
4162
+ "Empty input tap_merkle_root"
4163
+ ) ;
4164
+ assert_eq ! ( psbt. inputs[ 0 ] . tap_scripts. len( ) , 2 , "Empty tap_scripts" ) ;
4103
4165
}
4104
4166
}
4105
4167
0 commit comments