Skip to content

Commit c80aa7c

Browse files
committed
Merge #424: Fix up mixup of age/height
fec8014 Use lock_time instead of height (Tobin C. Harding) 3d76d02 Pass correct fields to evaluate_[after|older] (Tobin C. Harding) b9c9d5b Re-name function parameter to 'age' (Tobin C. Harding) bfd6991 Re-name function at_height -> at_lock_time (Tobin C. Harding) bb091eb Use correct parameter call order (Tobin C. Harding) Pull request description: We currently use age/height as identifiers for values related to CLTV and CSV. However we get them mixed up in the function call to `from_txdata`. Do a few improvements to fix the mixup and improve the overall situation. - Patch 2 is a breaking change, changes a public method name. - Patch 1 an 4 are bug fixes. (This description and PR are totally re-written, the comment directly below is now stale.) ACKs for top commit: apoelstra: ACK fec8014 sanket1729: utACK fec8014 Tree-SHA512: fd116b3595bad9a5523e9e38ef4ca8d0df370629115893ee04bb0e42e061ea60d4dbc2f77b128bef4e016300f44b8e20d15013f24faa25b93a205556fc6df873
2 parents 98ee329 + fec8014 commit c80aa7c

File tree

4 files changed

+48
-39
lines changed

4 files changed

+48
-39
lines changed

src/interpreter/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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: u32,
52-
height: u32,
52+
lock_time: u32,
5353
}
5454

5555
// A type representing functions for checking signatures that accept both
@@ -170,16 +170,16 @@ impl<'txin> Interpreter<'txin> {
170170
spk: &bitcoin::Script,
171171
script_sig: &'txin bitcoin::Script,
172172
witness: &'txin Witness,
173-
age: u32,
174-
height: u32,
173+
age: u32, // CSV, relative lock time.
174+
lock_time: u32, // CLTV, absolute lock time.
175175
) -> Result<Self, Error> {
176176
let (inner, stack, script_code) = inner::from_txdata(spk, script_sig, witness)?;
177177
Ok(Interpreter {
178178
inner,
179179
stack,
180180
script_code,
181181
age,
182-
height,
182+
lock_time,
183183
})
184184
}
185185

@@ -210,7 +210,7 @@ impl<'txin> Interpreter<'txin> {
210210
// call interpreter.iter() without mutating interpreter
211211
stack: self.stack.clone(),
212212
age: self.age,
213-
height: self.height,
213+
lock_time: self.lock_time,
214214
has_errored: false,
215215
}
216216
}
@@ -529,7 +529,7 @@ pub struct Iter<'intp, 'txin: 'intp> {
529529
state: Vec<NodeEvaluationState<'intp>>,
530530
stack: Stack<'txin>,
531531
age: u32,
532-
height: u32,
532+
lock_time: u32,
533533
has_errored: bool,
534534
}
535535

@@ -606,15 +606,15 @@ where
606606
Terminal::After(ref n) => {
607607
debug_assert_eq!(node_state.n_evaluated, 0);
608608
debug_assert_eq!(node_state.n_satisfied, 0);
609-
let res = self.stack.evaluate_after(n, self.age);
609+
let res = self.stack.evaluate_after(n, self.lock_time);
610610
if res.is_some() {
611611
return res;
612612
}
613613
}
614614
Terminal::Older(ref n) => {
615615
debug_assert_eq!(node_state.n_evaluated, 0);
616616
debug_assert_eq!(node_state.n_satisfied, 0);
617-
let res = self.stack.evaluate_older(n, self.height);
617+
let res = self.stack.evaluate_older(n, self.age);
618618
if res.is_some() {
619619
return res;
620620
}
@@ -1132,7 +1132,7 @@ mod tests {
11321132
n_satisfied: 0,
11331133
}],
11341134
age: 1002,
1135-
height: 1002,
1135+
lock_time: 1002,
11361136
has_errored: false,
11371137
}
11381138
}

src/interpreter/stack.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,9 @@ impl<'txin> Stack<'txin> {
232232
pub(super) fn evaluate_after(
233233
&mut self,
234234
n: &u32,
235-
age: u32,
235+
lock_time: u32,
236236
) -> Option<Result<SatisfiedConstraint, Error>> {
237-
if age >= *n {
237+
if lock_time >= *n {
238238
self.push(Element::Satisfied);
239239
Some(Ok(SatisfiedConstraint::AbsoluteTimelock { time: *n }))
240240
} else {
@@ -251,9 +251,9 @@ impl<'txin> Stack<'txin> {
251251
pub(super) fn evaluate_older(
252252
&mut self,
253253
n: &u32,
254-
height: u32,
254+
age: u32,
255255
) -> Option<Result<SatisfiedConstraint, Error>> {
256-
if height >= *n {
256+
if age >= *n {
257257
self.push(Element::Satisfied);
258258
Some(Ok(SatisfiedConstraint::RelativeTimelock { time: *n }))
259259
} else {

src/policy/semantic.rs

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -538,39 +538,39 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
538538
}
539539

540540
/// Filter a policy by eliminating relative timelock constraints
541-
/// that are not satisfied at the given age.
542-
pub fn at_age(mut self, time: u32) -> Policy<Pk> {
541+
/// that are not satisfied at the given `age`.
542+
pub fn at_age(mut self, age: u32) -> Policy<Pk> {
543543
self = match self {
544544
Policy::Older(t) => {
545-
if t > time {
545+
if t > age {
546546
Policy::Unsatisfiable
547547
} else {
548548
Policy::Older(t)
549549
}
550550
}
551551
Policy::Threshold(k, subs) => {
552-
Policy::Threshold(k, subs.into_iter().map(|sub| sub.at_age(time)).collect())
552+
Policy::Threshold(k, subs.into_iter().map(|sub| sub.at_age(age)).collect())
553553
}
554554
x => x,
555555
};
556556
self.normalized()
557557
}
558558

559559
/// Filter a policy by eliminating absolute timelock constraints
560-
/// that are not satisfied at the given age.
561-
pub fn at_height(mut self, time: u32) -> Policy<Pk> {
560+
/// that are not satisfied at the given `n` (`n OP_CHECKLOCKTIMEVERIFY`).
561+
pub fn at_lock_time(mut self, n: u32) -> Policy<Pk> {
562562
self = match self {
563563
Policy::After(t) => {
564-
if !timelock::absolute_timelocks_are_same_unit(t, time) {
564+
if !timelock::absolute_timelocks_are_same_unit(t, n) {
565565
Policy::Unsatisfiable
566-
} else if t > time {
566+
} else if t > n {
567567
Policy::Unsatisfiable
568568
} else {
569569
Policy::After(t)
570570
}
571571
}
572572
Policy::Threshold(k, subs) => {
573-
Policy::Threshold(k, subs.into_iter().map(|sub| sub.at_height(time)).collect())
573+
Policy::Threshold(k, subs.into_iter().map(|sub| sub.at_lock_time(n)).collect())
574574
}
575575
x => x,
576576
};
@@ -787,12 +787,15 @@ mod tests {
787787
assert_eq!(policy, Policy::After(1000));
788788
assert_eq!(policy.absolute_timelocks(), vec![1000]);
789789
assert_eq!(policy.relative_timelocks(), vec![]);
790-
assert_eq!(policy.clone().at_height(0), Policy::Unsatisfiable);
791-
assert_eq!(policy.clone().at_height(999), Policy::Unsatisfiable);
792-
assert_eq!(policy.clone().at_height(1000), policy.clone());
793-
assert_eq!(policy.clone().at_height(10000), policy.clone());
794-
// Pass a UNIX timestamp to at_height while policy uses a block height.
795-
assert_eq!(policy.clone().at_height(500_000_001), Policy::Unsatisfiable);
790+
assert_eq!(policy.clone().at_lock_time(0), Policy::Unsatisfiable);
791+
assert_eq!(policy.clone().at_lock_time(999), Policy::Unsatisfiable);
792+
assert_eq!(policy.clone().at_lock_time(1000), policy.clone());
793+
assert_eq!(policy.clone().at_lock_time(10000), policy.clone());
794+
// Pass a UNIX timestamp to at_lock_time while policy uses a block height.
795+
assert_eq!(
796+
policy.clone().at_lock_time(500_000_001),
797+
Policy::Unsatisfiable
798+
);
796799
assert_eq!(policy.n_keys(), 0);
797800
assert_eq!(policy.minimum_n_keys(), Some(0));
798801

@@ -801,16 +804,22 @@ mod tests {
801804
assert_eq!(policy, Policy::After(500_000_010));
802805
assert_eq!(policy.absolute_timelocks(), vec![500_000_010]);
803806
assert_eq!(policy.relative_timelocks(), vec![]);
804-
// Pass a block height to at_height while policy uses a UNIX timestapm.
805-
assert_eq!(policy.clone().at_height(0), Policy::Unsatisfiable);
806-
assert_eq!(policy.clone().at_height(999), Policy::Unsatisfiable);
807-
assert_eq!(policy.clone().at_height(1000), Policy::Unsatisfiable);
808-
assert_eq!(policy.clone().at_height(10000), Policy::Unsatisfiable);
809-
// And now pass a UNIX timestamp to at_height while policy also uses a timestamp.
810-
assert_eq!(policy.clone().at_height(500_000_000), Policy::Unsatisfiable);
811-
assert_eq!(policy.clone().at_height(500_000_001), Policy::Unsatisfiable);
812-
assert_eq!(policy.clone().at_height(500_000_010), policy.clone());
813-
assert_eq!(policy.clone().at_height(500_000_012), policy.clone());
807+
// Pass a block height to at_lock_time while policy uses a UNIX timestapm.
808+
assert_eq!(policy.clone().at_lock_time(0), Policy::Unsatisfiable);
809+
assert_eq!(policy.clone().at_lock_time(999), Policy::Unsatisfiable);
810+
assert_eq!(policy.clone().at_lock_time(1000), Policy::Unsatisfiable);
811+
assert_eq!(policy.clone().at_lock_time(10000), Policy::Unsatisfiable);
812+
// And now pass a UNIX timestamp to at_lock_time while policy also uses a timestamp.
813+
assert_eq!(
814+
policy.clone().at_lock_time(500_000_000),
815+
Policy::Unsatisfiable
816+
);
817+
assert_eq!(
818+
policy.clone().at_lock_time(500_000_001),
819+
Policy::Unsatisfiable
820+
);
821+
assert_eq!(policy.clone().at_lock_time(500_000_010), policy.clone());
822+
assert_eq!(policy.clone().at_lock_time(500_000_012), policy.clone());
814823
assert_eq!(policy.n_keys(), 0);
815824
assert_eq!(policy.minimum_n_keys(), Some(0));
816825
}

src/psbt/finalizer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ fn interpreter_inp_check<C: secp256k1::Verification, T: Borrow<TxOut>>(
295295
let cltv = psbt.unsigned_tx.lock_time;
296296
let csv = psbt.unsigned_tx.input[index].sequence;
297297
let interpreter =
298-
interpreter::Interpreter::from_txdata(spk, script_sig, witness, cltv, csv)
298+
interpreter::Interpreter::from_txdata(spk, script_sig, witness, csv, cltv)
299299
.map_err(|e| Error::InputError(InputError::Interpreter(e), index))?;
300300
let iter = interpreter.iter(secp, &psbt.unsigned_tx, index, utxos);
301301
if let Some(error) = iter.filter_map(Result::err).next() {

0 commit comments

Comments
 (0)