Merge rust-bitcoin/rust-bitcoin#2929: Introduce `ToU64` trait
579b76b7cb
Introduce ToU64 conversion trait (Tobin C. Harding) Pull request description: The idea for this was pulled out of Steven's work in #2133 We already explicitly do not support 16 bit machines. Also, because Rust supports `u182`s one cannot infallibly convert from a `usize` to a `u64`. This is unergonomic and results in a ton of casts. We can instead limit our code to running only on machines where `usize` is less that or equal to 64 bits then the infallible conversion is possible. Since 128 bit machines are not a thing yet this does not in reality introduce any limitations on the library. Add a "private" trait to the `internals` crate to do infallible conversion to a `u64` from `usize`. Implement it for all unsigned integers smaller than `u64` as well so we have the option to use the trait instead of `u32::from(foo)`. ACKs for top commit: Kixunil: ACK579b76b7cb
apoelstra: ACK579b76b7cb
successfully ran local tests Tree-SHA512: 2eaddfff995987a346e052386c6dfef3510e4732e674e3a2cfab60ee391b4cce1bf7ba4fb2dfd4926f8203d7251eea2198ccb61f0b40332e624c88fda4fa7f48
This commit is contained in:
commit
c59b9e3d1a
|
@ -9,7 +9,7 @@ use core::{convert, fmt, mem};
|
||||||
use std::error;
|
use std::error;
|
||||||
|
|
||||||
use hashes::{sha256, siphash24};
|
use hashes::{sha256, siphash24};
|
||||||
use internals::impl_array_newtype;
|
use internals::{impl_array_newtype, ToU64 as _};
|
||||||
use io::{BufRead, Write};
|
use io::{BufRead, Write};
|
||||||
|
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable, VarInt};
|
use crate::consensus::encode::{self, Decodable, Encodable, VarInt};
|
||||||
|
@ -287,7 +287,7 @@ impl Encodable for BlockTransactionsRequest {
|
||||||
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = self.block_hash.consensus_encode(w)?;
|
let mut len = self.block_hash.consensus_encode(w)?;
|
||||||
// Manually encode indexes because they are differentially encoded VarInts.
|
// Manually encode indexes because they are differentially encoded VarInts.
|
||||||
len += VarInt(self.indexes.len() as u64).consensus_encode(w)?;
|
len += VarInt(self.indexes.len().to_u64()).consensus_encode(w)?;
|
||||||
let mut last_idx = 0;
|
let mut last_idx = 0;
|
||||||
for idx in &self.indexes {
|
for idx in &self.indexes {
|
||||||
len += VarInt(*idx - last_idx).consensus_encode(w)?;
|
len += VarInt(*idx - last_idx).consensus_encode(w)?;
|
||||||
|
@ -383,7 +383,7 @@ impl BlockTransactions {
|
||||||
transactions: {
|
transactions: {
|
||||||
let mut txs = Vec::with_capacity(request.indexes.len());
|
let mut txs = Vec::with_capacity(request.indexes.len());
|
||||||
for idx in &request.indexes {
|
for idx in &request.indexes {
|
||||||
if *idx >= block.txdata.len() as u64 {
|
if *idx >= block.txdata.len().to_u64() {
|
||||||
return Err(TxIndexOutOfRangeError(*idx));
|
return Err(TxIndexOutOfRangeError(*idx));
|
||||||
}
|
}
|
||||||
txs.push(block.txdata[*idx as usize].clone());
|
txs.push(block.txdata[*idx as usize].clone());
|
||||||
|
|
|
@ -41,7 +41,7 @@ use core::cmp::{self, Ordering};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use hashes::{sha256d, siphash24, HashEngine as _};
|
use hashes::{sha256d, siphash24, HashEngine as _};
|
||||||
use internals::write_err;
|
use internals::{write_err, ToU64 as _};
|
||||||
use io::{BufRead, Write};
|
use io::{BufRead, Write};
|
||||||
|
|
||||||
use crate::block::{Block, BlockHash};
|
use crate::block::{Block, BlockHash};
|
||||||
|
@ -387,7 +387,7 @@ impl<'a, W: Write> GcsFilterWriter<'a, W> {
|
||||||
|
|
||||||
/// Writes the filter to the wrapped writer.
|
/// Writes the filter to the wrapped writer.
|
||||||
pub fn finish(&mut self) -> Result<usize, io::Error> {
|
pub fn finish(&mut self) -> Result<usize, io::Error> {
|
||||||
let nm = self.elements.len() as u64 * self.m;
|
let nm = self.elements.len().to_u64() * self.m;
|
||||||
|
|
||||||
// map hashes to [0, n_elements * M)
|
// map hashes to [0, n_elements * M)
|
||||||
let mut mapped: Vec<_> = self
|
let mut mapped: Vec<_> = self
|
||||||
|
|
|
@ -480,6 +480,7 @@ impl std::error::Error for ValidationError {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hex::{test_hex_unwrap as hex, FromHex};
|
use hex::{test_hex_unwrap as hex, FromHex};
|
||||||
|
use internals::ToU64 as _;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::consensus::encode::{deserialize, serialize};
|
||||||
|
@ -540,7 +541,7 @@ mod tests {
|
||||||
assert_eq!(real_decode.base_size(), some_block.len());
|
assert_eq!(real_decode.base_size(), some_block.len());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
real_decode.weight(),
|
real_decode.weight(),
|
||||||
Weight::from_non_witness_data_size(some_block.len() as u64)
|
Weight::from_non_witness_data_size(some_block.len().to_u64())
|
||||||
);
|
);
|
||||||
|
|
||||||
// should be also ok for a non-witness block as commitment is optional in that case
|
// should be also ok for a non-witness block as commitment is optional in that case
|
||||||
|
|
|
@ -25,6 +25,8 @@ pub mod fee_rate {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use internals::ToU64 as _;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -41,7 +43,7 @@ pub mod fee_rate {
|
||||||
|
|
||||||
let rate = FeeRate::from_sat_per_vb(1).expect("1 sat/byte is valid");
|
let rate = FeeRate::from_sat_per_vb(1).expect("1 sat/byte is valid");
|
||||||
|
|
||||||
assert_eq!(rate.fee_vb(tx.vsize() as u64), rate.fee_wu(tx.weight()));
|
assert_eq!(rate.fee_vb(tx.vsize().to_u64()), rate.fee_wu(tx.weight()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ use core::ops::{
|
||||||
Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
|
Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use internals::ToU64 as _;
|
||||||
|
|
||||||
use super::witness_version::WitnessVersion;
|
use super::witness_version::WitnessVersion;
|
||||||
use super::{
|
use super::{
|
||||||
bytes_to_asm_fmt, Builder, Instruction, InstructionIndices, Instructions, PushBytes,
|
bytes_to_asm_fmt, Builder, Instruction, InstructionIndices, Instructions, PushBytes,
|
||||||
|
@ -399,11 +401,11 @@ impl Script {
|
||||||
} else if self.is_witness_program() {
|
} else if self.is_witness_program() {
|
||||||
32 + 4 + 1 + (107 / 4) + 4 + // The spend cost copied from Core
|
32 + 4 + 1 + (107 / 4) + 4 + // The spend cost copied from Core
|
||||||
8 + // The serialized size of the TxOut's amount field
|
8 + // The serialized size of the TxOut's amount field
|
||||||
self.consensus_encode(&mut sink()).expect("sinks don't error") as u64 // The serialized size of this script_pubkey
|
self.consensus_encode(&mut sink()).expect("sinks don't error").to_u64() // The serialized size of this script_pubkey
|
||||||
} else {
|
} else {
|
||||||
32 + 4 + 1 + 107 + 4 + // The spend cost copied from Core
|
32 + 4 + 1 + 107 + 4 + // The spend cost copied from Core
|
||||||
8 + // The serialized size of the TxOut's amount field
|
8 + // The serialized size of the TxOut's amount field
|
||||||
self.consensus_encode(&mut sink()).expect("sinks don't error") as u64 // The serialized size of this script_pubkey
|
self.consensus_encode(&mut sink()).expect("sinks don't error").to_u64() // The serialized size of this script_pubkey
|
||||||
})
|
})
|
||||||
.expect("dust_relay_fee or script length should not be absurdly large")
|
.expect("dust_relay_fee or script length should not be absurdly large")
|
||||||
/ 1000; // divide by 1000 like in Core to get value as it cancels out DEFAULT_MIN_RELAY_TX_FEE
|
/ 1000; // divide by 1000 like in Core to get value as it cancels out DEFAULT_MIN_RELAY_TX_FEE
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
|
use internals::ToU64 as _;
|
||||||
|
|
||||||
use super::{opcode_to_verify, Builder, Instruction, PushBytes, Script};
|
use super::{opcode_to_verify, Builder, Instruction, PushBytes, Script};
|
||||||
use crate::opcodes::all::*;
|
use crate::opcodes::all::*;
|
||||||
|
@ -100,7 +101,7 @@ impl ScriptBuf {
|
||||||
/// Pushes the slice without reserving
|
/// Pushes the slice without reserving
|
||||||
fn push_slice_no_opt(&mut self, data: &PushBytes) {
|
fn push_slice_no_opt(&mut self, data: &PushBytes) {
|
||||||
// Start with a PUSH opcode
|
// Start with a PUSH opcode
|
||||||
match data.len() as u64 {
|
match data.len().to_u64() {
|
||||||
n if n < opcodes::Ordinary::OP_PUSHDATA1 as u64 => {
|
n if n < opcodes::Ordinary::OP_PUSHDATA1 as u64 => {
|
||||||
self.0.push(n as u8);
|
self.0.push(n as u8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
use core::{cmp, fmt, str};
|
use core::{cmp, fmt, str};
|
||||||
|
|
||||||
use hashes::sha256d;
|
use hashes::sha256d;
|
||||||
use internals::write_err;
|
use internals::{write_err, ToU64 as _};
|
||||||
use io::{BufRead, Write};
|
use io::{BufRead, Write};
|
||||||
use primitives::Sequence;
|
use primitives::Sequence;
|
||||||
use units::parse;
|
use units::parse;
|
||||||
|
@ -277,7 +277,7 @@ impl TxIn {
|
||||||
/// might increase more than `TxIn::legacy_weight`. This happens when the new input added causes
|
/// might increase more than `TxIn::legacy_weight`. This happens when the new input added causes
|
||||||
/// the input length `VarInt` to increase its encoding length.
|
/// the input length `VarInt` to increase its encoding length.
|
||||||
pub fn legacy_weight(&self) -> Weight {
|
pub fn legacy_weight(&self) -> Weight {
|
||||||
Weight::from_non_witness_data_size(self.base_size() as u64)
|
Weight::from_non_witness_data_size(self.base_size().to_u64())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The weight of the TxIn when it's included in a segwit transaction (i.e., a transaction
|
/// The weight of the TxIn when it's included in a segwit transaction (i.e., a transaction
|
||||||
|
@ -292,8 +292,8 @@ impl TxIn {
|
||||||
/// - the new input is the first segwit input added - this will add an additional 2WU to the
|
/// - the new input is the first segwit input added - this will add an additional 2WU to the
|
||||||
/// transaction weight to take into account the segwit marker
|
/// transaction weight to take into account the segwit marker
|
||||||
pub fn segwit_weight(&self) -> Weight {
|
pub fn segwit_weight(&self) -> Weight {
|
||||||
Weight::from_non_witness_data_size(self.base_size() as u64)
|
Weight::from_non_witness_data_size(self.base_size().to_u64())
|
||||||
+ Weight::from_witness_data_size(self.witness.size() as u64)
|
+ Weight::from_witness_data_size(self.witness.size().to_u64())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the base size of this input.
|
/// Returns the base size of this input.
|
||||||
|
@ -359,10 +359,10 @@ impl TxOut {
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If output size * 4 overflows, this should never happen under normal conditions. Use
|
/// If output size * 4 overflows, this should never happen under normal conditions. Use
|
||||||
/// `Weght::from_vb_checked(self.size() as u64)` if you are concerned.
|
/// `Weght::from_vb_checked(self.size().to_u64())` if you are concerned.
|
||||||
pub fn weight(&self) -> Weight {
|
pub fn weight(&self) -> Weight {
|
||||||
// Size is equivalent to virtual size since all bytes of a TxOut are non-witness bytes.
|
// Size is equivalent to virtual size since all bytes of a TxOut are non-witness bytes.
|
||||||
Weight::from_vb(self.size() as u64).expect("should never happen under normal conditions")
|
Weight::from_vb(self.size().to_u64()).expect("should never happen under normal conditions")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the total number of bytes that this output contributes to a transaction.
|
/// Returns the total number of bytes that this output contributes to a transaction.
|
||||||
|
@ -1184,7 +1184,7 @@ where
|
||||||
let (output_count, output_scripts_size) = output_script_lens.into_iter().fold(
|
let (output_count, output_scripts_size) = output_script_lens.into_iter().fold(
|
||||||
(0, 0),
|
(0, 0),
|
||||||
|(output_count, total_scripts_size), script_len| {
|
|(output_count, total_scripts_size), script_len| {
|
||||||
let script_size = script_len + VarInt(script_len as u64).size();
|
let script_size = script_len + VarInt(script_len.to_u64()).size();
|
||||||
(output_count + 1, total_scripts_size + script_size)
|
(output_count + 1, total_scripts_size + script_size)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1376,11 +1376,11 @@ impl InputWeightPrediction {
|
||||||
let (count, total_size) =
|
let (count, total_size) =
|
||||||
witness_element_lengths.into_iter().fold((0, 0), |(count, total_size), elem_len| {
|
witness_element_lengths.into_iter().fold((0, 0), |(count, total_size), elem_len| {
|
||||||
let elem_len = *elem_len.borrow();
|
let elem_len = *elem_len.borrow();
|
||||||
let elem_size = elem_len + VarInt(elem_len as u64).size();
|
let elem_size = elem_len + VarInt(elem_len.to_u64()).size();
|
||||||
(count + 1, total_size + elem_size)
|
(count + 1, total_size + elem_size)
|
||||||
});
|
});
|
||||||
let witness_size = if count > 0 { total_size + VarInt(count as u64).size() } else { 0 };
|
let witness_size = if count > 0 { total_size + VarInt(count as u64).size() } else { 0 };
|
||||||
let script_size = input_script_len + VarInt(input_script_len as u64).size();
|
let script_size = input_script_len + VarInt(input_script_len.to_u64()).size();
|
||||||
|
|
||||||
InputWeightPrediction { script_size, witness_size }
|
InputWeightPrediction { script_size, witness_size }
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use core::{fmt, mem};
|
||||||
|
|
||||||
use hashes::{sha256, sha256d, GeneralHash, Hash};
|
use hashes::{sha256, sha256d, GeneralHash, Hash};
|
||||||
use hex::error::{InvalidCharError, OddLengthStringError};
|
use hex::error::{InvalidCharError, OddLengthStringError};
|
||||||
use internals::write_err;
|
use internals::{write_err, ToU64 as _};
|
||||||
use io::{BufRead, Cursor, Read, Write};
|
use io::{BufRead, Cursor, Read, Write};
|
||||||
|
|
||||||
use crate::bip152::{PrefilledTransaction, ShortId};
|
use crate::bip152::{PrefilledTransaction, ShortId};
|
||||||
|
@ -369,7 +369,7 @@ pub trait Decodable: Sized {
|
||||||
/// instead.
|
/// instead.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<R: BufRead + ?Sized>(reader: &mut R) -> Result<Self, Error> {
|
fn consensus_decode<R: BufRead + ?Sized>(reader: &mut R) -> Result<Self, Error> {
|
||||||
Self::consensus_decode_from_finite_reader(&mut reader.take(MAX_VEC_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(&mut reader.take(MAX_VEC_SIZE.to_u64()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +458,7 @@ macro_rules! impl_var_int_from {
|
||||||
$(
|
$(
|
||||||
/// Creates a `VarInt` from a `usize` by casting the to a `u64`.
|
/// Creates a `VarInt` from a `usize` by casting the to a `u64`.
|
||||||
impl From<$ty> for VarInt {
|
impl From<$ty> for VarInt {
|
||||||
fn from(x: $ty) -> Self { VarInt(x as u64) }
|
fn from(x: $ty) -> Self { VarInt(x.to_u64()) }
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
@ -545,7 +545,7 @@ impl Encodable for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let b = self.as_bytes();
|
let b = self.as_bytes();
|
||||||
let vi_len = VarInt(b.len() as u64).consensus_encode(w)?;
|
let vi_len = VarInt(b.len().to_u64()).consensus_encode(w)?;
|
||||||
w.emit_slice(b)?;
|
w.emit_slice(b)?;
|
||||||
Ok(vi_len + b.len())
|
Ok(vi_len + b.len())
|
||||||
}
|
}
|
||||||
|
@ -563,7 +563,7 @@ impl Encodable for Cow<'static, str> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let b = self.as_bytes();
|
let b = self.as_bytes();
|
||||||
let vi_len = VarInt(b.len() as u64).consensus_encode(w)?;
|
let vi_len = VarInt(b.len().to_u64()).consensus_encode(w)?;
|
||||||
w.emit_slice(b)?;
|
w.emit_slice(b)?;
|
||||||
Ok(vi_len + b.len())
|
Ok(vi_len + b.len())
|
||||||
}
|
}
|
||||||
|
@ -644,7 +644,7 @@ macro_rules! impl_vec {
|
||||||
w: &mut W,
|
w: &mut W,
|
||||||
) -> core::result::Result<usize, io::Error> {
|
) -> core::result::Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
len += VarInt(self.len() as u64).consensus_encode(w)?;
|
len += VarInt(self.len().to_u64()).consensus_encode(w)?;
|
||||||
for c in self.iter() {
|
for c in self.iter() {
|
||||||
len += c.consensus_encode(w)?;
|
len += c.consensus_encode(w)?;
|
||||||
}
|
}
|
||||||
|
@ -700,7 +700,7 @@ pub(crate) fn consensus_encode_with_size<W: Write + ?Sized>(
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
w: &mut W,
|
w: &mut W,
|
||||||
) -> Result<usize, io::Error> {
|
) -> Result<usize, io::Error> {
|
||||||
let vi_len = VarInt(data.len() as u64).consensus_encode(w)?;
|
let vi_len = VarInt(data.len().to_u64()).consensus_encode(w)?;
|
||||||
w.emit_slice(data)?;
|
w.emit_slice(data)?;
|
||||||
Ok(vi_len + data.len())
|
Ok(vi_len + data.len())
|
||||||
}
|
}
|
||||||
|
@ -1202,7 +1202,7 @@ mod tests {
|
||||||
T: fmt::Debug,
|
T: fmt::Debug,
|
||||||
{
|
{
|
||||||
let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, ""));
|
let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, ""));
|
||||||
let varint = VarInt((super::MAX_VEC_SIZE / mem::size_of::<T>()) as u64);
|
let varint = VarInt((super::MAX_VEC_SIZE / mem::size_of::<T>()).to_u64());
|
||||||
let err = deserialize::<Vec<T>>(&serialize(&varint)).unwrap_err();
|
let err = deserialize::<Vec<T>>(&serialize(&varint)).unwrap_err();
|
||||||
assert_eq!(discriminant(&err), discriminant(&rand_io_err));
|
assert_eq!(discriminant(&err), discriminant(&rand_io_err));
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,9 @@ macro_rules! impl_consensus_encoding {
|
||||||
fn consensus_decode<R: $crate::io::BufRead + ?Sized>(
|
fn consensus_decode<R: $crate::io::BufRead + ?Sized>(
|
||||||
r: &mut R,
|
r: &mut R,
|
||||||
) -> core::result::Result<$thing, $crate::consensus::encode::Error> {
|
) -> core::result::Result<$thing, $crate::consensus::encode::Error> {
|
||||||
let mut r = r.take($crate::consensus::encode::MAX_VEC_SIZE as u64);
|
use internals::ToU64 as _;
|
||||||
|
|
||||||
|
let mut r = r.take($crate::consensus::encode::MAX_VEC_SIZE.to_u64());
|
||||||
Ok($thing {
|
Ok($thing {
|
||||||
$($field: $crate::consensus::Decodable::consensus_decode(&mut r)?),+
|
$($field: $crate::consensus::Decodable::consensus_decode(&mut r)?),+
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
|
use internals::ToU64 as _;
|
||||||
use io::{BufRead, Write};
|
use io::{BufRead, Write};
|
||||||
|
|
||||||
use self::MerkleBlockError::*;
|
use self::MerkleBlockError::*;
|
||||||
|
@ -245,7 +246,7 @@ impl PartialMerkleTree {
|
||||||
return Err(NoTransactions);
|
return Err(NoTransactions);
|
||||||
};
|
};
|
||||||
// check for excessively high numbers of transactions
|
// check for excessively high numbers of transactions
|
||||||
if self.num_transactions as u64 > Weight::MAX_BLOCK / Weight::MIN_TRANSACTION {
|
if self.num_transactions.to_u64() > Weight::MAX_BLOCK / Weight::MIN_TRANSACTION {
|
||||||
return Err(TooManyTransactions);
|
return Err(TooManyTransactions);
|
||||||
}
|
}
|
||||||
// there can never be more hashes provided than one for every txid
|
// there can never be more hashes provided than one for every txid
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
use core::{fmt, iter};
|
use core::{fmt, iter};
|
||||||
|
|
||||||
use hashes::sha256d;
|
use hashes::sha256d;
|
||||||
|
use internals::ToU64 as _;
|
||||||
use io::{BufRead, Write};
|
use io::{BufRead, Write};
|
||||||
|
|
||||||
use crate::consensus::encode::{self, CheckedData, Decodable, Encodable, VarInt};
|
use crate::consensus::encode::{self, CheckedData, Decodable, Encodable, VarInt};
|
||||||
|
@ -426,7 +427,7 @@ impl Decodable for HeaderDeserializationWrapper {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE.to_u64()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +532,7 @@ impl Decodable for RawNetworkMessage {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE.to_u64()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
use internals::ToU64 as _;
|
||||||
use io::{BufRead, Cursor, Read};
|
use io::{BufRead, Cursor, Read};
|
||||||
|
|
||||||
use crate::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpub};
|
use crate::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpub};
|
||||||
|
@ -71,7 +72,7 @@ impl Map for Psbt {
|
||||||
|
|
||||||
impl Psbt {
|
impl Psbt {
|
||||||
pub(crate) fn decode_global<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, Error> {
|
pub(crate) fn decode_global<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, Error> {
|
||||||
let mut r = r.take(MAX_VEC_SIZE as u64);
|
let mut r = r.take(MAX_VEC_SIZE.to_u64());
|
||||||
let mut tx: Option<Transaction> = None;
|
let mut tx: Option<Transaction> = None;
|
||||||
let mut version: Option<u32> = None;
|
let mut version: Option<u32> = None;
|
||||||
let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default();
|
let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default();
|
||||||
|
@ -100,7 +101,7 @@ impl Psbt {
|
||||||
lock_time: Decodable::consensus_decode(&mut decoder)?,
|
lock_time: Decodable::consensus_decode(&mut decoder)?,
|
||||||
});
|
});
|
||||||
|
|
||||||
if decoder.position() != vlen as u64 {
|
if decoder.position() != vlen.to_u64() {
|
||||||
return Err(Error::PartialDataConsumption);
|
return Err(Error::PartialDataConsumption);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
|
use internals::ToU64 as _;
|
||||||
use io::{BufRead, Write};
|
use io::{BufRead, Write};
|
||||||
|
|
||||||
use super::serialize::{Deserialize, Serialize};
|
use super::serialize::{Deserialize, Serialize};
|
||||||
|
@ -80,7 +81,7 @@ impl Key {
|
||||||
|
|
||||||
let key_byte_size: u64 = byte_size - 1;
|
let key_byte_size: u64 = byte_size - 1;
|
||||||
|
|
||||||
if key_byte_size > MAX_VEC_SIZE as u64 {
|
if key_byte_size > MAX_VEC_SIZE.to_u64() {
|
||||||
return Err(encode::Error::OversizedVectorAllocation {
|
return Err(encode::Error::OversizedVectorAllocation {
|
||||||
requested: key_byte_size as usize,
|
requested: key_byte_size as usize,
|
||||||
max: MAX_VEC_SIZE,
|
max: MAX_VEC_SIZE,
|
||||||
|
|
|
@ -35,3 +35,28 @@ mod parse;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod serde;
|
pub mod serde;
|
||||||
|
|
||||||
|
/// A conversion trait for unsigned integer types smaller than or equal to 64-bits.
|
||||||
|
///
|
||||||
|
/// This trait exists because [`usize`] doesn't implement `Into<u64>`. We only support 32 and 64 bit
|
||||||
|
/// architectures because of consensus code so we can infallibly do the conversion.
|
||||||
|
pub trait ToU64 {
|
||||||
|
/// Converts unsigned integer type to a [`u64`].
|
||||||
|
fn to_u64(self) -> u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_to_u64 {
|
||||||
|
($($ty:ident),*) => {
|
||||||
|
$(
|
||||||
|
impl ToU64 for $ty { fn to_u64(self) -> u64 { self.into() } }
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl_to_u64!(u8, u16, u32, u64);
|
||||||
|
|
||||||
|
impl ToU64 for usize {
|
||||||
|
fn to_u64(self) -> u64 {
|
||||||
|
crate::const_assert!(core::mem::size_of::<usize>() <= 8);
|
||||||
|
self as u64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue