@@ -14,9 +14,10 @@ use crate::display::{fmt_list, indentation_params, PrettyDisplay};
1414use crate :: runtime:: {
1515 Array , Error , FieldAccess , FromValue , Mutable , Number :: Int , Result , ScopeRef , Value ,
1616} ;
17- use crate :: stdlib:: btc:: WshScript ;
1817use crate :: util:: { DescriptorExt , DescriptorPubKeyExt , PsbtInExt , PsbtOutExt , TapInfoExt , EC } ;
1918
19+ use super :: { btc:: WshScript , keys:: MasterXpriv } ;
20+
2021pub fn attach_stdlib ( scope : & ScopeRef < Mutable > ) {
2122 let mut scope = scope. borrow_mut ( ) ;
2223 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
201202 }
202203
203204 // 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 )
206207 }
207208
208209 // Keys provided as [ $single_sk1, $single_sk2, ... ]
@@ -212,15 +213,16 @@ fn sign_psbt(psbt: &mut Psbt, keys_val: Value) -> Result<(SigningKeysMap, Signin
212213 _ => bail ! ( Error :: PsbtInvalidSignKeys ) ,
213214 }
214215 }
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+ }
217220
218- // Key provided as one single key
221+ // Key provided as a single key
219222 Value :: SecKey ( DescriptorSecretKey :: Single ( _) ) => {
220223 psbt. sign ( & single_seckey_to_map ( PrivateKey :: try_from ( keys_val) ?) , & EC )
221224 }
222225
223- // TODO support signing with MultiXpriv
224226 _ => bail ! ( Error :: PsbtInvalidSignKeys ) ,
225227 } ;
226228 // 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 {
736738 }
737739}
738740
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>
741742struct 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>.
742761impl psbt:: GetKey for XprivSet {
743762 type Error = <Xpriv as psbt:: GetKey >:: Error ;
744763
0 commit comments