witness: Improve element access methods with get() and get_back()
Enhance Witness struct element access methods: - Rename `nth()` to `get()` for clearer slice-like element retrieval - Introduce `get_back()` method for flexible reverse indexing - Remove redundant `second_to_last()` and `third_to_last()` methods - Add `#[track_caller]` to index implementation for better error tracking - Update all references to use new method names - Improve documentation with usage examples The changes provide a more intuitive and consistent approach to accessing witness elements.
This commit is contained in:
commit
3ca3218c23
|
@ -29,8 +29,8 @@ fn compute_sighash_p2wpkh(raw_tx: &[u8], inp_idx: usize, amount: Amount) {
|
||||||
// BIP-141: The witness must consist of exactly 2 items (≤ 520 bytes each). The first one a
|
// BIP-141: The witness must consist of exactly 2 items (≤ 520 bytes each). The first one a
|
||||||
// signature, and the second one a public key.
|
// signature, and the second one a public key.
|
||||||
assert_eq!(witness.len(), 2);
|
assert_eq!(witness.len(), 2);
|
||||||
let sig_bytes = witness.nth(0).unwrap();
|
let sig_bytes = witness.get(0).unwrap();
|
||||||
let pk_bytes = witness.nth(1).unwrap();
|
let pk_bytes = witness.get(1).unwrap();
|
||||||
|
|
||||||
let sig = ecdsa::Signature::from_slice(sig_bytes).expect("failed to parse sig");
|
let sig = ecdsa::Signature::from_slice(sig_bytes).expect("failed to parse sig");
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ fn compute_sighash_p2wsh(raw_tx: &[u8], inp_idx: usize, amount: Amount) {
|
||||||
|
|
||||||
//in an M of N multisig, the witness elements from 1 (0-based) to M-2 are signatures (with sighash flags as the last byte)
|
//in an M of N multisig, the witness elements from 1 (0-based) to M-2 are signatures (with sighash flags as the last byte)
|
||||||
for n in 1..=witness.len() - 2 {
|
for n in 1..=witness.len() - 2 {
|
||||||
let sig_bytes = witness.nth(n).expect("out of bounds");
|
let sig_bytes = witness.get(n).expect("out of bounds");
|
||||||
let sig = ecdsa::Signature::from_slice(sig_bytes).expect("failed to parse sig");
|
let sig = ecdsa::Signature::from_slice(sig_bytes).expect("failed to parse sig");
|
||||||
let sig_len = sig_bytes.len() - 1; //last byte is EcdsaSighashType sighash flag
|
let sig_len = sig_bytes.len() - 1; //last byte is EcdsaSighashType sighash flag
|
||||||
//ECDSA signature in DER format lengths are between 70 and 72 bytes
|
//ECDSA signature in DER format lengths are between 70 and 72 bytes
|
||||||
|
|
|
@ -257,7 +257,7 @@ impl<'a> P2TrSpend<'a> {
|
||||||
}),
|
}),
|
||||||
2 if witness.last().expect("len > 0").starts_with(&[TAPROOT_ANNEX_PREFIX]) => {
|
2 if witness.last().expect("len > 0").starts_with(&[TAPROOT_ANNEX_PREFIX]) => {
|
||||||
let spend = P2TrSpend::Key {
|
let spend = P2TrSpend::Key {
|
||||||
// signature: witness.second_to_last().expect("len > 1"),
|
// signature: witness.get_back(1).expect("len > 1"),
|
||||||
annex: witness.last(),
|
annex: witness.last(),
|
||||||
};
|
};
|
||||||
Some(spend)
|
Some(spend)
|
||||||
|
@ -267,15 +267,15 @@ impl<'a> P2TrSpend<'a> {
|
||||||
// arm.
|
// arm.
|
||||||
3.. if witness.last().expect("len > 0").starts_with(&[TAPROOT_ANNEX_PREFIX]) => {
|
3.. if witness.last().expect("len > 0").starts_with(&[TAPROOT_ANNEX_PREFIX]) => {
|
||||||
let spend = P2TrSpend::Script {
|
let spend = P2TrSpend::Script {
|
||||||
leaf_script: Script::from_bytes(witness.third_to_last().expect("len > 2")),
|
leaf_script: Script::from_bytes(witness.get_back(2).expect("len > 2")),
|
||||||
control_block: witness.second_to_last().expect("len > 1"),
|
control_block: witness.get_back(1).expect("len > 1"),
|
||||||
annex: witness.last(),
|
annex: witness.last(),
|
||||||
};
|
};
|
||||||
Some(spend)
|
Some(spend)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let spend = P2TrSpend::Script {
|
let spend = P2TrSpend::Script {
|
||||||
leaf_script: Script::from_bytes(witness.second_to_last().expect("len > 1")),
|
leaf_script: Script::from_bytes(witness.get_back(1).expect("len > 1")),
|
||||||
control_block: witness.last().expect("len > 0"),
|
control_block: witness.last().expect("len > 0"),
|
||||||
annex: None,
|
annex: None,
|
||||||
};
|
};
|
||||||
|
@ -514,13 +514,10 @@ mod test {
|
||||||
assert_eq!(expected_wit[i], wit_el.to_lower_hex_string());
|
assert_eq!(expected_wit[i], wit_el.to_lower_hex_string());
|
||||||
}
|
}
|
||||||
assert_eq!(expected_wit[1], tx.input[0].witness.last().unwrap().to_lower_hex_string());
|
assert_eq!(expected_wit[1], tx.input[0].witness.last().unwrap().to_lower_hex_string());
|
||||||
assert_eq!(
|
assert_eq!(expected_wit[0], tx.input[0].witness.get_back(1).unwrap().to_lower_hex_string());
|
||||||
expected_wit[0],
|
assert_eq!(expected_wit[0], tx.input[0].witness.get(0).unwrap().to_lower_hex_string());
|
||||||
tx.input[0].witness.second_to_last().unwrap().to_lower_hex_string()
|
assert_eq!(expected_wit[1], tx.input[0].witness.get(1).unwrap().to_lower_hex_string());
|
||||||
);
|
assert_eq!(None, tx.input[0].witness.get(2));
|
||||||
assert_eq!(expected_wit[0], tx.input[0].witness.nth(0).unwrap().to_lower_hex_string());
|
|
||||||
assert_eq!(expected_wit[1], tx.input[0].witness.nth(1).unwrap().to_lower_hex_string());
|
|
||||||
assert_eq!(None, tx.input[0].witness.nth(2));
|
|
||||||
assert_eq!(expected_wit[0], tx.input[0].witness[0].to_lower_hex_string());
|
assert_eq!(expected_wit[0], tx.input[0].witness[0].to_lower_hex_string());
|
||||||
assert_eq!(expected_wit[1], tx.input[0].witness[1].to_lower_hex_string());
|
assert_eq!(expected_wit[1], tx.input[0].witness[1].to_lower_hex_string());
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ where
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl Block<Unchecked> {
|
impl Block<Unchecked> {
|
||||||
/// Constructs a new `Block` without doing any validation.
|
/// Constructs a new `Block` without doing any validation.
|
||||||
|
#[inline]
|
||||||
pub fn new_unchecked(header: Header, transactions: Vec<Transaction>) -> Block<Unchecked> {
|
pub fn new_unchecked(header: Header, transactions: Vec<Transaction>) -> Block<Unchecked> {
|
||||||
Block { header, transactions, witness_root: None, marker: PhantomData::<Unchecked> }
|
Block { header, transactions, witness_root: None, marker: PhantomData::<Unchecked> }
|
||||||
}
|
}
|
||||||
|
@ -78,6 +79,7 @@ impl Block<Unchecked> {
|
||||||
///
|
///
|
||||||
/// You should only use this function if you trust the block i.e., it comes from a trusted node.
|
/// You should only use this function if you trust the block i.e., it comes from a trusted node.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
pub fn assume_checked(self, witness_root: Option<WitnessMerkleNode>) -> Block<Checked> {
|
pub fn assume_checked(self, witness_root: Option<WitnessMerkleNode>) -> Block<Checked> {
|
||||||
Block {
|
Block {
|
||||||
header: self.header,
|
header: self.header,
|
||||||
|
@ -88,37 +90,44 @@ impl Block<Unchecked> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decomposes block into its constituent parts.
|
/// Decomposes block into its constituent parts.
|
||||||
|
#[inline]
|
||||||
pub fn into_parts(self) -> (Header, Vec<Transaction>) { (self.header, self.transactions) }
|
pub fn into_parts(self) -> (Header, Vec<Transaction>) { (self.header, self.transactions) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl Block<Checked> {
|
impl Block<Checked> {
|
||||||
/// Gets a reference to the block header.
|
/// Gets a reference to the block header.
|
||||||
|
#[inline]
|
||||||
pub fn header(&self) -> &Header { &self.header }
|
pub fn header(&self) -> &Header { &self.header }
|
||||||
|
|
||||||
/// Gets a reference to the block's list of transactions.
|
/// Gets a reference to the block's list of transactions.
|
||||||
|
#[inline]
|
||||||
pub fn transactions(&self) -> &[Transaction] { &self.transactions }
|
pub fn transactions(&self) -> &[Transaction] { &self.transactions }
|
||||||
|
|
||||||
/// Returns the cached witness root if one is present.
|
/// Returns the cached witness root if one is present.
|
||||||
///
|
///
|
||||||
/// It is assumed that a block will have the witness root calculated and cached as part of the
|
/// It is assumed that a block will have the witness root calculated and cached as part of the
|
||||||
/// validation process.
|
/// validation process.
|
||||||
|
#[inline]
|
||||||
pub fn cached_witness_root(&self) -> Option<WitnessMerkleNode> { self.witness_root }
|
pub fn cached_witness_root(&self) -> Option<WitnessMerkleNode> { self.witness_root }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<V: Validation> Block<V> {
|
impl<V: Validation> Block<V> {
|
||||||
/// Returns the block hash.
|
/// Returns the block hash.
|
||||||
|
#[inline]
|
||||||
pub fn block_hash(&self) -> BlockHash { self.header.block_hash() }
|
pub fn block_hash(&self) -> BlockHash { self.header.block_hash() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl From<Block> for BlockHash {
|
impl From<Block> for BlockHash {
|
||||||
|
#[inline]
|
||||||
fn from(block: Block) -> BlockHash { block.block_hash() }
|
fn from(block: Block) -> BlockHash { block.block_hash() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl From<&Block> for BlockHash {
|
impl From<&Block> for BlockHash {
|
||||||
|
#[inline]
|
||||||
fn from(block: &Block) -> BlockHash { block.block_hash() }
|
fn from(block: &Block) -> BlockHash { block.block_hash() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,10 +221,12 @@ impl fmt::Debug for Header {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Header> for BlockHash {
|
impl From<Header> for BlockHash {
|
||||||
|
#[inline]
|
||||||
fn from(header: Header) -> BlockHash { header.block_hash() }
|
fn from(header: Header) -> BlockHash { header.block_hash() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Header> for BlockHash {
|
impl From<&Header> for BlockHash {
|
||||||
|
#[inline]
|
||||||
fn from(header: &Header) -> BlockHash { header.block_hash() }
|
fn from(header: &Header) -> BlockHash { header.block_hash() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +274,7 @@ impl Version {
|
||||||
/// Returns the inner `i32` value.
|
/// Returns the inner `i32` value.
|
||||||
///
|
///
|
||||||
/// This is the data type used in consensus code in Bitcoin Core.
|
/// This is the data type used in consensus code in Bitcoin Core.
|
||||||
|
#[inline]
|
||||||
pub fn to_consensus(self) -> i32 { self.0 }
|
pub fn to_consensus(self) -> i32 { self.0 }
|
||||||
|
|
||||||
/// Checks whether the version number is signalling a soft fork at the given bit.
|
/// Checks whether the version number is signalling a soft fork at the given bit.
|
||||||
|
@ -286,6 +298,7 @@ impl Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Version {
|
impl Default for Version {
|
||||||
|
#[inline]
|
||||||
fn default() -> Version { Self::NO_SOFT_FORK_SIGNALLING }
|
fn default() -> Version { Self::NO_SOFT_FORK_SIGNALLING }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,7 @@ impl LockTime {
|
||||||
///
|
///
|
||||||
/// # Ok::<_, units::parse::PrefixedHexError>(())
|
/// # Ok::<_, units::parse::PrefixedHexError>(())
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
|
pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
|
||||||
let lock_time = parse::hex_u32_prefixed(s)?;
|
let lock_time = parse::hex_u32_prefixed(s)?;
|
||||||
Ok(Self::from_consensus(lock_time))
|
Ok(Self::from_consensus(lock_time))
|
||||||
|
@ -119,6 +120,7 @@ impl LockTime {
|
||||||
///
|
///
|
||||||
/// # Ok::<_, units::parse::UnprefixedHexError>(())
|
/// # Ok::<_, units::parse::UnprefixedHexError>(())
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
||||||
let lock_time = parse::hex_u32_unprefixed(s)?;
|
let lock_time = parse::hex_u32_unprefixed(s)?;
|
||||||
Ok(Self::from_consensus(lock_time))
|
Ok(Self::from_consensus(lock_time))
|
||||||
|
@ -320,6 +322,7 @@ impl From<Time> for LockTime {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for LockTime {
|
impl fmt::Debug for LockTime {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use LockTime::*;
|
use LockTime::*;
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ impl LockTime {
|
||||||
///
|
///
|
||||||
/// # Ok::<_, bitcoin_primitives::relative::DisabledLockTimeError>(())
|
/// # Ok::<_, bitcoin_primitives::relative::DisabledLockTimeError>(())
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
pub fn from_consensus(n: u32) -> Result<Self, DisabledLockTimeError> {
|
pub fn from_consensus(n: u32) -> Result<Self, DisabledLockTimeError> {
|
||||||
let sequence = crate::Sequence::from_consensus(n);
|
let sequence = crate::Sequence::from_consensus(n);
|
||||||
sequence.to_relative_lock_time().ok_or(DisabledLockTimeError(n))
|
sequence.to_relative_lock_time().ok_or(DisabledLockTimeError(n))
|
||||||
|
@ -370,12 +371,14 @@ impl fmt::Display for LockTime {
|
||||||
|
|
||||||
impl convert::TryFrom<Sequence> for LockTime {
|
impl convert::TryFrom<Sequence> for LockTime {
|
||||||
type Error = DisabledLockTimeError;
|
type Error = DisabledLockTimeError;
|
||||||
|
#[inline]
|
||||||
fn try_from(seq: Sequence) -> Result<LockTime, DisabledLockTimeError> {
|
fn try_from(seq: Sequence) -> Result<LockTime, DisabledLockTimeError> {
|
||||||
LockTime::from_sequence(seq)
|
LockTime::from_sequence(seq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LockTime> for Sequence {
|
impl From<LockTime> for Sequence {
|
||||||
|
#[inline]
|
||||||
fn from(lt: LockTime) -> Sequence { lt.to_sequence() }
|
fn from(lt: LockTime) -> Sequence { lt.to_sequence() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,10 +390,12 @@ pub struct DisabledLockTimeError(u32);
|
||||||
impl DisabledLockTimeError {
|
impl DisabledLockTimeError {
|
||||||
/// Accessor for the `u32` whose "disable" flag was set, preventing
|
/// Accessor for the `u32` whose "disable" flag was set, preventing
|
||||||
/// it from being parsed as a relative locktime.
|
/// it from being parsed as a relative locktime.
|
||||||
|
#[inline]
|
||||||
pub fn disabled_locktime_value(&self) -> u32 { self.0 }
|
pub fn disabled_locktime_value(&self) -> u32 { self.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for DisabledLockTimeError {
|
impl fmt::Display for DisabledLockTimeError {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "lock time 0x{:08x} has disable flag set", self.0)
|
write!(f, "lock time 0x{:08x} has disable flag set", self.0)
|
||||||
}
|
}
|
||||||
|
@ -417,6 +422,7 @@ impl IncompatibleHeightError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for IncompatibleHeightError {
|
impl fmt::Display for IncompatibleHeightError {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
@ -447,6 +453,7 @@ impl IncompatibleTimeError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for IncompatibleTimeError {
|
impl fmt::Display for IncompatibleTimeError {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
|
|
@ -440,6 +440,7 @@ impl From<u8> for Opcode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Opcode {
|
impl fmt::Debug for Opcode {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Display::fmt(self, f) }
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Display::fmt(self, f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,11 @@ pub struct CompactTarget(u32);
|
||||||
|
|
||||||
impl CompactTarget {
|
impl CompactTarget {
|
||||||
/// Constructs a new [`CompactTarget`] from a consensus encoded `u32`.
|
/// Constructs a new [`CompactTarget`] from a consensus encoded `u32`.
|
||||||
|
#[inline]
|
||||||
pub fn from_consensus(bits: u32) -> Self { Self(bits) }
|
pub fn from_consensus(bits: u32) -> Self { Self(bits) }
|
||||||
|
|
||||||
/// Returns the consensus encoded `u32` representation of this [`CompactTarget`].
|
/// Returns the consensus encoded `u32` representation of this [`CompactTarget`].
|
||||||
|
#[inline]
|
||||||
pub fn to_consensus(self) -> u32 { self.0 }
|
pub fn to_consensus(self) -> u32 { self.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,12 +124,14 @@ impl Sequence {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a new `Sequence` from a prefixed hex string.
|
/// Constructs a new `Sequence` from a prefixed hex string.
|
||||||
|
#[inline]
|
||||||
pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
|
pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
|
||||||
let lock_time = parse::hex_u32_prefixed(s)?;
|
let lock_time = parse::hex_u32_prefixed(s)?;
|
||||||
Ok(Self::from_consensus(lock_time))
|
Ok(Self::from_consensus(lock_time))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a new `Sequence` from an unprefixed hex string.
|
/// Constructs a new `Sequence` from an unprefixed hex string.
|
||||||
|
#[inline]
|
||||||
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
||||||
let lock_time = parse::hex_u32_unprefixed(s)?;
|
let lock_time = parse::hex_u32_unprefixed(s)?;
|
||||||
Ok(Self::from_consensus(lock_time))
|
Ok(Self::from_consensus(lock_time))
|
||||||
|
@ -203,23 +205,28 @@ impl Sequence {
|
||||||
/// Returns the low 16 bits from sequence number.
|
/// Returns the low 16 bits from sequence number.
|
||||||
///
|
///
|
||||||
/// BIP-68 only uses the low 16 bits for relative lock value.
|
/// 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 {
|
impl Default for Sequence {
|
||||||
/// The default value of sequence is 0xffffffff.
|
/// The default value of sequence is 0xffffffff.
|
||||||
|
#[inline]
|
||||||
fn default() -> Self { Sequence::MAX }
|
fn default() -> Self { Sequence::MAX }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Sequence> for u32 {
|
impl From<Sequence> for u32 {
|
||||||
|
#[inline]
|
||||||
fn from(sequence: Sequence) -> u32 { sequence.0 }
|
fn from(sequence: Sequence) -> u32 { sequence.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Sequence {
|
impl fmt::Display for Sequence {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::LowerHex for Sequence {
|
impl fmt::LowerHex for Sequence {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
|
||||||
}
|
}
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
|
@ -228,10 +235,12 @@ internals::impl_to_hex_from_lower_hex!(Sequence, |sequence: &Sequence| {
|
||||||
});
|
});
|
||||||
|
|
||||||
impl fmt::UpperHex for Sequence {
|
impl fmt::UpperHex for Sequence {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Sequence {
|
impl fmt::Debug for Sequence {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
// 10 because its 8 digits + 2 for the '0x'
|
// 10 because its 8 digits + 2 for the '0x'
|
||||||
write!(f, "Sequence({:#010x})", self.0)
|
write!(f, "Sequence({:#010x})", self.0)
|
||||||
|
|
|
@ -115,15 +115,19 @@ impl Transaction {
|
||||||
pub const MAX_STANDARD_WEIGHT: Weight = Weight::from_wu(400_000);
|
pub const MAX_STANDARD_WEIGHT: Weight = Weight::from_wu(400_000);
|
||||||
|
|
||||||
/// Returns a reference to the transaction inputs.
|
/// Returns a reference to the transaction inputs.
|
||||||
|
#[inline]
|
||||||
pub fn inputs(&self) -> &[TxIn] { &self.input }
|
pub fn inputs(&self) -> &[TxIn] { &self.input }
|
||||||
|
|
||||||
/// Returns a mutable reference to the transaction inputs.
|
/// Returns a mutable reference to the transaction inputs.
|
||||||
|
#[inline]
|
||||||
pub fn inputs_mut(&mut self) -> &mut [TxIn] { &mut self.input }
|
pub fn inputs_mut(&mut self) -> &mut [TxIn] { &mut self.input }
|
||||||
|
|
||||||
/// Returns a reference to the transaction outputs.
|
/// Returns a reference to the transaction outputs.
|
||||||
|
#[inline]
|
||||||
pub fn outputs(&self) -> &[TxOut] { &self.output }
|
pub fn outputs(&self) -> &[TxOut] { &self.output }
|
||||||
|
|
||||||
/// Returns a mutable reference to the transaction outputs.
|
/// Returns a mutable reference to the transaction outputs.
|
||||||
|
#[inline]
|
||||||
pub fn outputs_mut(&mut self) -> &mut [TxOut] { &mut self.output }
|
pub fn outputs_mut(&mut self) -> &mut [TxOut] { &mut self.output }
|
||||||
|
|
||||||
/// Computes a "normalized TXID" which does not include any signatures.
|
/// Computes a "normalized TXID" which does not include any signatures.
|
||||||
|
@ -155,6 +159,7 @@ impl Transaction {
|
||||||
/// witness fields themselves). For non-SegWit transactions which do not have any SegWit data,
|
/// witness fields themselves). For non-SegWit transactions which do not have any SegWit data,
|
||||||
/// this will be equal to [`Transaction::compute_wtxid()`].
|
/// this will be equal to [`Transaction::compute_wtxid()`].
|
||||||
#[doc(alias = "txid")]
|
#[doc(alias = "txid")]
|
||||||
|
#[inline]
|
||||||
pub fn compute_txid(&self) -> Txid {
|
pub fn compute_txid(&self) -> Txid {
|
||||||
let hash = hash_transaction(self, false);
|
let hash = hash_transaction(self, false);
|
||||||
Txid::from_byte_array(hash.to_byte_array())
|
Txid::from_byte_array(hash.to_byte_array())
|
||||||
|
@ -166,6 +171,7 @@ impl Transaction {
|
||||||
/// witness fields themselves). For non-SegWit transactions which do not have any SegWit data,
|
/// witness fields themselves). For non-SegWit transactions which do not have any SegWit data,
|
||||||
/// this will be equal to [`Transaction::compute_txid()`].
|
/// this will be equal to [`Transaction::compute_txid()`].
|
||||||
#[doc(alias = "wtxid")]
|
#[doc(alias = "wtxid")]
|
||||||
|
#[inline]
|
||||||
pub fn compute_wtxid(&self) -> Wtxid {
|
pub fn compute_wtxid(&self) -> Wtxid {
|
||||||
let hash = hash_transaction(self, self.uses_segwit_serialization());
|
let hash = hash_transaction(self, self.uses_segwit_serialization());
|
||||||
Wtxid::from_byte_array(hash.to_byte_array())
|
Wtxid::from_byte_array(hash.to_byte_array())
|
||||||
|
@ -173,6 +179,7 @@ impl Transaction {
|
||||||
|
|
||||||
/// Returns whether or not to serialize transaction as specified in BIP-144.
|
/// Returns whether or not to serialize transaction as specified in BIP-144.
|
||||||
// This is duplicated in `bitcoin`, if you change it please do so in both places.
|
// This is duplicated in `bitcoin`, if you change it please do so in both places.
|
||||||
|
#[inline]
|
||||||
fn uses_segwit_serialization(&self) -> bool {
|
fn uses_segwit_serialization(&self) -> bool {
|
||||||
if self.input.iter().any(|input| !input.witness.is_empty()) {
|
if self.input.iter().any(|input| !input.witness.is_empty()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -185,6 +192,7 @@ impl Transaction {
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl cmp::PartialOrd for Transaction {
|
impl cmp::PartialOrd for Transaction {
|
||||||
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,21 +209,25 @@ impl cmp::Ord for Transaction {
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl From<Transaction> for Txid {
|
impl From<Transaction> for Txid {
|
||||||
|
#[inline]
|
||||||
fn from(tx: Transaction) -> Txid { tx.compute_txid() }
|
fn from(tx: Transaction) -> Txid { tx.compute_txid() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl From<&Transaction> for Txid {
|
impl From<&Transaction> for Txid {
|
||||||
|
#[inline]
|
||||||
fn from(tx: &Transaction) -> Txid { tx.compute_txid() }
|
fn from(tx: &Transaction) -> Txid { tx.compute_txid() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl From<Transaction> for Wtxid {
|
impl From<Transaction> for Wtxid {
|
||||||
|
#[inline]
|
||||||
fn from(tx: Transaction) -> Wtxid { tx.compute_wtxid() }
|
fn from(tx: Transaction) -> Wtxid { tx.compute_wtxid() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl From<&Transaction> for Wtxid {
|
impl From<&Transaction> for Wtxid {
|
||||||
|
#[inline]
|
||||||
fn from(tx: &Transaction) -> Wtxid { tx.compute_wtxid() }
|
fn from(tx: &Transaction) -> Wtxid { tx.compute_wtxid() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,6 +389,7 @@ impl OutPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for OutPoint {
|
impl fmt::Display for OutPoint {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}:{}", self.txid, self.vout)
|
write!(f, "{}:{}", self.txid, self.vout)
|
||||||
}
|
}
|
||||||
|
@ -439,6 +452,7 @@ pub enum ParseOutPointError {
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl From<Infallible> for ParseOutPointError {
|
impl From<Infallible> for ParseOutPointError {
|
||||||
|
#[inline]
|
||||||
fn from(never: Infallible) -> Self { match never {} }
|
fn from(never: Infallible) -> Self { match never {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,10 +567,12 @@ impl Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Version {
|
impl fmt::Display for Version {
|
||||||
|
#[inline]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Version> for u32 {
|
impl From<Version> for u32 {
|
||||||
|
#[inline]
|
||||||
fn from(version: Version) -> Self { version.0 }
|
fn from(version: Version) -> Self { version.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,18 +99,22 @@ impl Witness {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to create an array of byte-arrays from this 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(|s| s.to_vec()).collect() }
|
||||||
|
|
||||||
/// Returns `true` if the witness contains no element.
|
/// Returns `true` if the witness contains no element.
|
||||||
|
#[inline]
|
||||||
pub fn is_empty(&self) -> bool { self.witness_elements == 0 }
|
pub fn is_empty(&self) -> bool { self.witness_elements == 0 }
|
||||||
|
|
||||||
/// Returns a struct implementing [`Iterator`].
|
/// Returns a struct implementing [`Iterator`].
|
||||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||||
|
#[inline]
|
||||||
pub fn iter(&self) -> Iter {
|
pub fn iter(&self) -> Iter {
|
||||||
Iter { inner: self.content.as_slice(), indices_start: self.indices_start, current_index: 0 }
|
Iter { inner: self.content.as_slice(), indices_start: self.indices_start, current_index: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of elements this witness holds.
|
/// Returns the number of elements this witness holds.
|
||||||
|
#[inline]
|
||||||
pub fn len(&self) -> usize { self.witness_elements }
|
pub fn len(&self) -> usize { self.witness_elements }
|
||||||
|
|
||||||
/// Returns the number of bytes this witness contributes to a transactions total size.
|
/// Returns the number of bytes this witness contributes to a transactions total size.
|
||||||
|
@ -130,6 +134,7 @@ impl Witness {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the witness.
|
/// Clear the witness.
|
||||||
|
#[inline]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.content.clear();
|
self.content.clear();
|
||||||
self.witness_elements = 0;
|
self.witness_elements = 0;
|
||||||
|
@ -137,6 +142,7 @@ impl Witness {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a new element on the witness, requires an allocation.
|
/// Push a new element on the witness, requires an allocation.
|
||||||
|
#[inline]
|
||||||
pub fn push<T: AsRef<[u8]>>(&mut self, new_element: T) {
|
pub fn push<T: AsRef<[u8]>>(&mut self, new_element: T) {
|
||||||
self.push_slice(new_element.as_ref());
|
self.push_slice(new_element.as_ref());
|
||||||
}
|
}
|
||||||
|
@ -178,34 +184,42 @@ impl Witness {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last element in the witness, if any.
|
/// Returns the last element in the witness, if any.
|
||||||
pub fn last(&self) -> Option<&[u8]> {
|
#[inline]
|
||||||
if self.witness_elements == 0 {
|
pub fn last(&self) -> Option<&[u8]> { self.get_back(0) }
|
||||||
|
|
||||||
|
/// Retrieves an element from the end of the witness by its reverse index.
|
||||||
|
///
|
||||||
|
/// `index` is 0-based from the end, where 0 is the last element, 1 is the second-to-last, etc.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the requested index is beyond the witness's elements.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use bitcoin_primitives::witness::Witness;
|
||||||
|
///
|
||||||
|
/// let mut witness = Witness::new();
|
||||||
|
/// witness.push(b"A");
|
||||||
|
/// witness.push(b"B");
|
||||||
|
/// witness.push(b"C");
|
||||||
|
/// witness.push(b"D");
|
||||||
|
///
|
||||||
|
/// assert_eq!(witness.get_back(0), Some(b"D".as_slice()));
|
||||||
|
/// assert_eq!(witness.get_back(1), Some(b"C".as_slice()));
|
||||||
|
/// assert_eq!(witness.get_back(2), Some(b"B".as_slice()));
|
||||||
|
/// assert_eq!(witness.get_back(3), Some(b"A".as_slice()));
|
||||||
|
/// assert_eq!(witness.get_back(4), None);
|
||||||
|
/// ```
|
||||||
|
pub fn get_back(&self, index: usize) -> Option<&[u8]> {
|
||||||
|
if self.witness_elements <= index {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
self.nth(self.witness_elements - 1)
|
self.get(self.witness_elements - 1 - index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the second-to-last element in the witness, if any.
|
/// Returns a specific element from the witness by its index, if any.
|
||||||
pub fn second_to_last(&self) -> Option<&[u8]> {
|
#[inline]
|
||||||
if self.witness_elements <= 1 {
|
pub fn get(&self, index: usize) -> Option<&[u8]> {
|
||||||
None
|
|
||||||
} else {
|
|
||||||
self.nth(self.witness_elements - 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the third-to-last element in the witness, if any.
|
|
||||||
pub fn third_to_last(&self) -> Option<&[u8]> {
|
|
||||||
if self.witness_elements <= 2 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
self.nth(self.witness_elements - 3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the nth element in the witness, if any
|
|
||||||
pub fn nth(&self, index: usize) -> Option<&[u8]> {
|
|
||||||
let pos = decode_cursor(&self.content, self.indices_start, index)?;
|
let pos = decode_cursor(&self.content, self.indices_start, index)?;
|
||||||
self.element_at(pos)
|
self.element_at(pos)
|
||||||
}
|
}
|
||||||
|
@ -264,7 +278,9 @@ pub struct Iter<'a> {
|
||||||
impl Index<usize> for Witness {
|
impl Index<usize> for Witness {
|
||||||
type Output = [u8];
|
type Output = [u8];
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output { self.nth(index).expect("out of bounds") }
|
#[track_caller]
|
||||||
|
#[inline]
|
||||||
|
fn index(&self, index: usize) -> &Self::Output { self.get(index).expect("out of bounds") }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Iter<'a> {
|
impl<'a> Iterator for Iter<'a> {
|
||||||
|
@ -281,6 +297,7 @@ impl<'a> Iterator for Iter<'a> {
|
||||||
Some(&slice[..end])
|
Some(&slice[..end])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
let total_count = (self.inner.len() - self.indices_start) / 4;
|
let total_count = (self.inner.len() - self.indices_start) / 4;
|
||||||
let remaining = total_count - self.current_index;
|
let remaining = total_count - self.current_index;
|
||||||
|
@ -294,6 +311,7 @@ impl<'a> IntoIterator for &'a Witness {
|
||||||
type IntoIter = Iter<'a>;
|
type IntoIter = Iter<'a>;
|
||||||
type Item = &'a [u8];
|
type Item = &'a [u8];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn into_iter(self) -> Self::IntoIter { self.iter() }
|
fn into_iter(self) -> Self::IntoIter { self.iter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,22 +399,27 @@ impl<'de> serde::Deserialize<'de> for Witness {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Vec<u8>>> for Witness {
|
impl From<Vec<Vec<u8>>> for Witness {
|
||||||
|
#[inline]
|
||||||
fn from(vec: Vec<Vec<u8>>) -> Self { Witness::from_slice(&vec) }
|
fn from(vec: Vec<Vec<u8>>) -> Self { Witness::from_slice(&vec) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[&[u8]]> for Witness {
|
impl From<&[&[u8]]> for Witness {
|
||||||
|
#[inline]
|
||||||
fn from(slice: &[&[u8]]) -> Self { Witness::from_slice(slice) }
|
fn from(slice: &[&[u8]]) -> Self { Witness::from_slice(slice) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[Vec<u8>]> for Witness {
|
impl From<&[Vec<u8>]> for Witness {
|
||||||
|
#[inline]
|
||||||
fn from(slice: &[Vec<u8>]) -> Self { Witness::from_slice(slice) }
|
fn from(slice: &[Vec<u8>]) -> Self { Witness::from_slice(slice) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<&[u8]>> for Witness {
|
impl From<Vec<&[u8]>> for Witness {
|
||||||
|
#[inline]
|
||||||
fn from(vec: Vec<&[u8]>) -> Self { Witness::from_slice(&vec) }
|
fn from(vec: Vec<&[u8]>) -> Self { Witness::from_slice(&vec) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Witness {
|
impl Default for Witness {
|
||||||
|
#[inline]
|
||||||
fn default() -> Self { Self::new() }
|
fn default() -> Self { Self::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,12 +473,12 @@ mod test {
|
||||||
let mut witness = Witness::default();
|
let mut witness = Witness::default();
|
||||||
assert!(witness.is_empty());
|
assert!(witness.is_empty());
|
||||||
assert_eq!(witness.last(), None);
|
assert_eq!(witness.last(), None);
|
||||||
assert_eq!(witness.second_to_last(), None);
|
assert_eq!(witness.get_back(1), None);
|
||||||
|
|
||||||
assert_eq!(witness.nth(0), None);
|
assert_eq!(witness.get(0), None);
|
||||||
assert_eq!(witness.nth(1), None);
|
assert_eq!(witness.get(1), None);
|
||||||
assert_eq!(witness.nth(2), None);
|
assert_eq!(witness.get(2), None);
|
||||||
assert_eq!(witness.nth(3), None);
|
assert_eq!(witness.get(3), None);
|
||||||
|
|
||||||
// Push a single byte element onto the witness stack.
|
// Push a single byte element onto the witness stack.
|
||||||
let push = [11_u8];
|
let push = [11_u8];
|
||||||
|
@ -473,13 +496,13 @@ mod test {
|
||||||
let element_0 = push.as_slice();
|
let element_0 = push.as_slice();
|
||||||
assert_eq!(element_0, &witness[0]);
|
assert_eq!(element_0, &witness[0]);
|
||||||
|
|
||||||
assert_eq!(witness.second_to_last(), None);
|
assert_eq!(witness.get_back(1), None);
|
||||||
assert_eq!(witness.last(), Some(element_0));
|
assert_eq!(witness.last(), Some(element_0));
|
||||||
|
|
||||||
assert_eq!(witness.nth(0), Some(element_0));
|
assert_eq!(witness.get(0), Some(element_0));
|
||||||
assert_eq!(witness.nth(1), None);
|
assert_eq!(witness.get(1), None);
|
||||||
assert_eq!(witness.nth(2), None);
|
assert_eq!(witness.get(2), None);
|
||||||
assert_eq!(witness.nth(3), None);
|
assert_eq!(witness.get(3), None);
|
||||||
|
|
||||||
// Now push 2 byte element onto the witness stack.
|
// Now push 2 byte element onto the witness stack.
|
||||||
let push = [21u8, 22u8];
|
let push = [21u8, 22u8];
|
||||||
|
@ -496,12 +519,12 @@ mod test {
|
||||||
let element_1 = push.as_slice();
|
let element_1 = push.as_slice();
|
||||||
assert_eq!(element_1, &witness[1]);
|
assert_eq!(element_1, &witness[1]);
|
||||||
|
|
||||||
assert_eq!(witness.nth(0), Some(element_0));
|
assert_eq!(witness.get(0), Some(element_0));
|
||||||
assert_eq!(witness.nth(1), Some(element_1));
|
assert_eq!(witness.get(1), Some(element_1));
|
||||||
assert_eq!(witness.nth(2), None);
|
assert_eq!(witness.get(2), None);
|
||||||
assert_eq!(witness.nth(3), None);
|
assert_eq!(witness.get(3), None);
|
||||||
|
|
||||||
assert_eq!(witness.second_to_last(), Some(element_0));
|
assert_eq!(witness.get_back(1), Some(element_0));
|
||||||
assert_eq!(witness.last(), Some(element_1));
|
assert_eq!(witness.last(), Some(element_1));
|
||||||
|
|
||||||
// Now push another 2 byte element onto the witness stack.
|
// Now push another 2 byte element onto the witness stack.
|
||||||
|
@ -519,13 +542,13 @@ mod test {
|
||||||
let element_2 = push.as_slice();
|
let element_2 = push.as_slice();
|
||||||
assert_eq!(element_2, &witness[2]);
|
assert_eq!(element_2, &witness[2]);
|
||||||
|
|
||||||
assert_eq!(witness.nth(0), Some(element_0));
|
assert_eq!(witness.get(0), Some(element_0));
|
||||||
assert_eq!(witness.nth(1), Some(element_1));
|
assert_eq!(witness.get(1), Some(element_1));
|
||||||
assert_eq!(witness.nth(2), Some(element_2));
|
assert_eq!(witness.get(2), Some(element_2));
|
||||||
assert_eq!(witness.nth(3), None);
|
assert_eq!(witness.get(3), None);
|
||||||
|
|
||||||
assert_eq!(witness.third_to_last(), Some(element_0));
|
assert_eq!(witness.get_back(2), Some(element_0));
|
||||||
assert_eq!(witness.second_to_last(), Some(element_1));
|
assert_eq!(witness.get_back(1), Some(element_1));
|
||||||
assert_eq!(witness.last(), Some(element_2));
|
assert_eq!(witness.last(), Some(element_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,8 +579,8 @@ mod test {
|
||||||
let indices_start = elements.len();
|
let indices_start = elements.len();
|
||||||
let witness =
|
let witness =
|
||||||
Witness::from_parts__unstable(content.clone(), witness_elements, indices_start);
|
Witness::from_parts__unstable(content.clone(), witness_elements, indices_start);
|
||||||
assert_eq!(witness.nth(0).unwrap(), [11_u8]);
|
assert_eq!(witness.get(0).unwrap(), [11_u8]);
|
||||||
assert_eq!(witness.nth(1).unwrap(), [21_u8, 22]);
|
assert_eq!(witness.get(1).unwrap(), [21_u8, 22]);
|
||||||
assert_eq!(witness.size(), 6);
|
assert_eq!(witness.size(), 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue