Skip to content

Commit 2ff9f11

Browse files
authored
Merge pull request #200 from sanket1729/satisfy_fixes
Satisfy fixes
2 parents 2b940e1 + bb85c70 commit 2ff9f11

File tree

3 files changed

+34
-27
lines changed

3 files changed

+34
-27
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "miniscript"
3-
version = "4.0.0"
3+
version = "4.0.1"
44
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>, Sanket Kanjalkar <sanket1729@gmail.com>"]
55
repository = "https://github.com/apoelstra/miniscript"
66
description = "Miniscript: a subset of Bitcoin Script designed for analysis"

src/miniscript/satisfy.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,6 @@ pub struct Older(pub u32);
127127

128128
impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for Older {
129129
fn check_older(&self, n: u32) -> bool {
130-
// if n > self.0; we will be returning false anyways
131-
if n < HEIGHT_TIME_THRESHOLD && self.0 >= HEIGHT_TIME_THRESHOLD {
132-
false
133-
} else {
134-
n <= self.0
135-
}
136-
}
137-
}
138-
139-
/// Newtype around `u32` which implements `Satisfier` using `n` as an
140-
/// absolute locktime
141-
pub struct After(pub u32);
142-
143-
impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for After {
144-
fn check_after(&self, n: u32) -> bool {
145130
if self.0 & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
146131
return true;
147132
}
@@ -161,6 +146,21 @@ impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx,
161146
}
162147
}
163148

149+
/// Newtype around `u32` which implements `Satisfier` using `n` as an
150+
/// absolute locktime
151+
pub struct After(pub u32);
152+
153+
impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for After {
154+
fn check_after(&self, n: u32) -> bool {
155+
// if n > self.0; we will be returning false anyways
156+
if n < HEIGHT_TIME_THRESHOLD && self.0 >= HEIGHT_TIME_THRESHOLD {
157+
false
158+
} else {
159+
n <= self.0
160+
}
161+
}
162+
}
163+
164164
impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk>
165165
for HashMap<Pk, BitcoinSig>
166166
{
@@ -627,9 +627,9 @@ impl Satisfaction {
627627
sat_indices.sort_by_key(|&i| {
628628
let stack_weight = match (&sats[i].stack, &ret_stack[i].stack) {
629629
(&Witness::Unavailable, _) | (&Witness::Impossible, _) => i64::MAX,
630-
(_, &Witness::Unavailable) | (_, &Witness::Impossible) => {
631-
unreachable!("Threshold fragments must be 'd'")
632-
}
630+
// This can only be the case when we have PkH without the corresponding
631+
// Pubkey.
632+
(_, &Witness::Unavailable) | (_, &Witness::Impossible) => i64::MIN,
633633
(&Witness::Stack(ref s), &Witness::Stack(ref d)) => {
634634
witness_size(s) as i64 - witness_size(d) as i64
635635
}
@@ -669,7 +669,9 @@ impl Satisfaction {
669669
// For example, the fragment thresh(2, hash, hash, 0, 0)
670670
// is uniquely satisfyiable because there is no satisfaction
671671
// for the 0 fragment
672-
else if !sats[sat_indices[k]].has_sig && sats[sat_indices[k]].stack != Witness::Impossible
672+
else if k < sat_indices.len()
673+
&& !sats[sat_indices[k]].has_sig
674+
&& sats[sat_indices[k]].stack != Witness::Impossible
673675
{
674676
// All arguments should be `d`, so dissatisfactions have no
675677
// signatures; and in this branch we assume too many weak
@@ -744,9 +746,8 @@ impl Satisfaction {
744746
sat_indices.sort_by_key(|&i| {
745747
let stack_weight = match (&sats[i].stack, &ret_stack[i].stack) {
746748
(&Witness::Unavailable, _) | (&Witness::Impossible, _) => i64::MAX,
747-
(_, &Witness::Unavailable) | (_, &Witness::Impossible) => {
748-
unreachable!("Threshold fragments must be 'd'")
749-
}
749+
// This is only possible when one of the branches has PkH
750+
(_, &Witness::Unavailable) | (_, &Witness::Impossible) => i64::MIN,
750751
(&Witness::Stack(ref s), &Witness::Stack(ref d)) => {
751752
witness_size(s) as i64 - witness_size(d) as i64
752753
}

src/psbt/finalizer.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ fn get_amt(psbt: &Psbt, index: usize) -> Result<u64, InputError> {
6363
// Also sanity checks that the witness script and
6464
// redeem script are consistent with the script pubkey.
6565
// Does *not* check signatures
66+
// We parse the insane version while satisfying because
67+
// we want to move the script is probably already created
68+
// and we want to satisfy it in any way possible.
6669
fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, InputError> {
6770
// Figure out Scriptpubkey
6871
let script_pubkey = get_scriptpubkey(psbt, index)?;
@@ -120,7 +123,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
120123
p2wsh_expected: script_pubkey.clone(),
121124
});
122125
}
123-
let ms = Miniscript::<bitcoin::PublicKey, Segwitv0>::parse(witness_script)?;
126+
let ms = Miniscript::<bitcoin::PublicKey, Segwitv0>::parse_insane(witness_script)?;
124127
Ok(Descriptor::Wsh(ms))
125128
} else {
126129
Err(InputError::MissingWitnessScript)
@@ -144,7 +147,9 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
144147
p2wsh_expected: redeem_script.clone(),
145148
});
146149
}
147-
let ms = Miniscript::<bitcoin::PublicKey, Segwitv0>::parse(witness_script)?;
150+
let ms = Miniscript::<bitcoin::PublicKey, Segwitv0>::parse_insane(
151+
witness_script,
152+
)?;
148153
Ok(Descriptor::ShWsh(ms))
149154
} else {
150155
Err(InputError::MissingWitnessScript)
@@ -170,7 +175,8 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
170175
return Err(InputError::NonEmptyWitnessScript);
171176
}
172177
if let Some(ref redeem_script) = inp.redeem_script {
173-
let ms = Miniscript::<bitcoin::PublicKey, Legacy>::parse(redeem_script)?;
178+
let ms =
179+
Miniscript::<bitcoin::PublicKey, Legacy>::parse_insane(redeem_script)?;
174180
Ok(Descriptor::Sh(ms))
175181
} else {
176182
Err(InputError::MissingWitnessScript)
@@ -186,7 +192,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result<Descriptor<PublicKey>, In
186192
if inp.redeem_script.is_some() {
187193
return Err(InputError::NonEmptyRedeemScript);
188194
}
189-
let ms = Miniscript::<bitcoin::PublicKey, Bare>::parse(script_pubkey)?;
195+
let ms = Miniscript::<bitcoin::PublicKey, Bare>::parse_insane(script_pubkey)?;
190196
Ok(Descriptor::Bare(ms))
191197
}
192198
}

0 commit comments

Comments
 (0)