From 24ebc2900546c598ae0fc747727423ca274e89fa Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 11 Jul 2019 15:01:28 +0000 Subject: [PATCH 1/7] fix some recent rustc warnings --- src/util/address.rs | 3 --- src/util/psbt/raw.rs | 9 ++++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/util/address.rs b/src/util/address.rs index 26c892aa..24499457 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -137,7 +137,6 @@ impl Address { /// Create a witness pay to script hash address pub fn p2wsh (script: &script::Script, network: Network) -> Address { use bitcoin_hashes::sha256; - use bitcoin_hashes::Hash; Address { network: network, @@ -156,8 +155,6 @@ impl Address { /// This is a segwit address type that looks familiar (as p2sh) to legacy clients pub fn p2shwsh (script: &script::Script, network: Network) -> Address { use bitcoin_hashes::sha256; - use bitcoin_hashes::Hash; - use bitcoin_hashes::hash160; let ws = script::Builder::new().push_int(0) .push_slice(&sha256::Hash::hash(&script[..])[..]) diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 21a58b6e..3f7fbba5 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -43,9 +43,12 @@ pub struct Pair { impl fmt::Display for Key { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use hex; - - write!(f, "type: {:#x}, key: {}", self.type_value, hex::encode(&self.key)) + write!( + f, + "type: {:#x}, key: {}", + self.type_value, + ::hex::encode(&self.key) + ) } } From 7e6ad7c8936ae758aff2e8d9798100e1fba198eb Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 23 May 2019 18:43:47 +0000 Subject: [PATCH 2/7] rename Encoder to WriteExt and Decoder to ReadExt --- src/blockdata/opcodes.rs | 7 ++-- src/blockdata/script.rs | 7 ++-- src/blockdata/transaction.rs | 16 ++++---- src/consensus/encode.rs | 68 ++++++++++++++++---------------- src/consensus/mod.rs | 4 +- src/internal_macros.rs | 7 ++-- src/network/address.rs | 6 +-- src/network/constants.rs | 7 ++-- src/network/message.rs | 14 +++---- src/network/message_blockdata.rs | 6 +-- src/util/merkleblock.rs | 10 ++--- src/util/psbt/macros.rs | 16 ++++---- src/util/psbt/map/global.rs | 4 +- src/util/psbt/mod.rs | 6 +-- src/util/psbt/raw.rs | 10 ++--- src/util/uint.rs | 8 ++-- 16 files changed, 96 insertions(+), 100 deletions(-) diff --git a/src/blockdata/opcodes.rs b/src/blockdata/opcodes.rs index 9c664a35..a79081a3 100644 --- a/src/blockdata/opcodes.rs +++ b/src/blockdata/opcodes.rs @@ -24,8 +24,7 @@ use std::fmt; -use consensus::encode::{self, Decoder, Encoder}; -use consensus::encode::{Decodable, Encodable}; +use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; // Note: I am deliberately not implementing PartialOrd or Ord on the // opcode enum. If you want to check ranges of opcodes, etc., @@ -715,14 +714,14 @@ impl From for All { display_from_debug!(All); -impl Decodable for All { +impl Decodable for All { #[inline] fn consensus_decode(d: &mut D) -> Result { Ok(All::from(d.read_u8()?)) } } -impl Encodable for All { +impl Encodable for All { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { s.emit_u8(self.code) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index f683e4b9..845fb8f8 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -30,8 +30,7 @@ use std::{error, fmt}; #[cfg(feature = "serde")] use serde; use blockdata::opcodes; -use consensus::encode::{Decodable, Encodable}; -use consensus::encode::{self, Decoder, Encoder}; +use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; use bitcoin_hashes::{hash160, sha256, Hash}; #[cfg(feature="bitcoinconsensus")] use bitcoinconsensus; #[cfg(feature="bitcoinconsensus")] use std::convert; @@ -726,14 +725,14 @@ impl serde::Serialize for Script { } // Network serialization -impl Encodable for Script { +impl Encodable for Script { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { self.0.consensus_encode(s) } } -impl Decodable for Script { +impl Decodable for Script { #[inline] fn consensus_decode(d: &mut D) -> Result { Ok(Script(Decodable::consensus_decode(d)?)) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index d0d18309..ff59f8a1 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -34,8 +34,8 @@ use bitcoin_hashes::hex::FromHex; use util::hash::BitcoinHash; #[cfg(feature="bitcoinconsensus")] use blockdata::script; use blockdata::script::Script; -use consensus::encode::{self, serialize, Encoder, Decoder}; -use consensus::encode::{Encodable, Decodable, VarInt}; +use consensus::{encode, serialize, Decodable, Encodable, ReadExt, WriteExt}; +use VarInt; /// A reference to a transaction output #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] @@ -439,13 +439,13 @@ impl BitcoinHash for Transaction { impl_consensus_encoding!(TxOut, value, script_pubkey); -impl Encodable for OutPoint { +impl Encodable for OutPoint { fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { self.txid.consensus_encode(s)?; self.vout.consensus_encode(s) } } -impl Decodable for OutPoint { +impl Decodable for OutPoint { fn consensus_decode(d: &mut D) -> Result { Ok(OutPoint { txid: Decodable::consensus_decode(d)?, @@ -454,14 +454,14 @@ impl Decodable for OutPoint { } } -impl Encodable for TxIn { +impl Encodable for TxIn { fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { self.previous_output.consensus_encode(s)?; self.script_sig.consensus_encode(s)?; self.sequence.consensus_encode(s) } } -impl Decodable for TxIn { +impl Decodable for TxIn { fn consensus_decode(d: &mut D) -> Result { Ok(TxIn { previous_output: Decodable::consensus_decode(d)?, @@ -472,7 +472,7 @@ impl Decodable for TxIn { } } -impl Encodable for Transaction { +impl Encodable for Transaction { fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { self.version.consensus_encode(s)?; let mut have_witness = self.input.is_empty(); @@ -498,7 +498,7 @@ impl Encodable for Transaction { } } -impl Decodable for Transaction { +impl Decodable for Transaction { fn consensus_decode(d: &mut D) -> Result { let version: u32 = Decodable::consensus_decode(d)?; let input: Vec = Decodable::consensus_decode(d)?; diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 7620137a..b2c10c88 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -242,8 +242,8 @@ pub fn deserialize_partial<'a, T>(data: &'a [u8]) -> Result<(T, usize), Error> } -/// A simple Encoder trait -pub trait Encoder { +/// Extensions of `Write` to encode data as per Bitcoin consensus +pub trait WriteExt { /// Output a 64-bit uint fn emit_u64(&mut self, v: u64) -> Result<(), Error>; /// Output a 32-bit uint @@ -269,8 +269,8 @@ pub trait Encoder { fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error>; } -/// A simple Decoder trait -pub trait Decoder { +/// Extensions of `Read` to decode data as per Bitcoin consensus +pub trait ReadExt { /// Read a 64-bit uint fn read_u64(&mut self) -> Result; /// Read a 32-bit uint @@ -314,7 +314,7 @@ macro_rules! decoder_fn { } } -impl Encoder for W { +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); @@ -340,7 +340,7 @@ impl Encoder for W { } } -impl Decoder for R { +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); @@ -358,7 +358,7 @@ impl Decoder for R { } #[inline] fn read_bool(&mut self) -> Result { - Decoder::read_i8(self).map(|bit| bit != 0) + ReadExt::read_i8(self).map(|bit| bit != 0) } #[inline] fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error> { @@ -370,14 +370,14 @@ impl Decoder for R { pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024; /// Data which can be encoded in a consensus-consistent way -pub trait Encodable { +pub trait Encodable { /// Encode an object with a well-defined format, should only ever error if - /// the underlying Encoder errors. + /// the underlying WriteExt errors. fn consensus_encode(&self, e: &mut S) -> Result<(), self::Error>; } /// Data which can be encoded in a consensus-consistent way -pub trait Decodable: Sized { +pub trait Decodable: Sized { /// Decode an object with a well-defined format fn consensus_decode(d: &mut D) -> Result; } @@ -393,12 +393,12 @@ pub struct CheckedData(pub Vec); // Primitive types macro_rules! impl_int_encodable{ ($ty:ident, $meth_dec:ident, $meth_enc:ident) => ( - impl Decodable for $ty { + impl Decodable for $ty { #[inline] fn consensus_decode(d: &mut D) -> Result<$ty, self::Error> { d.$meth_dec().map($ty::from_le) } } - impl Encodable for $ty { + impl Encodable for $ty { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.$meth_enc(self.to_le()) } } @@ -429,7 +429,7 @@ impl VarInt { } } -impl Encodable for VarInt { +impl Encodable for VarInt { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { match self.0 { @@ -441,7 +441,7 @@ impl Encodable for VarInt { } } -impl Decodable for VarInt { +impl Decodable for VarInt { #[inline] fn consensus_decode(d: &mut D) -> Result { let n = d.read_u8()?; @@ -477,18 +477,18 @@ impl Decodable for VarInt { // Booleans -impl Encodable for bool { +impl Encodable for bool { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.emit_u8(if *self {1} else {0}) } } -impl Decodable for bool { +impl Decodable for bool { #[inline] fn consensus_decode(d: &mut D) -> Result { d.read_u8().map(|n| n != 0) } } // Strings -impl Encodable for String { +impl Encodable for String { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { let b = self.as_bytes(); @@ -497,7 +497,7 @@ impl Encodable for String { } } -impl Decodable for String { +impl Decodable for String { #[inline] fn consensus_decode(d: &mut D) -> Result { String::from_utf8(Decodable::consensus_decode(d)?) @@ -509,14 +509,14 @@ impl Decodable for String { // Arrays macro_rules! impl_array { ( $size:expr ) => ( - impl Encodable for [u8; $size] { + impl Encodable for [u8; $size] { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.emit_slice(&self[..]) } } - impl Decodable for [u8; $size] { + impl Decodable for [u8; $size] { #[inline] fn consensus_decode(d: &mut D) -> Result<[u8; $size], self::Error> { let mut ret = [0; $size]; @@ -535,7 +535,7 @@ impl_array!(16); impl_array!(32); impl_array!(33); -impl Decodable for [u16; 8] { +impl Decodable for [u16; 8] { #[inline] fn consensus_decode(d: &mut D) -> Result<[u16; 8], self::Error> { let mut res = [0; 8]; @@ -546,7 +546,7 @@ impl Decodable for [u16; 8] { } } -impl Encodable for [u16; 8] { +impl Encodable for [u16; 8] { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { for c in self.iter() { c.consensus_encode(s)?; } @@ -557,7 +557,7 @@ impl Encodable for [u16; 8] { // Vectors macro_rules! impl_vec { ($type: ty) => { - impl Encodable for Vec<$type> { + impl Encodable for Vec<$type> { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { VarInt(self.len() as u64).consensus_encode(s)?; @@ -566,7 +566,7 @@ macro_rules! impl_vec { } } - impl Decodable for Vec<$type> { + impl Decodable for Vec<$type> { #[inline] fn consensus_decode(d: &mut D) -> Result, self::Error> { let len = VarInt::consensus_decode(d)?.0; @@ -592,7 +592,7 @@ impl_vec!(Vec); impl_vec!((u32, Address)); impl_vec!(u64); -impl Encodable for Vec { +impl Encodable for Vec { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { VarInt(self.len() as u64).consensus_encode(s)?; @@ -600,7 +600,7 @@ impl Encodable for Vec { } } -impl Decodable for Vec { +impl Decodable for Vec { #[inline] fn consensus_decode(d: &mut D) -> Result, self::Error> { let len = VarInt::consensus_decode(d)?.0; @@ -615,7 +615,7 @@ impl Decodable for Vec { } } -impl Encodable for Box<[u8]> { +impl Encodable for Box<[u8]> { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { VarInt(self.len() as u64).consensus_encode(s)?; @@ -623,7 +623,7 @@ impl Encodable for Box<[u8]> { } } -impl Decodable for Box<[u8]> { +impl Decodable for Box<[u8]> { #[inline] fn consensus_decode(d: &mut D) -> Result, self::Error> { let len = VarInt::consensus_decode(d)?.0; @@ -646,7 +646,7 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { } // Checked data -impl Encodable for CheckedData { +impl Encodable for CheckedData { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { (self.0.len() as u32).consensus_encode(s)?; @@ -655,7 +655,7 @@ impl Encodable for CheckedData { } } -impl Decodable for CheckedData { +impl Decodable for CheckedData { #[inline] fn consensus_decode(d: &mut D) -> Result { let len: u32 = Decodable::consensus_decode(d)?; @@ -684,7 +684,7 @@ impl Decodable for CheckedData { // Tuples macro_rules! tuple_encode { ($($x:ident),*) => ( - impl ),*> Encodable for ($($x),*) { + impl ),*> Encodable for ($($x),*) { #[inline] #[allow(non_snake_case)] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { @@ -694,7 +694,7 @@ macro_rules! tuple_encode { } } - impl),*> Decodable for ($($x),*) { + impl),*> Decodable for ($($x),*) { #[inline] #[allow(non_snake_case)] fn consensus_decode(d: &mut D) -> Result<($($x),*), self::Error> { @@ -709,13 +709,13 @@ tuple_encode!(T0, T1, T2, T3); tuple_encode!(T0, T1, T2, T3, T4, T5); tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); -impl Encodable for sha256d::Hash { +impl Encodable for sha256d::Hash { fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { self.into_inner().consensus_encode(s) } } -impl Decodable for sha256d::Hash { +impl Decodable for sha256d::Hash { fn consensus_decode(d: &mut D) -> Result { let inner: [u8; 32] = Decodable::consensus_decode(d)?; Ok(sha256d::Hash::from_slice(&inner).unwrap()) diff --git a/src/consensus/mod.rs b/src/consensus/mod.rs index 634b23ca..1e302333 100644 --- a/src/consensus/mod.rs +++ b/src/consensus/mod.rs @@ -21,6 +21,6 @@ pub mod encode; pub mod params; -pub use self::encode::{Encodable, Decodable, Encoder, Decoder, - serialize, deserialize, deserialize_partial}; +pub use self::encode::{Encodable, Decodable, WriteExt, ReadExt}; +pub use self::encode::{serialize, deserialize, deserialize_partial}; pub use self::params::Params; diff --git a/src/internal_macros.rs b/src/internal_macros.rs index f891c46b..86cec029 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -18,7 +18,7 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( - impl ::consensus::encode::Encodable for $thing { + impl ::consensus::Encodable for $thing { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> { $( self.$field.consensus_encode(s)?; )+ @@ -26,12 +26,11 @@ macro_rules! impl_consensus_encoding { } } - impl ::consensus::encode::Decodable for $thing { + impl ::consensus::Decodable for $thing { #[inline] fn consensus_decode(d: &mut D) -> Result<$thing, ::consensus::encode::Error> { - use consensus::encode::Decodable; Ok($thing { - $( $field: Decodable::consensus_decode(d)?, )+ + $( $field: ::consensus::Decodable::consensus_decode(d)?, )+ }) } } diff --git a/src/network/address.rs b/src/network/address.rs index c6871486..36531b2a 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -22,7 +22,7 @@ use std::io; use std::fmt; use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; -use consensus::encode::{self, Encoder, Decoder}; +use consensus::{encode, ReadExt, WriteExt}; use consensus::encode::{Decodable, Encodable}; /// A message which can be sent on the Bitcoin network @@ -72,7 +72,7 @@ fn addr_to_be(addr: [u16; 8]) -> [u16; 8] { addr[4].to_be(), addr[5].to_be(), addr[6].to_be(), addr[7].to_be()] } -impl Encodable for Address { +impl Encodable for Address { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { self.services.consensus_encode(s)?; @@ -81,7 +81,7 @@ impl Encodable for Address { } } -impl Decodable for Address { +impl Decodable for Address { #[inline] fn consensus_decode(d: &mut D) -> Result { Ok(Address { diff --git a/src/network/constants.rs b/src/network/constants.rs index 0315fb13..7f44ff02 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -37,8 +37,7 @@ //! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]); //! ``` -use consensus::encode::{Decodable, Encodable}; -use consensus::encode::{self, Encoder, Decoder}; +use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; /// Version of the protocol as appearing in network message headers pub const PROTOCOL_VERSION: u32 = 70001; @@ -102,7 +101,7 @@ impl Network { } } -impl Encodable for Network { +impl Encodable for Network { /// Encodes the magic bytes of `Network`. #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { @@ -110,7 +109,7 @@ impl Encodable for Network { } } -impl Decodable for Network { +impl Decodable for Network { /// Decodes the magic bytes of `Network`. #[inline] fn consensus_decode(d: &mut D) -> Result { diff --git a/src/network/message.rs b/src/network/message.rs index 2e01c708..40d1e051 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -30,14 +30,14 @@ use network::message_blockdata; use network::message_filter; use consensus::encode::{Decodable, Encodable}; use consensus::encode::{CheckedData, VarInt}; -use consensus::encode::{self, serialize, Encoder, Decoder}; +use consensus::{encode, serialize, ReadExt, WriteExt}; use consensus::encode::MAX_VEC_SIZE; /// Serializer for command string #[derive(PartialEq, Eq, Clone, Debug)] pub struct CommandString(pub String); -impl Encodable for CommandString { +impl Encodable for CommandString { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { let &CommandString(ref inner_str) = self; @@ -53,7 +53,7 @@ impl Encodable for CommandString { } } -impl Decodable for CommandString { +impl Decodable for CommandString { #[inline] fn consensus_decode(d: &mut D) -> Result { let rawbytes: [u8; 12] = Decodable::consensus_decode(d)?; @@ -160,7 +160,7 @@ impl RawNetworkMessage { } struct HeaderSerializationWrapper<'a>(&'a Vec); -impl <'a, S: Encoder> Encodable for HeaderSerializationWrapper<'a> { +impl <'a, S: WriteExt> Encodable for HeaderSerializationWrapper<'a> { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { VarInt(self.0.len() as u64).consensus_encode(s)?; @@ -172,7 +172,7 @@ impl <'a, S: Encoder> Encodable for HeaderSerializationWrapper<'a> { } } -impl Encodable for RawNetworkMessage { +impl Encodable for RawNetworkMessage { fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { self.magic.consensus_encode(s)?; CommandString(self.command()).consensus_encode(s)?; @@ -205,7 +205,7 @@ impl Encodable for RawNetworkMessage { } struct HeaderDeserializationWrapper(Vec); -impl Decodable for HeaderDeserializationWrapper { +impl Decodable for HeaderDeserializationWrapper { #[inline] fn consensus_decode(d: &mut D) -> Result { let len = VarInt::consensus_decode(d)?.0; @@ -226,7 +226,7 @@ impl Decodable for HeaderDeserializationWrapper { } } -impl Decodable for RawNetworkMessage { +impl Decodable for RawNetworkMessage { fn consensus_decode(d: &mut D) -> Result { let magic = Decodable::consensus_decode(d)?; let CommandString(cmd): CommandString= Decodable::consensus_decode(d)?; diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 67834d86..b9f76b3b 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -20,7 +20,7 @@ use network::constants; use consensus::encode::{Decodable, Encodable}; -use consensus::encode::{self, Decoder, Encoder}; +use consensus::{encode, ReadExt, WriteExt}; use bitcoin_hashes::sha256d; #[derive(PartialEq, Eq, Clone, Debug)] @@ -101,7 +101,7 @@ impl GetHeadersMessage { impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); -impl Encodable for Inventory { +impl Encodable for Inventory { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { match self.inv_type { @@ -115,7 +115,7 @@ impl Encodable for Inventory { } } -impl Decodable for Inventory { +impl Decodable for Inventory { #[inline] fn consensus_decode(d: &mut D) -> Result { let int_type: u32 = Decodable::consensus_decode(d)?; diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 6b2eb6b2..6ae1512e 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -62,7 +62,7 @@ use bitcoin_hashes::{sha256d, Hash}; use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT}; use consensus::encode::{Encodable, Error}; -use consensus::{Decodable, Decoder, Encoder}; +use consensus::{Decodable, ReadExt, WriteExt}; use util::hash::BitcoinHash; use util::merkleblock::MerkleBlockError::*; use {Block, BlockHeader}; @@ -353,7 +353,7 @@ impl PartialMerkleTree { } } -impl Encodable for PartialMerkleTree { +impl Encodable for PartialMerkleTree { fn consensus_encode(&self, s: &mut S) -> Result<(), Error> { self.num_transactions.consensus_encode(s)?; self.hashes.consensus_encode(s)?; @@ -365,7 +365,7 @@ impl Encodable for PartialMerkleTree { } } -impl Decodable for PartialMerkleTree { +impl Decodable for PartialMerkleTree { fn consensus_decode(d: &mut D) -> Result { let num_transactions: u32 = Decodable::consensus_decode(d)?; let hashes: Vec = Decodable::consensus_decode(d)?; @@ -471,14 +471,14 @@ impl MerkleBlock { } } -impl Encodable for MerkleBlock { +impl Encodable for MerkleBlock { fn consensus_encode(&self, s: &mut S) -> Result<(), Error> { self.header.consensus_encode(s)?; self.txn.consensus_encode(s) } } -impl Decodable for MerkleBlock { +impl Decodable for MerkleBlock { fn consensus_decode(d: &mut D) -> Result { Ok(MerkleBlock { header: Decodable::consensus_decode(d)?, diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 21a4be8a..50363f4b 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -14,7 +14,7 @@ #[allow(unused_macros)] macro_rules! hex_psbt { - ($s:expr) => { ::consensus::encode::deserialize(&::hex::decode($s).unwrap()) }; + ($s:expr) => { ::consensus::deserialize(&::hex::decode($s).unwrap()) }; } macro_rules! merge { @@ -36,7 +36,7 @@ macro_rules! impl_psbt_deserialize { ($thing:ty) => { impl ::util::psbt::serialize::Deserialize for $thing { fn deserialize(bytes: &[u8]) -> Result { - ::consensus::encode::deserialize(&bytes[..]) + ::consensus::deserialize(&bytes[..]) } } }; @@ -46,7 +46,7 @@ macro_rules! impl_psbt_serialize { ($thing:ty) => { impl ::util::psbt::serialize::Serialize for $thing { fn serialize(&self) -> Vec { - ::consensus::encode::serialize(self) + ::consensus::serialize(self) } } }; @@ -54,13 +54,13 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { - impl ::consensus::encode::Encodable for $thing { + impl ::consensus::Encodable for $thing { fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> { for pair in ::util::psbt::Map::get_pairs(self)? { - ::consensus::encode::Encodable::consensus_encode(&pair, s)? + ::consensus::Encodable::consensus_encode(&pair, s)? } - ::consensus::encode::Encodable::consensus_encode(&0x00_u8, s) + ::consensus::Encodable::consensus_encode(&0x00_u8, s) } } }; @@ -68,12 +68,12 @@ macro_rules! impl_psbtmap_consensus_encoding { macro_rules! impl_psbtmap_consensus_decoding { ($thing:ty) => { - impl ::consensus::encode::Decodable for $thing { + impl ::consensus::Decodable for $thing { fn consensus_decode(d: &mut D) -> Result { let mut rv: Self = ::std::default::Default::default(); loop { - match ::consensus::encode::Decodable::consensus_decode(d) { + match ::consensus::Decodable::consensus_decode(d) { Ok(pair) => ::util::psbt::Map::insert_pair(&mut rv, pair)?, Err(::consensus::encode::Error::Psbt(::util::psbt::Error::NoMorePairs)) => return Ok(rv), Err(e) => return Err(e), diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index faa59dcc..9e14bd68 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use std::io::Cursor; use blockdata::transaction::Transaction; -use consensus::encode::{self, Encodable, Decodable, Decoder}; +use consensus::{encode, Encodable, Decodable, ReadExt}; use util::psbt::map::Map; use util::psbt::raw; use util::psbt; @@ -120,7 +120,7 @@ impl Map for Global { impl_psbtmap_consensus_encoding!(Global); -impl Decodable for Global { +impl Decodable for Global { fn consensus_decode(d: &mut D) -> Result { let mut tx: Option = None; diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 2f149105..e3299d09 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -20,7 +20,7 @@ use blockdata::script::Script; use blockdata::transaction::Transaction; -use consensus::encode::{self, Encodable, Decodable, Encoder, Decoder}; +use consensus::{encode, Encodable, Decodable, WriteExt, ReadExt}; mod error; pub use self::error::Error; @@ -88,7 +88,7 @@ impl PartiallySignedTransaction { } } -impl Encodable for PartiallySignedTransaction { +impl Encodable for PartiallySignedTransaction { fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { b"psbt".consensus_encode(s)?; @@ -108,7 +108,7 @@ impl Encodable for PartiallySignedTransaction { } } -impl Decodable for PartiallySignedTransaction { +impl Decodable for PartiallySignedTransaction { fn consensus_decode(d: &mut D) -> Result { let magic: [u8; 4] = Decodable::consensus_decode(d)?; diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 3f7fbba5..1753cf1b 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -20,7 +20,7 @@ use std::fmt; use consensus::encode::{Decodable, Encodable, VarInt, MAX_VEC_SIZE}; -use consensus::encode::{self, Decoder, Encoder}; +use consensus::{encode, ReadExt, WriteExt}; use util::psbt::Error; /// A PSBT key in its raw byte form. @@ -52,7 +52,7 @@ impl fmt::Display for Key { } } -impl Decodable for Key { +impl Decodable for Key { fn consensus_decode(d: &mut D) -> Result { let VarInt(byte_size): VarInt = Decodable::consensus_decode(d)?; @@ -80,7 +80,7 @@ impl Decodable for Key { } } -impl Encodable for Key { +impl Encodable for Key { fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { VarInt((self.key.len() + 1) as u64).consensus_encode(s)?; @@ -94,14 +94,14 @@ impl Encodable for Key { } } -impl Encodable for Pair { +impl Encodable for Pair { fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { self.key.consensus_encode(s)?; self.value.consensus_encode(s) } } -impl Decodable for Pair { +impl Decodable for Pair { fn consensus_decode(d: &mut D) -> Result { Ok(Pair { key: Decodable::consensus_decode(d)?, diff --git a/src/util/uint.rs b/src/util/uint.rs index 05d4a95a..42abdbfa 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -336,7 +336,7 @@ macro_rules! construct_uint { } } - impl ::consensus::encode::Encodable for $name { + impl ::consensus::Encodable for $name { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { let &$name(ref data) = self; @@ -345,9 +345,9 @@ macro_rules! construct_uint { } } - impl ::consensus::encode::Decodable for $name { + impl ::consensus::Decodable for $name { fn consensus_decode(d: &mut D) -> Result<$name, encode::Error> { - use consensus::encode::Decodable; + use consensus::Decodable; let mut ret: [u64; $n_words] = [0; $n_words]; for i in 0..$n_words { ret[i] = Decodable::consensus_decode(d)?; @@ -388,7 +388,7 @@ impl Uint256 { #[cfg(test)] mod tests { - use consensus::encode::{deserialize, serialize}; + use consensus::{deserialize, serialize}; use util::uint::Uint256; use util::BitArray; From abb9210c04b790caebf240c3d1d5b1f3f65ebb25 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 23 May 2019 19:22:43 +0000 Subject: [PATCH 3/7] make `VarInt::len` and `Transaction::get_weight` return a usize --- fuzz/fuzz_targets/deserialize_transaction.rs | 4 ++-- src/blockdata/transaction.rs | 20 ++++++++++---------- src/consensus/encode.rs | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fuzz/fuzz_targets/deserialize_transaction.rs b/fuzz/fuzz_targets/deserialize_transaction.rs index 7f4a5d04..b0cd7ab5 100644 --- a/fuzz/fuzz_targets/deserialize_transaction.rs +++ b/fuzz/fuzz_targets/deserialize_transaction.rs @@ -7,12 +7,12 @@ fn do_test(data: &[u8]) { Ok(mut tx) => { let ser = bitcoin::consensus::encode::serialize(&tx); assert_eq!(&ser[..], data); - let len = ser.len() as u64; + let len = ser.len(); let calculated_weight = tx.get_weight(); for input in &mut tx.input { input.witness = vec![]; } - let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len() as u64; + let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len(); // For 0-input transactions, `no_witness_len` will be incorrect because // we serialize as segwit even after "stripping the witnesses". We need // to drop two bytes (i.e. eight weight) diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index ff59f8a1..f79b3069 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -368,40 +368,40 @@ impl Transaction { /// witness, this is the non-witness consensus-serialized size multiplied by 3 plus the /// with-witness consensus-serialized size. #[inline] - pub fn get_weight(&self) -> u64 { + pub fn get_weight(&self) -> usize { let mut input_weight = 0; let mut inputs_with_witnesses = 0; for input in &self.input { input_weight += 4*(32 + 4 + 4 + // outpoint (32+4) + nSequence - VarInt(input.script_sig.len() as u64).encoded_length() + - input.script_sig.len() as u64); + VarInt(input.script_sig.len() as u64).len() + + input.script_sig.len()); if !input.witness.is_empty() { inputs_with_witnesses += 1; - input_weight += VarInt(input.witness.len() as u64).encoded_length(); + input_weight += VarInt(input.witness.len() as u64).len(); for elem in &input.witness { - input_weight += VarInt(elem.len() as u64).encoded_length() + elem.len() as u64; + input_weight += VarInt(elem.len() as u64).len() + elem.len(); } } } let mut output_size = 0; for output in &self.output { output_size += 8 + // value - VarInt(output.script_pubkey.len() as u64).encoded_length() + - output.script_pubkey.len() as u64; + VarInt(output.script_pubkey.len() as u64).len() + + output.script_pubkey.len(); } let non_input_size = // version: 4 + // count varints: - VarInt(self.input.len() as u64).encoded_length() + - VarInt(self.output.len() as u64).encoded_length() + + VarInt(self.input.len() as u64).len() + + VarInt(self.output.len() as u64).len() + output_size + // lock_time 4; if inputs_with_witnesses == 0 { non_input_size * 4 + input_weight } else { - non_input_size * 4 + input_weight + self.input.len() as u64 - inputs_with_witnesses + 2 + non_input_size * 4 + input_weight + self.input.len() - inputs_with_witnesses + 2 } } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index b2c10c88..fba5cf53 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -419,7 +419,7 @@ impl VarInt { /// Returns 1 for 0...0xFC, 3 for 0xFD...(2^16-1), 5 for 0x10000...(2^32-1), /// and 9 otherwise. #[inline] - pub fn encoded_length(&self) -> u64 { + pub fn len(&self) -> usize { match self.0 { 0...0xFC => { 1 } 0xFD...0xFFFF => { 3 } From b734d6488a22519f7248e4fdd39a3ce2f55d5255 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 23 May 2019 20:28:10 +0000 Subject: [PATCH 4/7] make consensus_encode return the encoded length --- src/blockdata/opcodes.rs | 20 -------- src/blockdata/script.rs | 2 +- src/blockdata/transaction.rs | 38 ++++++++------- src/consensus/encode.rs | 80 +++++++++++++++++++------------- src/internal_macros.rs | 7 +-- src/network/address.rs | 10 ++-- src/network/constants.rs | 67 ++++++++++++-------------- src/network/message.rs | 25 +++++----- src/network/message_blockdata.rs | 6 +-- src/util/merkleblock.rs | 13 +++--- src/util/psbt/macros.rs | 7 +-- src/util/psbt/mod.rs | 15 +++--- src/util/psbt/raw.rs | 17 +++---- src/util/uint.rs | 9 ++-- 14 files changed, 160 insertions(+), 156 deletions(-) diff --git a/src/blockdata/opcodes.rs b/src/blockdata/opcodes.rs index a79081a3..96da7673 100644 --- a/src/blockdata/opcodes.rs +++ b/src/blockdata/opcodes.rs @@ -24,8 +24,6 @@ use std::fmt; -use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; - // Note: I am deliberately not implementing PartialOrd or Ord on the // opcode enum. If you want to check ranges of opcodes, etc., // write an #[inline] helper function which casts to u8s. @@ -714,20 +712,6 @@ impl From for All { display_from_debug!(All); -impl Decodable for All { - #[inline] - fn consensus_decode(d: &mut D) -> Result { - Ok(All::from(d.read_u8()?)) - } -} - -impl Encodable for All { - #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - s.emit_u8(self.code) - } -} - #[cfg(feature = "serde")] impl serde::Serialize for All { fn serialize(&self, serializer: S) -> Result @@ -834,7 +818,6 @@ impl Ordinary { mod tests { use std::collections::HashSet; - use consensus::encode::{serialize, deserialize}; use super::*; macro_rules! roundtrip { @@ -846,9 +829,6 @@ mod tests { assert_eq!(s1, s2); assert_eq!(s1, stringify!($op)); assert!($unique.insert(s1)); - - let enc = serialize(&all::$op); - assert_eq!(all::$op, deserialize(&enc).unwrap()); } } diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 845fb8f8..ec1ae8b1 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -727,7 +727,7 @@ impl serde::Serialize for Script { // Network serialization impl Encodable for Script { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { self.0.consensus_encode(s) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index f79b3069..e7c4675f 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -440,9 +440,9 @@ impl BitcoinHash for Transaction { impl_consensus_encoding!(TxOut, value, script_pubkey); impl Encodable for OutPoint { - fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { - self.txid.consensus_encode(s)?; - self.vout.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let len = self.txid.consensus_encode(s)?; + Ok(len + self.vout.consensus_encode(s)?) } } impl Decodable for OutPoint { @@ -455,10 +455,12 @@ impl Decodable for OutPoint { } impl Encodable for TxIn { - fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { - self.previous_output.consensus_encode(s)?; - self.script_sig.consensus_encode(s)?; - self.sequence.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.previous_output.consensus_encode(s)?; + len += self.script_sig.consensus_encode(s)?; + len += self.sequence.consensus_encode(s)?; + Ok(len) } } impl Decodable for TxIn { @@ -473,8 +475,9 @@ impl Decodable for TxIn { } impl Encodable for Transaction { - fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { - self.version.consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.version.consensus_encode(s)?; let mut have_witness = self.input.is_empty(); for input in &self.input { if !input.witness.is_empty() { @@ -483,18 +486,19 @@ impl Encodable for Transaction { } } if !have_witness { - self.input.consensus_encode(s)?; - self.output.consensus_encode(s)?; + len += self.input.consensus_encode(s)?; + len += self.output.consensus_encode(s)?; } else { - 0u8.consensus_encode(s)?; - 1u8.consensus_encode(s)?; - self.input.consensus_encode(s)?; - self.output.consensus_encode(s)?; + len += 0u8.consensus_encode(s)?; + len += 1u8.consensus_encode(s)?; + len += self.input.consensus_encode(s)?; + len += self.output.consensus_encode(s)?; for input in &self.input { - input.witness.consensus_encode(s)?; + len += input.witness.consensus_encode(s)?; } } - self.lock_time.consensus_encode(s) + len += self.lock_time.consensus_encode(s)?; + Ok(len) } } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index fba5cf53..02cf6af6 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -372,8 +372,9 @@ pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024; /// Data which can be encoded in a consensus-consistent way pub trait Encodable { /// Encode an object with a well-defined format, should only ever error if - /// the underlying WriteExt errors. - fn consensus_encode(&self, e: &mut S) -> Result<(), self::Error>; + /// the underlying WriteExt errors. Returns the number of bytes written on + /// success + fn consensus_encode(&self, e: &mut S) -> Result; } /// Data which can be encoded in a consensus-consistent way @@ -400,7 +401,10 @@ macro_rules! impl_int_encodable{ impl Encodable for $ty { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.$meth_enc(self.to_le()) } + fn consensus_encode(&self, s: &mut S) -> Result { + s.$meth_enc(self.to_le())?; + Ok(mem::size_of::<$ty>()) + } } ) } @@ -431,12 +435,12 @@ impl VarInt { impl Encodable for VarInt { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { match self.0 { - 0...0xFC => { (self.0 as u8).consensus_encode(s) } - 0xFD...0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s) } - 0x10000...0xFFFFFFFF => { s.emit_u8(0xFE)?; (self.0 as u32).consensus_encode(s) } - _ => { s.emit_u8(0xFF)?; (self.0 as u64).consensus_encode(s) } + 0...0xFC => { (self.0 as u8).consensus_encode(s)?; Ok(1) } + 0xFD...0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s)?; Ok(3) } + 0x10000...0xFFFFFFFF => { s.emit_u8(0xFE)?; (self.0 as u32).consensus_encode(s)?; Ok(5) } + _ => { s.emit_u8(0xFF)?; (self.0 as u64).consensus_encode(s)?; Ok(9) } } } } @@ -479,7 +483,10 @@ impl Decodable for VarInt { // Booleans impl Encodable for bool { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.emit_u8(if *self {1} else {0}) } + fn consensus_encode(&self, s: &mut S) -> Result { + s.emit_u8(if *self {1} else {0})?; + Ok(1) + } } impl Decodable for bool { @@ -490,10 +497,11 @@ impl Decodable for bool { // Strings impl Encodable for String { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let b = self.as_bytes(); - VarInt(b.len() as u64).consensus_encode(s)?; - s.emit_slice(&b) + let vi_len = VarInt(b.len() as u64).consensus_encode(s)?; + s.emit_slice(&b)?; + Ok(vi_len + b.len()) } } @@ -511,8 +519,9 @@ macro_rules! impl_array { ( $size:expr ) => ( impl Encodable for [u8; $size] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - s.emit_slice(&self[..]) + fn consensus_encode(&self, s: &mut S) -> Result { + s.emit_slice(&self[..])?; + Ok(self.len()) } } @@ -548,9 +557,9 @@ impl Decodable for [u16; 8] { impl Encodable for [u16; 8] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { for c in self.iter() { c.consensus_encode(s)?; } - Ok(()) + Ok(16) } } @@ -559,10 +568,13 @@ macro_rules! impl_vec { ($type: ty) => { impl Encodable for Vec<$type> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - VarInt(self.len() as u64).consensus_encode(s)?; - for c in self.iter() { c.consensus_encode(s)?; } - Ok(()) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).consensus_encode(s)?; + for c in self.iter() { + len += c.consensus_encode(s)?; + } + Ok(len) } } @@ -594,9 +606,10 @@ impl_vec!(u64); impl Encodable for Vec { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - VarInt(self.len() as u64).consensus_encode(s)?; - s.emit_slice(&self) + fn consensus_encode(&self, s: &mut S) -> Result { + let vi_len = VarInt(self.len() as u64).consensus_encode(s)?; + s.emit_slice(&self)?; + Ok(vi_len + self.len()) } } @@ -617,9 +630,10 @@ impl Decodable for Vec { impl Encodable for Box<[u8]> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - VarInt(self.len() as u64).consensus_encode(s)?; - s.emit_slice(&self) + fn consensus_encode(&self, s: &mut S) -> Result { + let vi_len = VarInt(self.len() as u64).consensus_encode(s)?; + s.emit_slice(&self)?; + Ok(vi_len + self.len()) } } @@ -648,10 +662,11 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { // Checked data impl Encodable for CheckedData { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { (self.0.len() as u32).consensus_encode(s)?; sha2_checksum(&self.0).consensus_encode(s)?; - s.emit_slice(&self.0) + s.emit_slice(&self.0)?; + Ok(8 + self.0.len()) } } @@ -687,10 +702,11 @@ macro_rules! tuple_encode { impl ),*> Encodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let &($(ref $x),*) = self; - $( $x.consensus_encode(s)?; )* - Ok(()) + let mut len = 0; + $(len += $x.consensus_encode(s)?;)* + Ok(len) } } @@ -710,7 +726,7 @@ tuple_encode!(T0, T1, T2, T3, T4, T5); tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); impl Encodable for sha256d::Hash { - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { self.into_inner().consensus_encode(s) } } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 86cec029..27cbb5af 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -20,9 +20,10 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( impl ::consensus::Encodable for $thing { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> { - $( self.$field.consensus_encode(s)?; )+ - Ok(()) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + $(len += self.$field.consensus_encode(s)?;)+ + Ok(len) } } diff --git a/src/network/address.rs b/src/network/address.rs index 36531b2a..142ae41d 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -74,10 +74,12 @@ fn addr_to_be(addr: [u16; 8]) -> [u16; 8] { impl Encodable for Address { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.services.consensus_encode(s)?; - addr_to_be(self.address).consensus_encode(s)?; - self.port.to_be().consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.services.consensus_encode(s)?; + len += addr_to_be(self.address).consensus_encode(s)?; + len += self.port.to_be().consensus_encode(s)?; + Ok(len) } } diff --git a/src/network/constants.rs b/src/network/constants.rs index 7f44ff02..bd7b523b 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -32,13 +32,11 @@ //! use bitcoin::consensus::encode::serialize; //! //! let network = Network::Bitcoin; -//! let bytes = serialize(&network); +//! let bytes = serialize(&network.magic()); //! //! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]); //! ``` -use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; - /// Version of the protocol as appearing in network message headers pub const PROTOCOL_VERSION: u32 = 70001; /// Bitfield of services provided by this node @@ -101,44 +99,39 @@ impl Network { } } -impl Encodable for Network { - /// Encodes the magic bytes of `Network`. - #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.magic().consensus_encode(s) - } -} - -impl Decodable for Network { - /// Decodes the magic bytes of `Network`. - #[inline] - fn consensus_decode(d: &mut D) -> Result { - u32::consensus_decode(d) - .and_then(|m| { - Network::from_magic(m) - .ok_or(encode::Error::UnknownNetworkMagic(m)) - }) - } -} - #[cfg(test)] mod tests { - use super::Network; - use consensus::encode::{deserialize, serialize}; + use super::Network; + use consensus::encode::{deserialize, serialize}; - #[test] - fn serialize_test() { - assert_eq!(serialize(&Network::Bitcoin), vec![0xf9, 0xbe, 0xb4, 0xd9]); - assert_eq!(serialize(&Network::Testnet), vec![0x0b, 0x11, 0x09, 0x07]); - assert_eq!(serialize(&Network::Regtest), vec![0xfa, 0xbf, 0xb5, 0xda]); + #[test] + fn serialize_test() { + assert_eq!( + serialize(&Network::Bitcoin.magic()), + &[0xf9, 0xbe, 0xb4, 0xd9] + ); + assert_eq!( + serialize(&Network::Testnet.magic()), + &[0x0b, 0x11, 0x09, 0x07] + ); + assert_eq!( + serialize(&Network::Regtest.magic()), + &[0xfa, 0xbf, 0xb5, 0xda] + ); - assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin)); - assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet)); - assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest)); - - let bad: Result = deserialize("fakenet".as_bytes()); - assert!(bad.is_err()); - } + assert_eq!( + deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), + Some(Network::Bitcoin.magic()) + ); + assert_eq!( + deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), + Some(Network::Testnet.magic()) + ); + assert_eq!( + deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), + Some(Network::Regtest.magic()) + ); + } #[test] fn string_test() { diff --git a/src/network/message.rs b/src/network/message.rs index 40d1e051..d8dcfd08 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -39,7 +39,7 @@ pub struct CommandString(pub String); impl Encodable for CommandString { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let &CommandString(ref inner_str) = self; let mut rawbytes = [0u8; 12]; let strbytes = inner_str.as_bytes(); @@ -162,21 +162,23 @@ impl RawNetworkMessage { struct HeaderSerializationWrapper<'a>(&'a Vec); impl <'a, S: WriteExt> Encodable for HeaderSerializationWrapper<'a> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - VarInt(self.0.len() as u64).consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.0.len() as u64).consensus_encode(s)?; for header in self.0.iter() { - header.consensus_encode(s)?; - 0u8.consensus_encode(s)?; + len += header.consensus_encode(s)?; + len += 0u8.consensus_encode(s)?; } - Ok(()) + Ok(len) } } impl Encodable for RawNetworkMessage { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.magic.consensus_encode(s)?; - CommandString(self.command()).consensus_encode(s)?; - CheckedData(match self.payload { + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.magic.consensus_encode(s)?; + len += CommandString(self.command()).consensus_encode(s)?; + len += CheckedData(match self.payload { NetworkMessage::Version(ref dat) => serialize(dat), NetworkMessage::Addr(ref dat) => serialize(dat), NetworkMessage::Inv(ref dat) => serialize(dat), @@ -200,7 +202,8 @@ impl Encodable for RawNetworkMessage { | NetworkMessage::SendHeaders | NetworkMessage::MemPool | NetworkMessage::GetAddr => vec![], - }).consensus_encode(s) + }).consensus_encode(s)?; + Ok(len) } } diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index b9f76b3b..c74c0543 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -103,15 +103,15 @@ impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); impl Encodable for Inventory { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - match self.inv_type { + fn consensus_encode(&self, s: &mut S) -> Result { + let inv_len = match self.inv_type { InvType::Error => 0u32, InvType::Transaction => 1, InvType::Block => 2, InvType::WitnessBlock => 0x40000002, InvType::WitnessTransaction => 0x40000001 }.consensus_encode(s)?; - self.hash.consensus_encode(s) + Ok(inv_len + self.hash.consensus_encode(s)?) } } diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 6ae1512e..9eb551e5 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -354,14 +354,14 @@ impl PartialMerkleTree { } impl Encodable for PartialMerkleTree { - fn consensus_encode(&self, s: &mut S) -> Result<(), Error> { - self.num_transactions.consensus_encode(s)?; - self.hashes.consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let ret = self.num_transactions.consensus_encode(s)? + + self.hashes.consensus_encode(s)?; let mut bytes: Vec = vec![0; (self.bits.len() + 7) / 8]; for p in 0..self.bits.len() { bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8; } - bytes.consensus_encode(s) + Ok(ret + bytes.consensus_encode(s)?) } } @@ -472,9 +472,8 @@ impl MerkleBlock { } impl Encodable for MerkleBlock { - fn consensus_encode(&self, s: &mut S) -> Result<(), Error> { - self.header.consensus_encode(s)?; - self.txn.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + Ok(self.header.consensus_encode(s)? + self.txn.consensus_encode(s)?) } } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 50363f4b..5e652c54 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -55,12 +55,13 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { impl ::consensus::Encodable for $thing { - fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; for pair in ::util::psbt::Map::get_pairs(self)? { - ::consensus::Encodable::consensus_encode(&pair, s)? + len += ::consensus::Encodable::consensus_encode(&pair, s)?; } - ::consensus::Encodable::consensus_encode(&0x00_u8, s) + Ok(len + ::consensus::Encodable::consensus_encode(&0x00_u8, s)?) } } }; diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index e3299d09..088192bc 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -89,22 +89,23 @@ impl PartiallySignedTransaction { } impl Encodable for PartiallySignedTransaction { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - b"psbt".consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += b"psbt".consensus_encode(s)?; - 0xff_u8.consensus_encode(s)?; + len += 0xff_u8.consensus_encode(s)?; - self.global.consensus_encode(s)?; + len += self.global.consensus_encode(s)?; for i in &self.inputs { - i.consensus_encode(s)?; + len += i.consensus_encode(s)?; } for i in &self.outputs { - i.consensus_encode(s)?; + len += i.consensus_encode(s)?; } - Ok(()) + Ok(len) } } diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 1753cf1b..880b437f 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -81,23 +81,24 @@ impl Decodable for Key { } impl Encodable for Key { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - VarInt((self.key.len() + 1) as u64).consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt((self.key.len() + 1) as u64).consensus_encode(s)?; - self.type_value.consensus_encode(s)?; + len += self.type_value.consensus_encode(s)?; for key in &self.key { - key.consensus_encode(s)? + len += key.consensus_encode(s)? } - Ok(()) + Ok(len) } } impl Encodable for Pair { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.key.consensus_encode(s)?; - self.value.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let len = self.key.consensus_encode(s)?; + Ok(len + self.value.consensus_encode(s)?) } } diff --git a/src/util/uint.rs b/src/util/uint.rs index 42abdbfa..de98411f 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -338,10 +338,13 @@ macro_rules! construct_uint { impl ::consensus::Encodable for $name { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let &$name(ref data) = self; - for word in data.iter() { word.consensus_encode(s)?; } - Ok(()) + let mut len = 0; + for word in data.iter() { + len += word.consensus_encode(s)?; + } + Ok(len) } } From 87e7ebcf1b64e12074e2ba4a315e05fc2e18ba87 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 5 Jun 2019 13:59:44 +0000 Subject: [PATCH 5/7] prevent compilation on 16-bit targets so we can use `usize` and assume it is 32 bits --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 4e7409ba..f407738b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,6 +54,9 @@ extern crate secp256k1; #[cfg(all(test, feature = "unstable"))] extern crate test; #[cfg(feature="bitcoinconsensus")] extern crate bitcoinconsensus; +#[cfg(target_pointer_width = "16")] +compile_error!("rust-bitcoin cannot be used on 16-bit architectures"); + #[cfg(test)] #[macro_use] mod test_macros; From 42960b959f97c12772e7b936b355881fe5f5d612 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 11 Jul 2019 14:56:37 +0000 Subject: [PATCH 6/7] eliminate type parameter from `Encodable` trait --- src/blockdata/script.rs | 11 +-- src/blockdata/transaction.rs | 47 ++++++++----- src/consensus/encode.rs | 115 ++++++++++++++++++------------- src/internal_macros.rs | 9 ++- src/network/address.rs | 16 +++-- src/network/message.rs | 38 ++++++---- src/network/message_blockdata.rs | 17 +++-- src/util/merkleblock.rs | 19 ++--- src/util/psbt/macros.rs | 12 +++- src/util/psbt/mod.rs | 21 +++--- src/util/psbt/raw.rs | 26 ++++--- src/util/uint.rs | 9 ++- 12 files changed, 209 insertions(+), 131 deletions(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index ec1ae8b1..116c2bdd 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -25,12 +25,12 @@ //! use std::default::Default; -use std::{error, fmt}; +use std::{error, fmt, io}; #[cfg(feature = "serde")] use serde; use blockdata::opcodes; -use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; +use consensus::{encode, Decodable, Encodable, ReadExt}; use bitcoin_hashes::{hash160, sha256, Hash}; #[cfg(feature="bitcoinconsensus")] use bitcoinconsensus; #[cfg(feature="bitcoinconsensus")] use std::convert; @@ -725,9 +725,12 @@ impl serde::Serialize for Script { } // Network serialization -impl Encodable for Script { +impl Encodable for Script { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + s: S, + ) -> Result { self.0.consensus_encode(s) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index e7c4675f..3d83d06c 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -25,7 +25,7 @@ use byteorder::{LittleEndian, WriteBytesExt}; use std::default::Default; -use std::fmt; +use std::{fmt, io}; #[cfg(feature="bitcoinconsensus")] use std::collections::HashMap; use bitcoin_hashes::{self, sha256d, Hash}; @@ -34,7 +34,7 @@ use bitcoin_hashes::hex::FromHex; use util::hash::BitcoinHash; #[cfg(feature="bitcoinconsensus")] use blockdata::script; use blockdata::script::Script; -use consensus::{encode, serialize, Decodable, Encodable, ReadExt, WriteExt}; +use consensus::{encode, serialize, Decodable, Encodable, ReadExt}; use VarInt; /// A reference to a transaction output @@ -439,9 +439,12 @@ impl BitcoinHash for Transaction { impl_consensus_encoding!(TxOut, value, script_pubkey); -impl Encodable for OutPoint { - fn consensus_encode(&self, s: &mut S) -> Result { - let len = self.txid.consensus_encode(s)?; +impl Encodable for OutPoint { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { + let len = self.txid.consensus_encode(&mut s)?; Ok(len + self.vout.consensus_encode(s)?) } } @@ -454,11 +457,14 @@ impl Decodable for OutPoint { } } -impl Encodable for TxIn { - fn consensus_encode(&self, s: &mut S) -> Result { +impl Encodable for TxIn { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - len += self.previous_output.consensus_encode(s)?; - len += self.script_sig.consensus_encode(s)?; + len += self.previous_output.consensus_encode(&mut s)?; + len += self.script_sig.consensus_encode(&mut s)?; len += self.sequence.consensus_encode(s)?; Ok(len) } @@ -474,10 +480,13 @@ impl Decodable for TxIn { } } -impl Encodable for Transaction { - fn consensus_encode(&self, s: &mut S) -> Result { +impl Encodable for Transaction { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - len += self.version.consensus_encode(s)?; + len += self.version.consensus_encode(&mut s)?; let mut have_witness = self.input.is_empty(); for input in &self.input { if !input.witness.is_empty() { @@ -486,15 +495,15 @@ impl Encodable for Transaction { } } if !have_witness { - len += self.input.consensus_encode(s)?; - len += self.output.consensus_encode(s)?; + len += self.input.consensus_encode(&mut s)?; + len += self.output.consensus_encode(&mut s)?; } else { - len += 0u8.consensus_encode(s)?; - len += 1u8.consensus_encode(s)?; - len += self.input.consensus_encode(s)?; - len += self.output.consensus_encode(s)?; + len += 0u8.consensus_encode(&mut s)?; + len += 1u8.consensus_encode(&mut s)?; + len += self.input.consensus_encode(&mut s)?; + len += self.output.consensus_encode(&mut s)?; for input in &self.input { - len += input.witness.consensus_encode(s)?; + len += input.witness.consensus_encode(&mut s)?; } } len += self.lock_time.consensus_encode(s)?; diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 02cf6af6..a1e88229 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -199,18 +199,14 @@ impl From for Error { } /// Encode an object into a vector -pub fn serialize(data: &T) -> Vec - where T: Encodable>>, -{ +pub fn serialize(data: &T) -> Vec { let mut encoder = Cursor::new(vec![]); data.consensus_encode(&mut encoder).unwrap(); encoder.into_inner() } /// Encode an object into a hex-encoded string -pub fn serialize_hex(data: &T) -> String - where T: Encodable>> -{ +pub fn serialize_hex(data: &T) -> String { hex_encode(serialize(data)) } @@ -370,11 +366,11 @@ impl ReadExt for R { pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024; /// Data which can be encoded in a consensus-consistent way -pub trait Encodable { +pub trait Encodable { /// Encode an object with a well-defined format, should only ever error if - /// the underlying WriteExt errors. Returns the number of bytes written on + /// the underlying `Write` errors. Returns the number of bytes written on /// success - fn consensus_encode(&self, e: &mut S) -> Result; + fn consensus_encode(&self, e: W) -> Result; } /// Data which can be encoded in a consensus-consistent way @@ -399,9 +395,12 @@ macro_rules! impl_int_encodable{ fn consensus_decode(d: &mut D) -> Result<$ty, self::Error> { d.$meth_dec().map($ty::from_le) } } - impl Encodable for $ty { + impl Encodable for $ty { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { s.$meth_enc(self.to_le())?; Ok(mem::size_of::<$ty>()) } @@ -433,14 +432,29 @@ impl VarInt { } } -impl Encodable for VarInt { +impl Encodable for VarInt { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode(&self, mut s: S) -> Result { match self.0 { - 0...0xFC => { (self.0 as u8).consensus_encode(s)?; Ok(1) } - 0xFD...0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s)?; Ok(3) } - 0x10000...0xFFFFFFFF => { s.emit_u8(0xFE)?; (self.0 as u32).consensus_encode(s)?; Ok(5) } - _ => { s.emit_u8(0xFF)?; (self.0 as u64).consensus_encode(s)?; Ok(9) } + 0...0xFC => { + (self.0 as u8).consensus_encode(s)?; + Ok(1) + }, + 0xFD...0xFFFF => { + s.emit_u8(0xFD)?; + (self.0 as u16).consensus_encode(s)?; + Ok(3) + }, + 0x10000...0xFFFFFFFF => { + s.emit_u8(0xFE)?; + (self.0 as u32).consensus_encode(s)?; + Ok(5) + }, + _ => { + s.emit_u8(0xFF)?; + (self.0 as u64).consensus_encode(s)?; + Ok(9) + }, } } } @@ -481,9 +495,9 @@ impl Decodable for VarInt { // Booleans -impl Encodable for bool { +impl Encodable for bool { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode(&self, mut s: S) -> Result { s.emit_u8(if *self {1} else {0})?; Ok(1) } @@ -495,11 +509,11 @@ impl Decodable for bool { } // Strings -impl Encodable for String { +impl Encodable for String { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode(&self, mut s: S) -> Result { let b = self.as_bytes(); - let vi_len = VarInt(b.len() as u64).consensus_encode(s)?; + let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?; s.emit_slice(&b)?; Ok(vi_len + b.len()) } @@ -517,9 +531,12 @@ impl Decodable for String { // Arrays macro_rules! impl_array { ( $size:expr ) => ( - impl Encodable for [u8; $size] { + impl Encodable for [u8; $size] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { s.emit_slice(&self[..])?; Ok(self.len()) } @@ -555,10 +572,10 @@ impl Decodable for [u16; 8] { } } -impl Encodable for [u16; 8] { +impl Encodable for [u16; 8] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { - for c in self.iter() { c.consensus_encode(s)?; } + fn consensus_encode(&self, mut s: S) -> Result { + for c in self.iter() { c.consensus_encode(&mut s)?; } Ok(16) } } @@ -566,13 +583,16 @@ impl Encodable for [u16; 8] { // Vectors macro_rules! impl_vec { ($type: ty) => { - impl Encodable for Vec<$type> { + impl Encodable for Vec<$type> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - len += VarInt(self.len() as u64).consensus_encode(s)?; + len += VarInt(self.len() as u64).consensus_encode(&mut s)?; for c in self.iter() { - len += c.consensus_encode(s)?; + len += c.consensus_encode(&mut s)?; } Ok(len) } @@ -604,10 +624,10 @@ impl_vec!(Vec); impl_vec!((u32, Address)); impl_vec!(u64); -impl Encodable for Vec { +impl Encodable for Vec { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { - let vi_len = VarInt(self.len() as u64).consensus_encode(s)?; + fn consensus_encode(&self, mut s: S) -> Result { + let vi_len = VarInt(self.len() as u64).consensus_encode(&mut s)?; s.emit_slice(&self)?; Ok(vi_len + self.len()) } @@ -628,10 +648,10 @@ impl Decodable for Vec { } } -impl Encodable for Box<[u8]> { +impl Encodable for Box<[u8]> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { - let vi_len = VarInt(self.len() as u64).consensus_encode(s)?; + fn consensus_encode(&self, mut s: S) -> Result { + let vi_len = VarInt(self.len() as u64).consensus_encode(&mut s)?; s.emit_slice(&self)?; Ok(vi_len + self.len()) } @@ -660,11 +680,11 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { } // Checked data -impl Encodable for CheckedData { +impl Encodable for CheckedData { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { - (self.0.len() as u32).consensus_encode(s)?; - sha2_checksum(&self.0).consensus_encode(s)?; + fn consensus_encode(&self, mut s: S) -> Result { + (self.0.len() as u32).consensus_encode(&mut s)?; + sha2_checksum(&self.0).consensus_encode(&mut s)?; s.emit_slice(&self.0)?; Ok(8 + self.0.len()) } @@ -699,13 +719,16 @@ impl Decodable for CheckedData { // Tuples macro_rules! tuple_encode { ($($x:ident),*) => ( - impl ),*> Encodable for ($($x),*) { + impl <$($x: Encodable),*> Encodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let &($(ref $x),*) = self; let mut len = 0; - $(len += $x.consensus_encode(s)?;)* + $(len += $x.consensus_encode(&mut s)?;)* Ok(len) } } @@ -725,8 +748,8 @@ tuple_encode!(T0, T1, T2, T3); tuple_encode!(T0, T1, T2, T3, T4, T5); tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); -impl Encodable for sha256d::Hash { - fn consensus_encode(&self, s: &mut S) -> Result { +impl Encodable for sha256d::Hash { + fn consensus_encode(&self, s: S) -> Result { self.into_inner().consensus_encode(s) } } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 27cbb5af..30fe0bb1 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -18,11 +18,14 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( - impl ::consensus::Encodable for $thing { + impl ::consensus::Encodable for $thing { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - $(len += self.$field.consensus_encode(s)?;)+ + $(len += self.$field.consensus_encode(&mut s)?;)+ Ok(len) } } diff --git a/src/network/address.rs b/src/network/address.rs index 142ae41d..87a91564 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -22,7 +22,7 @@ use std::io; use std::fmt; use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; -use consensus::{encode, ReadExt, WriteExt}; +use consensus::{encode, ReadExt}; use consensus::encode::{Decodable, Encodable}; /// A message which can be sent on the Bitcoin network @@ -72,13 +72,15 @@ fn addr_to_be(addr: [u16; 8]) -> [u16; 8] { addr[4].to_be(), addr[5].to_be(), addr[6].to_be(), addr[7].to_be()] } -impl Encodable for Address { +impl Encodable for Address { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { - let mut len = 0; - len += self.services.consensus_encode(s)?; - len += addr_to_be(self.address).consensus_encode(s)?; - len += self.port.to_be().consensus_encode(s)?; + fn consensus_encode( + &self, + mut s: S, + ) -> Result { + let len = self.services.consensus_encode(&mut s)? + + addr_to_be(self.address).consensus_encode(&mut s)? + + self.port.to_be().consensus_encode(s)?; Ok(len) } } diff --git a/src/network/message.rs b/src/network/message.rs index d8dcfd08..de00d783 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -19,7 +19,7 @@ //! also defines (de)serialization routines for many primitives. //! -use std::{iter, mem}; +use std::{io, iter, mem}; use std::io::Cursor; use blockdata::block; @@ -30,16 +30,19 @@ use network::message_blockdata; use network::message_filter; use consensus::encode::{Decodable, Encodable}; use consensus::encode::{CheckedData, VarInt}; -use consensus::{encode, serialize, ReadExt, WriteExt}; +use consensus::{encode, serialize, ReadExt}; use consensus::encode::MAX_VEC_SIZE; /// Serializer for command string #[derive(PartialEq, Eq, Clone, Debug)] pub struct CommandString(pub String); -impl Encodable for CommandString { +impl Encodable for CommandString { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + s: S, + ) -> Result { let &CommandString(ref inner_str) = self; let mut rawbytes = [0u8; 12]; let strbytes = inner_str.as_bytes(); @@ -160,24 +163,31 @@ impl RawNetworkMessage { } struct HeaderSerializationWrapper<'a>(&'a Vec); -impl <'a, S: WriteExt> Encodable for HeaderSerializationWrapper<'a> { + +impl<'a> Encodable for HeaderSerializationWrapper<'a> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - len += VarInt(self.0.len() as u64).consensus_encode(s)?; + len += VarInt(self.0.len() as u64).consensus_encode(&mut s)?; for header in self.0.iter() { - len += header.consensus_encode(s)?; - len += 0u8.consensus_encode(s)?; + len += header.consensus_encode(&mut s)?; + len += 0u8.consensus_encode(&mut s)?; } Ok(len) } } -impl Encodable for RawNetworkMessage { - fn consensus_encode(&self, s: &mut S) -> Result { +impl Encodable for RawNetworkMessage { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - len += self.magic.consensus_encode(s)?; - len += CommandString(self.command()).consensus_encode(s)?; + len += self.magic.consensus_encode(&mut s)?; + len += CommandString(self.command()).consensus_encode(&mut s)?; len += CheckedData(match self.payload { NetworkMessage::Version(ref dat) => serialize(dat), NetworkMessage::Addr(ref dat) => serialize(dat), @@ -202,7 +212,7 @@ impl Encodable for RawNetworkMessage { | NetworkMessage::SendHeaders | NetworkMessage::MemPool | NetworkMessage::GetAddr => vec![], - }).consensus_encode(s)?; + }).consensus_encode(&mut s)?; Ok(len) } } diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index c74c0543..7d3a7701 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -20,9 +20,11 @@ use network::constants; use consensus::encode::{Decodable, Encodable}; -use consensus::{encode, ReadExt, WriteExt}; +use consensus::{encode, ReadExt}; use bitcoin_hashes::sha256d; +use std::io; + #[derive(PartialEq, Eq, Clone, Debug)] /// The type of an inventory object pub enum InvType { @@ -101,17 +103,20 @@ impl GetHeadersMessage { impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); -impl Encodable for Inventory { +impl Encodable for Inventory { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let inv_len = match self.inv_type { - InvType::Error => 0u32, + InvType::Error => 0u32, InvType::Transaction => 1, InvType::Block => 2, InvType::WitnessBlock => 0x40000002, InvType::WitnessTransaction => 0x40000001 - }.consensus_encode(s)?; - Ok(inv_len + self.hash.consensus_encode(s)?) + }.consensus_encode(&mut s)?; + Ok(inv_len + self.hash.consensus_encode(&mut s)?) } } diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 9eb551e5..bd42d608 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -57,12 +57,13 @@ //! ``` use std::collections::HashSet; +use std::io; use bitcoin_hashes::{sha256d, Hash}; use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT}; use consensus::encode::{Encodable, Error}; -use consensus::{Decodable, ReadExt, WriteExt}; +use consensus::{Decodable, ReadExt}; use util::hash::BitcoinHash; use util::merkleblock::MerkleBlockError::*; use {Block, BlockHeader}; @@ -353,10 +354,10 @@ impl PartialMerkleTree { } } -impl Encodable for PartialMerkleTree { - fn consensus_encode(&self, s: &mut S) -> Result { - let ret = self.num_transactions.consensus_encode(s)? - + self.hashes.consensus_encode(s)?; +impl Encodable for PartialMerkleTree { + fn consensus_encode(&self, mut s: S) -> Result { + let ret = self.num_transactions.consensus_encode(&mut s)? + + self.hashes.consensus_encode(&mut s)?; let mut bytes: Vec = vec![0; (self.bits.len() + 7) / 8]; for p in 0..self.bits.len() { bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8; @@ -471,9 +472,11 @@ impl MerkleBlock { } } -impl Encodable for MerkleBlock { - fn consensus_encode(&self, s: &mut S) -> Result { - Ok(self.header.consensus_encode(s)? + self.txn.consensus_encode(s)?) +impl Encodable for MerkleBlock { + fn consensus_encode(&self, mut s: S) -> Result { + let len = self.header.consensus_encode(&mut s)? + + self.txn.consensus_encode(s)?; + Ok(len) } } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 5e652c54..3531da63 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -54,11 +54,17 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { - impl ::consensus::Encodable for $thing { - fn consensus_encode(&self, s: &mut S) -> Result { + impl ::consensus::Encodable for $thing { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; for pair in ::util::psbt::Map::get_pairs(self)? { - len += ::consensus::Encodable::consensus_encode(&pair, s)?; + len += ::consensus::Encodable::consensus_encode( + &pair, + &mut s, + )?; } Ok(len + ::consensus::Encodable::consensus_encode(&0x00_u8, s)?) diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 088192bc..342265c4 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -20,7 +20,9 @@ use blockdata::script::Script; use blockdata::transaction::Transaction; -use consensus::{encode, Encodable, Decodable, WriteExt, ReadExt}; +use consensus::{encode, Encodable, Decodable, ReadExt}; + +use std::io; mod error; pub use self::error::Error; @@ -88,21 +90,24 @@ impl PartiallySignedTransaction { } } -impl Encodable for PartiallySignedTransaction { - fn consensus_encode(&self, s: &mut S) -> Result { +impl Encodable for PartiallySignedTransaction { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - len += b"psbt".consensus_encode(s)?; + len += b"psbt".consensus_encode(&mut s)?; - len += 0xff_u8.consensus_encode(s)?; + len += 0xff_u8.consensus_encode(&mut s)?; - len += self.global.consensus_encode(s)?; + len += self.global.consensus_encode(&mut s)?; for i in &self.inputs { - len += i.consensus_encode(s)?; + len += i.consensus_encode(&mut s)?; } for i in &self.outputs { - len += i.consensus_encode(s)?; + len += i.consensus_encode(&mut s)?; } Ok(len) diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 880b437f..808f23bf 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -17,10 +17,10 @@ //! Raw PSBT key-value pairs as defined at //! https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki. -use std::fmt; +use std::{fmt, io}; use consensus::encode::{Decodable, Encodable, VarInt, MAX_VEC_SIZE}; -use consensus::{encode, ReadExt, WriteExt}; +use consensus::{encode, ReadExt}; use util::psbt::Error; /// A PSBT key in its raw byte form. @@ -80,24 +80,30 @@ impl Decodable for Key { } } -impl Encodable for Key { - fn consensus_encode(&self, s: &mut S) -> Result { +impl Encodable for Key { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let mut len = 0; - len += VarInt((self.key.len() + 1) as u64).consensus_encode(s)?; + len += VarInt((self.key.len() + 1) as u64).consensus_encode(&mut s)?; - len += self.type_value.consensus_encode(s)?; + len += self.type_value.consensus_encode(&mut s)?; for key in &self.key { - len += key.consensus_encode(s)? + len += key.consensus_encode(&mut s)? } Ok(len) } } -impl Encodable for Pair { - fn consensus_encode(&self, s: &mut S) -> Result { - let len = self.key.consensus_encode(s)?; +impl Encodable for Pair { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { + let len = self.key.consensus_encode(&mut s)?; Ok(len + self.value.consensus_encode(s)?) } } diff --git a/src/util/uint.rs b/src/util/uint.rs index de98411f..b1856a97 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -336,13 +336,16 @@ macro_rules! construct_uint { } } - impl ::consensus::Encodable for $name { + impl ::consensus::Encodable for $name { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let &$name(ref data) = self; let mut len = 0; for word in data.iter() { - len += word.consensus_encode(s)?; + len += word.consensus_encode(&mut s)?; } Ok(len) } From 3b9a94a17818d1949c48324af12e00ac6d9d7533 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 11 Jul 2019 17:06:42 +0000 Subject: [PATCH 7/7] eliminate type parameter from the `Decodable` trait --- src/blockdata/script.rs | 6 +- src/blockdata/transaction.rs | 34 ++++++------ src/consensus/encode.rs | 95 ++++++++++++++++---------------- src/internal_macros.rs | 8 ++- src/network/address.rs | 11 ++-- src/network/message.rs | 42 +++++++------- src/network/message_blockdata.rs | 9 ++- src/util/address.rs | 8 +-- src/util/merkleblock.rs | 27 +++++---- src/util/psbt/macros.rs | 8 ++- src/util/psbt/map/global.rs | 10 ++-- src/util/psbt/mod.rs | 16 +++--- src/util/psbt/raw.rs | 24 ++++---- src/util/psbt/serialize.rs | 16 ++---- src/util/uint.rs | 8 ++- 15 files changed, 166 insertions(+), 156 deletions(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 116c2bdd..a87cb17c 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -30,7 +30,7 @@ use std::{error, fmt, io}; #[cfg(feature = "serde")] use serde; use blockdata::opcodes; -use consensus::{encode, Decodable, Encodable, ReadExt}; +use consensus::{encode, Decodable, Encodable}; use bitcoin_hashes::{hash160, sha256, Hash}; #[cfg(feature="bitcoinconsensus")] use bitcoinconsensus; #[cfg(feature="bitcoinconsensus")] use std::convert; @@ -735,9 +735,9 @@ impl Encodable for Script { } } -impl Decodable for Script { +impl Decodable for Script { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: D) -> Result { Ok(Script(Decodable::consensus_decode(d)?)) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 3d83d06c..cd15963d 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -34,7 +34,7 @@ use bitcoin_hashes::hex::FromHex; use util::hash::BitcoinHash; #[cfg(feature="bitcoinconsensus")] use blockdata::script; use blockdata::script::Script; -use consensus::{encode, serialize, Decodable, Encodable, ReadExt}; +use consensus::{encode, serialize, Decodable, Encodable}; use VarInt; /// A reference to a transaction output @@ -448,10 +448,10 @@ impl Encodable for OutPoint { Ok(len + self.vout.consensus_encode(s)?) } } -impl Decodable for OutPoint { - fn consensus_decode(d: &mut D) -> Result { +impl Decodable for OutPoint { + fn consensus_decode(mut d: D) -> Result { Ok(OutPoint { - txid: Decodable::consensus_decode(d)?, + txid: Decodable::consensus_decode(&mut d)?, vout: Decodable::consensus_decode(d)?, }) } @@ -469,11 +469,11 @@ impl Encodable for TxIn { Ok(len) } } -impl Decodable for TxIn { - fn consensus_decode(d: &mut D) -> Result { +impl Decodable for TxIn { + fn consensus_decode(mut d: D) -> Result { Ok(TxIn { - previous_output: Decodable::consensus_decode(d)?, - script_sig: Decodable::consensus_decode(d)?, + previous_output: Decodable::consensus_decode(&mut d)?, + script_sig: Decodable::consensus_decode(&mut d)?, sequence: Decodable::consensus_decode(d)?, witness: vec![], }) @@ -511,20 +511,20 @@ impl Encodable for Transaction { } } -impl Decodable for Transaction { - fn consensus_decode(d: &mut D) -> Result { - let version: u32 = Decodable::consensus_decode(d)?; - let input: Vec = Decodable::consensus_decode(d)?; +impl Decodable for Transaction { + fn consensus_decode(mut d: D) -> Result { + let version = u32::consensus_decode(&mut d)?; + let input = Vec::::consensus_decode(&mut d)?; // segwit if input.is_empty() { - let segwit_flag: u8 = Decodable::consensus_decode(d)?; + let segwit_flag = u8::consensus_decode(&mut d)?; match segwit_flag { // BIP144 input witnesses 1 => { - let mut input: Vec = Decodable::consensus_decode(d)?; - let output: Vec = Decodable::consensus_decode(d)?; + let mut input = Vec::::consensus_decode(&mut d)?; + let output = Vec::::consensus_decode(&mut d)?; for txin in input.iter_mut() { - txin.witness = Decodable::consensus_decode(d)?; + txin.witness = Decodable::consensus_decode(&mut d)?; } if !input.is_empty() && input.iter().all(|input| input.witness.is_empty()) { Err(encode::Error::ParseFailed("witness flag set but no witnesses present")) @@ -547,7 +547,7 @@ impl Decodable for Transaction { Ok(Transaction { version: version, input: input, - output: Decodable::consensus_decode(d)?, + output: Decodable::consensus_decode(&mut d)?, lock_time: Decodable::consensus_decode(d)?, }) } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index a1e88229..87b0a450 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -212,9 +212,7 @@ pub fn serialize_hex(data: &T) -> String { /// Deserialize an object from a vector, will error if said deserialization /// doesn't consume the entire vector. -pub fn deserialize<'a, T>(data: &'a [u8]) -> Result - where T: Decodable> -{ +pub fn deserialize<'a, T: Decodable>(data: &'a [u8]) -> Result { let (rv, consumed) = deserialize_partial(data)?; // Fail if data are not consumed entirely. @@ -227,9 +225,9 @@ pub fn deserialize<'a, T>(data: &'a [u8]) -> Result /// Deserialize an object from a vector, but will not report an error if said deserialization /// doesn't consume the entire vector. -pub fn deserialize_partial<'a, T>(data: &'a [u8]) -> Result<(T, usize), Error> - where T: Decodable> -{ +pub fn deserialize_partial<'a, T: Decodable>( + data: &'a [u8], +) -> Result<(T, usize), Error> { let mut decoder = Cursor::new(data); let rv = Decodable::consensus_decode(&mut decoder)?; let consumed = decoder.position() as usize; @@ -374,9 +372,9 @@ pub trait Encodable { } /// Data which can be encoded in a consensus-consistent way -pub trait Decodable: Sized { +pub trait Decodable: Sized { /// Decode an object with a well-defined format - fn consensus_decode(d: &mut D) -> Result; + fn consensus_decode(d: D) -> Result; } /// A variable-length unsigned integer @@ -390,9 +388,11 @@ pub struct CheckedData(pub Vec); // Primitive types macro_rules! impl_int_encodable{ ($ty:ident, $meth_dec:ident, $meth_enc:ident) => ( - impl Decodable for $ty { + impl Decodable for $ty { #[inline] - fn consensus_decode(d: &mut D) -> Result<$ty, self::Error> { d.$meth_dec().map($ty::from_le) } + fn consensus_decode(mut d: D) -> Result { + ReadExt::$meth_dec(&mut d).map($ty::from_le) + } } impl Encodable for $ty { @@ -459,13 +459,13 @@ impl Encodable for VarInt { } } -impl Decodable for VarInt { +impl Decodable for VarInt { #[inline] - fn consensus_decode(d: &mut D) -> Result { - let n = d.read_u8()?; + fn consensus_decode(mut d: D) -> Result { + let n = ReadExt::read_u8(&mut d)?; match n { 0xFF => { - let x = d.read_u64()?; + let x = ReadExt::read_u64(&mut d)?; if x < 0x100000000 { Err(self::Error::ParseFailed("non-minimal varint")) } else { @@ -473,7 +473,7 @@ impl Decodable for VarInt { } } 0xFE => { - let x = d.read_u32()?; + let x = ReadExt::read_u32(&mut d)?; if x < 0x10000 { Err(self::Error::ParseFailed("non-minimal varint")) } else { @@ -481,7 +481,7 @@ impl Decodable for VarInt { } } 0xFD => { - let x = d.read_u16()?; + let x = ReadExt::read_u16(&mut d)?; if x < 0xFD { Err(self::Error::ParseFailed("non-minimal varint")) } else { @@ -503,9 +503,11 @@ impl Encodable for bool { } } -impl Decodable for bool { +impl Decodable for bool { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_u8().map(|n| n != 0) } + fn consensus_decode(mut d: D) -> Result { + ReadExt::read_u8(&mut d).map(|n| n != 0) + } } // Strings @@ -519,9 +521,9 @@ impl Encodable for String { } } -impl Decodable for String { +impl Decodable for String { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: D) -> Result { String::from_utf8(Decodable::consensus_decode(d)?) .map_err(|_| self::Error::ParseFailed("String was not valid UTF8")) } @@ -542,9 +544,9 @@ macro_rules! impl_array { } } - impl Decodable for [u8; $size] { + impl Decodable for [u8; $size] { #[inline] - fn consensus_decode(d: &mut D) -> Result<[u8; $size], self::Error> { + fn consensus_decode(mut d: D) -> Result { let mut ret = [0; $size]; d.read_slice(&mut ret)?; Ok(ret) @@ -561,12 +563,12 @@ impl_array!(16); impl_array!(32); impl_array!(33); -impl Decodable for [u16; 8] { +impl Decodable for [u16; 8] { #[inline] - fn consensus_decode(d: &mut D) -> Result<[u16; 8], self::Error> { + fn consensus_decode(mut d: D) -> Result { let mut res = [0; 8]; for i in 0..8 { - res[i] = Decodable::consensus_decode(d)?; + res[i] = Decodable::consensus_decode(&mut d)?; } Ok(res) } @@ -598,10 +600,10 @@ macro_rules! impl_vec { } } - impl Decodable for Vec<$type> { + impl Decodable for Vec<$type> { #[inline] - fn consensus_decode(d: &mut D) -> Result, self::Error> { - let len = VarInt::consensus_decode(d)?.0; + fn consensus_decode(mut d: D) -> Result { + let len = VarInt::consensus_decode(&mut d)?.0; let byte_size = (len as usize) .checked_mul(mem::size_of::<$type>()) .ok_or(self::Error::ParseFailed("Invalid length"))?; @@ -609,7 +611,9 @@ macro_rules! impl_vec { return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE }) } let mut ret = Vec::with_capacity(len as usize); - for _ in 0..len { ret.push(Decodable::consensus_decode(d)?); } + for _ in 0..len { + ret.push(Decodable::consensus_decode(&mut d)?); + } Ok(ret) } } @@ -633,11 +637,10 @@ impl Encodable for Vec { } } -impl Decodable for Vec { +impl Decodable for Vec { #[inline] - fn consensus_decode(d: &mut D) -> Result, self::Error> { - let len = VarInt::consensus_decode(d)?.0; - let len = len as usize; + fn consensus_decode(mut d: D) -> Result { + let len = VarInt::consensus_decode(&mut d)?.0 as usize; if len > MAX_VEC_SIZE { return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE }) } @@ -657,10 +660,10 @@ impl Encodable for Box<[u8]> { } } -impl Decodable for Box<[u8]> { +impl Decodable for Box<[u8]> { #[inline] - fn consensus_decode(d: &mut D) -> Result, self::Error> { - let len = VarInt::consensus_decode(d)?.0; + fn consensus_decode(mut d: D) -> Result { + let len = VarInt::consensus_decode(&mut d)?.0; let len = len as usize; if len > MAX_VEC_SIZE { return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE }) @@ -690,17 +693,17 @@ impl Encodable for CheckedData { } } -impl Decodable for CheckedData { +impl Decodable for CheckedData { #[inline] - fn consensus_decode(d: &mut D) -> Result { - let len: u32 = Decodable::consensus_decode(d)?; + fn consensus_decode(mut d: D) -> Result { + let len = u32::consensus_decode(&mut d)?; if len > MAX_VEC_SIZE as u32 { return Err(self::Error::OversizedVectorAllocation { requested: len as usize, max: MAX_VEC_SIZE }); } - let checksum: [u8; 4] = Decodable::consensus_decode(d)?; + let checksum = <[u8; 4]>::consensus_decode(&mut d)?; let mut ret = Vec::with_capacity(len as usize); ret.resize(len as usize, 0); d.read_slice(&mut ret)?; @@ -733,11 +736,11 @@ macro_rules! tuple_encode { } } - impl),*> Decodable for ($($x),*) { + impl<$($x: Decodable),*> Decodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_decode(d: &mut D) -> Result<($($x),*), self::Error> { - Ok(($({let $x = Decodable::consensus_decode(d)?; $x }),*)) + fn consensus_decode(mut d: D) -> Result { + Ok(($({let $x = Decodable::consensus_decode(&mut d)?; $x }),*)) } } ); @@ -754,9 +757,9 @@ impl Encodable for sha256d::Hash { } } -impl Decodable for sha256d::Hash { - fn consensus_decode(d: &mut D) -> Result { - let inner: [u8; 32] = Decodable::consensus_decode(d)?; +impl Decodable for sha256d::Hash { + fn consensus_decode(d: D) -> Result { + let inner = <[u8; 32]>::consensus_decode(d)?; Ok(sha256d::Hash::from_slice(&inner).unwrap()) } } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 30fe0bb1..b7121625 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -30,11 +30,13 @@ macro_rules! impl_consensus_encoding { } } - impl ::consensus::Decodable for $thing { + impl ::consensus::Decodable for $thing { #[inline] - fn consensus_decode(d: &mut D) -> Result<$thing, ::consensus::encode::Error> { + fn consensus_decode( + mut d: D, + ) -> Result<$thing, ::consensus::encode::Error> { Ok($thing { - $( $field: ::consensus::Decodable::consensus_decode(d)?, )+ + $($field: ::consensus::Decodable::consensus_decode(&mut d)?),+ }) } } diff --git a/src/network/address.rs b/src/network/address.rs index 87a91564..ff841244 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -22,8 +22,7 @@ use std::io; use std::fmt; use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; -use consensus::{encode, ReadExt}; -use consensus::encode::{Decodable, Encodable}; +use consensus::encode::{self, Decodable, Encodable}; /// A message which can be sent on the Bitcoin network pub struct Address { @@ -85,12 +84,12 @@ impl Encodable for Address { } } -impl Decodable for Address { +impl Decodable for Address { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(mut d: D) -> Result { Ok(Address { - services: Decodable::consensus_decode(d)?, - address: addr_to_be(Decodable::consensus_decode(d)?), + services: Decodable::consensus_decode(&mut d)?, + address: addr_to_be(Decodable::consensus_decode(&mut d)?), port: u16::from_be(Decodable::consensus_decode(d)?) }) } diff --git a/src/network/message.rs b/src/network/message.rs index de00d783..7f15ae98 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -28,9 +28,8 @@ use network::address::Address; use network::message_network; use network::message_blockdata; use network::message_filter; -use consensus::encode::{Decodable, Encodable}; -use consensus::encode::{CheckedData, VarInt}; -use consensus::{encode, serialize, ReadExt}; +use consensus::encode::{CheckedData, Decodable, Encodable, VarInt}; +use consensus::{encode, serialize}; use consensus::encode::MAX_VEC_SIZE; /// Serializer for command string @@ -56,11 +55,15 @@ impl Encodable for CommandString { } } -impl Decodable for CommandString { +impl Decodable for CommandString { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: D) -> Result { let rawbytes: [u8; 12] = Decodable::consensus_decode(d)?; - let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None })); + let rv = iter::FromIterator::from_iter( + rawbytes + .iter() + .filter_map(|&u| if u > 0 { Some(u as char) } else { None }) + ); Ok(CommandString(rv)) } } @@ -218,10 +221,11 @@ impl Encodable for RawNetworkMessage { } struct HeaderDeserializationWrapper(Vec); -impl Decodable for HeaderDeserializationWrapper { + +impl Decodable for HeaderDeserializationWrapper { #[inline] - fn consensus_decode(d: &mut D) -> Result { - let len = VarInt::consensus_decode(d)?.0; + fn consensus_decode(mut d: D) -> Result { + let len = VarInt::consensus_decode(&mut d)?.0; let byte_size = (len as usize) .checked_mul(mem::size_of::()) .ok_or(encode::Error::ParseFailed("Invalid length"))?; @@ -230,8 +234,8 @@ impl Decodable for HeaderDeserializationWrapper { } let mut ret = Vec::with_capacity(len as usize); for _ in 0..len { - ret.push(Decodable::consensus_decode(d)?); - if >::consensus_decode(d)? != 0u8 { + ret.push(Decodable::consensus_decode(&mut d)?); + if u8::consensus_decode(&mut d)? != 0u8 { return Err(encode::Error::ParseFailed("Headers message should not contain transactions")); } } @@ -239,11 +243,11 @@ impl Decodable for HeaderDeserializationWrapper { } } -impl Decodable for RawNetworkMessage { - fn consensus_decode(d: &mut D) -> Result { - let magic = Decodable::consensus_decode(d)?; - let CommandString(cmd): CommandString= Decodable::consensus_decode(d)?; - let CheckedData(raw_payload): CheckedData = Decodable::consensus_decode(d)?; +impl Decodable for RawNetworkMessage { + fn consensus_decode(mut d: D) -> Result { + let magic = Decodable::consensus_decode(&mut d)?; + let cmd = CommandString::consensus_decode(&mut d)?.0; + let raw_payload = CheckedData::consensus_decode(&mut d)?.0; let mut mem_d = Cursor::new(raw_payload); let payload = match &cmd[..] { @@ -257,9 +261,9 @@ impl Decodable for RawNetworkMessage { "getheaders" => NetworkMessage::GetHeaders(Decodable::consensus_decode(&mut mem_d)?), "mempool" => NetworkMessage::MemPool, "block" => NetworkMessage::Block(Decodable::consensus_decode(&mut mem_d)?), - "headers" => - NetworkMessage::Headers(>>> - ::consensus_decode(&mut mem_d)?.0), + "headers" => NetworkMessage::Headers( + HeaderDeserializationWrapper::consensus_decode(&mut mem_d)?.0 + ), "sendheaders" => NetworkMessage::SendHeaders, "getaddr" => NetworkMessage::GetAddr, "ping" => NetworkMessage::Ping(Decodable::consensus_decode(&mut mem_d)?), diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 7d3a7701..6b5243af 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -19,8 +19,7 @@ //! use network::constants; -use consensus::encode::{Decodable, Encodable}; -use consensus::{encode, ReadExt}; +use consensus::encode::{self, Decodable, Encodable}; use bitcoin_hashes::sha256d; use std::io; @@ -120,10 +119,10 @@ impl Encodable for Inventory { } } -impl Decodable for Inventory { +impl Decodable for Inventory { #[inline] - fn consensus_decode(d: &mut D) -> Result { - let int_type: u32 = Decodable::consensus_decode(d)?; + fn consensus_decode(mut d: D) -> Result { + let int_type: u32 = Decodable::consensus_decode(&mut d)?; Ok(Inventory { inv_type: match int_type { 0 => InvType::Error, diff --git a/src/util/address.rs b/src/util/address.rs index 24499457..909cb785 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -20,13 +20,13 @@ //! ```rust //! extern crate secp256k1; //! extern crate bitcoin; -//! +//! //! use bitcoin::network::constants::Network; //! use bitcoin::util::address::Address; //! use bitcoin::util::key; //! use secp256k1::Secp256k1; //! use secp256k1::rand::thread_rng; -//! +//! //! fn main() { //! // Generate random key pair //! let s = Secp256k1::new(); @@ -34,7 +34,7 @@ //! compressed: true, //! key: s.generate_keypair(&mut thread_rng()).1, //! }; -//! +//! //! // Generate pay-to-pubkey-hash address //! let address = Address::p2pkh(&public_key, Network::Bitcoin); //! } @@ -427,7 +427,6 @@ mod tests { assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw"); } - #[test] fn test_p2wsh () { // stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667 @@ -436,7 +435,6 @@ mod tests { assert_eq!(&addr.to_string(), "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej"); } - #[test] fn test_bip173_vectors() { let addrstr = "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4"; diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index bd42d608..aa76479e 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -62,8 +62,7 @@ use std::io; use bitcoin_hashes::{sha256d, Hash}; use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT}; -use consensus::encode::{Encodable, Error}; -use consensus::{Decodable, ReadExt}; +use consensus::encode::{self, Decodable, Encodable}; use util::hash::BitcoinHash; use util::merkleblock::MerkleBlockError::*; use {Block, BlockHeader}; @@ -355,7 +354,10 @@ impl PartialMerkleTree { } impl Encodable for PartialMerkleTree { - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let ret = self.num_transactions.consensus_encode(&mut s)? + self.hashes.consensus_encode(&mut s)?; let mut bytes: Vec = vec![0; (self.bits.len() + 7) / 8]; @@ -366,10 +368,10 @@ impl Encodable for PartialMerkleTree { } } -impl Decodable for PartialMerkleTree { - fn consensus_decode(d: &mut D) -> Result { - let num_transactions: u32 = Decodable::consensus_decode(d)?; - let hashes: Vec = Decodable::consensus_decode(d)?; +impl Decodable for PartialMerkleTree { + fn consensus_decode(mut d: D) -> Result { + let num_transactions: u32 = Decodable::consensus_decode(&mut d)?; + let hashes: Vec = Decodable::consensus_decode(&mut d)?; let bytes: Vec = Decodable::consensus_decode(d)?; let mut bits: Vec = vec![false; bytes.len() * 8]; @@ -473,17 +475,20 @@ impl MerkleBlock { } impl Encodable for MerkleBlock { - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode( + &self, + mut s: S, + ) -> Result { let len = self.header.consensus_encode(&mut s)? + self.txn.consensus_encode(s)?; Ok(len) } } -impl Decodable for MerkleBlock { - fn consensus_decode(d: &mut D) -> Result { +impl Decodable for MerkleBlock { + fn consensus_decode(mut d: D) -> Result { Ok(MerkleBlock { - header: Decodable::consensus_decode(d)?, + header: Decodable::consensus_decode(&mut d)?, txn: Decodable::consensus_decode(d)?, }) } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 3531da63..020f1ff6 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -75,12 +75,14 @@ macro_rules! impl_psbtmap_consensus_encoding { macro_rules! impl_psbtmap_consensus_decoding { ($thing:ty) => { - impl ::consensus::Decodable for $thing { - fn consensus_decode(d: &mut D) -> Result { + impl ::consensus::Decodable for $thing { + fn consensus_decode( + mut d: D, + ) -> Result { let mut rv: Self = ::std::default::Default::default(); loop { - match ::consensus::Decodable::consensus_decode(d) { + match ::consensus::Decodable::consensus_decode(&mut d) { Ok(pair) => ::util::psbt::Map::insert_pair(&mut rv, pair)?, Err(::consensus::encode::Error::Psbt(::util::psbt::Error::NoMorePairs)) => return Ok(rv), Err(e) => return Err(e), diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index 9e14bd68..81fc3f57 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -13,10 +13,10 @@ // use std::collections::HashMap; -use std::io::Cursor; +use std::io::{self, Cursor}; use blockdata::transaction::Transaction; -use consensus::{encode, Encodable, Decodable, ReadExt}; +use consensus::{encode, Encodable, Decodable}; use util::psbt::map::Map; use util::psbt::raw; use util::psbt; @@ -120,14 +120,14 @@ impl Map for Global { impl_psbtmap_consensus_encoding!(Global); -impl Decodable for Global { - fn consensus_decode(d: &mut D) -> Result { +impl Decodable for Global { + fn consensus_decode(mut d: D) -> Result { let mut tx: Option = None; let mut unknowns: HashMap> = Default::default(); loop { - match raw::Pair::consensus_decode(d) { + match raw::Pair::consensus_decode(&mut d) { Ok(pair) => { match pair.key.type_value { 0u8 => { diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 342265c4..53b8508f 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -20,7 +20,7 @@ use blockdata::script::Script; use blockdata::transaction::Transaction; -use consensus::{encode, Encodable, Decodable, ReadExt}; +use consensus::{encode, Encodable, Decodable}; use std::io; @@ -114,19 +114,19 @@ impl Encodable for PartiallySignedTransaction { } } -impl Decodable for PartiallySignedTransaction { - fn consensus_decode(d: &mut D) -> Result { - let magic: [u8; 4] = Decodable::consensus_decode(d)?; +impl Decodable for PartiallySignedTransaction { + fn consensus_decode(mut d: D) -> Result { + let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?; if *b"psbt" != magic { return Err(Error::InvalidMagic.into()); } - if 0xff_u8 != u8::consensus_decode(d)? { + if 0xff_u8 != u8::consensus_decode(&mut d)? { return Err(Error::InvalidSeparator.into()); } - let global: Global = Decodable::consensus_decode(d)?; + let global: Global = Decodable::consensus_decode(&mut d)?; let inputs: Vec = { let inputs_len: usize = (&global.unsigned_tx.input).len(); @@ -134,7 +134,7 @@ impl Decodable for PartiallySignedTransaction { let mut inputs: Vec = Vec::with_capacity(inputs_len); for _ in 0..inputs_len { - inputs.push(Decodable::consensus_decode(d)?); + inputs.push(Decodable::consensus_decode(&mut d)?); } inputs @@ -146,7 +146,7 @@ impl Decodable for PartiallySignedTransaction { let mut outputs: Vec = Vec::with_capacity(outputs_len); for _ in 0..outputs_len { - outputs.push(Decodable::consensus_decode(d)?); + outputs.push(Decodable::consensus_decode(&mut d)?); } outputs diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 808f23bf..42c52e44 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -19,8 +19,7 @@ use std::{fmt, io}; -use consensus::encode::{Decodable, Encodable, VarInt, MAX_VEC_SIZE}; -use consensus::{encode, ReadExt}; +use consensus::encode::{self, Decodable, Encodable, VarInt, MAX_VEC_SIZE}; use util::psbt::Error; /// A PSBT key in its raw byte form. @@ -52,9 +51,9 @@ impl fmt::Display for Key { } } -impl Decodable for Key { - fn consensus_decode(d: &mut D) -> Result { - let VarInt(byte_size): VarInt = Decodable::consensus_decode(d)?; +impl Decodable for Key { + fn consensus_decode(mut d: D) -> Result { + let VarInt(byte_size): VarInt = Decodable::consensus_decode(&mut d)?; if byte_size == 0 { return Err(Error::NoMorePairs.into()); @@ -63,14 +62,17 @@ impl Decodable for Key { let key_byte_size: u64 = byte_size - 1; if key_byte_size > MAX_VEC_SIZE as u64 { - return Err(encode::Error::OversizedVectorAllocation { requested: key_byte_size as usize, max: MAX_VEC_SIZE } ) + return Err(encode::Error::OversizedVectorAllocation { + requested: key_byte_size as usize, + max: MAX_VEC_SIZE, + }) } - let type_value: u8 = Decodable::consensus_decode(d)?; + let type_value: u8 = Decodable::consensus_decode(&mut d)?; let mut key = Vec::with_capacity(key_byte_size as usize); for _ in 0..key_byte_size { - key.push(Decodable::consensus_decode(d)?); + key.push(Decodable::consensus_decode(&mut d)?); } Ok(Key { @@ -108,10 +110,10 @@ impl Encodable for Pair { } } -impl Decodable for Pair { - fn consensus_decode(d: &mut D) -> Result { +impl Decodable for Pair { + fn consensus_decode(mut d: D) -> Result { Ok(Pair { - key: Decodable::consensus_decode(d)?, + key: Decodable::consensus_decode(&mut d)?, value: Decodable::consensus_decode(d)?, }) } diff --git a/src/util/psbt/serialize.rs b/src/util/psbt/serialize.rs index 762d1895..8ecd2f34 100644 --- a/src/util/psbt/serialize.rs +++ b/src/util/psbt/serialize.rs @@ -17,7 +17,7 @@ //! Defines traits used for (de)serializing PSBT values into/from raw //! bytes in PSBT key-value pairs. -use std::io::{self, Cursor}; +use std::io; use blockdata::script::Script; use blockdata::transaction::{SigHashType, Transaction, TxOut}; @@ -93,16 +93,10 @@ impl Deserialize for (Fingerprint, DerivationPath) { let fprint: Fingerprint = Fingerprint::from(&bytes[0..4]); let mut dpath: Vec = Default::default(); - let d = &mut Cursor::new(&bytes[4..]); - loop { - match Decodable::consensus_decode(d) { - Ok(index) => { - dpath.push(>::from(index)); - - if d.position() == (bytes.len() - 4) as u64 { - break; - } - }, + let mut d = &bytes[4..]; + while !d.is_empty() { + match u32::consensus_decode(&mut d) { + Ok(index) => dpath.push(index.into()), Err(e) => return Err(e), } } diff --git a/src/util/uint.rs b/src/util/uint.rs index b1856a97..2e26f979 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -351,12 +351,14 @@ macro_rules! construct_uint { } } - impl ::consensus::Decodable for $name { - fn consensus_decode(d: &mut D) -> Result<$name, encode::Error> { + impl ::consensus::Decodable for $name { + fn consensus_decode( + mut d: D, + ) -> Result<$name, encode::Error> { use consensus::Decodable; let mut ret: [u64; $n_words] = [0; $n_words]; for i in 0..$n_words { - ret[i] = Decodable::consensus_decode(d)?; + ret[i] = Decodable::consensus_decode(&mut d)?; } Ok($name(ret)) }