Skip to content

Commit a332ad9

Browse files
committed
Use the new relative::LockTime module
Implement `check_older` using the new `relative::LockTime` API. This code seems upside down, I'm not sure I have the naming correct, i.e., I don't know which (`self` or arg) is doing the satisfying and which is satisfied? I believe the `<=` are going the correct direction, its the naming and which sequence value to call the 'lock' that I'm struggling with.
1 parent 93b7749 commit a332ad9

File tree

15 files changed

+110
-120
lines changed

15 files changed

+110
-120
lines changed

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,23 @@ compiler = []
1818
trace = []
1919

2020
unstable = []
21-
serde = ["actual-serde", "bitcoin/use-serde"]
21+
serde = ["actual-serde", "bitcoin/serde"]
2222
rand = ["bitcoin/rand"]
2323

2424
[dependencies]
25-
bitcoin = { version = "0.29.0", default-features = false }
25+
bitcoin = { path = "/home/tobin/build/github.com/tcharding/rust-bitcoin", default-features = false }
2626
hashbrown = { version = "0.11", optional = true }
2727

2828
# Do NOT use this as a feature! Use the `serde` feature instead.
2929
actual-serde = { package = "serde", version = "1.0", optional = true }
3030

3131

3232
[dev-dependencies]
33-
bitcoind = { git = "https://github.com/tcharding/bitcoind", branch = "dev-build", features=["22_0"] }
33+
bitcoind = { path = "/home/tobin/build/github.com/tcharding/bitcoind", features=["22_0"] }
3434
actual-rand = { package = "rand", version = "0.8.4"}
3535
secp256k1 = {version = "0.24.0", features = ["rand-std"]}
36-
bitcoin = { version = "0.29.0", features = ["rand"] }
36+
bitcoin = { path = "/home/tobin/build/github.com/tcharding/rust-bitcoin", features = ["rand"] }
37+
3738

3839
[[example]]
3940
name = "htlc"

examples/sign_multisig.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::collections::HashMap;
1818
use std::str::FromStr;
1919

2020
use bitcoin::blockdata::witness::Witness;
21-
use bitcoin::{secp256k1, PackedLockTime, Sequence};
21+
use bitcoin::{secp256k1, absolute, Sequence};
2222

2323
fn main() {
2424
let mut tx = spending_transaction();
@@ -91,7 +91,7 @@ fn main() {
9191
fn spending_transaction() -> bitcoin::Transaction {
9292
bitcoin::Transaction {
9393
version: 2,
94-
lock_time: PackedLockTime::ZERO,
94+
lock_time: absolute::PackedLockTime::ZERO,
9595
input: vec![bitcoin::TxIn {
9696
previous_output: Default::default(),
9797
script_sig: bitcoin::Script::new(),

examples/verify_tx.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::str::FromStr;
1919
use bitcoin::consensus::Decodable;
2020
use bitcoin::secp256k1::{self, Secp256k1};
2121
use bitcoin::util::sighash;
22-
use bitcoin::{LockTime, Sequence};
22+
use bitcoin::{absolute, Sequence};
2323
use miniscript::interpreter::KeySigPair;
2424

2525
fn main() {
@@ -35,7 +35,7 @@ fn main() {
3535
&tx.input[0].script_sig,
3636
&tx.input[0].witness,
3737
Sequence::ZERO,
38-
LockTime::ZERO,
38+
absolute::LockTime::ZERO,
3939
)
4040
.unwrap();
4141

src/interpreter/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use core::str::FromStr;
2525
use bitcoin::blockdata::witness::Witness;
2626
use bitcoin::hashes::{hash160, ripemd160, sha256};
2727
use bitcoin::util::{sighash, taproot};
28-
use bitcoin::{self, secp256k1, LockTime, Sequence, TxOut};
28+
use bitcoin::{self, secp256k1, absolute, Sequence, TxOut};
2929

3030
use crate::miniscript::context::NoChecks;
3131
use crate::miniscript::ScriptContext;
@@ -49,7 +49,7 @@ pub struct Interpreter<'txin> {
4949
/// is the leaf script; for key-spends it is `None`.
5050
script_code: Option<bitcoin::Script>,
5151
age: Sequence,
52-
lock_time: LockTime,
52+
lock_time: absolute::LockTime,
5353
}
5454

5555
// A type representing functions for checking signatures that accept both
@@ -174,7 +174,7 @@ impl<'txin> Interpreter<'txin> {
174174
script_sig: &'txin bitcoin::Script,
175175
witness: &'txin Witness,
176176
age: Sequence, // CSV, relative lock time.
177-
lock_time: LockTime, // CLTV, absolute lock time.
177+
lock_time: absolute::LockTime, // CLTV, absolute lock time.
178178
) -> Result<Self, Error> {
179179
let (inner, stack, script_code) = inner::from_txdata(spk, script_sig, witness)?;
180180
Ok(Interpreter {
@@ -496,7 +496,7 @@ pub enum SatisfiedConstraint {
496496
///Absolute Timelock for CLTV.
497497
AbsoluteTimelock {
498498
/// The value of Absolute timelock
499-
n: LockTime,
499+
n: absolute::LockTime,
500500
},
501501
}
502502

@@ -532,7 +532,7 @@ pub struct Iter<'intp, 'txin: 'intp> {
532532
state: Vec<NodeEvaluationState<'intp>>,
533533
stack: Stack<'txin>,
534534
age: Sequence,
535-
lock_time: LockTime,
535+
lock_time: absolute::LockTime,
536536
has_errored: bool,
537537
}
538538

@@ -1146,7 +1146,7 @@ mod tests {
11461146
n_satisfied: 0,
11471147
}],
11481148
age: Sequence::from_height(1002),
1149-
lock_time: LockTime::from_height(1002).unwrap(),
1149+
lock_time: absolute::LockTime::from_height(1002).unwrap(),
11501150
has_errored: false,
11511151
}
11521152
}
@@ -1210,7 +1210,7 @@ mod tests {
12101210
assert_eq!(
12111211
after_satisfied.unwrap(),
12121212
vec![SatisfiedConstraint::AbsoluteTimelock {
1213-
n: LockTime::from_height(1000).unwrap()
1213+
n: absolute::LockTime::from_height(1000).unwrap()
12141214
}]
12151215
);
12161216

src/interpreter/stack.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use bitcoin;
1818
use bitcoin::blockdata::{opcodes, script};
1919
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
20-
use bitcoin::{LockTime, Sequence};
20+
use bitcoin::{absolute, Sequence};
2121

2222
use super::error::PkEvalErrInner;
2323
use super::{
@@ -231,10 +231,10 @@ impl<'txin> Stack<'txin> {
231231
/// booleans
232232
pub(super) fn evaluate_after(
233233
&mut self,
234-
n: &LockTime,
235-
lock_time: LockTime,
234+
n: &absolute::LockTime,
235+
lock_time: absolute::LockTime,
236236
) -> Option<Result<SatisfiedConstraint, Error>> {
237-
use LockTime::*;
237+
use absolute::LockTime::*;
238238

239239
let is_satisfied = match (*n, lock_time) {
240240
(Blocks(n), Blocks(lock_time)) => n <= lock_time,

src/miniscript/astelem.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use core::fmt;
2323
use core::str::FromStr;
2424

2525
use bitcoin::blockdata::{opcodes, script};
26-
use bitcoin::{LockTime, Sequence};
26+
use bitcoin::{absolute, Sequence};
2727
use sync::Arc;
2828

2929
use crate::miniscript::context::SigType;
@@ -460,7 +460,7 @@ impl_from_tree!(
460460
}
461461
("pk_h", 1) => expression::terminal(&top.args[0], |x| Pk::from_str(x).map(Terminal::PkH)),
462462
("after", 1) => expression::terminal(&top.args[0], |x| {
463-
expression::parse_num(x).map(|x| Terminal::After(LockTime::from_consensus(x).into()))
463+
expression::parse_num(x).map(|x| Terminal::After(absolute::LockTime::from_consensus(x).into()))
464464
}),
465465
("older", 1) => expression::terminal(&top.args[0], |x| {
466466
expression::parse_num(x).map(|x| Terminal::Older(Sequence::from_consensus(x)))

src/miniscript/decode.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT;
2626
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
2727
use sync::Arc;
2828

29-
use crate::bitcoin::{LockTime, PackedLockTime, Sequence};
29+
use crate::bitcoin::{absolute, Sequence};
3030
use crate::miniscript::lex::{Token as Tk, TokenIter};
3131
use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
3232
use crate::miniscript::types::extra_props::ExtData;
@@ -140,7 +140,7 @@ pub enum Terminal<Pk: MiniscriptKey, Ctx: ScriptContext> {
140140
RawPkH(Pk::RawPkHash),
141141
// timelocks
142142
/// `n CHECKLOCKTIMEVERIFY`
143-
After(PackedLockTime),
143+
After(absolute::PackedLockTime),
144144
/// `n CHECKSEQUENCEVERIFY`
145145
Older(Sequence),
146146
// hashlocks
@@ -395,7 +395,7 @@ pub fn parse<Ctx: ScriptContext>(
395395
Tk::CheckSequenceVerify, Tk::Num(n)
396396
=> term.reduce0(Terminal::Older(Sequence::from_consensus(n)))?,
397397
Tk::CheckLockTimeVerify, Tk::Num(n)
398-
=> term.reduce0(Terminal::After(LockTime::from_consensus(n).into()))?,
398+
=> term.reduce0(Terminal::After(absolute::LockTime::from_consensus(n).into()))?,
399399
// hashlocks
400400
Tk::Equal => match_token!(
401401
tokens,

src/miniscript/satisfy.rs

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use core::{cmp, i64, mem};
2222

2323
use bitcoin::secp256k1::XOnlyPublicKey;
2424
use bitcoin::util::taproot::{ControlBlock, LeafVersion, TapLeafHash};
25-
use bitcoin::{LockTime, Sequence};
25+
use bitcoin::{absolute, relative, Sequence};
2626
use sync::Arc;
2727

2828
use crate::prelude::*;
@@ -106,12 +106,12 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
106106
}
107107

108108
/// Assert whether an relative locktime is satisfied
109-
fn check_older(&self, _: Sequence) -> bool {
109+
fn check_older(&self, _: relative::LockTime) -> bool {
110110
false
111111
}
112112

113113
/// Assert whether a absolute locktime is satisfied
114-
fn check_after(&self, _: LockTime) -> bool {
114+
fn check_after(&self, _: absolute::LockTime) -> bool {
115115
false
116116
}
117117
}
@@ -120,32 +120,17 @@ pub trait Satisfier<Pk: MiniscriptKey + ToPublicKey> {
120120
impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for () {}
121121

122122
impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for Sequence {
123-
fn check_older(&self, n: Sequence) -> bool {
124-
if !self.is_relative_lock_time() {
125-
return false;
126-
}
127-
128-
// We need a relative lock time type in rust-bitcoin to clean this up.
129-
130-
/* If nSequence encodes a relative lock-time, this mask is
131-
* applied to extract that lock-time from the sequence field. */
132-
const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000ffff;
133-
const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 0x00400000;
134-
135-
let mask = SEQUENCE_LOCKTIME_MASK | SEQUENCE_LOCKTIME_TYPE_FLAG;
136-
let masked_n = n.to_consensus_u32() & mask;
137-
let masked_seq = self.to_consensus_u32() & mask;
138-
if masked_n < SEQUENCE_LOCKTIME_TYPE_FLAG && masked_seq >= SEQUENCE_LOCKTIME_TYPE_FLAG {
139-
false
140-
} else {
141-
masked_n <= masked_seq
123+
fn check_older(&self, n: relative::LockTime) -> bool {
124+
match self.to_relative_lock_time() {
125+
None => false,
126+
Some(lock_time) => n.is_satisfied_by(lock_time),
142127
}
143128
}
144129
}
145130

146-
impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for LockTime {
147-
fn check_after(&self, n: LockTime) -> bool {
148-
use LockTime::*;
131+
impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for absolute::LockTime {
132+
fn check_after(&self, n: absolute::LockTime) -> bool {
133+
use absolute::LockTime::*;
149134

150135
match (n, *self) {
151136
(Blocks(n), Blocks(lock_time)) => n <= lock_time,
@@ -265,11 +250,11 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
265250
(**self).lookup_hash160(h)
266251
}
267252

268-
fn check_older(&self, t: Sequence) -> bool {
253+
fn check_older(&self, t: relative::LockTime) -> bool {
269254
(**self).check_older(t)
270255
}
271256

272-
fn check_after(&self, n: LockTime) -> bool {
257+
fn check_after(&self, n: absolute::LockTime) -> bool {
273258
(**self).check_after(n)
274259
}
275260
}
@@ -327,11 +312,11 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier<Pk>> Satisfier<Pk> for &'
327312
(**self).lookup_hash160(h)
328313
}
329314

330-
fn check_older(&self, t: Sequence) -> bool {
315+
fn check_older(&self, t: relative::LockTime) -> bool {
331316
(**self).check_older(t)
332317
}
333318

334-
fn check_after(&self, n: LockTime) -> bool {
319+
fn check_after(&self, n: absolute::LockTime) -> bool {
335320
(**self).check_after(n)
336321
}
337322
}
@@ -465,7 +450,7 @@ macro_rules! impl_tuple_satisfier {
465450
None
466451
}
467452

468-
fn check_older(&self, n: Sequence) -> bool {
453+
fn check_older(&self, n: relative::LockTime) -> bool {
469454
let &($(ref $ty,)*) = self;
470455
$(
471456
if $ty.check_older(n) {
@@ -475,7 +460,7 @@ macro_rules! impl_tuple_satisfier {
475460
false
476461
}
477462

478-
fn check_after(&self, n: LockTime) -> bool {
463+
fn check_after(&self, n: absolute::LockTime) -> bool {
479464
let &($(ref $ty,)*) = self;
480465
$(
481466
if $ty.check_after(n) {
@@ -953,21 +938,31 @@ impl Satisfaction {
953938
},
954939
has_sig: false,
955940
},
956-
Terminal::Older(t) => Satisfaction {
957-
stack: if stfr.check_older(t) {
958-
Witness::empty()
959-
} else if root_has_sig {
960-
// If the root terminal has signature, the
961-
// signature covers the nLockTime and nSequence
962-
// values. The sender of the transaction should
963-
// take care that it signs the value such that the
964-
// timelock is not met
965-
Witness::Impossible
966-
} else {
967-
Witness::Unavailable
968-
},
941+
Terminal::Older(t) => {
942+
let older = {
943+
match t.to_relative_lock_time() {
944+
// https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
945+
// Disable flag set => return true.
946+
None => true,
947+
Some(lock) => stfr.check_older(lock),
948+
}
949+
};
950+
Satisfaction {
951+
stack: if older {
952+
Witness::empty()
953+
} else if root_has_sig {
954+
// If the root terminal has signature, the
955+
// signature covers the nLockTime and nSequence
956+
// values. The sender of the transaction should
957+
// take care that it signs the value such that the
958+
// timelock is not met
959+
Witness::Impossible
960+
} else {
961+
Witness::Unavailable
962+
},
969963

970-
has_sig: false,
964+
has_sig: false,
965+
}
971966
},
972967
Terminal::Ripemd160(ref h) => Satisfaction {
973968
stack: Witness::ripemd160_preimage(stfr, h),

src/miniscript/types/extra_props.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use core::cmp;
55
use core::iter::once;
66

7-
use bitcoin::{LockTime, PackedLockTime, Sequence};
7+
use bitcoin::{absolute, Sequence};
88

99
use super::{Error, ErrorKind, Property, ScriptContext};
1010
use crate::miniscript::context::SigType;
@@ -337,7 +337,7 @@ impl Property for ExtData {
337337
unreachable!()
338338
}
339339

340-
fn from_after(t: LockTime) -> Self {
340+
fn from_after(t: absolute::LockTime) -> Self {
341341
ExtData {
342342
pk_cost: script_num_size(t.to_consensus_u32() as usize) + 1,
343343
has_free_verify: false,
@@ -933,7 +933,7 @@ impl Property for ExtData {
933933
// Note that for CLTV this is a limitation not of Bitcoin but Miniscript. The
934934
// number on the stack would be a 5 bytes signed integer but Miniscript's B type
935935
// only consumes 4 bytes from the stack.
936-
if t == PackedLockTime::ZERO {
936+
if t == absolute::PackedLockTime::ZERO {
937937
return Err(Error {
938938
fragment: fragment.clone(),
939939
error: ErrorKind::InvalidTime,

0 commit comments

Comments
 (0)