From 2674327c9399b1ff938aeb5d291a3e1e974495ad Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 31 Aug 2022 14:45:14 +1000 Subject: [PATCH] Remove the endian module Now we have MSRV of 1.41.1 we can use the `from_le_bytes` and `to_be_bytes` methods, these became available in Rust 1.32. Remove the `endian` module replacing its logic with calls to methods on the respective stdlib integer types. --- bitcoin/src/bip152.rs | 5 +- bitcoin/src/bip158.rs | 10 +-- bitcoin/src/bip32.rs | 15 ++-- bitcoin/src/consensus/encode.rs | 47 ++++++------ bitcoin/src/sighash.rs | 4 +- bitcoin/src/util/base58.rs | 16 +++-- bitcoin/src/util/endian.rs | 106 ---------------------------- bitcoin/src/util/mod.rs | 2 - bitcoin/src/util/psbt/map/global.rs | 5 +- 9 files changed, 51 insertions(+), 159 deletions(-) delete mode 100644 bitcoin/src/util/endian.rs diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index 1b9c63e0..2b81a1cd 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -5,7 +5,7 @@ //! Implementation of compact blocks data structure and algorithms. //! -use core::convert::TryFrom; +use core::convert::{TryFrom, TryInto}; use core::{convert, fmt, mem}; #[cfg(feature = "std")] use std::error; @@ -16,7 +16,6 @@ use crate::consensus::encode::{self, Decodable, Encodable, VarInt}; use crate::hashes::{sha256, siphash24, Hash}; use crate::internal_macros::{impl_bytes_newtype, impl_consensus_encoding}; use crate::prelude::*; -use crate::util::endian; use crate::{io, Block, BlockHash, BlockHeader, Transaction}; /// A BIP-152 error @@ -112,7 +111,7 @@ impl ShortId { // 2. Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1) // set to the first two little-endian 64-bit integers from the above hash, respectively. - (endian::slice_to_u64_le(&h[0..8]), endian::slice_to_u64_le(&h[8..16])) + (u64::from_le_bytes(h[0..8].try_into().expect("8 byte slice")), u64::from_le_bytes(h[8..16].try_into().expect("8 byte slice"))) } /// Calculate the short ID with the given (w)txid and using the provided SipHash keys. diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs index 7692d5a2..4f1d8e0a 100644 --- a/bitcoin/src/bip158.rs +++ b/bitcoin/src/bip158.rs @@ -40,6 +40,7 @@ //! use core::cmp::{self, Ordering}; +use core::convert::TryInto; use core::fmt::{self, Display, Formatter}; use bitcoin_internals::write_err; @@ -53,7 +54,6 @@ use crate::hash_types::{BlockHash, FilterHash, FilterHeader}; use crate::hashes::{siphash24, Hash}; use crate::io; use crate::prelude::*; -use crate::util::endian; /// Golomb encoding parameter as in BIP-158, see also https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845 const P: u8 = 19; @@ -170,8 +170,8 @@ impl<'a, W: io::Write> BlockFilterWriter<'a, W> { /// Creates a new [`BlockFilterWriter`] from `block`. pub fn new(writer: &'a mut W, block: &'a Block) -> BlockFilterWriter<'a, W> { let block_hash_as_int = block.block_hash().into_inner(); - let k0 = endian::slice_to_u64_le(&block_hash_as_int[0..8]); - let k1 = endian::slice_to_u64_le(&block_hash_as_int[8..16]); + let k0 = u64::from_le_bytes(block_hash_as_int[0..8].try_into().expect("8 byte slice")); + let k1 = u64::from_le_bytes(block_hash_as_int[8..16].try_into().expect("8 byte slice")); let writer = GcsFilterWriter::new(writer, k0, k1, M, P); BlockFilterWriter { block, writer } } @@ -224,8 +224,8 @@ impl BlockFilterReader { /// Creates a new [`BlockFilterReader`] from `block_hash`. pub fn new(block_hash: &BlockHash) -> BlockFilterReader { let block_hash_as_int = block_hash.into_inner(); - let k0 = endian::slice_to_u64_le(&block_hash_as_int[0..8]); - let k1 = endian::slice_to_u64_le(&block_hash_as_int[8..16]); + let k0 = u64::from_le_bytes(block_hash_as_int[0..8].try_into().expect("8 byte slice")); + let k1 = u64::from_le_bytes(block_hash_as_int[8..16].try_into().expect("8 byte slice")); BlockFilterReader { reader: GcsFilterReader::new(k0, k1, M, P) } } diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index d31a969e..dcb9dbc7 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -7,6 +7,7 @@ //! at . //! +use core::convert::TryInto; use core::default::Default; use core::fmt; use core::ops::Index; @@ -24,7 +25,7 @@ use crate::io::Write; use crate::network::constants::Network; use crate::prelude::*; use crate::util::key::{KeyPair, PrivateKey, PublicKey}; -use crate::util::{base58, endian, key}; +use crate::util::{base58, key}; /// A chain code #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -574,7 +575,7 @@ impl ExtendedPrivKey { } } - hmac_engine.input(&endian::u32_to_array_be(u32::from(i))); + hmac_engine.input(&u32::from(i).to_be_bytes()); let hmac_result: Hmac = Hmac::from_engine(hmac_engine); let sk = secp256k1::SecretKey::from_slice(&hmac_result[..32]) .expect("statistically impossible to hit"); @@ -611,7 +612,7 @@ impl ExtendedPrivKey { network, depth: data[4], parent_fingerprint: Fingerprint::from(&data[5..9]), - child_number: endian::slice_to_u32_be(&data[9..13]).into(), + child_number: u32::from_be_bytes(data[9..13].try_into().expect("4 byte slice")).into(), chain_code: ChainCode::from(&data[13..45]), private_key: secp256k1::SecretKey::from_slice(&data[46..78])?, }) @@ -628,7 +629,7 @@ impl ExtendedPrivKey { ); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); - ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); + ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes()); ret[13..45].copy_from_slice(&self.chain_code[..]); ret[45] = 0; ret[46..78].copy_from_slice(&self.private_key[..]); @@ -695,7 +696,7 @@ impl ExtendedPubKey { let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); hmac_engine.input(&self.public_key.serialize()[..]); - hmac_engine.input(&endian::u32_to_array_be(n)); + hmac_engine.input(&n.to_be_bytes()); let hmac_result: Hmac = Hmac::from_engine(hmac_engine); @@ -743,7 +744,7 @@ impl ExtendedPubKey { }, depth: data[4], parent_fingerprint: Fingerprint::from(&data[5..9]), - child_number: endian::slice_to_u32_be(&data[9..13]).into(), + child_number: u32::from_be_bytes(data[9..13].try_into().expect("4 byte slice")).into(), chain_code: ChainCode::from(&data[13..45]), public_key: secp256k1::PublicKey::from_slice(&data[45..78])?, }) @@ -760,7 +761,7 @@ impl ExtendedPubKey { ); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); - ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); + ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes()); ret[13..45].copy_from_slice(&self.chain_code[..]); ret[45..78].copy_from_slice(&self.public_key.serialize()[..]); ret diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs index 0e70f4ce..73b07f7e 100644 --- a/bitcoin/src/consensus/encode.rs +++ b/bitcoin/src/consensus/encode.rs @@ -26,7 +26,6 @@ use crate::hashes::{sha256d, Hash, sha256}; use crate::hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader}; use crate::io::{self, Cursor, Read}; -use crate::util::endian; use crate::util::psbt; use crate::bip152::{ShortId, PrefilledTransaction}; use crate::util::taproot::TapLeafHash; @@ -207,33 +206,32 @@ pub trait ReadExt : io::Read { } macro_rules! encoder_fn { - ($name:ident, $val_type:ty, $writefn:ident) => { + ($name:ident, $val_type:ty) => { #[inline] fn $name(&mut self, v: $val_type) -> Result<(), io::Error> { - self.write_all(&endian::$writefn(v)) + self.write_all(&v.to_le_bytes()) } } } macro_rules! decoder_fn { - ($name:ident, $val_type:ty, $readfn:ident, $byte_len: expr) => { + ($name:ident, $val_type:ty, $byte_len: expr) => { #[inline] fn $name(&mut self) -> Result<$val_type, Error> { - bitcoin_internals::const_assert!(core::mem::size_of::<$val_type>() == $byte_len); let mut val = [0; $byte_len]; self.read_exact(&mut val[..]).map_err(Error::Io)?; - Ok(endian::$readfn(&val)) + Ok(<$val_type>::from_le_bytes(val)) } } } impl WriteExt for W { - encoder_fn!(emit_u64, u64, u64_to_array_le); - encoder_fn!(emit_u32, u32, u32_to_array_le); - encoder_fn!(emit_u16, u16, u16_to_array_le); - encoder_fn!(emit_i64, i64, i64_to_array_le); - encoder_fn!(emit_i32, i32, i32_to_array_le); - encoder_fn!(emit_i16, i16, i16_to_array_le); + encoder_fn!(emit_u64, u64); + encoder_fn!(emit_u32, u32); + encoder_fn!(emit_u16, u16); + encoder_fn!(emit_i64, i64); + encoder_fn!(emit_i32, i32); + encoder_fn!(emit_i16, i16); #[inline] fn emit_i8(&mut self, v: i8) -> Result<(), io::Error> { @@ -254,12 +252,12 @@ impl WriteExt for W { } impl ReadExt for R { - decoder_fn!(read_u64, u64, slice_to_u64_le, 8); - decoder_fn!(read_u32, u32, slice_to_u32_le, 4); - decoder_fn!(read_u16, u16, slice_to_u16_le, 2); - decoder_fn!(read_i64, i64, slice_to_i64_le, 8); - decoder_fn!(read_i32, i32, slice_to_i32_le, 4); - decoder_fn!(read_i16, i16, slice_to_i16_le, 2); + decoder_fn!(read_u64, u64, 8); + decoder_fn!(read_u32, u32, 4); + decoder_fn!(read_u16, u16, 2); + decoder_fn!(read_i64, i64, 8); + decoder_fn!(read_i32, i32, 4); + decoder_fn!(read_i16, i16, 2); #[inline] fn read_u8(&mut self) -> Result { @@ -831,7 +829,6 @@ mod tests { use super::{deserialize, serialize, Error, CheckedData, VarInt}; use super::{Transaction, BlockHash, FilterHash, TxMerkleNode, TxOut, TxIn}; use crate::consensus::{Encodable, deserialize_partial, Decodable}; - use crate::util::endian::{u64_to_array_le, u32_to_array_le, u16_to_array_le}; use secp256k1::rand::{thread_rng, Rng}; #[cfg(feature = "std")] use crate::network::{Address, message_blockdata::Inventory}; @@ -893,9 +890,9 @@ mod tests { assert_eq!(serialize(&VarInt(0xFFF)), vec![0xFDu8, 0xFF, 0xF]); assert_eq!(serialize(&VarInt(0xF0F0F0F)), vec![0xFEu8, 0xF, 0xF, 0xF, 0xF]); assert_eq!(serialize(&VarInt(0xF0F0F0F0F0E0)), vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0]); - assert_eq!(test_varint_encode(0xFF, &u64_to_array_le(0x100000000)).unwrap(), VarInt(0x100000000)); - assert_eq!(test_varint_encode(0xFE, &u64_to_array_le(0x10000)).unwrap(), VarInt(0x10000)); - assert_eq!(test_varint_encode(0xFD, &u64_to_array_le(0xFD)).unwrap(), VarInt(0xFD)); + assert_eq!(test_varint_encode(0xFF, &0x100000000_u64.to_le_bytes()).unwrap(), VarInt(0x100000000)); + assert_eq!(test_varint_encode(0xFE, &0x10000_u64.to_le_bytes()).unwrap(), VarInt(0x10000)); + assert_eq!(test_varint_encode(0xFD, &0xFD_u64.to_le_bytes()).unwrap(), VarInt(0xFD)); // Test that length calc is working correctly test_varint_len(VarInt(0), 1); @@ -924,11 +921,11 @@ mod tests { #[test] fn deserialize_nonminimal_vec() { // Check the edges for variant int - assert_eq!(discriminant(&test_varint_encode(0xFF, &u64_to_array_le(0x100000000-1)).unwrap_err()), + assert_eq!(discriminant(&test_varint_encode(0xFF, &(0x100000000_u64-1).to_le_bytes()).unwrap_err()), discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&test_varint_encode(0xFE, &u32_to_array_le(0x10000-1)).unwrap_err()), + assert_eq!(discriminant(&test_varint_encode(0xFE, &(0x10000_u64-1).to_le_bytes()).unwrap_err()), discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&test_varint_encode(0xFD, &u16_to_array_le(0xFD-1)).unwrap_err()), + assert_eq!(discriminant(&test_varint_encode(0xFD, &(0xFD_u64-1).to_le_bytes()).unwrap_err()), discriminant(&Error::NonMinimalVarInt)); assert_eq!(discriminant(&deserialize::>(&[0xfd, 0x00, 0x00]).unwrap_err()), diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/sighash.rs index 3b3fe380..43ac16ac 100644 --- a/bitcoin/src/sighash.rs +++ b/bitcoin/src/sighash.rs @@ -17,7 +17,6 @@ use crate::blockdata::transaction::EncodeSigningDataResult; use crate::blockdata::witness::Witness; use crate::consensus::{encode, Encodable}; use crate::error::impl_std_error; -use crate::util::endian; use crate::hashes::{sha256, sha256d, Hash}; use crate::prelude::*; use crate::util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash, LeafVersion}; @@ -879,8 +878,7 @@ impl> SighashCache { }; // hash the result tx.consensus_encode(&mut writer)?; - let sighash_arr = endian::u32_to_array_le(sighash_type); - sighash_arr.consensus_encode(&mut writer)?; + sighash_type.to_le_bytes().consensus_encode(&mut writer)?; Ok(()) } diff --git a/bitcoin/src/util/base58.rs b/bitcoin/src/util/base58.rs index 7fcc78a8..1f878a78 100644 --- a/bitcoin/src/util/base58.rs +++ b/bitcoin/src/util/base58.rs @@ -10,12 +10,13 @@ use crate::prelude::*; use core::{fmt, str, iter, slice}; +use core::convert::TryInto; use bitcoin_internals::write_err; use crate::hashes::{sha256d, Hash, hex}; use secp256k1; -use crate::util::{endian, key}; +use crate::util::key; /// An error that might occur during base58 decoding #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] @@ -171,14 +172,19 @@ pub fn from_check(data: &str) -> Result, Error> { if ret.len() < 4 { return Err(Error::TooShort(ret.len())); } - let ck_start = ret.len() - 4; - let expected = endian::slice_to_u32_le(&sha256d::Hash::hash(&ret[..ck_start])[..4]); - let actual = endian::slice_to_u32_le(&ret[ck_start..(ck_start + 4)]); + let check_start = ret.len() - 4; + + let hash_check = sha256d::Hash::hash(&ret[..check_start])[..4].try_into().expect("4 byte slice"); + let data_check = ret[check_start..].try_into().expect("4 byte slice"); + + let expected = u32::from_le_bytes(hash_check); + let actual = u32::from_le_bytes(data_check); + if expected != actual { return Err(Error::BadChecksum(expected, actual)); } - ret.truncate(ck_start); + ret.truncate(check_start); Ok(ret) } diff --git a/bitcoin/src/util/endian.rs b/bitcoin/src/util/endian.rs deleted file mode 100644 index 7f3299af..00000000 --- a/bitcoin/src/util/endian.rs +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -macro_rules! define_slice_to_be { - ($name: ident, $type: ty) => { - #[inline] - pub fn $name(slice: &[u8]) -> $type { - assert_eq!(slice.len(), core::mem::size_of::<$type>()); - let mut res = 0; - for i in 0..::core::mem::size_of::<$type>() { - res |= (slice[i] as $type) << (::core::mem::size_of::<$type>() - i - 1)*8; - } - res - } - } -} -macro_rules! define_slice_to_le { - ($name: ident, $type: ty) => { - #[inline] - pub fn $name(slice: &[u8]) -> $type { - assert_eq!(slice.len(), core::mem::size_of::<$type>()); - let mut res = 0; - for i in 0..::core::mem::size_of::<$type>() { - res |= (slice[i] as $type) << i*8; - } - res - } - } -} -macro_rules! define_be_to_array { - ($name: ident, $type: ty, $byte_len: expr) => { - #[inline] - pub fn $name(val: $type) -> [u8; $byte_len] { - bitcoin_internals::const_assert!(core::mem::size_of::<$type>() == $byte_len); - let mut res = [0; $byte_len]; - for i in 0..$byte_len { - res[i] = ((val >> ($byte_len - i - 1)*8) & 0xff) as u8; - } - res - } - } -} -macro_rules! define_le_to_array { - ($name: ident, $type: ty, $byte_len: expr) => { - #[inline] - pub fn $name(val: $type) -> [u8; $byte_len] { - bitcoin_internals::const_assert!(core::mem::size_of::<$type>() == $byte_len); - let mut res = [0; $byte_len]; - for i in 0..$byte_len { - res[i] = ((val >> i*8) & 0xff) as u8; - } - res - } - } -} - -define_slice_to_be!(slice_to_u32_be, u32); -define_be_to_array!(u32_to_array_be, u32, 4); -define_slice_to_le!(slice_to_u16_le, u16); -define_slice_to_le!(slice_to_u32_le, u32); -define_slice_to_le!(slice_to_u64_le, u64); -define_le_to_array!(u16_to_array_le, u16, 2); -define_le_to_array!(u32_to_array_le, u32, 4); -define_le_to_array!(u64_to_array_le, u64, 8); - -#[inline] -pub fn i16_to_array_le(val: i16) -> [u8; 2] { - u16_to_array_le(val as u16) -} -#[inline] -pub fn slice_to_i16_le(slice: &[u8]) -> i16 { - slice_to_u16_le(slice) as i16 -} -#[inline] -pub fn slice_to_i32_le(slice: &[u8]) -> i32 { - slice_to_u32_le(slice) as i32 -} -#[inline] -pub fn i32_to_array_le(val: i32) -> [u8; 4] { - u32_to_array_le(val as u32) -} -#[inline] -pub fn slice_to_i64_le(slice: &[u8]) -> i64 { - slice_to_u64_le(slice) as i64 -} -#[inline] -pub fn i64_to_array_le(val: i64) -> [u8; 8] { - u64_to_array_le(val as u64) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn endianness_test() { - assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef); - assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]); - - assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead); - assert_eq!(slice_to_u32_le(&[0xef, 0xbe, 0xad, 0xde]), 0xdeadbeef); - assert_eq!(slice_to_u64_le(&[0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]), 0x1badcafedeadbeef); - assert_eq!(u16_to_array_le(0xdead), [0xad, 0xde]); - assert_eq!(u32_to_array_le(0xdeadbeef), [0xef, 0xbe, 0xad, 0xde]); - assert_eq!(u64_to_array_le(0x1badcafedeadbeef), [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b]); - } -} diff --git a/bitcoin/src/util/mod.rs b/bitcoin/src/util/mod.rs index e254a6c3..3f96ab3e 100644 --- a/bitcoin/src/util/mod.rs +++ b/bitcoin/src/util/mod.rs @@ -16,8 +16,6 @@ pub mod merkleblock; pub mod psbt; pub mod taproot; -pub(crate) mod endian; - use crate::prelude::*; use crate::io; use core::fmt; diff --git a/bitcoin/src/util/psbt/map/global.rs b/bitcoin/src/util/psbt/map/global.rs index 5418e771..eec7eecd 100644 --- a/bitcoin/src/util/psbt/map/global.rs +++ b/bitcoin/src/util/psbt/map/global.rs @@ -12,7 +12,6 @@ use crate::consensus::encode::MAX_VEC_SIZE; use crate::util::psbt::map::Map; use crate::util::psbt::{raw, PartiallySignedTransaction}; use crate::util::psbt::Error; -use crate::util::endian::u32_to_array_le; use crate::util::bip32::{ExtendedPubKey, Fingerprint, DerivationPath, ChildNumber}; /// Type: Unsigned Transaction PSBT_GLOBAL_UNSIGNED_TX = 0x00 @@ -54,7 +53,7 @@ impl Map for PartiallySignedTransaction { value: { let mut ret = Vec::with_capacity(4 + derivation.len() * 4); ret.extend(fingerprint.as_bytes()); - derivation.into_iter().for_each(|n| ret.extend(&u32_to_array_le((*n).into()))); + derivation.into_iter().for_each(|n| ret.extend(&u32::from(*n).to_le_bytes())); ret } }); @@ -67,7 +66,7 @@ impl Map for PartiallySignedTransaction { type_value: PSBT_GLOBAL_VERSION, key: vec![], }, - value: u32_to_array_le(self.version).to_vec() + value: self.version.to_le_bytes().to_vec() }); }