From f1f7718b6c7d2cdc150e6da20b6fd22907ca910c Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 17 Oct 2019 16:50:27 -0400 Subject: [PATCH 1/3] Drop (non-test/serde) hex dep in favor of bitcoin_hashes' fn's --- Cargo.toml | 5 +++-- src/consensus/encode.rs | 6 +++--- src/lib.rs | 2 +- src/util/psbt/raw.rs | 3 ++- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 957b16a4..f05f52ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,8 @@ path = "src/lib.rs" [features] fuzztarget = ["secp256k1/fuzztarget", "bitcoin_hashes/fuzztarget"] unstable = [] -use-serde = ["serde", "bitcoin_hashes/serde", "secp256k1/serde"] rand = ["secp256k1/rand"] +use-serde = ["hex", "serde", "bitcoin_hashes/serde", "secp256k1/serde"] [dependencies] bech32 = "0.7.1" @@ -26,10 +26,11 @@ byteorder = "1.2" bitcoin_hashes = "0.7" bitcoinconsensus = { version = "0.17", optional = true } serde = { version = "1", optional = true } +hex = { version = "=0.3.2", optional = true } secp256k1 = "0.15" -hex = "=0.3.2" [dev-dependencies] +hex = "=0.3.2" serde_derive = "<1.0.99" serde_json = "1" serde_test = "1" diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index cd274ce8..19180fd5 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -36,7 +36,7 @@ use std::fmt; use std::io; use std::io::{Cursor, Read, Write}; use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt}; -use hex::encode as hex_encode; +use hashes::hex::ToHex; use hashes::{sha256d, Hash as HashTrait}; use secp256k1; @@ -104,7 +104,7 @@ impl fmt::Display for Error { Error::Psbt(ref e) => fmt::Display::fmt(e, f), Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e, a), Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "{}: requested {}, maximum {}", error::Error::description(self), r, m), - Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), hex_encode(e), hex_encode(a)), + Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e[..].to_hex(), a[..].to_hex()), Error::UnknownNetworkMagic(ref m) => write!(f, "{}: {}", error::Error::description(self), m), Error::ParseFailed(ref e) => write!(f, "{}: {}", error::Error::description(self), e), Error::UnsupportedSegwitFlag(ref swflag) => write!(f, "{}: {}", error::Error::description(self), swflag), @@ -189,7 +189,7 @@ pub fn serialize(data: &T) -> Vec { /// Encode an object into a hex-encoded string pub fn serialize_hex(data: &T) -> String { - hex_encode(serialize(data)) + serialize(data)[..].to_hex() } /// Deserialize an object from a vector, will error if said deserialization diff --git a/src/lib.rs b/src/lib.rs index 100425fb..87a788a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,8 +51,8 @@ pub extern crate bitcoin_hashes as hashes; pub extern crate secp256k1; pub extern crate bech32; +#[cfg(any(test, feature = "serde"))] extern crate hex; extern crate byteorder; -extern crate hex; #[cfg(feature = "serde")] extern crate serde; #[cfg(all(test, feature = "serde"))] #[macro_use] extern crate serde_derive; // for 1.22.0 compat #[cfg(all(test, feature = "serde"))] extern crate serde_json; diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 2568f333..9bf73ff9 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -20,6 +20,7 @@ use std::{fmt, io}; use consensus::encode::{self, Decodable, Encodable, VarInt, MAX_VEC_SIZE}; +use hashes::hex::ToHex; use util::psbt::Error; /// A PSBT key in its raw byte form. @@ -46,7 +47,7 @@ impl fmt::Display for Key { f, "type: {:#x}, key: {}", self.type_value, - ::hex::encode(&self.key) + self.key[..].to_hex() ) } } From acb43af9819dc3aea02b4edec791ff580ba9c709 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 17 Oct 2019 17:40:45 -0400 Subject: [PATCH 2/3] Drop byteorder dependency Taking an external dependency just to convert ints to byte arrays is somewhat of a waste, especially when Rust isn't very aggressive about doing cross-crate LTO. Note that the latest LLVM pattern-matches this, and while I haven't tested it, that should mean this means no loss of optimization. --- Cargo.toml | 1 - src/blockdata/block.rs | 4 +- src/blockdata/transaction.rs | 4 +- src/consensus/encode.rs | 49 +++++++------ src/lib.rs | 1 - src/network/message_network.rs | 3 +- src/util/base58.rs | 8 +-- src/util/bip158.rs | 10 +-- src/util/bip32.rs | 24 ++----- src/util/endian.rs | 125 +++++++++++++++++++++++++++++++++ src/util/mod.rs | 2 + 11 files changed, 175 insertions(+), 56 deletions(-) create mode 100644 src/util/endian.rs diff --git a/Cargo.toml b/Cargo.toml index f05f52ac..3b9ae51b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ use-serde = ["hex", "serde", "bitcoin_hashes/serde", "secp256k1/serde"] [dependencies] bech32 = "0.7.1" -byteorder = "1.2" bitcoin_hashes = "0.7" bitcoinconsensus = { version = "0.17", optional = true } serde = { version = "1", optional = true } diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 65d5eb42..9d4a40b3 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -165,15 +165,13 @@ impl BlockHeader { /// Checks that the proof-of-work for the block is valid. pub fn validate_pow(&self, required_target: &Uint256) -> Result<(), util::Error> { - use byteorder::{ByteOrder, LittleEndian}; - let target = &self.target(); if target != required_target { return Err(BlockBadTarget); } let data: [u8; 32] = self.bitcoin_hash().into_inner(); let mut ret = [0u64; 4]; - LittleEndian::read_u64_into(&data, &mut ret); + util::endian::bytes_to_u64_slice_le(&data, &mut ret); let hash = &Uint256(ret); if hash <= target { Ok(()) } else { Err(BlockBadProofOfWork) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index f6e759f5..f875b324 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -23,13 +23,13 @@ //! This module provides the structures and functions needed to support transactions. //! -use byteorder::{LittleEndian, WriteBytesExt}; use std::default::Default; use std::{fmt, io}; use hashes::{self, sha256d, Hash}; use hashes::hex::FromHex; +use util::endian; use util::hash::BitcoinHash; #[cfg(feature="bitcoinconsensus")] use blockdata::script; use blockdata::script::Script; @@ -358,7 +358,7 @@ impl Transaction { }; // hash the result let mut raw_vec = serialize(&tx); - raw_vec.write_u32::(sighash_u32).unwrap(); + raw_vec.extend_from_slice(&endian::u32_to_array_le(sighash_u32)); sha256d::Hash::hash(&raw_vec) } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 19180fd5..63a91227 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -35,12 +35,12 @@ use std::error; use std::fmt; use std::io; use std::io::{Cursor, Read, Write}; -use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt}; use hashes::hex::ToHex; use hashes::{sha256d, Hash as HashTrait}; use secp256k1; +use util::endian; use util::base58; use util::psbt; @@ -276,39 +276,42 @@ macro_rules! encoder_fn { ($name:ident, $val_type:ty, $writefn:ident) => { #[inline] fn $name(&mut self, v: $val_type) -> Result<(), Error> { - WriteBytesExt::$writefn::(self, v).map_err(Error::Io) + self.write_all(&endian::$writefn(v)).map_err(Error::Io) } } } macro_rules! decoder_fn { - ($name:ident, $val_type:ty, $readfn:ident) => { + ($name:ident, $val_type:ty, $readfn:ident, $byte_len: expr) => { #[inline] fn $name(&mut self) -> Result<$val_type, Error> { - ReadBytesExt::$readfn::(self).map_err(Error::Io) + assert_eq!(::std::mem::size_of::<$val_type>(), $byte_len); // size_of isn't a constfn in 1.22 + let mut val = [0; $byte_len]; + self.read_exact(&mut val[..]).map_err(Error::Io)?; + Ok(endian::$readfn(&val)) } } } impl WriteExt for W { - encoder_fn!(emit_u64, u64, write_u64); - encoder_fn!(emit_u32, u32, write_u32); - encoder_fn!(emit_u16, u16, write_u16); - encoder_fn!(emit_i64, i64, write_i64); - encoder_fn!(emit_i32, i32, write_i32); - encoder_fn!(emit_i16, i16, write_i16); + 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); #[inline] fn emit_i8(&mut self, v: i8) -> Result<(), Error> { - self.write_i8(v).map_err(Error::Io) + self.write_all(&[v as u8]).map_err(Error::Io) } #[inline] fn emit_u8(&mut self, v: u8) -> Result<(), Error> { - self.write_u8(v).map_err(Error::Io) + self.write_all(&[v]).map_err(Error::Io) } #[inline] fn emit_bool(&mut self, v: bool) -> Result<(), Error> { - self.write_i8(if v {1} else {0}).map_err(Error::Io) + self.write_all(&[if v {1} else {0}]).map_err(Error::Io) } #[inline] fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error> { @@ -317,20 +320,24 @@ impl WriteExt for W { } impl ReadExt for R { - decoder_fn!(read_u64, u64, read_u64); - decoder_fn!(read_u32, u32, read_u32); - decoder_fn!(read_u16, u16, read_u16); - decoder_fn!(read_i64, i64, read_i64); - decoder_fn!(read_i32, i32, read_i32); - decoder_fn!(read_i16, i16, read_i16); + 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); #[inline] fn read_u8(&mut self) -> Result { - ReadBytesExt::read_u8(self).map_err(Error::Io) + let mut slice = [0u8; 1]; + self.read_exact(&mut slice)?; + Ok(slice[0]) } #[inline] fn read_i8(&mut self) -> Result { - ReadBytesExt::read_i8(self).map_err(Error::Io) + let mut slice = [0u8; 1]; + self.read_exact(&mut slice)?; + Ok(slice[0] as i8) } #[inline] fn read_bool(&mut self) -> Result { diff --git a/src/lib.rs b/src/lib.rs index 87a788a2..75990cd2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,7 +52,6 @@ pub extern crate secp256k1; pub extern crate bech32; #[cfg(any(test, feature = "serde"))] extern crate hex; -extern crate byteorder; #[cfg(feature = "serde")] extern crate serde; #[cfg(all(test, feature = "serde"))] #[macro_use] extern crate serde_derive; // for 1.22.0 compat #[cfg(all(test, feature = "serde"))] extern crate serde_json; diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 4d83bbd8..68a2548d 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -23,7 +23,6 @@ use network::constants; use consensus::{Encodable, Decodable, ReadExt}; use consensus::encode; use std::io; -use byteorder::WriteBytesExt; use network::message_network::RejectReason::{MALFORMED, INVALID, OBSOLETE, DUPLICATE, NONSTANDARD, DUST, CHECKPOINT, FEE}; use hashes::sha256d; @@ -107,7 +106,7 @@ pub enum RejectReason { impl Encodable for RejectReason { fn consensus_encode(&self, mut e: W) -> Result { - e.write_u8(*self as u8)?; + e.write_all(&[*self as u8])?; Ok(1) } } diff --git a/src/util/base58.rs b/src/util/base58.rs index da6b0029..2a268eac 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -16,10 +16,10 @@ use std::{error, fmt, str, slice, iter}; -use byteorder::{ByteOrder, LittleEndian}; - use hashes::{sha256d, Hash}; +use util::endian; + /// An error that might occur during base58 decoding #[derive(Debug, PartialEq, Eq, Clone)] pub enum Error { @@ -162,8 +162,8 @@ pub fn from_check(data: &str) -> Result, Error> { return Err(Error::TooShort(ret.len())); } let ck_start = ret.len() - 4; - let expected = LittleEndian::read_u32(&sha256d::Hash::hash(&ret[..ck_start])[..4]); - let actual = LittleEndian::read_u32(&ret[ck_start..(ck_start + 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)]); if expected != actual { return Err(Error::BadChecksum(expected, actual)); } diff --git a/src/util/bip158.rs b/src/util/bip158.rs index 65926f9f..bc2504ff 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -51,13 +51,13 @@ use std::fmt::{Display, Formatter}; use std::io::Cursor; use hashes::{Hash, sha256d, siphash24}; -use byteorder::{ByteOrder, LittleEndian}; use blockdata::block::Block; use blockdata::script::Script; use blockdata::transaction::OutPoint; use consensus::{Decodable, Encodable}; use consensus::encode::VarInt; +use util::endian; use util::hash::BitcoinHash; /// Golomb encoding parameter as in BIP-158, see also https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845 @@ -155,8 +155,8 @@ impl<'a> BlockFilterWriter<'a> { /// Create a block filter writer pub fn new(writer: &'a mut io::Write, block: &'a Block) -> BlockFilterWriter<'a> { let block_hash_as_int = block.bitcoin_hash().into_inner(); - let k0 = LittleEndian::read_u64(&block_hash_as_int[0..8]); - let k1 = LittleEndian::read_u64(&block_hash_as_int[8..16]); + 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 writer = GCSFilterWriter::new(writer, k0, k1, M, P); BlockFilterWriter { block, writer } } @@ -208,8 +208,8 @@ impl BlockFilterReader { /// Create a block filter reader pub fn new(block_hash: &sha256d::Hash) -> BlockFilterReader { let block_hash_as_int = block_hash.into_inner(); - let k0 = LittleEndian::read_u64(&block_hash_as_int[0..8]); - let k1 = LittleEndian::read_u64(&block_hash_as_int[8..16]); + 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]); BlockFilterReader { reader: GCSFilterReader::new(k0, k1, M, P) } } diff --git a/src/util/bip32.rs b/src/util/bip32.rs index d21d5cf4..60d10457 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -17,17 +17,15 @@ //! at https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki use std::default::Default; -use std::io::Cursor; use std::{error, fmt}; use std::str::FromStr; #[cfg(feature = "serde")] use serde; -use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; use hashes::{hex, hash160, sha512, Hash, HashEngine, Hmac, HmacEngine}; use secp256k1::{self, Secp256k1}; use network::constants::Network; -use util::base58; +use util::{base58, endian}; use util::key::{PublicKey, PrivateKey}; /// A chain code @@ -448,7 +446,6 @@ impl ExtendedPrivKey { /// Private->Private child key derivation pub fn ckd_priv(&self, secp: &Secp256k1, i: ChildNumber) -> Result { let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); - let mut be_n = [0; 4]; match i { ChildNumber::Normal {..} => { // Non-hardened key: compute public data and use that @@ -460,9 +457,8 @@ impl ExtendedPrivKey { hmac_engine.input(&self.private_key[..]); } } - BigEndian::write_u32(&mut be_n, u32::from(i)); - hmac_engine.input(&be_n); + hmac_engine.input(&endian::u32_to_array_be(u32::from(i))); let hmac_result: Hmac = Hmac::from_engine(hmac_engine); let mut sk = PrivateKey { compressed: true, @@ -529,9 +525,7 @@ impl ExtendedPubKey { ChildNumber::Normal { index: n } => { let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); hmac_engine.input(&self.public_key.key.serialize()[..]); - let mut be_n = [0; 4]; - BigEndian::write_u32(&mut be_n, n); - hmac_engine.input(&be_n); + hmac_engine.input(&endian::u32_to_array_be(n)); let hmac_result: Hmac = Hmac::from_engine(hmac_engine); @@ -588,9 +582,7 @@ impl fmt::Display for ExtendedPrivKey { }[..]); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); - - BigEndian::write_u32(&mut ret[9..13], u32::from(self.child_number)); - + ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); ret[13..45].copy_from_slice(&self.chain_code[..]); ret[45] = 0; ret[46..78].copy_from_slice(&self.private_key[..]); @@ -608,7 +600,7 @@ impl FromStr for ExtendedPrivKey { return Err(base58::Error::InvalidLength(data.len())); } - let cn_int: u32 = Cursor::new(&data[9..13]).read_u32::().unwrap(); + let cn_int: u32 = endian::slice_to_u32_be(&data[9..13]); let child_number: ChildNumber = ChildNumber::from(cn_int); let network = if &data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] { @@ -647,9 +639,7 @@ impl fmt::Display for ExtendedPubKey { }[..]); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); - - BigEndian::write_u32(&mut ret[9..13], u32::from(self.child_number)); - + ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number))); ret[13..45].copy_from_slice(&self.chain_code[..]); ret[45..78].copy_from_slice(&self.public_key.key.serialize()[..]); fmt.write_str(&base58::check_encode_slice(&ret[..])) @@ -666,7 +656,7 @@ impl FromStr for ExtendedPubKey { return Err(base58::Error::InvalidLength(data.len())); } - let cn_int: u32 = Cursor::new(&data[9..13]).read_u32::().unwrap(); + let cn_int: u32 = endian::slice_to_u32_be(&data[9..13]); let child_number: ChildNumber = ChildNumber::from(cn_int); Ok(ExtendedPubKey { diff --git a/src/util/endian.rs b/src/util/endian.rs new file mode 100644 index 00000000..8c10b57a --- /dev/null +++ b/src/util/endian.rs @@ -0,0 +1,125 @@ +macro_rules! define_slice_to_be { + ($name: ident, $type: ty) => { + #[inline] + pub fn $name(slice: &[u8]) -> $type { + assert_eq!(slice.len(), ::std::mem::size_of::<$type>()); + let mut res = 0; + for i in 0..::std::mem::size_of::<$type>() { + res |= (slice[i] as $type) << (::std::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(), ::std::mem::size_of::<$type>()); + let mut res = 0; + for i in 0..::std::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] { + assert_eq!(::std::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22 + 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] { + assert_eq!(::std::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22 + 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) +} + +macro_rules! define_chunk_slice_to_int { + ($name: ident, $type: ty, $converter: ident) => { + #[inline] + pub fn $name(inp: &[u8], outp: &mut [$type]) { + assert_eq!(inp.len(), outp.len() * ::std::mem::size_of::<$type>()); + for (outp_val, data_bytes) in outp.iter_mut().zip(inp.chunks(::std::mem::size_of::<$type>())) { + *outp_val = $converter(data_bytes); + } + } + } +} +define_chunk_slice_to_int!(bytes_to_u64_slice_le, u64, slice_to_u64_le); + +#[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]); + } + + #[test] + fn endian_chunk_test() { + let inp = [0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, 0xfe, 0xca, 0xad, 0x1b, 0xce, 0xfa, 0x01, 0x02]; + let mut out = [0; 2]; + bytes_to_u64_slice_le(&inp, &mut out); + assert_eq!(out, [0x1badcafedeadbeef, 0x0201face1badcafe]); + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index d046f55c..36ebc5ee 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -30,6 +30,8 @@ pub mod psbt; pub mod uint; pub mod bip158; +pub(crate) mod endian; + use std::{error, fmt}; use network; From 824d52fe87f0a054be0eed1f83d0857bf5334ee9 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 28 Oct 2019 15:17:53 -0400 Subject: [PATCH 3/3] Disable useless lints --- src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 75990cd2..cabf24e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,6 +45,11 @@ #![deny(missing_docs)] #![forbid(unsafe_code)] +// In general, rust is absolutely horrid at supporting users doing things like, +// for example, compiling Rust code for real environments. Disable useless lints +// that don't do anything but annoy us and cant actually ever be resolved. +#![allow(bare_trait_objects)] +#![allow(ellipsis_inclusive_range_patterns)] // Re-exported dependencies. pub extern crate bitcoin_hashes as hashes;