Skip to content

Commit 9898534

Browse files
committed
Merge #87: Implement federation descriptor tweak with claiming script to match elements core getpeginaddress
931696f publicly expose Btc types (Riccardo Casatta) d79a2cf finish to implement get_bitcoin_satisfaction (Riccardo Casatta) 81b25cd move only: move TranslateTweak out so that is usable in other fn (Riccardo Casatta) cfe6306 add test_pegin to match with elements core (Riccardo Casatta) 97eb5ca remove the sha256 step in key tweak (will hmac<sha256> later) (Riccardo Casatta) 9d87b50 refactor out fn as free fn (Riccardo Casatta) 909b180 finish implement bitcoin_witness_script in dynafed pegin (Riccardo Casatta) Pull request description: This will be needed by lwk with a claim script generated by the lwk wallet so it will be able to claim pegins by its own ACKs for top commit: apoelstra: ACK 931696f successfully ran local tests Tree-SHA512: 6b0d2f8dd31934d2dc96786193632917e6be5d73eb66845050a8871ef507d08d7d51444dafe224d918021752e0e6753c39ebbb190b1a0c9578429f8cc380f690
2 parents 9425f2e + 931696f commit 9898534

File tree

2 files changed

+95
-46
lines changed

2 files changed

+95
-46
lines changed

src/descriptor/pegin/dynafed_pegin.rs

Lines changed: 94 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,15 @@ use std::convert::TryFrom;
2424
use std::fmt;
2525

2626
use bitcoin::blockdata::script::{self, PushBytes};
27-
use bitcoin::hashes::Hash;
28-
use bitcoin::{self, hashes, ScriptBuf as BtcScript};
27+
use bitcoin::{self, ScriptBuf as BtcScript};
2928
use elements::secp256k1_zkp;
3029

3130
use crate::descriptor::checksum::{desc_checksum, verify_checksum};
3231
use crate::expression::{self, FromTree};
3332
use crate::extensions::{CovExtArgs, CovenantExt};
3433
use crate::policy::{semantic, Liftable};
3534
use crate::{
36-
BtcDescriptor, BtcError, BtcFromTree, BtcLiftable, BtcPolicy, BtcSatisfier, BtcTree,
35+
tweak_key, BtcDescriptor, BtcError, BtcFromTree, BtcLiftable, BtcPolicy, BtcSatisfier, BtcTree,
3736
Descriptor, Error, MiniscriptKey, ToPublicKey,
3837
};
3938

@@ -198,7 +197,7 @@ impl<Pk: MiniscriptKey> Pegin<Pk> {
198197
/// for the others it is the witness script.
199198
pub fn bitcoin_witness_script<C: secp256k1_zkp::Verification>(
200199
&self,
201-
_secp: &secp256k1_zkp::Secp256k1<C>,
200+
secp: &secp256k1_zkp::Secp256k1<C>,
202201
) -> Result<BtcScript, Error>
203202
where
204203
Pk: ToPublicKey,
@@ -208,63 +207,33 @@ impl<Pk: MiniscriptKey> Pegin<Pk> {
208207
.explicit_script()
209208
.expect("Tr pegins unknown yet")
210209
.into_bytes();
211-
let _tweak = hashes::sha256::Hash::hash(&tweak_vec);
212-
213-
unreachable!("TODO: After upstream Refactor for Translator trait")
214-
// let derived = self.fed_desc.derive
215-
216-
// struct TranslateTweak<'a, C: secp256k1_zkp::Verification>(
217-
// hashes::sha256::Hash,
218-
// &'a secp256k1_zkp::Secp256k1<C>,
219-
// );
220-
221-
// impl<'a, Pk, C> PkTranslator<Pk, bitcoin::PublicKey, ()> for TranslateTweak<'a, C>
222-
// where
223-
// Pk: MiniscriptKey,
224-
// C: secp256k1_zkp::Verification,
225-
// {
226-
// fn pk(&mut self, pk: &Pk) -> Result<bitcoin::PublicKey, ()> {
227-
// tweak_key(pk, self.1, self.0.as_inner())
228-
// }
229-
230-
// fn pkh(
231-
// &mut self,
232-
// pkh: &<Pk as MiniscriptKey>::Hash,
233-
// ) -> Result<<bitcoin::PublicKey as MiniscriptKey>::Hash, ()> {
234-
// unreachable!("No keyhashes in elements descriptors")
235-
// }
236-
// }
237-
// let mut t = TranslateTweak(tweak, secp);
238-
239-
// let tweaked_desc = <bitcoin_miniscript::TranslatePk>::translate_pk(&self.fed_desc, t).expect("Tweaking must succeed"),
240-
// Ok(tweaked_desc.explicit_script()?)
210+
bitcoin_witness_script(&self.fed_desc, &tweak_vec[..], secp)
241211
}
242212

243213
/// Returns satisfying witness and scriptSig to spend an
244214
/// output controlled by the given descriptor if it possible to
245215
/// construct one using the satisfier S.
246216
pub fn get_bitcoin_satisfaction<S, C: secp256k1_zkp::Verification>(
247217
&self,
248-
_secp: &secp256k1_zkp::Secp256k1<C>,
249-
_satisfier: S,
218+
secp: &secp256k1_zkp::Secp256k1<C>,
219+
satisfier: S,
250220
) -> Result<(Vec<Vec<u8>>, BtcScript), Error>
251221
where
252222
S: BtcSatisfier<bitcoin::PublicKey>,
253223
Pk: ToPublicKey,
254224
{
255-
let tweak_vec = self
225+
let claim_script = self
256226
.elem_desc
257227
.explicit_script()
258228
.expect("Tr pegins unknown yet")
259229
.into_bytes();
260-
let _tweak = hashes::sha256::Hash::hash(&tweak_vec);
261-
unreachable!("TODO: After upstream refactor");
262-
// let tweaked_desc = self.fed_desc.translate_pk_infallible(
263-
// |pk| tweak_key(pk, secp, tweak.as_inner()),
264-
// |_| unreachable!("No keyhashes in elements descriptors"),
265-
// );
266-
// let res = tweaked_desc.get_satisfaction(satisfier)?;
267-
// Ok(res)
230+
let mut t = TranslateTweak(&claim_script[..], secp);
231+
232+
let tweaked_desc = bitcoin_miniscript::TranslatePk::translate_pk(&self.fed_desc, &mut t)
233+
.expect("Tweaking must succeed");
234+
235+
let res = tweaked_desc.get_satisfaction(satisfier)?;
236+
Ok(res)
268237
}
269238

270239
/// Computes an upper bound on the weight of a satisfying witness to the
@@ -303,3 +272,83 @@ impl<Pk: MiniscriptKey> Pegin<Pk> {
303272
self.elem_desc
304273
}
305274
}
275+
276+
fn bitcoin_witness_script<C: secp256k1_zkp::Verification, Pk: ToPublicKey>(
277+
fed_desc: &BtcDescriptor<Pk>,
278+
claim_script: &[u8],
279+
secp: &secp256k1_zkp::Secp256k1<C>,
280+
) -> Result<BtcScript, Error> {
281+
let mut t = TranslateTweak(claim_script, secp);
282+
283+
let tweaked_desc = bitcoin_miniscript::TranslatePk::translate_pk(fed_desc, &mut t)
284+
.expect("Tweaking must succeed");
285+
Ok(tweaked_desc.explicit_script()?)
286+
}
287+
288+
struct TranslateTweak<'a, 'b, C: secp256k1_zkp::Verification>(
289+
&'a [u8],
290+
&'b secp256k1_zkp::Secp256k1<C>,
291+
);
292+
293+
impl<'a, 'b, Pk, C> bitcoin_miniscript::Translator<Pk, bitcoin::PublicKey, ()>
294+
for TranslateTweak<'a, 'b, C>
295+
where
296+
Pk: MiniscriptKey + ToPublicKey,
297+
C: secp256k1_zkp::Verification,
298+
{
299+
fn pk(&mut self, pk: &Pk) -> Result<bitcoin::PublicKey, ()> {
300+
Ok(tweak_key(&pk.to_public_key(), self.1, &self.0[..]))
301+
}
302+
303+
// We don't need to implement these methods as we are not using them in the policy.
304+
// Fail if we encounter any hash fragments. See also translate_hash_clone! macro.
305+
translate_hash_fail!(Pk, bitcoin::PublicKey, ());
306+
}
307+
308+
#[cfg(test)]
309+
mod tests {
310+
use elements::hex::FromHex;
311+
312+
use crate::BtcDescriptor;
313+
314+
// test vector created with:
315+
// ```
316+
// $ elements-cli getnetworkinfo | jq .version
317+
// 230201
318+
// $ elements-cli getblockchaininfo | jq .blocks
319+
// 2976078
320+
// elements-cli getsidechaininfo | jq '.current_fedpegscripts[0]'`
321+
// "5b21020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b678172612102675333a4e4b8fb51d9d4e22fa5a8eaced3fdac8a8cbf9be8c030f75712e6af992102896807d54bc55c24981f24a453c60ad3e8993d693732288068a23df3d9f50d4821029e51a5ef5db3137051de8323b001749932f2ff0d34c82e96a2c2461de96ae56c2102a4e1a9638d46923272c266631d94d36bdb03a64ee0e14c7518e49d2f29bc401021031c41fdbcebe17bec8d49816e00ca1b5ac34766b91c9f2ac37d39c63e5e008afb2103079e252e85abffd3c401a69b087e590a9b86f33f574f08129ccbd3521ecf516b2103111cf405b627e22135b3b3733a4a34aa5723fb0f58379a16d32861bf576b0ec2210318f331b3e5d38156da6633b31929c5b220349859cc9ca3d33fb4e68aa08401742103230dae6b4ac93480aeab26d000841298e3b8f6157028e47b0897c1e025165de121035abff4281ff00660f99ab27bb53e6b33689c2cd8dcd364bc3c90ca5aea0d71a62103bd45cddfacf2083b14310ae4a84e25de61e451637346325222747b157446614c2103cc297026b06c71cbfa52089149157b5ff23de027ac5ab781800a578192d175462103d3bde5d63bdb3a6379b461be64dad45eabff42f758543a9645afd42f6d4248282103ed1e8d5109c9ed66f7941bc53cc71137baa76d50d274bda8d5e8ffbd6e61fe9a5fae736402c00fb269522103aab896d53a8e7d6433137bbba940f9c521e085dd07e60994579b64a6d992cf79210291b7d0b1b692f8f524516ed950872e5da10fb1b808b5a526dedc6fed1cf29807210386aa9372fbab374593466bc5451dc59954e90787f08060964d95c87ef34ca5bb53ae68"
322+
// $ elements-cli getpeginaddress
323+
// {
324+
// "mainchain_address": "bc1qyya0twwz58kgfslpdgsygeq0r4nngl9tkt89v6phk8nqrwyenwrq5h0dk8",
325+
// "claim_script": "0014a15906e643f2c9635527ab8658d370e8eaf149b5"
326+
// }
327+
// ```
328+
#[test]
329+
fn test_pegin() {
330+
let fedpegscript ="5b21020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b678172612102675333a4e4b8fb51d9d4e22fa5a8eaced3fdac8a8cbf9be8c030f75712e6af992102896807d54bc55c24981f24a453c60ad3e8993d693732288068a23df3d9f50d4821029e51a5ef5db3137051de8323b001749932f2ff0d34c82e96a2c2461de96ae56c2102a4e1a9638d46923272c266631d94d36bdb03a64ee0e14c7518e49d2f29bc401021031c41fdbcebe17bec8d49816e00ca1b5ac34766b91c9f2ac37d39c63e5e008afb2103079e252e85abffd3c401a69b087e590a9b86f33f574f08129ccbd3521ecf516b2103111cf405b627e22135b3b3733a4a34aa5723fb0f58379a16d32861bf576b0ec2210318f331b3e5d38156da6633b31929c5b220349859cc9ca3d33fb4e68aa08401742103230dae6b4ac93480aeab26d000841298e3b8f6157028e47b0897c1e025165de121035abff4281ff00660f99ab27bb53e6b33689c2cd8dcd364bc3c90ca5aea0d71a62103bd45cddfacf2083b14310ae4a84e25de61e451637346325222747b157446614c2103cc297026b06c71cbfa52089149157b5ff23de027ac5ab781800a578192d175462103d3bde5d63bdb3a6379b461be64dad45eabff42f758543a9645afd42f6d4248282103ed1e8d5109c9ed66f7941bc53cc71137baa76d50d274bda8d5e8ffbd6e61fe9a5fae736402c00fb269522103aab896d53a8e7d6433137bbba940f9c521e085dd07e60994579b64a6d992cf79210291b7d0b1b692f8f524516ed950872e5da10fb1b808b5a526dedc6fed1cf29807210386aa9372fbab374593466bc5451dc59954e90787f08060964d95c87ef34ca5bb53ae68";
331+
let s = bitcoin::ScriptBuf::from_hex(fedpegscript).unwrap();
332+
333+
type Segwitv0Script =
334+
bitcoin_miniscript::Miniscript<bitcoin::PublicKey, bitcoin_miniscript::Segwitv0>;
335+
336+
let m = Segwitv0Script::parse(&s).unwrap();
337+
assert_eq!(m.encode(), s);
338+
339+
let d = BtcDescriptor::<_>::new_wsh(m).unwrap();
340+
341+
let fedpegdesc = "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))))#7jwwklk4";
342+
assert_eq!(&d.to_string(), fedpegdesc);
343+
344+
let claimscript =
345+
Vec::<u8>::from_hex("0014de8e299d5347503f7ee33247e780b7f412727623").unwrap();
346+
let secp = secp256k1::Secp256k1::new();
347+
348+
let mainchain_address = "bc1qssx7ha3zxpq25l6uukphlwj3jumvmcv8qr3dy6uy8l8j4vwa5fhswpcw3p";
349+
350+
let s = super::bitcoin_witness_script(&d, &claimscript, &secp).unwrap();
351+
let b = bitcoin::Address::p2wsh(&s, bitcoin::Network::Bitcoin);
352+
assert_eq!(mainchain_address, b.to_string());
353+
}
354+
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ use bitcoin_miniscript::policy::semantic::Policy as BtcPolicy;
113113
use bitcoin_miniscript::policy::Liftable as BtcLiftable;
114114
// re-export imports
115115
pub use bitcoin_miniscript::{hash256, ForEachKey, MiniscriptKey, SigType, ToPublicKey};
116-
use bitcoin_miniscript::{
116+
pub use bitcoin_miniscript::{
117117
Descriptor as BtcDescriptor, Error as BtcError, Miniscript as BtcMiniscript,
118118
Satisfier as BtcSatisfier, Segwitv0 as BtcSegwitv0, Terminal as BtcTerminal,
119119
};

0 commit comments

Comments
 (0)