diff --git a/src/descriptor/pegin/dynafed_pegin.rs b/src/descriptor/pegin/dynafed_pegin.rs index e95b5479..0811d6e6 100644 --- a/src/descriptor/pegin/dynafed_pegin.rs +++ b/src/descriptor/pegin/dynafed_pegin.rs @@ -33,7 +33,7 @@ use crate::extensions::{CovExtArgs, CovenantExt}; use crate::policy::{semantic, Liftable}; use crate::{ tweak_key, BtcDescriptor, BtcError, BtcFromTree, BtcLiftable, BtcPolicy, BtcSatisfier, BtcTree, - Descriptor, Error, MiniscriptKey, ToPublicKey, + Descriptor, DescriptorPublicKey, Error, MiniscriptKey, ToPublicKey, }; /// New Pegin Descriptor with Miniscript support @@ -61,6 +61,18 @@ impl Pegin { } } +impl Pegin { + pub fn derived_descriptor( + &self, + arg: u32, + secp: &secp256k1_zkp::Secp256k1, + ) -> Result, Error> { + let elem_desc = self.elem_desc.at_derivation_index(arg)?; + let elem_desc = elem_desc.derived_descriptor(&secp)?; + Ok(Pegin::new(self.fed_desc.clone(), elem_desc)) + } +} + impl fmt::Debug for Pegin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "pegin({:?},{:?})", self.fed_desc, self.elem_desc) @@ -148,6 +160,7 @@ impl Pegin { { // TODO Ok(bitcoin::Address::p2shwsh( + // Should the address type taken from the top level user desc? &self .bitcoin_witness_script(secp) .expect("DO this cleanly after TR. Pay to taproot pegins unspecified till now"), @@ -365,4 +378,36 @@ mod tests { assert_eq!(pegin.to_string(), "pegin(wsh(or_d(multi(11,020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261,02675333a4e4b8fb51d9d4e22fa5a8eaced3fdac8a8cbf9be8c030f75712e6af99,02896807d54bc55c24981f24a453c60ad3e8993d693732288068a23df3d9f50d48,029e51a5ef5db3137051de8323b001749932f2ff0d34c82e96a2c2461de96ae56c,02a4e1a9638d46923272c266631d94d36bdb03a64ee0e14c7518e49d2f29bc4010,031c41fdbcebe17bec8d49816e00ca1b5ac34766b91c9f2ac37d39c63e5e008afb,03079e252e85abffd3c401a69b087e590a9b86f33f574f08129ccbd3521ecf516b,03111cf405b627e22135b3b3733a4a34aa5723fb0f58379a16d32861bf576b0ec2,0318f331b3e5d38156da6633b31929c5b220349859cc9ca3d33fb4e68aa0840174,03230dae6b4ac93480aeab26d000841298e3b8f6157028e47b0897c1e025165de1,035abff4281ff00660f99ab27bb53e6b33689c2cd8dcd364bc3c90ca5aea0d71a6,03bd45cddfacf2083b14310ae4a84e25de61e451637346325222747b157446614c,03cc297026b06c71cbfa52089149157b5ff23de027ac5ab781800a578192d17546,03d3bde5d63bdb3a6379b461be64dad45eabff42f758543a9645afd42f6d424828,03ed1e8d5109c9ed66f7941bc53cc71137baa76d50d274bda8d5e8ffbd6e61fe9a),and_v(v:older(4032),multi(2,03aab896d53a8e7d6433137bbba940f9c521e085dd07e60994579b64a6d992cf79,0291b7d0b1b692f8f524516ed950872e5da10fb1b808b5a526dedc6fed1cf29807,0386aa9372fbab374593466bc5451dc59954e90787f08060964d95c87ef34ca5bb)))),elwpkh(0321da398ca2ddc09be89caa26e6730ae84751b6ea3a1ca46aa365bb5e1c3d9620))#qp4fan9q"); } + + #[test] + fn test_pegin_derive() { + let elem_desc = "ct(slip77(ab5824f4477b4ebb00a132adfd8eb0b7935cf24f6ac151add5d1913db374ce92),elwpkh([759db348/84'/1'/0']tpubDCRMaF33e44pcJj534LXVhFbHibPbJ5vuLhSSPFAw57kYURv4tzXFL6LSnd78bkjqdmE3USedkbpXJUPA1tdzKfuYSL7PianceqAhwL2UkA/0/*))"; + let elem_desc: ConfidentialDescriptor = elem_desc.parse().unwrap(); + let fed_peg_desc = fed_peg_desc(); + let pegin = Pegin::new(fed_peg_desc, elem_desc.descriptor); + let secp = secp256k1::Secp256k1::new(); + + let witness_script_0 = pegin + .derived_descriptor(0, &secp) + .unwrap() + .bitcoin_witness_script(&secp) + .unwrap(); + let address_0 = bitcoin::Address::p2wsh(&witness_script_0, bitcoin::Network::Bitcoin); + assert_eq!( + address_0.to_string(), + "bc1qqkq6czql4zqwsylgrfzttjrn5wjeqmwfq5yn80p39amxtnkng9lsn6c5qr" + ); + + let witness_script_1 = pegin + .derived_descriptor(1, &secp) + .unwrap() + .bitcoin_witness_script(&secp) + .unwrap(); + let address_1 = bitcoin::Address::p2wsh(&witness_script_1, bitcoin::Network::Bitcoin); + assert_ne!(address_0, address_1); + assert_eq!( + address_1.to_string(), + "bc1qmevs3n40t394230lptclz55rmxkmr7dmnqhuflxf0cezdupsmvdsk25n3m" + ); + } } diff --git a/src/lib.rs b/src/lib.rs index 6ed2da2d..1127453f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -373,6 +373,9 @@ pub enum Error { /// At least two BIP389 key expressions in the descriptor contain tuples of /// derivation indexes of different lengths. MultipathDescLenMismatch, + + /// Conversion error in descriptor + Conversion(descriptor::ConversionError), } #[doc(hidden)] @@ -449,6 +452,12 @@ impl From for Error { } } +impl From for Error { + fn from(e: descriptor::ConversionError) -> Error { + Error::Conversion(e) + } +} + fn errstr(s: &str) -> Error { Error::Unexpected(s.to_owned()) } @@ -530,6 +539,8 @@ impl fmt::Display for Error { Error::TrNoScriptCode => write!(f, "No script code for Tr descriptors"), Error::TrNoExplicitScript => write!(f, "No script code for Tr descriptors"), Error::MultipathDescLenMismatch => write!(f, "At least two BIP389 key expressions in the descriptor contain tuples of derivation indexes of different lengths"), + Error::Conversion(ref e) => e.fmt(f), + } } } @@ -584,6 +595,7 @@ impl error::Error for Error { ContextError(e) => Some(e), AnalysisError(e) => Some(e), PubKeyCtxError(e, _) => Some(e), + Conversion(e) => Some(e), } } }