primitives: Enable pedantic lints
Enable all the pedantic lints and fix warnings. Notable items: - `enum_glob_used` import types with a single character alias - `doc_markdown`: add a whitelist that includes SegWit and OpenSSL
This commit is contained in:
parent
d96d0f72b5
commit
df500e9b71
|
@ -1,3 +1,4 @@
|
|||
msrv = "1.63.0"
|
||||
too-many-arguments-threshold = 13
|
||||
avoid-breaking-exported-api = false
|
||||
doc-valid-idents = ["SegWit", "OpenSSL"]
|
||||
|
|
|
@ -40,3 +40,131 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "deny", check-cfg = ['cfg(mutate)'] }
|
||||
|
||||
[lints.clippy]
|
||||
# Exclude lints we don't think are valuable.
|
||||
needless_question_mark = "allow" # https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
|
||||
manual_range_contains = "allow" # More readable than clippy's format.
|
||||
# Exhaustive list of pedantic clippy lints
|
||||
assigning_clones = "warn"
|
||||
bool_to_int_with_if = "warn"
|
||||
borrow_as_ptr = "warn"
|
||||
case_sensitive_file_extension_comparisons = "warn"
|
||||
cast_lossless = "warn"
|
||||
cast_possible_truncation = "allow" # All casts should include a code comment (except test code).
|
||||
cast_possible_wrap = "allow" # Same as above re code comment.
|
||||
cast_precision_loss = "warn"
|
||||
cast_ptr_alignment = "warn"
|
||||
cast_sign_loss = "allow" # All casts should include a code comment (except in test code).
|
||||
checked_conversions = "warn"
|
||||
cloned_instead_of_copied = "warn"
|
||||
copy_iterator = "warn"
|
||||
default_trait_access = "warn"
|
||||
doc_link_with_quotes = "warn"
|
||||
doc_markdown = "warn"
|
||||
empty_enum = "warn"
|
||||
enum_glob_use = "warn"
|
||||
expl_impl_clone_on_copy = "warn"
|
||||
explicit_deref_methods = "warn"
|
||||
explicit_into_iter_loop = "warn"
|
||||
explicit_iter_loop = "warn"
|
||||
filter_map_next = "warn"
|
||||
flat_map_option = "warn"
|
||||
float_cmp = "allow" # Bitcoin floats are typically limited to 8 decimal places and we want them exact.
|
||||
fn_params_excessive_bools = "warn"
|
||||
from_iter_instead_of_collect = "warn"
|
||||
if_not_else = "warn"
|
||||
ignored_unit_patterns = "warn"
|
||||
implicit_clone = "warn"
|
||||
implicit_hasher = "warn"
|
||||
inconsistent_struct_constructor = "warn"
|
||||
index_refutable_slice = "warn"
|
||||
inefficient_to_string = "warn"
|
||||
inline_always = "warn"
|
||||
into_iter_without_iter = "warn"
|
||||
invalid_upcast_comparisons = "warn"
|
||||
items_after_statements = "warn"
|
||||
iter_filter_is_ok = "warn"
|
||||
iter_filter_is_some = "warn"
|
||||
iter_not_returning_iterator = "warn"
|
||||
iter_without_into_iter = "warn"
|
||||
large_digit_groups = "warn"
|
||||
large_futures = "warn"
|
||||
large_stack_arrays = "warn"
|
||||
large_types_passed_by_value = "warn"
|
||||
linkedlist = "warn"
|
||||
macro_use_imports = "warn"
|
||||
manual_assert = "warn"
|
||||
manual_instant_elapsed = "warn"
|
||||
manual_is_power_of_two = "warn"
|
||||
manual_is_variant_and = "warn"
|
||||
manual_let_else = "warn"
|
||||
manual_ok_or = "warn"
|
||||
manual_string_new = "warn"
|
||||
many_single_char_names = "warn"
|
||||
map_unwrap_or = "warn"
|
||||
match_bool = "allow" # Adds extra indentation and LOC.
|
||||
match_on_vec_items = "warn"
|
||||
match_same_arms = "allow" # Collapses things that are conceptually unrelated to each other.
|
||||
match_wild_err_arm = "warn"
|
||||
match_wildcard_for_single_variants = "warn"
|
||||
maybe_infinite_iter = "warn"
|
||||
mismatching_type_param_order = "warn"
|
||||
missing_errors_doc = "allow" # TODO: Write errors section in docs.
|
||||
missing_fields_in_debug = "warn"
|
||||
missing_panics_doc = "warn"
|
||||
must_use_candidate = "allow" # Useful for audit but many false positives.
|
||||
mut_mut = "warn"
|
||||
naive_bytecount = "warn"
|
||||
needless_bitwise_bool = "warn"
|
||||
needless_continue = "warn"
|
||||
needless_for_each = "warn"
|
||||
needless_pass_by_value = "warn"
|
||||
needless_raw_string_hashes = "warn"
|
||||
no_effect_underscore_binding = "warn"
|
||||
no_mangle_with_rust_abi = "warn"
|
||||
option_as_ref_cloned = "warn"
|
||||
option_option = "warn"
|
||||
ptr_as_ptr = "warn"
|
||||
ptr_cast_constness = "warn"
|
||||
pub_underscore_fields = "warn"
|
||||
range_minus_one = "warn"
|
||||
range_plus_one = "warn"
|
||||
redundant_closure_for_method_calls = "warn"
|
||||
redundant_else = "warn"
|
||||
ref_as_ptr = "warn"
|
||||
ref_binding_to_reference = "warn"
|
||||
ref_option = "warn"
|
||||
ref_option_ref = "warn"
|
||||
return_self_not_must_use = "warn"
|
||||
same_functions_in_if_condition = "warn"
|
||||
semicolon_if_nothing_returned = "warn"
|
||||
should_panic_without_expect = "warn"
|
||||
similar_names = "allow" # Too many (subjectively) false positives.
|
||||
single_char_pattern = "warn"
|
||||
single_match_else = "warn"
|
||||
stable_sort_primitive = "warn"
|
||||
str_split_at_newline = "warn"
|
||||
string_add_assign = "warn"
|
||||
struct_excessive_bools = "warn"
|
||||
struct_field_names = "allow" # TODO: Triggers warning for `witness_elements`.
|
||||
too_many_lines = "warn"
|
||||
transmute_ptr_to_ptr = "warn"
|
||||
trivially_copy_pass_by_ref = "warn"
|
||||
unchecked_duration_subtraction = "warn"
|
||||
unicode_not_nfc = "warn"
|
||||
uninlined_format_args = "allow" # This is a subjective style choice.
|
||||
unnecessary_box_returns = "warn"
|
||||
unnecessary_join = "warn"
|
||||
unnecessary_literal_bound = "warn"
|
||||
unnecessary_wraps = "warn"
|
||||
unnested_or_patterns = "allow" # TODO
|
||||
unreadable_literal = "warn"
|
||||
unsafe_derive_deserialize = "warn"
|
||||
unused_async = "warn"
|
||||
unused_self = "warn"
|
||||
used_underscore_binding = "warn"
|
||||
used_underscore_items = "warn"
|
||||
verbose_bit_mask = "warn"
|
||||
wildcard_imports = "warn"
|
||||
zero_sized_map_values = "warn"
|
||||
|
|
|
@ -281,7 +281,7 @@ impl Version {
|
|||
///
|
||||
/// A block is signalling for a soft fork under BIP-9 if the first 3 bits are `001` and
|
||||
/// the version bit for the specific soft fork is toggled on.
|
||||
pub fn is_signalling_soft_fork(&self, bit: u8) -> bool {
|
||||
pub fn is_signalling_soft_fork(self, bit: u8) -> bool {
|
||||
// Only bits [0, 28] inclusive are used for signalling.
|
||||
if bit > 28 {
|
||||
return false;
|
||||
|
@ -362,36 +362,36 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn version_is_not_signalling_with_invalid_bit() {
|
||||
let arbitrary_version = Version::from_consensus(1234567890);
|
||||
let arbitrary_version = Version::from_consensus(1_234_567_890);
|
||||
// The max bit number to signal is 28.
|
||||
assert!(!Version::is_signalling_soft_fork(&arbitrary_version, 29));
|
||||
assert!(!Version::is_signalling_soft_fork(arbitrary_version, 29));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_is_not_signalling_when_use_version_bit_not_set() {
|
||||
let version = Version::from_consensus(0b01000000000000000000000000000000);
|
||||
let version = Version::from_consensus(0b0100_0000_0000_0000_0000_0000_0000_0000);
|
||||
// Top three bits must be 001 to signal.
|
||||
assert!(!Version::is_signalling_soft_fork(&version, 1));
|
||||
assert!(!Version::is_signalling_soft_fork(version, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_is_signalling() {
|
||||
let version = Version::from_consensus(0b00100000000000000000000000000010);
|
||||
assert!(Version::is_signalling_soft_fork(&version, 1));
|
||||
let version = Version::from_consensus(0b00110000000000000000000000000000);
|
||||
assert!(Version::is_signalling_soft_fork(&version, 28));
|
||||
let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010);
|
||||
assert!(Version::is_signalling_soft_fork(version, 1));
|
||||
let version = Version::from_consensus(0b0011_0000_0000_0000_0000_0000_0000_0000);
|
||||
assert!(Version::is_signalling_soft_fork(version, 28));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_is_not_signalling() {
|
||||
let version = Version::from_consensus(0b00100000000000000000000000000010);
|
||||
assert!(!Version::is_signalling_soft_fork(&version, 0));
|
||||
let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010);
|
||||
assert!(!Version::is_signalling_soft_fork(version, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_to_consensus() {
|
||||
let version = Version::from_consensus(1234567890);
|
||||
assert_eq!(version.to_consensus(), 1234567890);
|
||||
let version = Version::from_consensus(1_234_567_890);
|
||||
assert_eq!(version.to_consensus(), 1_234_567_890);
|
||||
}
|
||||
|
||||
// Check that the size of the header consensus serialization matches the const SIZE value
|
||||
|
|
|
@ -16,12 +16,6 @@
|
|||
#![warn(missing_docs)]
|
||||
#![warn(deprecated_in_future)]
|
||||
#![doc(test(attr(warn(unused))))]
|
||||
// Pedantic lints that we enforce.
|
||||
// #![warn(clippy::must_use_candidate)]
|
||||
#![warn(clippy::return_self_not_must_use)]
|
||||
// Exclude lints we don't think are valuable.
|
||||
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
|
||||
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Provides type [`LockTime`] that implements the logic around nLockTime/OP_CHECKLOCKTIMEVERIFY.
|
||||
//! Provides type [`LockTime`] that implements the logic around `nLockTime`/`OP_CHECKLOCKTIMEVERIFY`.
|
||||
//!
|
||||
//! There are two types of lock time: lock-by-blockheight and lock-by-blocktime, distinguished by
|
||||
//! whether `LockTime < LOCKTIME_THRESHOLD`.
|
||||
|
@ -22,7 +22,7 @@ pub use units::locktime::absolute::{ConversionError, Height, ParseHeightError, P
|
|||
/// since epoch).
|
||||
///
|
||||
/// Used for transaction lock time (`nLockTime` in Bitcoin Core and [`Transaction::lock_time`]
|
||||
/// in this library) and also for the argument to opcode 'OP_CHECKLOCKTIMEVERIFY`.
|
||||
/// in this library) and also for the argument to opcode `OP_CHECKLOCKTIMEVERIFY`.
|
||||
///
|
||||
/// ### Note on ordering
|
||||
///
|
||||
|
@ -42,13 +42,13 @@ pub use units::locktime::absolute::{ConversionError, Height, ParseHeightError, P
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use bitcoin_primitives::absolute::{self, LockTime::*};
|
||||
/// use bitcoin_primitives::absolute::{self, LockTime as L};
|
||||
/// # let n = absolute::LockTime::from_consensus(741521); // n OP_CHECKLOCKTIMEVERIFY
|
||||
/// # let lock_time = absolute::LockTime::from_consensus(741521); // nLockTime
|
||||
/// // To compare absolute lock times there are various `is_satisfied_*` methods, you may also use:
|
||||
/// let _is_satisfied = match (n, lock_time) {
|
||||
/// (Blocks(n), Blocks(lock_time)) => n <= lock_time,
|
||||
/// (Seconds(n), Seconds(lock_time)) => n <= lock_time,
|
||||
/// (L::Blocks(n), L::Blocks(lock_time)) => n <= lock_time,
|
||||
/// (L::Seconds(n), L::Seconds(lock_time)) => n <= lock_time,
|
||||
/// _ => panic!("handle invalid comparison error"),
|
||||
/// };
|
||||
/// ```
|
||||
|
@ -126,7 +126,7 @@ impl LockTime {
|
|||
Ok(Self::from_consensus(lock_time))
|
||||
}
|
||||
|
||||
/// Constructs a new `LockTime` from an nLockTime value or the argument to OP_CHEKCLOCKTIMEVERIFY.
|
||||
/// Constructs a new `LockTime` from an `nLockTime` value or the argument to `OP_CHEKCLOCKTIMEVERIFY`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -138,6 +138,7 @@ impl LockTime {
|
|||
/// let lock_time = absolute::LockTime::from_consensus(n_lock_time);
|
||||
/// assert_eq!(lock_time.to_consensus_u32(), n_lock_time);
|
||||
#[inline]
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn from_consensus(n: u32) -> Self {
|
||||
if units::locktime::absolute::is_block_height(n) {
|
||||
Self::Blocks(Height::from_consensus(n).expect("n is valid"))
|
||||
|
@ -197,7 +198,7 @@ impl LockTime {
|
|||
|
||||
/// Returns true if both lock times use the same unit i.e., both height based or both time based.
|
||||
#[inline]
|
||||
pub const fn is_same_unit(&self, other: LockTime) -> bool {
|
||||
pub const fn is_same_unit(self, other: LockTime) -> bool {
|
||||
matches!(
|
||||
(self, other),
|
||||
(LockTime::Blocks(_), LockTime::Blocks(_))
|
||||
|
@ -207,11 +208,11 @@ impl LockTime {
|
|||
|
||||
/// Returns true if this lock time value is a block height.
|
||||
#[inline]
|
||||
pub const fn is_block_height(&self) -> bool { matches!(*self, LockTime::Blocks(_)) }
|
||||
pub const fn is_block_height(self) -> bool { matches!(self, LockTime::Blocks(_)) }
|
||||
|
||||
/// Returns true if this lock time value is a block time (UNIX timestamp).
|
||||
#[inline]
|
||||
pub const fn is_block_time(&self) -> bool { !self.is_block_height() }
|
||||
pub const fn is_block_time(self) -> bool { !self.is_block_height() }
|
||||
|
||||
/// Returns true if this timelock constraint is satisfied by the respective `height`/`time`.
|
||||
///
|
||||
|
@ -219,7 +220,7 @@ impl LockTime {
|
|||
/// blocktime based lock it is checked against `time`.
|
||||
///
|
||||
/// A 'timelock constraint' refers to the `n` from `n OP_CHEKCLOCKTIMEVERIFY`, this constraint
|
||||
/// is satisfied if a transaction with nLockTime ([`Transaction::lock_time`]) set to
|
||||
/// is satisfied if a transaction with `nLockTime` ([`Transaction::lock_time`]) set to
|
||||
/// `height`/`time` is valid.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -236,12 +237,12 @@ impl LockTime {
|
|||
/// }
|
||||
/// ````
|
||||
#[inline]
|
||||
pub fn is_satisfied_by(&self, height: Height, time: Time) -> bool {
|
||||
use LockTime::*;
|
||||
pub fn is_satisfied_by(self, height: Height, time: Time) -> bool {
|
||||
use LockTime as L;
|
||||
|
||||
match *self {
|
||||
Blocks(n) => n <= height,
|
||||
Seconds(n) => n <= time,
|
||||
match self {
|
||||
L::Blocks(n) => n <= height,
|
||||
L::Seconds(n) => n <= time,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,18 +266,18 @@ impl LockTime {
|
|||
/// assert!(lock_time.is_implied_by(check));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_implied_by(&self, other: LockTime) -> bool {
|
||||
use LockTime::*;
|
||||
pub fn is_implied_by(self, other: LockTime) -> bool {
|
||||
use LockTime as L;
|
||||
|
||||
match (*self, other) {
|
||||
(Blocks(this), Blocks(other)) => this <= other,
|
||||
(Seconds(this), Seconds(other)) => this <= other,
|
||||
match (self, other) {
|
||||
(L::Blocks(this), L::Blocks(other)) => this <= other,
|
||||
(L::Seconds(this), L::Seconds(other)) => this <= other,
|
||||
_ => false, // Not the same units.
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the inner `u32` value. This is the value used when creating this `LockTime`
|
||||
/// i.e., `n OP_CHECKLOCKTIMEVERIFY` or nLockTime.
|
||||
/// i.e., `n OP_CHECKLOCKTIMEVERIFY` or `nLockTime`.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
|
@ -287,13 +288,13 @@ impl LockTime {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use bitcoin_primitives::absolute::{self, LockTime::*};
|
||||
/// use bitcoin_primitives::absolute::{self, LockTime as L};
|
||||
/// # let n = absolute::LockTime::from_consensus(741521); // n OP_CHECKLOCKTIMEVERIFY
|
||||
/// # let lock_time = absolute::LockTime::from_consensus(741521 + 1); // nLockTime
|
||||
///
|
||||
/// let _is_satisfied = match (n, lock_time) {
|
||||
/// (Blocks(n), Blocks(lock_time)) => n <= lock_time,
|
||||
/// (Seconds(n), Seconds(lock_time)) => n <= lock_time,
|
||||
/// (L::Blocks(n), L::Blocks(lock_time)) => n <= lock_time,
|
||||
/// (L::Seconds(n), L::Seconds(lock_time)) => n <= lock_time,
|
||||
/// _ => panic!("invalid comparison"),
|
||||
/// };
|
||||
///
|
||||
|
@ -324,28 +325,28 @@ impl From<Time> for LockTime {
|
|||
impl fmt::Debug for LockTime {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use LockTime::*;
|
||||
use LockTime as L;
|
||||
|
||||
match *self {
|
||||
Blocks(ref h) => write!(f, "{} blocks", h),
|
||||
Seconds(ref t) => write!(f, "{} seconds", t),
|
||||
L::Blocks(ref h) => write!(f, "{} blocks", h),
|
||||
L::Seconds(ref t) => write!(f, "{} seconds", t),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LockTime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use LockTime::*;
|
||||
use LockTime as L;
|
||||
|
||||
if f.alternate() {
|
||||
match *self {
|
||||
Blocks(ref h) => write!(f, "block-height {}", h),
|
||||
Seconds(ref t) => write!(f, "block-time {} (seconds since epoch)", t),
|
||||
L::Blocks(ref h) => write!(f, "block-height {}", h),
|
||||
L::Seconds(ref t) => write!(f, "block-time {} (seconds since epoch)", t),
|
||||
}
|
||||
} else {
|
||||
match *self {
|
||||
Blocks(ref h) => fmt::Display::fmt(h, f),
|
||||
Seconds(ref t) => fmt::Display::fmt(t, f),
|
||||
L::Blocks(ref h) => fmt::Display::fmt(h, f),
|
||||
L::Seconds(ref t) => fmt::Display::fmt(t, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -404,7 +405,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn display_and_alternate() {
|
||||
let lock_by_height = LockTime::from_consensus(741521);
|
||||
let lock_by_height = LockTime::from_consensus(741_521);
|
||||
let s = format!("{}", lock_by_height);
|
||||
assert_eq!(&s, "741521");
|
||||
|
||||
|
@ -415,25 +416,25 @@ mod tests {
|
|||
#[test]
|
||||
fn lock_time_from_hex_lower() {
|
||||
let lock_by_time = LockTime::from_hex("0x6289c350").unwrap();
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289C350));
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289_C350));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lock_time_from_hex_upper() {
|
||||
let lock_by_time = LockTime::from_hex("0X6289C350").unwrap();
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289C350));
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289_C350));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lock_time_from_unprefixed_hex_lower() {
|
||||
let lock_by_time = LockTime::from_unprefixed_hex("6289c350").unwrap();
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289C350));
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289_C350));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lock_time_from_unprefixed_hex_upper() {
|
||||
let lock_by_time = LockTime::from_unprefixed_hex("6289C350").unwrap();
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289C350));
|
||||
assert_eq!(lock_by_time, LockTime::from_consensus(0x6289_C350));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -450,7 +451,7 @@ mod tests {
|
|||
assert!(lock_by_height.is_block_height());
|
||||
assert!(!lock_by_height.is_block_time());
|
||||
|
||||
let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||
let t: u32 = 1_653_195_600; // May 22nd, 5am UTC.
|
||||
let lock_by_time = LockTime::from_consensus(t);
|
||||
|
||||
assert!(!lock_by_time.is_block_height());
|
||||
|
@ -459,7 +460,7 @@ mod tests {
|
|||
// Test is_same_unit() logic
|
||||
assert!(lock_by_height.is_same_unit(LockTime::from_consensus(800_000)));
|
||||
assert!(!lock_by_height.is_same_unit(lock_by_time));
|
||||
assert!(lock_by_time.is_same_unit(LockTime::from_consensus(1653282000)));
|
||||
assert!(lock_by_time.is_same_unit(LockTime::from_consensus(1_653_282_000)));
|
||||
assert!(!lock_by_time.is_same_unit(lock_by_height));
|
||||
}
|
||||
|
||||
|
@ -471,7 +472,7 @@ mod tests {
|
|||
let height_above = Height::from_consensus(800_000).expect("failed to parse height");
|
||||
let height_below = Height::from_consensus(700_000).expect("failed to parse height");
|
||||
|
||||
let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||
let t: u32 = 1_653_195_600; // May 22nd, 5am UTC.
|
||||
let time = Time::from_consensus(t).expect("invalid time value");
|
||||
|
||||
assert!(lock_by_height.is_satisfied_by(height_same, time));
|
||||
|
@ -481,11 +482,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn satisfied_by_time() {
|
||||
let lock_by_time = LockTime::from_consensus(1653195600); // May 22nd 2022, 5am UTC.
|
||||
let lock_by_time = LockTime::from_consensus(1_653_195_600); // May 22nd 2022, 5am UTC.
|
||||
|
||||
let time_same = Time::from_consensus(1653195600).expect("May 22nd 2022, 5am UTC");
|
||||
let time_after = Time::from_consensus(1653282000).expect("May 23rd 2022, 5am UTC");
|
||||
let time_before = Time::from_consensus(1653109200).expect("May 21th 2022, 5am UTC");
|
||||
let time_same = Time::from_consensus(1_653_195_600).expect("May 22nd 2022, 5am UTC");
|
||||
let time_after = Time::from_consensus(1_653_282_000).expect("May 23rd 2022, 5am UTC");
|
||||
let time_before = Time::from_consensus(1_653_109_200).expect("May 21th 2022, 5am UTC");
|
||||
|
||||
let height = Height::from_consensus(800_000).expect("failed to parse height");
|
||||
|
||||
|
@ -505,17 +506,17 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn time_correctly_implies() {
|
||||
let t: u32 = 1700000005;
|
||||
let t: u32 = 1_700_000_005;
|
||||
let lock_by_time = LockTime::from_consensus(t);
|
||||
|
||||
assert!(!lock_by_time.is_implied_by(LockTime::from_consensus(1700000004)));
|
||||
assert!(lock_by_time.is_implied_by(LockTime::from_consensus(1700000005)));
|
||||
assert!(lock_by_time.is_implied_by(LockTime::from_consensus(1700000006)));
|
||||
assert!(!lock_by_time.is_implied_by(LockTime::from_consensus(1_700_000_004)));
|
||||
assert!(lock_by_time.is_implied_by(LockTime::from_consensus(1_700_000_005)));
|
||||
assert!(lock_by_time.is_implied_by(LockTime::from_consensus(1_700_000_006)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incorrect_units_do_not_imply() {
|
||||
let lock_by_height = LockTime::from_consensus(750_005);
|
||||
assert!(!lock_by_height.is_implied_by(LockTime::from_consensus(1700000004)));
|
||||
assert!(!lock_by_height.is_implied_by(LockTime::from_consensus(1_700_000_004)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Provides type [`LockTime`] that implements the logic around nSequence/OP_CHECKSEQUENCEVERIFY.
|
||||
//! Provides type [`LockTime`] that implements the logic around `nSequence`/`OP_CHECKSEQUENCEVERIFY`.
|
||||
//!
|
||||
//! There are two types of lock time: lock-by-blockheight and lock-by-blocktime, distinguished by
|
||||
//! whether bit 22 of the `u32` consensus value is set.
|
||||
|
@ -18,7 +18,7 @@ pub use units::locktime::relative::{Height, Time, TimeOverflowError};
|
|||
/// A relative lock time value, representing either a block height or time (512 second intervals).
|
||||
///
|
||||
/// Used for sequence numbers (`nSequence` in Bitcoin Core and [`TxIn::sequence`]
|
||||
/// in this library) and also for the argument to opcode 'OP_CHECKSEQUENCEVERIFY`.
|
||||
/// in this library) and also for the argument to opcode `OP_CHECKSEQUENCEVERIFY`.
|
||||
///
|
||||
/// ### Note on ordering
|
||||
///
|
||||
|
@ -64,7 +64,7 @@ impl LockTime {
|
|||
/// The number of bytes that the locktime contributes to the size of a transaction.
|
||||
pub const SIZE: usize = 4; // Serialized length of a u32.
|
||||
|
||||
/// Constructs a new `LockTime` from an nSequence value or the argument to OP_CHECKSEQUENCEVERIFY.
|
||||
/// Constructs a new `LockTime` from an `nSequence` value or the argument to `OP_CHECKSEQUENCEVERIFY`.
|
||||
///
|
||||
/// This method will **not** round-trip with [`Self::to_consensus_u32`], because relative
|
||||
/// locktimes only use some bits of the underlying `u32` value and discard the rest. If
|
||||
|
@ -95,7 +95,7 @@ impl LockTime {
|
|||
sequence.to_relative_lock_time().ok_or(DisabledLockTimeError(n))
|
||||
}
|
||||
|
||||
/// Returns the `u32` value used to encode this locktime in an nSequence field or
|
||||
/// Returns the `u32` value used to encode this locktime in an `nSequence` field or
|
||||
/// argument to `OP_CHECKSEQUENCEVERIFY`.
|
||||
///
|
||||
/// # Warning
|
||||
|
@ -178,7 +178,7 @@ impl LockTime {
|
|||
|
||||
/// Returns true if both lock times use the same unit i.e., both height based or both time based.
|
||||
#[inline]
|
||||
pub const fn is_same_unit(&self, other: LockTime) -> bool {
|
||||
pub const fn is_same_unit(self, other: LockTime) -> bool {
|
||||
matches!(
|
||||
(self, other),
|
||||
(LockTime::Blocks(_), LockTime::Blocks(_)) | (LockTime::Time(_), LockTime::Time(_))
|
||||
|
@ -187,11 +187,11 @@ impl LockTime {
|
|||
|
||||
/// Returns true if this lock time value is in units of block height.
|
||||
#[inline]
|
||||
pub const fn is_block_height(&self) -> bool { matches!(*self, LockTime::Blocks(_)) }
|
||||
pub const fn is_block_height(self) -> bool { matches!(self, LockTime::Blocks(_)) }
|
||||
|
||||
/// Returns true if this lock time value is in units of time.
|
||||
#[inline]
|
||||
pub const fn is_block_time(&self) -> bool { !self.is_block_height() }
|
||||
pub const fn is_block_time(self) -> bool { !self.is_block_height() }
|
||||
|
||||
/// Returns true if this [`relative::LockTime`] is satisfied by either height or time.
|
||||
///
|
||||
|
@ -211,7 +211,7 @@ impl LockTime {
|
|||
/// assert!(lock.is_satisfied_by(current_height(), current_time()));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_satisfied_by(&self, h: Height, t: Time) -> bool {
|
||||
pub fn is_satisfied_by(self, h: Height, t: Time) -> bool {
|
||||
if let Ok(true) = self.is_satisfied_by_height(h) {
|
||||
true
|
||||
} else {
|
||||
|
@ -249,12 +249,12 @@ impl LockTime {
|
|||
/// assert!(satisfied);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_implied_by(&self, other: LockTime) -> bool {
|
||||
use LockTime::*;
|
||||
pub fn is_implied_by(self, other: LockTime) -> bool {
|
||||
use LockTime as L;
|
||||
|
||||
match (*self, other) {
|
||||
(Blocks(this), Blocks(other)) => this.value() <= other.value(),
|
||||
(Time(this), Time(other)) => this.value() <= other.value(),
|
||||
match (self, other) {
|
||||
(L::Blocks(this), L::Blocks(other)) => this.value() <= other.value(),
|
||||
(L::Time(this), L::Time(other)) => this.value() <= other.value(),
|
||||
_ => false, // Not the same units.
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ impl LockTime {
|
|||
/// # Ok::<_, bitcoin_primitives::relative::DisabledLockTimeError>(())
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_implied_by_sequence(&self, other: Sequence) -> bool {
|
||||
pub fn is_implied_by_sequence(self, other: Sequence) -> bool {
|
||||
if let Ok(other) = LockTime::from_sequence(other) {
|
||||
self.is_implied_by(other)
|
||||
} else {
|
||||
|
@ -305,12 +305,12 @@ impl LockTime {
|
|||
/// assert!(lock.is_satisfied_by_height(relative::Height::from(required_height + 1)).expect("a height"));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_satisfied_by_height(&self, height: Height) -> Result<bool, IncompatibleHeightError> {
|
||||
use LockTime::*;
|
||||
pub fn is_satisfied_by_height(self, height: Height) -> Result<bool, IncompatibleHeightError> {
|
||||
use LockTime as L;
|
||||
|
||||
match *self {
|
||||
Blocks(ref required_height) => Ok(required_height.value() <= height.value()),
|
||||
Time(time) => Err(IncompatibleHeightError { height, time }),
|
||||
match self {
|
||||
L::Blocks(ref required_height) => Ok(required_height.value() <= height.value()),
|
||||
L::Time(time) => Err(IncompatibleHeightError { height, time }),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,12 +331,12 @@ impl LockTime {
|
|||
/// assert!(lock.is_satisfied_by_time(relative::Time::from_512_second_intervals(intervals + 10)).expect("a time"));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_satisfied_by_time(&self, time: Time) -> Result<bool, IncompatibleTimeError> {
|
||||
use LockTime::*;
|
||||
pub fn is_satisfied_by_time(self, time: Time) -> Result<bool, IncompatibleTimeError> {
|
||||
use LockTime as L;
|
||||
|
||||
match *self {
|
||||
Time(ref t) => Ok(t.value() <= time.value()),
|
||||
Blocks(height) => Err(IncompatibleTimeError { time, height }),
|
||||
match self {
|
||||
L::Time(ref t) => Ok(t.value() <= time.value()),
|
||||
L::Blocks(height) => Err(IncompatibleTimeError { time, height }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,17 +353,17 @@ impl From<Time> for LockTime {
|
|||
|
||||
impl fmt::Display for LockTime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use LockTime::*;
|
||||
use LockTime as L;
|
||||
|
||||
if f.alternate() {
|
||||
match *self {
|
||||
Blocks(ref h) => write!(f, "block-height {}", h),
|
||||
Time(ref t) => write!(f, "block-time {} (512 second intervals)", t),
|
||||
L::Blocks(ref h) => write!(f, "block-height {}", h),
|
||||
L::Time(ref t) => write!(f, "block-time {} (512 second intervals)", t),
|
||||
}
|
||||
} else {
|
||||
match *self {
|
||||
Blocks(ref h) => fmt::Display::fmt(h, f),
|
||||
Time(ref t) => fmt::Display::fmt(t, f),
|
||||
L::Blocks(ref h) => fmt::Display::fmt(h, f),
|
||||
L::Time(ref t) => fmt::Display::fmt(t, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ pub struct Opcode {
|
|||
code: u8,
|
||||
}
|
||||
|
||||
#[allow(clippy::wildcard_imports)]
|
||||
use self::all::*;
|
||||
|
||||
macro_rules! all_opcodes {
|
||||
|
@ -41,7 +42,7 @@ macro_rules! all_opcodes {
|
|||
/// get all the `OP_FOO` opcodes without getting other types defined in `opcodes` (e.g. `Opcode`, `Class`).
|
||||
///
|
||||
/// This module is guaranteed to never contain anything except opcode constants and all opcode
|
||||
/// constants are guaranteed to begin with OP_.
|
||||
/// constants are guaranteed to begin with `OP_`.
|
||||
pub mod all {
|
||||
use super::Opcode;
|
||||
$(
|
||||
|
@ -52,13 +53,13 @@ macro_rules! all_opcodes {
|
|||
|
||||
/// Push an empty array onto the stack.
|
||||
pub static OP_0: Opcode = OP_PUSHBYTES_0;
|
||||
/// Empty stack is also FALSE.
|
||||
/// Empty stack is also `FALSE`.
|
||||
pub static OP_FALSE: Opcode = OP_PUSHBYTES_0;
|
||||
/// Number 1 is also TRUE.
|
||||
pub static OP_TRUE: Opcode = OP_PUSHNUM_1;
|
||||
/// Previously called OP_NOP2.
|
||||
/// Previously called `OP_NOP2`.
|
||||
pub static OP_NOP2: Opcode = OP_CLTV;
|
||||
/// Previously called OP_NOP3.
|
||||
/// Previously called `OP_NOP3`.
|
||||
pub static OP_NOP3: Opcode = OP_CSV;
|
||||
|
||||
impl fmt::Display for Opcode {
|
||||
|
@ -402,10 +403,10 @@ impl Opcode {
|
|||
|
||||
// 16 opcodes of PushNum class
|
||||
(op, _) if op.code >= OP_PUSHNUM_1.code && op.code <= OP_PUSHNUM_16.code =>
|
||||
Class::PushNum(1 + self.code as i32 - OP_PUSHNUM_1.code as i32),
|
||||
Class::PushNum(1 + i32::from(self.code) - i32::from(OP_PUSHNUM_1.code)),
|
||||
|
||||
// 76 opcodes of PushBytes class
|
||||
(op, _) if op.code <= OP_PUSHBYTES_75.code => Class::PushBytes(self.code as u32),
|
||||
(op, _) if op.code <= OP_PUSHBYTES_75.code => Class::PushBytes(u32::from(self.code)),
|
||||
|
||||
// opcodes of Ordinary class: 61 for Legacy and 60 for TapScript context
|
||||
(_, _) => Class::Ordinary(Ordinary::with(self)),
|
||||
|
@ -640,6 +641,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::too_many_lines)] // This is fine, we never need to read it.
|
||||
fn str_roundtrip() {
|
||||
let mut unique = HashSet::new();
|
||||
roundtrip!(unique, OP_PUSHBYTES_0);
|
||||
|
|
|
@ -52,9 +52,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn compact_target_ordering() {
|
||||
let lower = CompactTarget::from_consensus(0x1d00fffe);
|
||||
let lower_copy = CompactTarget::from_consensus(0x1d00fffe);
|
||||
let higher = CompactTarget::from_consensus(0x1d00ffff);
|
||||
let lower = CompactTarget::from_consensus(0x1d00_fffe);
|
||||
let lower_copy = CompactTarget::from_consensus(0x1d00_fffe);
|
||||
let higher = CompactTarget::from_consensus(0x1d00_ffff);
|
||||
|
||||
assert!(lower < higher);
|
||||
assert!(lower == lower_copy);
|
||||
|
@ -62,9 +62,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn compact_target_formatting() {
|
||||
let compact_target = CompactTarget::from_consensus(0x1d00ffff);
|
||||
let compact_target = CompactTarget::from_consensus(0x1d00_ffff);
|
||||
assert_eq!(format!("{:x}", compact_target), "1d00ffff");
|
||||
assert_eq!(format!("{:X}", compact_target), "1D00FFFF");
|
||||
assert_eq!(compact_target.to_consensus(), 0x1d00ffff);
|
||||
assert_eq!(compact_target.to_consensus(), 0x1d00_ffff);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use hashes::{hash160, sha256};
|
|||
use hex::DisplayHex;
|
||||
use internals::script::{self, PushDataLenLen};
|
||||
|
||||
#[allow(clippy::wildcard_imports)]
|
||||
use crate::opcodes::all::*;
|
||||
use crate::opcodes::{self, Opcode};
|
||||
use crate::prelude::rc::Rc;
|
||||
|
@ -522,14 +523,6 @@ impl<'de> serde::Deserialize<'de> for &'de Script {
|
|||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
use crate::serde::de::Error;
|
||||
|
||||
return Err(D::Error::custom(
|
||||
"deserialization of `&Script` from human-readable formats is not possible",
|
||||
));
|
||||
}
|
||||
|
||||
struct Visitor;
|
||||
impl<'de> serde::de::Visitor<'de> for Visitor {
|
||||
type Value = &'de Script;
|
||||
|
@ -545,6 +538,15 @@ impl<'de> serde::Deserialize<'de> for &'de Script {
|
|||
Ok(Script::from_bytes(v))
|
||||
}
|
||||
}
|
||||
|
||||
if deserializer.is_human_readable() {
|
||||
use crate::serde::de::Error;
|
||||
|
||||
return Err(D::Error::custom(
|
||||
"deserialization of `&Script` from human-readable formats is not possible",
|
||||
));
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(Visitor)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ impl Sequence {
|
|||
/// The maximum allowable sequence number.
|
||||
///
|
||||
/// The sequence number that disables replace-by-fee, absolute lock time and relative lock time.
|
||||
pub const MAX: Self = Sequence(0xFFFFFFFF);
|
||||
pub const MAX: Self = Sequence(0xFFFF_FFFF);
|
||||
/// Zero value sequence.
|
||||
///
|
||||
/// This sequence number enables replace-by-fee and absolute lock time.
|
||||
|
@ -49,12 +49,12 @@ impl Sequence {
|
|||
/// The sequence number that enables replace-by-fee and absolute lock time but
|
||||
/// disables relative lock time.
|
||||
#[deprecated(since = "TBD", note = "use `ENABLE_LOCKTIME_AND_RBF` instead")]
|
||||
pub const ENABLE_RBF_NO_LOCKTIME: Self = Sequence(0xFFFFFFFD);
|
||||
pub const ENABLE_RBF_NO_LOCKTIME: Self = Sequence(0xFFFF_FFFD);
|
||||
/// The maximum sequence number that enables replace-by-fee and absolute lock time but
|
||||
/// disables relative lock time.
|
||||
///
|
||||
/// This sequence number has no meaning other than to enable RBF and the absolute locktime.
|
||||
pub const ENABLE_LOCKTIME_AND_RBF: Self = Sequence(0xFFFFFFFD);
|
||||
pub const ENABLE_LOCKTIME_AND_RBF: Self = Sequence(0xFFFF_FFFD);
|
||||
|
||||
/// The number of bytes that a sequence number contributes to the size of a transaction.
|
||||
pub const SIZE: usize = 4; // Serialized length of a u32.
|
||||
|
@ -66,15 +66,15 @@ impl Sequence {
|
|||
/// (Explicit Signalling [BIP-125]).
|
||||
///
|
||||
/// [BIP-125]: <https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki]>
|
||||
const MIN_NO_RBF: Self = Sequence(0xFFFFFFFE);
|
||||
const MIN_NO_RBF: Self = Sequence(0xFFFF_FFFE);
|
||||
/// BIP-68 relative lock time disable flag mask.
|
||||
const LOCK_TIME_DISABLE_FLAG_MASK: u32 = 0x80000000;
|
||||
const LOCK_TIME_DISABLE_FLAG_MASK: u32 = 0x8000_0000;
|
||||
/// BIP-68 relative lock time type flag mask.
|
||||
const LOCK_TYPE_MASK: u32 = 0x00400000;
|
||||
const LOCK_TYPE_MASK: u32 = 0x0040_0000;
|
||||
|
||||
/// Returns `true` if the sequence number enables absolute lock-time ([`Transaction::lock_time`]).
|
||||
#[inline]
|
||||
pub fn enables_absolute_lock_time(&self) -> bool { *self != Sequence::MAX }
|
||||
pub fn enables_absolute_lock_time(self) -> bool { self != Sequence::MAX }
|
||||
|
||||
/// Returns `true` if the sequence number indicates that the transaction is finalized.
|
||||
///
|
||||
|
@ -96,30 +96,30 @@ impl Sequence {
|
|||
///
|
||||
/// [BIP-112]: <https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki>
|
||||
#[inline]
|
||||
pub fn is_final(&self) -> bool { !self.enables_absolute_lock_time() }
|
||||
pub fn is_final(self) -> bool { !self.enables_absolute_lock_time() }
|
||||
|
||||
/// Returns true if the transaction opted-in to BIP125 replace-by-fee.
|
||||
///
|
||||
/// Replace by fee is signaled by the sequence being less than 0xfffffffe which is checked by
|
||||
/// this method. Note, this is the highest "non-final" value (see [`Sequence::is_final`]).
|
||||
#[inline]
|
||||
pub fn is_rbf(&self) -> bool { *self < Sequence::MIN_NO_RBF }
|
||||
pub fn is_rbf(self) -> bool { self < Sequence::MIN_NO_RBF }
|
||||
|
||||
/// Returns `true` if the sequence has a relative lock-time.
|
||||
#[inline]
|
||||
pub fn is_relative_lock_time(&self) -> bool {
|
||||
pub fn is_relative_lock_time(self) -> bool {
|
||||
self.0 & Sequence::LOCK_TIME_DISABLE_FLAG_MASK == 0
|
||||
}
|
||||
|
||||
/// Returns `true` if the sequence number encodes a block based relative lock-time.
|
||||
#[inline]
|
||||
pub fn is_height_locked(&self) -> bool {
|
||||
pub fn is_height_locked(self) -> bool {
|
||||
self.is_relative_lock_time() & (self.0 & Sequence::LOCK_TYPE_MASK == 0)
|
||||
}
|
||||
|
||||
/// Returns `true` if the sequence number encodes a time interval based relative lock-time.
|
||||
#[inline]
|
||||
pub fn is_time_locked(&self) -> bool {
|
||||
pub fn is_time_locked(self) -> bool {
|
||||
self.is_relative_lock_time() & (self.0 & Sequence::LOCK_TYPE_MASK > 0)
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ impl Sequence {
|
|||
///
|
||||
/// BIP-68 only uses the low 16 bits for relative lock value.
|
||||
#[inline]
|
||||
fn low_u16(&self) -> u16 { self.0 as u16 }
|
||||
fn low_u16(self) -> u16 { self.0 as u16 }
|
||||
}
|
||||
|
||||
impl Default for Sequence {
|
||||
|
@ -319,9 +319,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn sequence_properties() {
|
||||
let seq_max = Sequence(0xFFFFFFFF);
|
||||
let seq_no_rbf = Sequence(0xFFFFFFFE);
|
||||
let seq_rbf = Sequence(0xFFFFFFFD);
|
||||
let seq_max = Sequence(0xFFFF_FFFF);
|
||||
let seq_no_rbf = Sequence(0xFFFF_FFFE);
|
||||
let seq_rbf = Sequence(0xFFFF_FFFD);
|
||||
|
||||
assert!(seq_max.is_final());
|
||||
assert!(!seq_no_rbf.is_final());
|
||||
|
@ -332,12 +332,12 @@ mod tests {
|
|||
assert!(seq_rbf.is_rbf());
|
||||
assert!(!seq_no_rbf.is_rbf());
|
||||
|
||||
let seq_relative = Sequence(0x7FFFFFFF);
|
||||
let seq_relative = Sequence(0x7FFF_FFFF);
|
||||
assert!(seq_relative.is_relative_lock_time());
|
||||
assert!(!seq_max.is_relative_lock_time());
|
||||
|
||||
let seq_height_locked = Sequence(0x00399999);
|
||||
let seq_time_locked = Sequence(0x00400000);
|
||||
let seq_height_locked = Sequence(0x0039_9999);
|
||||
let seq_time_locked = Sequence(0x0040_0000);
|
||||
assert!(seq_height_locked.is_height_locked());
|
||||
assert!(seq_time_locked.is_time_locked());
|
||||
assert!(!seq_time_locked.is_height_locked());
|
||||
|
@ -346,12 +346,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn sequence_formatting() {
|
||||
let sequence = Sequence(0x7FFFFFFF);
|
||||
let sequence = Sequence(0x7FFF_FFFF);
|
||||
assert_eq!(format!("{:x}", sequence), "7fffffff");
|
||||
assert_eq!(format!("{:X}", sequence), "7FFFFFFF");
|
||||
|
||||
// Test From<Sequence> for u32
|
||||
let sequence_u32: u32 = sequence.into();
|
||||
assert_eq!(sequence_u32, 0x7FFFFFFF);
|
||||
assert_eq!(sequence_u32, 0x7FFF_FFFF);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ fn hash_transaction(tx: &Transaction, uses_segwit_serialization: bool) -> sha256
|
|||
enc.input(compact_size::encode(script_sig_bytes.len()).as_slice());
|
||||
enc.input(script_sig_bytes);
|
||||
|
||||
enc.input(&input.sequence.0.to_le_bytes())
|
||||
enc.input(&input.sequence.0.to_le_bytes());
|
||||
}
|
||||
|
||||
// Encode outputs with leading compact size encoded int.
|
||||
|
@ -285,7 +285,7 @@ fn hash_transaction(tx: &Transaction, uses_segwit_serialization: bool) -> sha256
|
|||
for input in &tx.input {
|
||||
// Same as `Encodable for Witness`.
|
||||
enc.input(compact_size::encode(input.witness.len()).as_slice());
|
||||
for element in input.witness.iter() {
|
||||
for element in &input.witness {
|
||||
enc.input(compact_size::encode(element.len()).as_slice());
|
||||
enc.input(element);
|
||||
}
|
||||
|
@ -322,9 +322,9 @@ pub struct TxIn {
|
|||
/// the miner behavior cannot be enforced.
|
||||
pub sequence: Sequence,
|
||||
/// Witness data: an array of byte-arrays.
|
||||
/// Note that this field is *not* (de)serialized with the rest of the TxIn in
|
||||
/// Note that this field is *not* (de)serialized with the rest of the `TxIn` in
|
||||
/// Encodable/Decodable, as it is (de)serialized at the end of the full
|
||||
/// Transaction. It *is* (de)serialized with the rest of the TxIn in other
|
||||
/// Transaction. It *is* (de)serialized with the rest of the `TxIn` in other
|
||||
/// (de)serialization routines.
|
||||
pub witness: Witness,
|
||||
}
|
||||
|
@ -459,14 +459,14 @@ impl From<Infallible> for ParseOutPointError {
|
|||
#[cfg(feature = "alloc")]
|
||||
impl fmt::Display for ParseOutPointError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use ParseOutPointError::*;
|
||||
use ParseOutPointError as E;
|
||||
|
||||
match *self {
|
||||
Txid(ref e) => write_err!(f, "error parsing TXID"; e),
|
||||
Vout(ref e) => write_err!(f, "error parsing vout"; e),
|
||||
Format => write!(f, "OutPoint not in <txid>:<vout> format"),
|
||||
TooLong => write!(f, "vout should be at most 10 digits"),
|
||||
VoutNotCanonical => write!(f, "no leading zeroes or + allowed in vout part"),
|
||||
E::Txid(ref e) => write_err!(f, "error parsing TXID"; e),
|
||||
E::Vout(ref e) => write_err!(f, "error parsing vout"; e),
|
||||
E::Format => write!(f, "OutPoint not in <txid>:<vout> format"),
|
||||
E::TooLong => write!(f, "vout should be at most 10 digits"),
|
||||
E::VoutNotCanonical => write!(f, "no leading zeroes or + allowed in vout part"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -474,12 +474,12 @@ impl fmt::Display for ParseOutPointError {
|
|||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for ParseOutPointError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
use ParseOutPointError::*;
|
||||
use ParseOutPointError as E;
|
||||
|
||||
match self {
|
||||
Txid(e) => Some(e),
|
||||
Vout(e) => Some(e),
|
||||
Format | TooLong | VoutNotCanonical => None,
|
||||
E::Txid(e) => Some(e),
|
||||
E::Vout(e) => Some(e),
|
||||
E::Format | E::TooLong | E::VoutNotCanonical => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -561,8 +561,8 @@ impl Version {
|
|||
/// As of Bitcoin Core 28.0 ([release notes](https://bitcoincore.org/en/releases/28.0/)),
|
||||
/// versions 1, 2, and 3 are considered standard.
|
||||
#[inline]
|
||||
pub fn is_standard(&self) -> bool {
|
||||
*self == Version::ONE || *self == Version::TWO || *self == Version::THREE
|
||||
pub fn is_standard(self) -> bool {
|
||||
self == Version::ONE || self == Version::TWO || self == Version::THREE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,11 +657,11 @@ mod tests {
|
|||
witness: Witness::new(),
|
||||
};
|
||||
|
||||
let txout = TxOut { value: Amount::from_sat(123456789), script_pubkey: ScriptBuf::new() };
|
||||
let txout = TxOut { value: Amount::from_sat(123_456_789), script_pubkey: ScriptBuf::new() };
|
||||
|
||||
let tx_orig = Transaction {
|
||||
version: Version::ONE,
|
||||
lock_time: absolute::LockTime::from_consensus(1738968231), // The time this was written
|
||||
lock_time: absolute::LockTime::from_consensus(1_738_968_231), // The time this was written
|
||||
input: vec![txin.clone()],
|
||||
output: vec![txout.clone()],
|
||||
};
|
||||
|
@ -669,9 +669,9 @@ mod tests {
|
|||
// Test changing the transaction
|
||||
let mut tx = tx_orig.clone();
|
||||
tx.inputs_mut()[0].previous_output.txid = Txid::from_byte_array([0xFF; 32]);
|
||||
tx.outputs_mut()[0].value = Amount::from_sat(987654321);
|
||||
tx.outputs_mut()[0].value = Amount::from_sat(987_654_321);
|
||||
assert_eq!(tx.inputs()[0].previous_output.txid.to_byte_array(), [0xFF; 32]);
|
||||
assert_eq!(tx.outputs()[0].value.to_sat(), 987654321);
|
||||
assert_eq!(tx.outputs()[0].value.to_sat(), 987_654_321);
|
||||
|
||||
// Test uses_segwit_serialization
|
||||
assert!(!tx.uses_segwit_serialization());
|
||||
|
|
|
@ -100,7 +100,7 @@ impl Witness {
|
|||
|
||||
/// Convenience method to create an array of byte-arrays from this witness.
|
||||
#[inline]
|
||||
pub fn to_vec(&self) -> Vec<Vec<u8>> { self.iter().map(|s| s.to_vec()).collect() }
|
||||
pub fn to_vec(&self) -> Vec<Vec<u8>> { self.iter().map(<[u8]>::to_vec).collect() }
|
||||
|
||||
/// Returns `true` if the witness contains no element.
|
||||
#[inline]
|
||||
|
@ -172,17 +172,6 @@ impl Witness {
|
|||
.copy_from_slice(new_element);
|
||||
}
|
||||
|
||||
/// Note `index` is the index into the `content` vector and should be the result of calling
|
||||
/// `decode_cursor`, which returns a valid index.
|
||||
fn element_at(&self, index: usize) -> Option<&[u8]> {
|
||||
let mut slice = &self.content[index..]; // Start of element.
|
||||
let element_len = compact_size::decode_unchecked(&mut slice);
|
||||
// Compact size should always fit into a u32 because of `MAX_SIZE` in Core.
|
||||
// ref: https://github.com/rust-bitcoin/rust-bitcoin/issues/3264
|
||||
let end = element_len as usize;
|
||||
Some(&slice[..end])
|
||||
}
|
||||
|
||||
/// Returns the last element in the witness, if any.
|
||||
#[inline]
|
||||
pub fn last(&self) -> Option<&[u8]> {
|
||||
|
@ -217,7 +206,13 @@ impl Witness {
|
|||
#[inline]
|
||||
pub fn nth(&self, index: usize) -> Option<&[u8]> {
|
||||
let pos = decode_cursor(&self.content, self.indices_start, index)?;
|
||||
self.element_at(pos)
|
||||
|
||||
let mut slice = &self.content[pos..]; // Start of element.
|
||||
let element_len = compact_size::decode_unchecked(&mut slice);
|
||||
// Compact size should always fit into a u32 because of `MAX_SIZE` in Core.
|
||||
// ref: https://github.com/rust-bitcoin/rust-bitcoin/issues/3264
|
||||
let end = element_len as usize;
|
||||
Some(&slice[..end])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,9 +242,10 @@ fn decode_cursor(bytes: &[u8], start_of_indices: usize, index: usize) -> Option<
|
|||
/// - Number of witness elements
|
||||
/// - Total bytes across all elements
|
||||
/// - List of hex-encoded witness elements
|
||||
#[allow(clippy::missing_fields_in_debug)] // We don't want to show `indices_start`.
|
||||
impl fmt::Debug for Witness {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let total_bytes: usize = self.iter().map(|elem| elem.len()).sum();
|
||||
let total_bytes: usize = self.iter().map(<[u8]>::len).sum();
|
||||
|
||||
f.debug_struct("Witness")
|
||||
.field("num_elements", &self.witness_elements)
|
||||
|
@ -257,7 +253,7 @@ impl fmt::Debug for Witness {
|
|||
.field(
|
||||
"elements",
|
||||
&WrapDebug(|f| {
|
||||
f.debug_list().entries(self.iter().map(|elem| elem.as_hex())).finish()
|
||||
f.debug_list().entries(self.iter().map(DisplayHex::as_hex)).finish()
|
||||
}),
|
||||
)
|
||||
.finish()
|
||||
|
@ -323,7 +319,7 @@ impl serde::Serialize for Witness {
|
|||
let mut seq = serializer.serialize_seq(Some(self.witness_elements))?;
|
||||
|
||||
// Note that the `Iter` strips the varints out when iterating.
|
||||
for elem in self.iter() {
|
||||
for elem in self {
|
||||
if human_readable {
|
||||
seq.serialize_element(&internals::serde::SerializeBytesAsHex(elem))?;
|
||||
} else {
|
||||
|
@ -355,7 +351,7 @@ impl<'de> serde::Deserialize<'de> for Witness {
|
|||
mut a: A,
|
||||
) -> Result<Self::Value, A::Error> {
|
||||
use hex::FromHex;
|
||||
use hex::HexToBytesError::*;
|
||||
use hex::HexToBytesError as E;
|
||||
use serde::de::{self, Unexpected};
|
||||
|
||||
let mut ret = match a.size_hint() {
|
||||
|
@ -365,7 +361,7 @@ impl<'de> serde::Deserialize<'de> for Witness {
|
|||
|
||||
while let Some(elem) = a.next_element::<String>()? {
|
||||
let vec = Vec::<u8>::from_hex(&elem).map_err(|e| match e {
|
||||
InvalidChar(ref e) => match core::char::from_u32(e.invalid_char().into()) {
|
||||
E::InvalidChar(ref e) => match core::char::from_u32(e.invalid_char().into()) {
|
||||
Some(c) => de::Error::invalid_value(
|
||||
Unexpected::Char(c),
|
||||
&"a valid hex character",
|
||||
|
@ -375,7 +371,7 @@ impl<'de> serde::Deserialize<'de> for Witness {
|
|||
&"a valid hex character",
|
||||
),
|
||||
},
|
||||
OddLengthString(ref e) =>
|
||||
E::OddLengthString(ref e) =>
|
||||
de::Error::invalid_length(e.length(), &"an even length string"),
|
||||
})?;
|
||||
ret.push(vec);
|
||||
|
@ -459,7 +455,7 @@ mod test {
|
|||
let mut got = Witness::new();
|
||||
got.push([]);
|
||||
let want = single_empty_element();
|
||||
assert_eq!(got, want)
|
||||
assert_eq!(got, want);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in New Issue