units: stop using MtpAndHeight in locktime::relative is_satisfied_by methods
Keep using it in primitives; will remove it there in the next commit.
This commit is contained in:
parent
d933c754f5
commit
72d5fbad73
|
@ -255,8 +255,10 @@ impl LockTime {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn is_satisfied_by(self, chain_tip: MtpAndHeight, utxo_mined_at: MtpAndHeight) -> bool {
|
pub fn is_satisfied_by(self, chain_tip: MtpAndHeight, utxo_mined_at: MtpAndHeight) -> bool {
|
||||||
match self {
|
match self {
|
||||||
LockTime::Blocks(blocks) => blocks.is_satisfied_by(chain_tip, utxo_mined_at),
|
LockTime::Blocks(blocks) =>
|
||||||
LockTime::Time(time) => time.is_satisfied_by(chain_tip, utxo_mined_at),
|
blocks.is_satisfied_by(chain_tip.to_height(), utxo_mined_at.to_height()),
|
||||||
|
LockTime::Time(time) =>
|
||||||
|
time.is_satisfied_by(chain_tip.to_mtp(), utxo_mined_at.to_mtp()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ use arbitrary::{Arbitrary, Unstructured};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::mtp_height::MtpAndHeight;
|
|
||||||
|
|
||||||
#[deprecated(since = "TBD", note = "use `HeightIterval` instead")]
|
#[deprecated(since = "TBD", note = "use `HeightIterval` instead")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub type Height = HeightInterval;
|
pub type Height = HeightInterval;
|
||||||
|
@ -59,21 +57,26 @@ impl HeightInterval {
|
||||||
/// Determines whether a relative‐height locktime has matured, taking into account
|
/// Determines whether a relative‐height locktime has matured, taking into account
|
||||||
/// both the chain tip and the height at which the UTXO was confirmed.
|
/// both the chain tip and the height at which the UTXO was confirmed.
|
||||||
///
|
///
|
||||||
|
/// If you have two height intervals `x` and `y`, and want to know whether `x`
|
||||||
|
/// is satisfied by `y`, use `x >= y`.
|
||||||
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
/// - `self` – The relative block‐height delay (`h`) required after confirmation.
|
/// - `self` – the relative block‐height delay (`h`) required after confirmation.
|
||||||
/// - `chain_tip` – The current chain state (contains the tip height).
|
/// - `chain_tip` – the height of the current chain tip
|
||||||
/// - `utxo_mined_at` – The chain state at the UTXO’s confirmation block (contains that height).
|
/// - `utxo_mined_at` – the height of the UTXO’s confirmation block
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// - `true` if a UTXO locked by `self` can be spent in a block after `chain_tip`.
|
/// - `true` if a UTXO locked by `self` can be spent in a block after `chain_tip`.
|
||||||
/// - `false` if the UTXO is still locked at `chain_tip`.
|
/// - `false` if the UTXO is still locked at `chain_tip`.
|
||||||
pub fn is_satisfied_by(self, chain_tip: MtpAndHeight, utxo_mined_at: MtpAndHeight) -> bool {
|
pub fn is_satisfied_by(
|
||||||
// let chain_tip_height = BlockHeight::from(chain_tip);
|
self,
|
||||||
// let utxo_mined_at_height = BlockHeight::from(utxo_mined_at);
|
chain_tip: crate::BlockHeight,
|
||||||
match u32::from(self.to_height()).checked_add(utxo_mined_at.to_height().to_u32()) {
|
utxo_mined_at: crate::BlockHeight,
|
||||||
Some(target_height) => chain_tip.to_height().to_u32() >= target_height,
|
) -> bool {
|
||||||
None => false,
|
chain_tip
|
||||||
}
|
.checked_sub(utxo_mined_at)
|
||||||
|
.and_then(|diff: crate::BlockHeightInterval| diff.try_into().ok())
|
||||||
|
.map_or(false, |diff: Self| diff >= self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,22 +183,26 @@ impl MtpInterval {
|
||||||
/// Determines whether a relative‑time lock has matured, taking into account both
|
/// Determines whether a relative‑time lock has matured, taking into account both
|
||||||
/// the UTXO’s Median Time Past at confirmation and the required delay.
|
/// the UTXO’s Median Time Past at confirmation and the required delay.
|
||||||
///
|
///
|
||||||
|
/// If you have two MTP intervals `x` and `y`, and want to know whether `x`
|
||||||
|
/// is satisfied by `y`, use `x >= y`.
|
||||||
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
/// - `self` – The relative time delay (`t`) in 512‑second intervals.
|
/// - `self` – the relative time delay (`t`) in 512‑second intervals.
|
||||||
/// - `chain_tip` – The current chain state, providing the tip’s MTP.
|
/// - `chain_tip` – the MTP of the current chain tip
|
||||||
/// - `utxo_mined_at` – The chain state at the UTXO’s confirmation, providing its MTP.
|
/// - `utxo_mined_at` – the MTP of the UTXO’s confirmation block
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// - `true` if the relative‐time lock has expired by the tip’s MTP
|
/// - `true` if the relative‐time lock has expired by the tip’s MTP
|
||||||
/// - `false` if the lock has not yet expired by the tip’s MTP
|
/// - `false` if the lock has not yet expired by the tip’s MTP
|
||||||
pub fn is_satisfied_by(self, chain_tip: MtpAndHeight, utxo_mined_at: MtpAndHeight) -> bool {
|
pub fn is_satisfied_by(
|
||||||
match u32::from(self.to_512_second_intervals()).checked_mul(512) {
|
self,
|
||||||
Some(seconds) => match seconds.checked_add(utxo_mined_at.to_mtp().to_u32()) {
|
chain_tip: crate::BlockMtp,
|
||||||
Some(required_seconds) => chain_tip.to_mtp().to_u32() >= required_seconds,
|
utxo_mined_at: crate::BlockMtp,
|
||||||
None => false,
|
) -> bool {
|
||||||
},
|
chain_tip
|
||||||
None => false,
|
.checked_sub(utxo_mined_at)
|
||||||
}
|
.and_then(|diff: crate::BlockMtpInterval| diff.to_relative_mtp_interval_floor().ok())
|
||||||
|
.map_or(false, |diff: Self| diff >= self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +277,7 @@ mod tests {
|
||||||
use internals::serde_round_trip;
|
use internals::serde_round_trip;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{BlockHeight, BlockTime};
|
use crate::BlockTime;
|
||||||
|
|
||||||
const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512;
|
const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512;
|
||||||
|
|
||||||
|
@ -355,6 +362,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_time_chain_state() {
|
fn test_time_chain_state() {
|
||||||
|
use crate::BlockMtp;
|
||||||
|
|
||||||
let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
|
let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
|
||||||
let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
|
let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
|
||||||
|
|
||||||
|
@ -367,49 +376,48 @@ mod tests {
|
||||||
// Test case 1: Satisfaction (current_mtp >= utxo_mtp + required_seconds)
|
// Test case 1: Satisfaction (current_mtp >= utxo_mtp + required_seconds)
|
||||||
// 10 intervals × 512 seconds = 5120 seconds
|
// 10 intervals × 512 seconds = 5120 seconds
|
||||||
let time_lock = MtpInterval::from_512_second_intervals(10);
|
let time_lock = MtpInterval::from_512_second_intervals(10);
|
||||||
let chain_state1 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps);
|
let chain_state1 = BlockMtp::new(timestamps);
|
||||||
let utxo_state1 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
|
let utxo_state1 = BlockMtp::new(utxo_timestamps);
|
||||||
assert!(time_lock.is_satisfied_by(chain_state1, utxo_state1));
|
assert!(time_lock.is_satisfied_by(chain_state1, utxo_state1));
|
||||||
|
|
||||||
// Test case 2: Not satisfied (current_mtp < utxo_mtp + required_seconds)
|
// Test case 2: Not satisfied (current_mtp < utxo_mtp + required_seconds)
|
||||||
let chain_state2 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps2);
|
let chain_state2 = BlockMtp::new(timestamps2);
|
||||||
let utxo_state2 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps2);
|
let utxo_state2 = BlockMtp::new(utxo_timestamps2);
|
||||||
assert!(!time_lock.is_satisfied_by(chain_state2, utxo_state2));
|
assert!(!time_lock.is_satisfied_by(chain_state2, utxo_state2));
|
||||||
|
|
||||||
// Test case 3: Test with a larger value (100 intervals = 51200 seconds)
|
// Test case 3: Test with a larger value (100 intervals = 51200 seconds)
|
||||||
let larger_lock = MtpInterval::from_512_second_intervals(100);
|
let larger_lock = MtpInterval::from_512_second_intervals(100);
|
||||||
let chain_state3 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps3);
|
let chain_state3 = BlockMtp::new(timestamps3);
|
||||||
let utxo_state3 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps3);
|
let utxo_state3 = BlockMtp::new(utxo_timestamps3);
|
||||||
assert!(larger_lock.is_satisfied_by(chain_state3, utxo_state3));
|
assert!(larger_lock.is_satisfied_by(chain_state3, utxo_state3));
|
||||||
|
|
||||||
// Test case 4: Overflow handling - tests that is_satisfied_by handles overflow gracefully
|
// Test case 4: Overflow handling - tests that is_satisfied_by handles overflow gracefully
|
||||||
let max_time_lock = MtpInterval::MAX;
|
let max_time_lock = MtpInterval::MAX;
|
||||||
let chain_state4 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps);
|
let chain_state4 = BlockMtp::new(timestamps);
|
||||||
let utxo_state4 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
|
let utxo_state4 = BlockMtp::new(utxo_timestamps);
|
||||||
assert!(!max_time_lock.is_satisfied_by(chain_state4, utxo_state4));
|
assert!(!max_time_lock.is_satisfied_by(chain_state4, utxo_state4));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_height_chain_state() {
|
fn test_height_chain_state() {
|
||||||
let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
|
use crate::BlockHeight;
|
||||||
let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
|
|
||||||
|
|
||||||
let height_lock = HeightInterval(10);
|
let height_lock = HeightInterval(10);
|
||||||
|
|
||||||
// Test case 1: Satisfaction (current_height >= utxo_height + required)
|
// Test case 1: Satisfaction (current_height >= utxo_height + required)
|
||||||
let chain_state1 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps);
|
let chain_state1 = BlockHeight::from_u32(100);
|
||||||
let utxo_state1 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
|
let utxo_state1 = BlockHeight::from_u32(80);
|
||||||
assert!(height_lock.is_satisfied_by(chain_state1, utxo_state1));
|
assert!(height_lock.is_satisfied_by(chain_state1, utxo_state1));
|
||||||
|
|
||||||
// Test case 2: Not satisfied (current_height < utxo_height + required)
|
// Test case 2: Not satisfied (current_height < utxo_height + required)
|
||||||
let chain_state2 = MtpAndHeight::new(BlockHeight::from_u32(89), timestamps);
|
let chain_state2 = BlockHeight::from_u32(89);
|
||||||
let utxo_state2 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
|
let utxo_state2 = BlockHeight::from_u32(80);
|
||||||
assert!(!height_lock.is_satisfied_by(chain_state2, utxo_state2));
|
assert!(!height_lock.is_satisfied_by(chain_state2, utxo_state2));
|
||||||
|
|
||||||
// Test case 3: Overflow handling - tests that is_satisfied_by handles overflow gracefully
|
// Test case 3: Overflow handling - tests that is_satisfied_by handles overflow gracefully
|
||||||
let max_height_lock = HeightInterval::MAX;
|
let max_height_lock = HeightInterval::MAX;
|
||||||
let chain_state3 = MtpAndHeight::new(BlockHeight::from_u32(1000), timestamps);
|
let chain_state3 = BlockHeight::from_u32(1000);
|
||||||
let utxo_state3 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
|
let utxo_state3 = BlockHeight::from_u32(80);
|
||||||
assert!(!max_height_lock.is_satisfied_by(chain_state3, utxo_state3));
|
assert!(!max_height_lock.is_satisfied_by(chain_state3, utxo_state3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue