Skip to content

Commit 1bff4d5

Browse files
committed
add satisfaction checks
1 parent e18d52c commit 1bff4d5

File tree

5 files changed

+62
-21
lines changed

5 files changed

+62
-21
lines changed

src/descriptor/mod.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use miniscript::{decode::Terminal, Legacy, Miniscript, Segwitv0};
4545
use policy;
4646
use push_opcode_size;
4747
use script_num_size;
48+
use util::witness_to_scriptsig;
4849
use Bare;
4950
use Error;
5051
use MiniscriptKey;
@@ -983,18 +984,6 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
983984
Pk: ToPublicKey<ToPkCtx>,
984985
S: Satisfier<ToPkCtx, Pk>,
985986
{
986-
fn witness_to_scriptsig(witness: &[Vec<u8>]) -> Script {
987-
let mut b = script::Builder::new();
988-
for wit in witness {
989-
if let Ok(n) = script::read_scriptint(wit) {
990-
b = b.push_int(n);
991-
} else {
992-
b = b.push_slice(wit);
993-
}
994-
}
995-
b.into_script()
996-
}
997-
998987
match *self {
999988
Descriptor::Bare(ref d) => {
1000989
let wit = match d.satisfy(satisfier, to_pk_ctx) {

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ pub mod miniscript;
119119
pub mod policy;
120120
pub mod psbt;
121121

122+
mod util;
123+
122124
use std::str::FromStr;
123125
use std::{error, fmt, hash, str};
124126

src/miniscript/context.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use miniscript::types::extra_props::{
1818
MAX_STANDARD_P2WSH_SCRIPT_SIZE, MAX_STANDARD_P2WSH_STACK_ITEMS,
1919
};
2020
use std::fmt;
21+
use util::{witness_size, witness_to_scriptsig};
2122
use Error;
2223
use {Miniscript, MiniscriptKey, Terminal};
2324
/// Error for Script Context
@@ -111,6 +112,18 @@ pub trait ScriptContext:
111112
_frag: &Terminal<Pk, Ctx>,
112113
) -> Result<(), ScriptContextError>;
113114

115+
/// Check whether the given satisfaction is valid under the ScriptContext
116+
/// For example, segwit satisfactions may fail if the witness len is more
117+
/// 3600 or number of stack elements are more than 100.
118+
fn check_witness<Pk: MiniscriptKey, Ctx: ScriptContext>(
119+
_witness: &[Vec<u8>],
120+
) -> Result<(), ScriptContextError> {
121+
// Only really need to do this for segwitv0 and legacy
122+
// Bare is already restrcited by standardness rules
123+
// and would reach these limits.
124+
Ok(())
125+
}
126+
114127
/// Depending on script context, the size of a satifaction witness may slightly differ.
115128
fn max_satisfaction_size<Pk: MiniscriptKey, Ctx: ScriptContext>(
116129
ms: &Miniscript<Pk, Ctx>,
@@ -241,6 +254,17 @@ impl ScriptContext for Legacy {
241254
}
242255
}
243256

257+
fn check_witness<Pk: MiniscriptKey, Ctx: ScriptContext>(
258+
witness: &[Vec<u8>],
259+
) -> Result<(), ScriptContextError> {
260+
// In future, we could avoid by having a function to count only
261+
// len of script instead of converting it.
262+
if witness_to_scriptsig(witness).len() > MAX_SCRIPTSIG_SIZE {
263+
return Err(ScriptContextError::MaxScriptSigSizeExceeded);
264+
}
265+
Ok(())
266+
}
267+
244268
fn check_global_consensus_validity<Pk: MiniscriptKey, Ctx: ScriptContext>(
245269
ms: &Miniscript<Pk, Ctx>,
246270
) -> Result<(), ScriptContextError> {
@@ -294,6 +318,17 @@ impl ScriptContext for Segwitv0 {
294318
Ok(())
295319
}
296320

321+
fn check_witness<Pk: MiniscriptKey, Ctx: ScriptContext>(
322+
witness: &[Vec<u8>],
323+
) -> Result<(), ScriptContextError> {
324+
if witness_size(witness) > MAX_STANDARD_P2WSH_SCRIPT_SIZE {
325+
return Err(ScriptContextError::MaxScriptSigSizeExceeded);
326+
} else if witness.len() > MAX_STANDARD_P2WSH_STACK_ITEMS {
327+
return Err(ScriptContextError::MaxWitnessItemssExceeded);
328+
}
329+
Ok(())
330+
}
331+
297332
fn check_global_consensus_validity<Pk: MiniscriptKey, Ctx: ScriptContext>(
298333
ms: &Miniscript<Pk, Ctx>,
299334
) -> Result<(), ScriptContextError> {

src/miniscript/satisfy.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use {MiniscriptKey, ToPublicKey};
2929
use miniscript::types::extra_props::{
3030
HEIGHT_TIME_THRESHOLD, SEQUENCE_LOCKTIME_DISABLE_FLAG, SEQUENCE_LOCKTIME_TYPE_FLAG,
3131
};
32+
use util::witness_size;
3233
use Error;
3334
use Miniscript;
3435
use NullCtx;
@@ -415,15 +416,6 @@ impl PartialOrd for Witness {
415416
}
416417
}
417418

418-
fn varint_len(n: usize) -> usize {
419-
bitcoin::VarInt(n as u64).len()
420-
}
421-
422-
// Helper function to calculate witness size
423-
fn witness_size(wit: &[Vec<u8>]) -> usize {
424-
wit.iter().map(Vec::len).sum::<usize>() + varint_len(wit.len())
425-
}
426-
427419
impl Ord for Witness {
428420
fn cmp(&self, other: &Self) -> cmp::Ordering {
429421
match (self, other) {

src/util.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use bitcoin;
2+
use bitcoin::blockdata::script;
3+
use bitcoin::Script;
4+
pub(crate) fn varint_len(n: usize) -> usize {
5+
bitcoin::VarInt(n as u64).len()
6+
}
7+
8+
// Helper function to calculate witness size
9+
pub(crate) fn witness_size(wit: &[Vec<u8>]) -> usize {
10+
wit.iter().map(Vec::len).sum::<usize>() + varint_len(wit.len())
11+
}
12+
13+
pub(crate) fn witness_to_scriptsig(witness: &[Vec<u8>]) -> Script {
14+
let mut b = script::Builder::new();
15+
for wit in witness {
16+
if let Ok(n) = script::read_scriptint(wit) {
17+
b = b.push_int(n);
18+
} else {
19+
b = b.push_slice(wit);
20+
}
21+
}
22+
b.into_script()
23+
}

0 commit comments

Comments
 (0)