@@ -14,9 +14,10 @@ use crate::display::{fmt_list, indentation_params, PrettyDisplay};
14
14
use crate :: runtime:: {
15
15
Array , Error , FieldAccess , FromValue , Mutable , Number :: Int , Result , ScopeRef , Value ,
16
16
} ;
17
- use crate :: stdlib:: btc:: WshScript ;
18
17
use crate :: util:: { DescriptorExt , DescriptorPubKeyExt , PsbtInExt , PsbtOutExt , TapInfoExt , EC } ;
19
18
19
+ use super :: { btc:: WshScript , keys:: MasterXpriv } ;
20
+
20
21
pub fn attach_stdlib ( scope : & ScopeRef < Mutable > ) {
21
22
let mut scope = scope. borrow_mut ( ) ;
22
23
scope. set_fn ( "psbt" , fns:: psbt) . unwrap ( ) ; // create or update
@@ -201,8 +202,8 @@ fn sign_psbt(psbt: &mut Psbt, keys_val: Value) -> Result<(SigningKeysMap, Signin
201
202
}
202
203
203
204
// Keys provided as [ $xpriv1, $xpriv2, ... ]
204
- Value :: SecKey ( DescriptorSecretKey :: XPrv ( _) ) => {
205
- psbt. sign ( & XprivSet ( keys. try_into ( ) ? ) , & EC )
205
+ Value :: SecKey ( DescriptorSecretKey :: XPrv ( _) | DescriptorSecretKey :: MultiXPrv ( _ ) ) => {
206
+ psbt. sign ( & XprivSet :: try_from ( keys) ? , & EC )
206
207
}
207
208
208
209
// Keys provided as [ $single_sk1, $single_sk2, ... ]
@@ -212,15 +213,16 @@ fn sign_psbt(psbt: &mut Psbt, keys_val: Value) -> Result<(SigningKeysMap, Signin
212
213
_ => bail ! ( Error :: PsbtInvalidSignKeys ) ,
213
214
}
214
215
}
215
- // Key provided as one Xpriv
216
- Value :: SecKey ( DescriptorSecretKey :: XPrv ( _) ) => psbt. sign ( & Xpriv :: try_from ( keys_val) ?, & EC ) ,
216
+ // Key provided as an Xpriv
217
+ Value :: SecKey ( DescriptorSecretKey :: XPrv ( _) | DescriptorSecretKey :: MultiXPrv ( _) ) => {
218
+ psbt. sign ( & MasterXpriv :: try_from ( keys_val) ?. 0 , & EC )
219
+ }
217
220
218
- // Key provided as one single key
221
+ // Key provided as a single key
219
222
Value :: SecKey ( DescriptorSecretKey :: Single ( _) ) => {
220
223
psbt. sign ( & single_seckey_to_map ( PrivateKey :: try_from ( keys_val) ?) , & EC )
221
224
}
222
225
223
- // TODO support signing with MultiXpriv
224
226
_ => bail ! ( Error :: PsbtInvalidSignKeys ) ,
225
227
} ;
226
228
// Returns input signing failures in the the Ok variant. An Err is only raised if the `seckeys` argument is invalid.
@@ -736,9 +738,26 @@ impl TryFrom<Value> for raw::ProprietaryKey {
736
738
}
737
739
}
738
740
739
- // GetKey wrapper around Vec<Xpriv>, needed as a workaround for https://github.com/rust-bitcoin/rust-bitcoin/pull/2850
740
- // Could otherwise directly use `psbt.sign(&Vec::<Xpriv>::try_from(seckeys)?, &EC)`
741
+ // GetKey wrapper around Vec<Xpriv>
741
742
struct XprivSet ( Vec < Xpriv > ) ;
743
+
744
+ // Convert an Array into a set of Xprivs used for PSBT signing.
745
+ // Unlike the the standard TryInto<Xpriv> conversion which derives the final child Xpriv after applying all derivation
746
+ // steps, this instead uses the top-most known Xpriv without deriving. The PSBT bip32_derivation/tap_key_origins fields
747
+ // are expected to point to the fingerprint of the top-most key, and not to that of the child.
748
+ impl TryFrom < Array > for XprivSet {
749
+ type Error = Error ;
750
+ fn try_from ( arr : Array ) -> Result < Self > {
751
+ Ok ( Self (
752
+ arr. into_iter_of ( )
753
+ . map ( |xprv : Result < MasterXpriv > | Ok ( xprv?. 0 ) )
754
+ . collect :: < Result < Vec < Xpriv > > > ( ) ?,
755
+ ) )
756
+ }
757
+ }
758
+
759
+ // Needed as a workaround for https://github.com/rust-bitcoin/rust-bitcoin/pull/2850
760
+ // Could otherwise use Psbt::sign() with the inner Vec<Xpriv>.
742
761
impl psbt:: GetKey for XprivSet {
743
762
type Error = <Xpriv as psbt:: GetKey >:: Error ;
744
763
0 commit comments