Skip to content

Commit 2b940e1

Browse files
authored
Merge pull request #196 from darosior/satisfy_error_max_wit_size
Satisfy error: return a max witness size error for Segwitv0
2 parents 977a367 + 0c9661f commit 2b940e1

File tree

8 files changed

+58
-54
lines changed

8 files changed

+58
-54
lines changed

doc/resource_limitations.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ TODO: Rust-miniscript behaviour for resource limitations:
33
# Safe vs Valid vs Sanity/Analyzable/Liftable
44
This document refers to bitcoin consensus and standardness rules as of bitcoin core release 0.20.
55

6-
One of Miniscript’s goals are to make advanced Script functionality accommodate both machine and human analysis. However such a analysis is not possible in all cases.
6+
One of Miniscript’s goals are to make advanced Script functionality accommodate both machine and human analysis. However such an analysis is not possible in all cases.
77

88
- **Validity**: Validity refers to whether the Miniscript tree constructions follows the grammar rules. For eg: Top level must be `B`, or `thresh` must have all of it's arguments being dissatifyable.
99
- **Safety**: Whether all satisfactions of Miniscript require a digital signature.
1010
- **Sanity/Analyzable/Liftable**: Even if the given is valid and safe, it does not imply that Miniscript is consensus and standardness complete. That is, there may exist some semantics implied by the lifted miniscript which cannot be realized in bitcoin network rules. This maybe because of three main reasons
11-
- Miniscript may contain a invalid timelock and heightlock combination[article](https://medium.com/blockstream/dont-mix-your-timelocks-d9939b665094).
11+
- Miniscript may contain an [invalid timelock and heightlock combination](https://medium.com/blockstream/dont-mix-your-timelocks-d9939b665094).
1212
- Resource limitations: Discussed in the next section
1313
- Repeated use of public keys or public key hashes
1414

@@ -25,17 +25,17 @@ There are two types of limitations within the resource limitations: 1) Those tha
2525
Certain limitations like script size are independent of satisfactions and as such those can script creation time. If there is any script that does not satisfy these
2626
- Scripts over 520 bytes are invalid by consensus (P2SH).
2727
- Scripts over 10000 bytes are invalid by consensus (bare, P2SH, P2WSH, P2SH-P2WSH).
28-
- Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) up to n=3 is invalid by standardness (bare).
28+
- For bare scripts (ie not P2PKH, P2SH, [p2sh-]P2WPKH, [p2sh-]P2WSH), anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) up to n=3 is invalid by standardness.
2929
- Scripts over 3600 bytes are invalid by standardness (P2WSH, P2SH-P2WSH).
3030

3131
rust-miniscript errors on parsing descriptors with these limitations and the compiler would not create these scripts.
3232

3333
## Limitations dependent on satisfactions
3434

35-
Some limitations are dependent on satisfaction path taken by script. It is possible that certain script satisfaction paths are not valid by consensus rules because they exceed the following limits:
35+
Some limitations are dependent on satisfaction path taken by script. It is possible that certain script satisfaction paths are not valid because they exceed the following limits:
3636

3737
- Script satisfactions where the total number of non-push opcodes plus the number of keys participating in all executed thresh_ms, is above 201, are invalid by consensus (bare, P2SH, P2WSH, P2SH-P2WSH).
3838
- Script satisfactions with a serialized scriptSig over 1650 bytes are invalid by standardness (P2SH).
3939
- Script satisfactions with a witness consisting of over 100 stack elements (excluding the script itself) are invalid by standardness (P2WSH, P2SH-P2WSH).
4040

41-
rust-miniscript correctly parses these miniscripts, but does not allow lifting/analyzing these scripts if any of the spend paths exceeds the above limits. The satisfier logic does **not** guarantee to find the satisfactions for these scripts.
41+
rust-miniscript correctly parses these miniscripts, but does not allow lifting/analyzing these scripts if any of the spend paths exceeds the above limits. The satisfier logic does **not** guarantee to find the satisfactions for these scripts. The policy compiler would not create such scripts.

src/miniscript/context.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
1313
//
1414

15-
use miniscript::types;
16-
use miniscript::types::extra_props::{
15+
use miniscript::limits::{
1716
MAX_OPS_PER_SCRIPT, MAX_SCRIPTSIG_SIZE, MAX_SCRIPT_ELEMENT_SIZE, MAX_SCRIPT_SIZE,
1817
MAX_STANDARD_P2WSH_SCRIPT_SIZE, MAX_STANDARD_P2WSH_STACK_ITEMS,
1918
};
19+
use miniscript::types;
2020
use std::fmt;
21-
use util::{witness_size, witness_to_scriptsig};
21+
use util::witness_to_scriptsig;
2222
use Error;
2323
use {Miniscript, MiniscriptKey, Terminal};
2424
/// Error for Script Context
@@ -321,9 +321,7 @@ impl ScriptContext for Segwitv0 {
321321
fn check_witness<Pk: MiniscriptKey, Ctx: ScriptContext>(
322322
witness: &[Vec<u8>],
323323
) -> 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 {
324+
if witness.len() > MAX_STANDARD_P2WSH_STACK_ITEMS {
327325
return Err(ScriptContextError::MaxWitnessItemssExceeded);
328326
}
329327
Ok(())

src/miniscript/limits.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//! Miscellaneous constraints imposed by Bitcoin.
2+
//! These constraints can be either Consensus or Policy (standardness) rules, for either Segwitv0
3+
//! or Legacy scripts.
4+
5+
/// Maximum operations per script
6+
// https://github.com/bitcoin/bitcoin/blob/875e1ccc9fe01e026e564dfd39a64d9a4b332a89/src/script/script.h#L26
7+
pub const MAX_OPS_PER_SCRIPT: usize = 201;
8+
/// Maximum p2wsh initial stack items
9+
// https://github.com/bitcoin/bitcoin/blob/875e1ccc9fe01e026e564dfd39a64d9a4b332a89/src/policy/policy.h#L40
10+
pub const MAX_STANDARD_P2WSH_STACK_ITEMS: usize = 100;
11+
/// Maximum script size allowed by consensus rules
12+
// https://github.com/bitcoin/bitcoin/blob/42b66a6b814bca130a9ccf0a3f747cf33d628232/src/script/script.h#L32
13+
pub const MAX_SCRIPT_SIZE: usize = 10_000;
14+
/// Maximum script size allowed by standardness rules
15+
// https://github.com/bitcoin/bitcoin/blob/283a73d7eaea2907a6f7f800f529a0d6db53d7a6/src/policy/policy.h#L44
16+
pub const MAX_STANDARD_P2WSH_SCRIPT_SIZE: usize = 3600;
17+
/// The Threshold for deciding whether `nLockTime` is interpreted as
18+
/// time or height.
19+
// https://github.com/bitcoin/bitcoin/blob/9ccaee1d5e2e4b79b0a7c29aadb41b97e4741332/src/script/script.h#L39
20+
pub const HEIGHT_TIME_THRESHOLD: u32 = 500_000_000;
21+
22+
/// Bit flag for deciding whether sequence number is
23+
/// interpreted as height or time
24+
/* If nSequence encodes a relative lock-time and this flag
25+
* is set, the relative lock-time has units of 512 seconds,
26+
* otherwise it specifies blocks with a granularity of 1. */
27+
// https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
28+
pub const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 1 << 22;
29+
30+
/// Disable flag for sequence locktime
31+
/* Below flags apply in the context of BIP 68*/
32+
/* If this flag set, nSequence is NOT interpreted as a
33+
* relative lock-time. For future soft-fork compatibility*/
34+
// https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
35+
pub const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1 << 31;
36+
37+
/// Maximum script element size allowed by consensus rules
38+
// https://github.com/bitcoin/bitcoin/blob/42b66a6b814bca130a9ccf0a3f747cf33d628232/src/script/script.h#L23
39+
pub const MAX_SCRIPT_ELEMENT_SIZE: usize = 520;
40+
/// Maximum script sig size allowed by standardness rules
41+
// https://github.com/bitcoin/bitcoin/blob/42b66a6b814bca130a9ccf0a3f747cf33d628232/src/policy/policy.cpp#L102
42+
pub const MAX_SCRIPTSIG_SIZE: usize = 1650;

src/miniscript/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub(crate) mod context;
3838
pub mod decode;
3939
pub mod iter;
4040
pub mod lex;
41+
pub mod limits;
4142
pub mod satisfy;
4243
pub mod types;
4344

src/miniscript/satisfy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d};
2626
use bitcoin::{self, secp256k1};
2727
use {MiniscriptKey, ToPublicKey};
2828

29-
use miniscript::types::extra_props::{
29+
use miniscript::limits::{
3030
HEIGHT_TIME_THRESHOLD, SEQUENCE_LOCKTIME_DISABLE_FLAG, SEQUENCE_LOCKTIME_TYPE_FLAG,
3131
};
3232
use util::witness_size;

src/miniscript/types/extra_props.rs

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,15 @@
11
//! Other miscellaneous type properties which are not related to
22
//! correctness or malleability.
33
4+
use miniscript::limits::{HEIGHT_TIME_THRESHOLD, SEQUENCE_LOCKTIME_TYPE_FLAG};
5+
46
use super::{Error, ErrorKind, Property, ScriptContext};
57
use script_num_size;
68
use std::cmp;
79
use std::iter::once;
810
use MiniscriptKey;
911
use Terminal;
1012

11-
/// Maximum operations per script
12-
// https://github.com/bitcoin/bitcoin/blob/875e1ccc9fe01e026e564dfd39a64d9a4b332a89/src/script/script.h#L26
13-
pub const MAX_OPS_PER_SCRIPT: usize = 201;
14-
/// Maximum p2wsh initial stack items
15-
// https://github.com/bitcoin/bitcoin/blob/875e1ccc9fe01e026e564dfd39a64d9a4b332a89/src/policy/policy.h#L40
16-
pub const MAX_STANDARD_P2WSH_STACK_ITEMS: usize = 100;
17-
/// Maximum script size allowed by consensus rules
18-
// https://github.com/bitcoin/bitcoin/blob/42b66a6b814bca130a9ccf0a3f747cf33d628232/src/script/script.h#L32
19-
pub const MAX_SCRIPT_SIZE: usize = 10_000;
20-
/// Maximum script size allowed by standardness rules
21-
// https://github.com/bitcoin/bitcoin/blob/283a73d7eaea2907a6f7f800f529a0d6db53d7a6/src/policy/policy.h#L44
22-
pub const MAX_STANDARD_P2WSH_SCRIPT_SIZE: usize = 3600;
23-
/// The Threshold for deciding whether `nLockTime` is interpreted as
24-
/// time or height.
25-
// https://github.com/bitcoin/bitcoin/blob/9ccaee1d5e2e4b79b0a7c29aadb41b97e4741332/src/script/script.h#L39
26-
pub const HEIGHT_TIME_THRESHOLD: u32 = 500_000_000;
27-
28-
/// Bit flag for deciding whether sequence number is
29-
/// interpreted as height or time
30-
/* If nSequence encodes a relative lock-time and this flag
31-
* is set, the relative lock-time has units of 512 seconds,
32-
* otherwise it specifies blocks with a granularity of 1. */
33-
// https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
34-
pub const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 1 << 22;
35-
36-
/// Disable flag for sequence locktime
37-
/* Below flags apply in the context of BIP 68*/
38-
/* If this flag set, nSequence is NOT interpreted as a
39-
* relative lock-time. For future soft-fork compatibility*/
40-
// https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
41-
pub const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1 << 31;
42-
43-
/// Maximum script element size allowed by consensus rules
44-
// https://github.com/bitcoin/bitcoin/blob/42b66a6b814bca130a9ccf0a3f747cf33d628232/src/script/script.h#L23
45-
pub const MAX_SCRIPT_ELEMENT_SIZE: usize = 520;
46-
/// Maximum script sig size allowed by standardness rules
47-
// https://github.com/bitcoin/bitcoin/blob/42b66a6b814bca130a9ccf0a3f747cf33d628232/src/policy/policy.cpp#L102
48-
pub const MAX_SCRIPTSIG_SIZE: usize = 1650;
4913
/// Helper struct Whether any satisfaction of this fragment contains any timelocks
5014
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
5115
pub struct TimeLockInfo {

src/policy/concrete.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ use std::{error, fmt, str};
2323
use super::ENTAILMENT_MAX_TERMINALS;
2424
use errstr;
2525
use expression::{self, FromTree};
26-
use miniscript::types::extra_props::{
27-
TimeLockInfo, HEIGHT_TIME_THRESHOLD, SEQUENCE_LOCKTIME_TYPE_FLAG,
28-
};
26+
use miniscript::limits::{HEIGHT_TIME_THRESHOLD, SEQUENCE_LOCKTIME_TYPE_FLAG};
27+
use miniscript::types::extra_props::TimeLockInfo;
2928
#[cfg(feature = "compiler")]
3029
use miniscript::ScriptContext;
3130
#[cfg(feature = "compiler")]

src/psbt/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
2727
use bitcoin::Script;
2828

2929
use interpreter;
30+
use miniscript::limits::SEQUENCE_LOCKTIME_DISABLE_FLAG;
3031
use miniscript::satisfy::{bitcoinsig_from_rawsig, After, Older};
31-
use miniscript::types::extra_props::SEQUENCE_LOCKTIME_DISABLE_FLAG;
3232
use BitcoinSig;
3333
use Satisfier;
3434
use {MiniscriptKey, ToPublicKey};

0 commit comments

Comments
 (0)