Skip to content

Commit 8887663

Browse files
committed
Merge #246: miniscript/types: check that timelock values aren't too large
a3dd9fe miniscript/types: check that timelock values aren't too large (Antoine Poinsot) Pull request description: Wonder if we should check that the timelock value is minimal too, what do you think? ACKs for top commit: sanket1729: utACK a3dd9fe . Thanks for doing this. apoelstra: ACK a3dd9fe Tree-SHA512: 900c4de066581a0aa3137349c75336c30bc2b70239f47d5dab4ce2b1b33fb40428ce27837916767e51c03a1340c3f86cec036825e5da277216b892cbdbfb54a2
2 parents 7d33643 + a3dd9fe commit 8887663

File tree

2 files changed

+29
-21
lines changed

2 files changed

+29
-21
lines changed

src/miniscript/types/extra_props.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
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};
4+
use miniscript::limits::{
5+
HEIGHT_TIME_THRESHOLD, SEQUENCE_LOCKTIME_DISABLE_FLAG, SEQUENCE_LOCKTIME_TYPE_FLAG,
6+
};
57

68
use super::{Error, ErrorKind, Property, ScriptContext};
79
use script_num_size;
@@ -851,20 +853,22 @@ impl Property for ExtData {
851853
Ok(Self::from_multi(k, pks.len()))
852854
}
853855
Terminal::After(t) => {
854-
// FIXME check if t > 2^31 - 1
855-
if t == 0 {
856+
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The
857+
// number on the stack would be a 5 bytes signed integer but Miniscript's B type
858+
// only consumes 4 bytes from the stack.
859+
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) == 1 {
856860
return Err(Error {
857861
fragment: fragment.clone(),
858-
error: ErrorKind::ZeroTime,
862+
error: ErrorKind::InvalidTime,
859863
});
860864
}
861865
Ok(Self::from_after(t))
862866
}
863867
Terminal::Older(t) => {
864-
if t == 0 {
868+
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) == 1 {
865869
return Err(Error {
866870
fragment: fragment.clone(),
867-
error: ErrorKind::ZeroTime,
871+
error: ErrorKind::InvalidTime,
868872
});
869873
}
870874
Ok(Self::from_older(t))

src/miniscript/types/mod.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use std::{error, fmt};
2525
pub use self::correctness::{Base, Correctness, Input};
2626
pub use self::extra_props::ExtData;
2727
pub use self::malleability::{Dissat, Malleability};
28-
use super::ScriptContext;
28+
use super::{limits::SEQUENCE_LOCKTIME_DISABLE_FLAG, ScriptContext};
2929
use MiniscriptKey;
3030
use Terminal;
3131

@@ -38,8 +38,8 @@ fn return_none<T>(_: usize) -> Option<T> {
3838
/// Detailed type of a typechecker error
3939
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
4040
pub enum ErrorKind {
41-
/// Relative or absolute timelock had a time value of 0
42-
ZeroTime,
41+
/// Relative or absolute timelock had an invalid time value (either 0, or >=0x80000000)
42+
InvalidTime,
4343
/// Passed a `z` argument to a `d` wrapper when `z` was expected
4444
NonZeroDupIf,
4545
/// Multisignature or threshold policy had a `k` value of 0
@@ -117,9 +117,9 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> error::Error for Error<Pk, Ctx> {
117117
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Error<Pk, Ctx> {
118118
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119119
match self.error {
120-
ErrorKind::ZeroTime => write!(
120+
ErrorKind::InvalidTime => write!(
121121
f,
122-
"fragment «{}» represents a 0-valued timelock (use `1` instead)",
122+
"fragment «{}» represents a timelock which value is invalid (time must be in [1; 0x80000000])",
123123
self.fragment,
124124
),
125125
ErrorKind::NonZeroDupIf => write!(
@@ -426,20 +426,22 @@ pub trait Property: Sized {
426426
Ok(Self::from_multi(k, pks.len()))
427427
}
428428
Terminal::After(t) => {
429-
if t == 0 {
429+
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The
430+
// number on the stack would be a 5 bytes signed integer but Miniscript's B type
431+
// only consumes 4 bytes from the stack.
432+
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) == 1 {
430433
return Err(Error {
431434
fragment: fragment.clone(),
432-
error: ErrorKind::ZeroTime,
435+
error: ErrorKind::InvalidTime,
433436
});
434437
}
435438
Ok(Self::from_after(t))
436439
}
437440
Terminal::Older(t) => {
438-
// FIXME check if t > 2^31 - 1
439-
if t == 0 {
441+
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) == 1 {
440442
return Err(Error {
441443
fragment: fragment.clone(),
442-
error: ErrorKind::ZeroTime,
444+
error: ErrorKind::InvalidTime,
443445
});
444446
}
445447
Ok(Self::from_older(t))
@@ -803,20 +805,22 @@ impl Property for Type {
803805
Ok(Self::from_multi(k, pks.len()))
804806
}
805807
Terminal::After(t) => {
806-
// FIXME check if t > 2^31 - 1
807-
if t == 0 {
808+
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The
809+
// number on the stack would be a 5 bytes signed integer but Miniscript's B type
810+
// only consumes 4 bytes from the stack.
811+
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) == 1 {
808812
return Err(Error {
809813
fragment: fragment.clone(),
810-
error: ErrorKind::ZeroTime,
814+
error: ErrorKind::InvalidTime,
811815
});
812816
}
813817
Ok(Self::from_after(t))
814818
}
815819
Terminal::Older(t) => {
816-
if t == 0 {
820+
if t == 0 || (t & SEQUENCE_LOCKTIME_DISABLE_FLAG) == 1 {
817821
return Err(Error {
818822
fragment: fragment.clone(),
819-
error: ErrorKind::ZeroTime,
823+
error: ErrorKind::InvalidTime,
820824
});
821825
}
822826
Ok(Self::from_older(t))

0 commit comments

Comments
 (0)