Implement ArbitaryOrd for absolute::LockTime

At times we would like to provide types that do not implement
`PartialOrd` and `Ord` because it does not make sense. I.e., we do not
want users writing `a < b`. This could range from kind-of-iffy to
down-right-buggy (like comparing absolute locktimes).

However this decision effects downstream users who may not care about
what the ordering means they just need to use it for some other reason
e.g., to use as part of a key for a `BTreeMap` (as we do in `miniscript`
requiring the `AbsLockTime` type).

A solution to this problem is to provide a wrapper data type that adds
`PartialOrd` and `Ord` implementations. I wrote the `ordered` crate is
for this very purpose.

Feature gate a new dependency on `ordered` and implement `ArbitraryOrd`
for `absolute::LockTime`.
This commit is contained in:
Tobin C. Harding 2023-12-02 08:50:51 +11:00
parent de9f20a620
commit 518f0970c9
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
5 changed files with 33 additions and 0 deletions

View File

@ -45,6 +45,7 @@ dependencies = [
"hex-conservative",
"hex_lit",
"mutagen",
"ordered",
"secp256k1",
"serde",
"serde_json",
@ -235,6 +236,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "ordered"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f0642533dea0bb58bd5cae31bafc1872429f0f12ac8c61fe2b4ba44f80b959b"
[[package]]
name = "ppv-lite86"
version = "0.2.8"

View File

@ -44,6 +44,7 @@ dependencies = [
"hex-conservative",
"hex_lit",
"mutagen",
"ordered",
"secp256k1",
"serde",
"serde_json",
@ -234,6 +235,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "ordered"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f0642533dea0bb58bd5cae31bafc1872429f0f12ac8c61fe2b4ba44f80b959b"
[[package]]
name = "ppv-lite86"
version = "0.2.17"

View File

@ -38,6 +38,7 @@ secp256k1 = { version = "0.28.0", default-features = false, features = ["hashes"
units = { package = "bitcoin-units", version = "0.1.0", default-features = false, features = ["alloc"] }
base64 = { version = "0.21.3", optional = true }
ordered = { version = "0.2.0", optional = true }
# Only use this feature for no-std builds, otherwise use bitcoinconsensus-std.
bitcoinconsensus = { version = "0.20.2-0.5.0", default-features = false, optional = true }

View File

@ -389,6 +389,20 @@ impl<'de> serde::Deserialize<'de> for LockTime {
}
}
#[cfg(feature = "ordered")]
impl ordered::ArbitraryOrd for LockTime {
fn arbitrary_cmp(&self, other: &Self) -> Ordering {
use LockTime::*;
match (self, other) {
(Blocks(_), Seconds(_)) => Ordering::Less,
(Seconds(_), Blocks(_)) => Ordering::Greater,
(Blocks(this), Blocks(that)) => this.cmp(that),
(Seconds(this), Seconds(that)) => this.cmp(that),
}
}
}
/// An absolute block height, guaranteed to always contain a valid height value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

View File

@ -70,6 +70,10 @@ pub extern crate hex;
/// Re-export the `bitcoin-io` crate.
pub extern crate io;
/// Re-export the `ordered` crate.
#[cfg(feature = "ordered")]
pub extern crate ordered;
/// Rust wrapper library for Pieter Wuille's libsecp256k1. Implements ECDSA and BIP 340 signatures
/// for the SECG elliptic curve group secp256k1 and related utilities.
pub extern crate secp256k1;