Skip to content

Commit 8aec456

Browse files
committed
Add descriptor malleable satisfaction support
1 parent ea7170e commit 8aec456

File tree

4 files changed

+91
-3
lines changed

4 files changed

+91
-3
lines changed

src/descriptor/bare.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,17 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Bare<Pk> {
158158
Ok((witness, script_sig))
159159
}
160160

161+
fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
162+
where
163+
Pk: ToPublicKey,
164+
S: Satisfier<Pk>,
165+
{
166+
let ms = self.ms.satisfy_malleable(satisfier)?;
167+
let script_sig = witness_to_scriptsig(&ms);
168+
let witness = vec![];
169+
Ok((witness, script_sig))
170+
}
171+
161172
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
162173
let scriptsig_len = self.ms.max_satisfaction_size()?;
163174
Ok(4 * (varint_len(scriptsig_len) + scriptsig_len))
@@ -338,6 +349,14 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Pkh<Pk> {
338349
}
339350
}
340351

352+
fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
353+
where
354+
Pk: ToPublicKey,
355+
S: Satisfier<Pk>,
356+
{
357+
self.get_satisfaction(satisfier)
358+
}
359+
341360
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
342361
Ok(4 * (1 + 73 + BareCtx::pk_len(&self.pk)))
343362
}

src/descriptor/mod.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,23 @@ pub trait DescriptorTrait<Pk: MiniscriptKey> {
114114
where
115115
Pk: ToPublicKey;
116116

117-
/// Returns satisfying witness and scriptSig to spend an
117+
/// Returns satisfying non-malleable witness and scriptSig to spend an
118118
/// output controlled by the given descriptor if it possible to
119119
/// construct one using the satisfier S.
120120
fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
121121
where
122122
Pk: ToPublicKey,
123123
S: Satisfier<Pk>;
124124

125-
/// Attempts to produce a satisfying witness and scriptSig to spend an
125+
/// Returns satisfying, possibly malleable witness and scriptSig to spend an
126+
/// output controlled by the given descriptor if it possible to
127+
/// construct one using the satisfier S.
128+
fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
129+
where
130+
Pk: ToPublicKey,
131+
S: Satisfier<Pk>;
132+
133+
/// Attempts to produce a non-malleable satisfying witness and scriptSig to spend an
126134
/// output controlled by the given descriptor; add the data to a given
127135
/// `TxIn` output.
128136
fn satisfy<S>(&self, txin: &mut bitcoin::TxIn, satisfier: S) -> Result<(), Error>
@@ -421,7 +429,7 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Descriptor<Pk> {
421429
}
422430
}
423431

424-
/// Returns satisfying witness and scriptSig to spend an
432+
/// Returns satisfying non-malleable witness and scriptSig to spend an
425433
/// output controlled by the given descriptor if it possible to
426434
/// construct one using the satisfier S.
427435
fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
@@ -438,6 +446,23 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Descriptor<Pk> {
438446
}
439447
}
440448

449+
/// Returns a possilbly mallable satisfying non-malleable witness and scriptSig to spend an
450+
/// output controlled by the given descriptor if it possible to
451+
/// construct one using the satisfier S.
452+
fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
453+
where
454+
Pk: ToPublicKey,
455+
S: Satisfier<Pk>,
456+
{
457+
match *self {
458+
Descriptor::Bare(ref bare) => bare.get_satisfaction_mall(satisfier),
459+
Descriptor::Pkh(ref pkh) => pkh.get_satisfaction_mall(satisfier),
460+
Descriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction_mall(satisfier),
461+
Descriptor::Wsh(ref wsh) => wsh.get_satisfaction_mall(satisfier),
462+
Descriptor::Sh(ref sh) => sh.get_satisfaction_mall(satisfier),
463+
}
464+
}
465+
441466
/// Computes an upper bound on the weight of a satisfying witness to the
442467
/// transaction. Assumes all signatures are 73 bytes, including push opcode
443468
/// and sighash suffix. Includes the weight of the VarInts encoding the

src/descriptor/segwitv0.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,20 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wsh<Pk> {
215215
Ok((witness, script_sig))
216216
}
217217

218+
fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
219+
where
220+
Pk: ToPublicKey,
221+
S: Satisfier<Pk>,
222+
{
223+
let mut witness = match self.inner {
224+
WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
225+
WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
226+
};
227+
witness.push(self.explicit_script().into_bytes());
228+
let script_sig = Script::new();
229+
Ok((witness, script_sig))
230+
}
231+
218232
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
219233
let (script_size, max_sat_elems, max_sat_size) = match self.inner {
220234
WshInner::SortedMulti(ref smv) => (
@@ -433,6 +447,14 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Wpkh<Pk> {
433447
}
434448
}
435449

450+
fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
451+
where
452+
Pk: ToPublicKey,
453+
S: Satisfier<Pk>,
454+
{
455+
self.get_satisfaction(satisfier)
456+
}
457+
436458
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
437459
Ok(4 + 1 + 73 + Segwitv0::pk_len(&self.pk))
438460
}

src/descriptor/sh.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,28 @@ impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for Sh<Pk> {
293293
}
294294
}
295295

296+
fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
297+
where
298+
Pk: ToPublicKey,
299+
S: Satisfier<Pk>,
300+
{
301+
let script_sig = self.unsigned_script_sig();
302+
match self.inner {
303+
ShInner::Wsh(ref wsh) => {
304+
let (witness, _) = wsh.get_satisfaction_mall(satisfier)?;
305+
Ok((witness, script_sig))
306+
}
307+
ShInner::Ms(ref ms) => {
308+
let mut script_witness = ms.satisfy_malleable(satisfier)?;
309+
script_witness.push(ms.encode().into_bytes());
310+
let script_sig = witness_to_scriptsig(&script_witness);
311+
let witness = vec![];
312+
Ok((witness, script_sig))
313+
}
314+
_ => self.get_satisfaction(satisfier),
315+
}
316+
}
317+
296318
fn max_satisfaction_weight(&self) -> Result<usize, Error> {
297319
Ok(match self.inner {
298320
// add weighted script sig, len byte stays the same

0 commit comments

Comments
 (0)