From 9c754ca4ded8710887b2bff69ad64dbff10e75ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Thu, 2 Jun 2022 21:50:42 -0700 Subject: [PATCH 1/3] Take Writer/Reader by `&mut` in consensus en/decoding Fix #1020 (see more relevant discussion there) This definitely makes the amount of generics compiler has to generate by avoding generating the same functions for `R`, &mut R`, `&mut &mut R` and so on. old: ``` > ls -al target/release/deps/bitcoin-07a9dabf1f3e0266 -rwxrwxr-x 1 dpc dpc 9947832 Jun 2 22:42 target/release/deps/bitcoin-07a9dabf1f3e0266 > strip target/release/deps/bitcoin-07a9dabf1f3e0266 > ls -al target/release/deps/bitcoin-07a9dabf1f3e0266 -rwxrwxr-x 1 dpc dpc 4463024 Jun 2 22:46 target/release/deps/bitcoin-07a9dabf1f3e0266 ``` new: ``` > ls -al target/release/deps/bitcoin-07a9dabf1f3e0266 -rwxrwxr-x 1 dpc dpc 9866800 Jun 2 22:44 target/release/deps/bitcoin-07a9dabf1f3e0266 > strip target/release/deps/bitcoin-07a9dabf1f3e0266 > ls -al target/release/deps/bitcoin-07a9dabf1f3e0266 -rwxrwxr-x 1 dpc dpc 4393392 Jun 2 22:45 target/release/deps/bitcoin-07a9dabf1f3e0266 ``` In the unit-test binary itself, it saves ~100KB of data. I did not expect much performance gains, but turn out I was wrong(*): old: ``` test blockdata::block::benches::bench_block_deserialize ... bench: 1,072,710 ns/iter (+/- 21,871) test blockdata::block::benches::bench_block_serialize ... bench: 191,223 ns/iter (+/- 5,833) test blockdata::block::benches::bench_block_serialize_logic ... bench: 37,543 ns/iter (+/- 732) test blockdata::block::benches::bench_stream_reader ... bench: 1,872,455 ns/iter (+/- 149,519) test blockdata::transaction::benches::bench_transaction_deserialize ... bench: 136 ns/iter (+/- 3) test blockdata::transaction::benches::bench_transaction_serialize ... bench: 51 ns/iter (+/- 8) test blockdata::transaction::benches::bench_transaction_serialize_logic ... bench: 5 ns/iter (+/- 0) test blockdata::transaction::benches::bench_transaction_size ... bench: 3 ns/iter (+/- 0) ``` new: ``` test blockdata::block::benches::bench_block_deserialize ... bench: 1,028,574 ns/iter (+/- 10,910) test blockdata::block::benches::bench_block_serialize ... bench: 162,143 ns/iter (+/- 3,363) test blockdata::block::benches::bench_block_serialize_logic ... bench: 30,725 ns/iter (+/- 695) test blockdata::block::benches::bench_stream_reader ... bench: 1,437,071 ns/iter (+/- 53,694) test blockdata::transaction::benches::bench_transaction_deserialize ... bench: 92 ns/iter (+/- 2) test blockdata::transaction::benches::bench_transaction_serialize ... bench: 17 ns/iter (+/- 0) test blockdata::transaction::benches::bench_transaction_serialize_logic ... bench: 5 ns/iter (+/- 0) test blockdata::transaction::benches::bench_transaction_size ... bench: 4 ns/iter (+/- 0) ``` (*) - I'm benchmarking on a noisy laptop. Take this with a grain of salt. But I think at least it doesn't make anything slower. While doing all this manual labor that will probably generate conflicts, I took a liberty of changing generic type names and variable names to `r` and `R` (reader) and `w` and `W` for writer. --- src/blockdata/script.rs | 13 +- src/blockdata/transaction.rs | 77 ++++++------ src/blockdata/witness.rs | 24 ++-- src/consensus/encode.rs | 198 +++++++++++++++---------------- src/hash_types.rs | 8 +- src/internal_macros.rs | 21 ++-- src/network/address.rs | 72 +++++------ src/network/constants.rs | 8 +- src/network/message.rs | 49 ++++---- src/network/message_blockdata.rs | 20 ++-- src/network/message_bloom.rs | 8 +- src/network/message_network.rs | 8 +- src/util/merkleblock.rs | 28 ++--- src/util/psbt/macros.rs | 12 +- src/util/psbt/map/global.rs | 6 +- src/util/psbt/map/mod.rs | 6 +- src/util/psbt/mod.rs | 33 +++--- src/util/psbt/raw.rs | 44 +++---- src/util/sighash.rs | 4 +- src/util/uint.rs | 12 +- 20 files changed, 330 insertions(+), 321 deletions(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 99b07476..bb6e757f 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -27,6 +27,7 @@ use crate::consensus::encode::MAX_VEC_SIZE; use crate::prelude::*; use crate::io; +use io::Read as _; use core::{fmt, default::Default}; use core::ops::Index; @@ -1092,20 +1093,20 @@ impl serde::Serialize for Script { impl Encodable for Script { #[inline] - fn consensus_encode(&self, s: S) -> Result { - self.0.consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) } } impl Decodable for Script { #[inline] - fn consensus_decode_from_finite_reader(d: D) -> Result { - Ok(Script(Decodable::consensus_decode_from_finite_reader(d)?)) + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + Ok(Script(Decodable::consensus_decode_from_finite_reader(r)?)) } #[inline] - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64)) + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(r.take(MAX_VEC_SIZE as u64).by_ref()) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index e397ef16..105ff285 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -26,6 +26,7 @@ use crate::prelude::*; use crate::io; +use io::Read as _; use core::{fmt, str, default::Default}; use crate::hashes::{self, Hash, sha256d}; @@ -653,50 +654,50 @@ impl Transaction { impl_consensus_encoding!(TxOut, value, script_pubkey); 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)?) + fn consensus_encode(&self, w: &mut W) -> Result { + let len = self.txid.consensus_encode(w)?; + Ok(len + self.vout.consensus_encode(w)?) } } impl Decodable for OutPoint { - fn consensus_decode(mut d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(OutPoint { - txid: Decodable::consensus_decode(&mut d)?, - vout: Decodable::consensus_decode(d)?, + txid: Decodable::consensus_decode(r)?, + vout: Decodable::consensus_decode(r)?, }) } } impl Encodable for TxIn { - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += self.previous_output.consensus_encode(&mut s)?; - len += self.script_sig.consensus_encode(&mut s)?; - len += self.sequence.consensus_encode(s)?; + len += self.previous_output.consensus_encode(w)?; + len += self.script_sig.consensus_encode(w)?; + len += self.sequence.consensus_encode(w)?; Ok(len) } } impl Decodable for TxIn { #[inline] - fn consensus_decode_from_finite_reader(mut d: D) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { Ok(TxIn { - previous_output: Decodable::consensus_decode_from_finite_reader(&mut d)?, - script_sig: Decodable::consensus_decode_from_finite_reader(&mut d)?, - sequence: Decodable::consensus_decode_from_finite_reader(d)?, + previous_output: Decodable::consensus_decode_from_finite_reader(r)?, + script_sig: Decodable::consensus_decode_from_finite_reader(r)?, + sequence: Decodable::consensus_decode_from_finite_reader(r)?, witness: Witness::default(), }) } #[inline] - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64)) + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(r.take(MAX_VEC_SIZE as u64).by_ref()) } } impl Encodable for Transaction { - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += self.version.consensus_encode(&mut s)?; + len += self.version.consensus_encode(w)?; // To avoid serialization ambiguity, no inputs means we use BIP141 serialization (see // `Transaction` docs for full explanation). let mut have_witness = self.input.is_empty(); @@ -707,36 +708,36 @@ impl Encodable for Transaction { } } if !have_witness { - len += self.input.consensus_encode(&mut s)?; - len += self.output.consensus_encode(&mut s)?; + len += self.input.consensus_encode(w)?; + len += self.output.consensus_encode(w)?; } else { - 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)?; + len += 0u8.consensus_encode(w)?; + len += 1u8.consensus_encode(w)?; + len += self.input.consensus_encode(w)?; + len += self.output.consensus_encode(w)?; for input in &self.input { - len += input.witness.consensus_encode(&mut s)?; + len += input.witness.consensus_encode(w)?; } } - len += self.lock_time.consensus_encode(s)?; + len += self.lock_time.consensus_encode(w)?; Ok(len) } } impl Decodable for Transaction { - fn consensus_decode_from_finite_reader(mut d: D) -> Result { - let version = i32::consensus_decode_from_finite_reader(&mut d)?; - let input = Vec::::consensus_decode_from_finite_reader(&mut d)?; + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + let version = i32::consensus_decode_from_finite_reader(r)?; + let input = Vec::::consensus_decode_from_finite_reader(r)?; // segwit if input.is_empty() { - let segwit_flag = u8::consensus_decode_from_finite_reader(&mut d)?; + let segwit_flag = u8::consensus_decode_from_finite_reader(r)?; match segwit_flag { // BIP144 input witnesses 1 => { - let mut input = Vec::::consensus_decode_from_finite_reader(&mut d)?; - let output = Vec::::consensus_decode_from_finite_reader(&mut d)?; + let mut input = Vec::::consensus_decode_from_finite_reader(r)?; + let output = Vec::::consensus_decode_from_finite_reader(r)?; for txin in input.iter_mut() { - txin.witness = Decodable::consensus_decode_from_finite_reader(&mut d)?; + txin.witness = Decodable::consensus_decode_from_finite_reader(r)?; } if !input.is_empty() && input.iter().all(|input| input.witness.is_empty()) { Err(encode::Error::ParseFailed("witness flag set but no witnesses present")) @@ -745,7 +746,7 @@ impl Decodable for Transaction { version, input, output, - lock_time: Decodable::consensus_decode_from_finite_reader(d)?, + lock_time: Decodable::consensus_decode_from_finite_reader(r)?, }) } } @@ -757,14 +758,14 @@ impl Decodable for Transaction { Ok(Transaction { version, input, - output: Decodable::consensus_decode_from_finite_reader(&mut d)?, - lock_time: Decodable::consensus_decode_from_finite_reader(d)?, + output: Decodable::consensus_decode_from_finite_reader(r)?, + lock_time: Decodable::consensus_decode_from_finite_reader(r)?, }) } } - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64)) + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64)) } } diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index c1fa40f4..2339162e 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -49,8 +49,8 @@ pub struct Iter<'a> { } impl Decodable for Witness { - fn consensus_decode(mut d: D) -> Result { - let witness_elements = VarInt::consensus_decode(&mut d)?.0 as usize; + fn consensus_decode(r: &mut R) -> Result { + let witness_elements = VarInt::consensus_decode(r)?.0 as usize; if witness_elements == 0 { Ok(Witness::default()) } else { @@ -65,7 +65,7 @@ impl Decodable for Witness { for _ in 0..witness_elements { second_to_last = last; last = cursor; - let element_size_varint = VarInt::consensus_decode(&mut d)?; + let element_size_varint = VarInt::consensus_decode(r)?; let element_size_varint_len = element_size_varint.len(); let element_size = element_size_varint.0 as usize; let required_len = cursor @@ -89,9 +89,9 @@ impl Decodable for Witness { resize_if_needed(&mut content, required_len); element_size_varint - .consensus_encode(&mut content[cursor..cursor + element_size_varint_len])?; + .consensus_encode(&mut &mut content[cursor..cursor + element_size_varint_len])?; cursor += element_size_varint_len; - d.read_exact(&mut content[cursor..cursor + element_size])?; + r.read_exact(&mut content[cursor..cursor + element_size])?; cursor += element_size; } content.truncate(cursor); @@ -116,10 +116,10 @@ fn resize_if_needed(vec: &mut Vec, required_len: usize) { } impl Encodable for Witness { - fn consensus_encode(&self, mut writer: W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let len = VarInt(self.witness_elements as u64); - len.consensus_encode(&mut writer)?; - writer.emit_slice(&self.content[..])?; + len.consensus_encode(w)?; + w.emit_slice(&self.content[..])?; Ok(self.content.len() + len.len()) } } @@ -148,7 +148,7 @@ impl Witness { last = cursor; let el_len_varint = VarInt(el.len() as u64); el_len_varint - .consensus_encode(&mut content[cursor..cursor + el_len_varint.len()]) + .consensus_encode(&mut &mut content[cursor..cursor + el_len_varint.len()]) .expect("writers on vec don't errors, space granted by content_size"); cursor += el_len_varint.len(); content[cursor..cursor + el.len()].copy_from_slice(&el); @@ -211,7 +211,7 @@ impl Witness { .resize(current_content_len + element_len_varint.len() + new_element.len(), 0); let end_varint = current_content_len + element_len_varint.len(); element_len_varint - .consensus_encode(&mut self.content[current_content_len..end_varint]) + .consensus_encode(&mut &mut self.content[current_content_len..end_varint]) .expect("writers on vec don't error, space granted through previous resize"); self.content[end_varint..].copy_from_slice(new_element); } @@ -228,7 +228,7 @@ impl Witness { fn element_at(&self, index: usize) -> Option<&[u8]> { - let varint = VarInt::consensus_decode(&self.content[index..]).ok()?; + let varint = VarInt::consensus_decode(&mut &self.content[index..]).ok()?; let start = index + varint.len(); Some(&self.content[start..start + varint.0 as usize]) } @@ -256,7 +256,7 @@ impl<'a> Iterator for Iter<'a> { type Item = &'a [u8]; fn next(&mut self) -> Option { - let varint = VarInt::consensus_decode(self.inner.as_slice()).ok()?; + let varint = VarInt::consensus_decode(&mut self.inner.as_slice()).ok()?; self.inner.nth(varint.len() - 1)?; // VarInt::len returns at least 1 let len = varint.0 as usize; let slice = &self.inner.as_slice()[..len]; diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 9e3b2804..b2b254c9 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -315,7 +315,7 @@ pub trait Encodable { /// Returns the number of bytes written on success. /// /// The only errors returned are errors propagated from the writer. - fn consensus_encode(&self, writer: W) -> Result; + fn consensus_encode(&self, writer: &mut W) -> Result; } /// Data which can be encoded in a consensus-consistent way @@ -353,16 +353,16 @@ pub trait Decodable: Sized { /// should also implement it applying same rules, and in addition make sure to call /// `consensus_decode_from_finite_reader` on all members, to avoid creating redundant /// `Take` wrappers. Failure to do so might result only in a tiny performance hit. - fn consensus_decode_from_finite_reader(d: D) -> Result { + fn consensus_decode_from_finite_reader(reader: &mut R) -> Result { // This method is always strictly less general than, `consensus_decode`, // so it's safe and make sense to default to just calling it. // This way most types, that don't care about protecting against // resource exhaustion due to malicious input, can just ignore it. - Self::consensus_decode(d) + Self::consensus_decode(reader) } /// Decode an object with a well-defined format - fn consensus_decode(d: D) -> Result; + fn consensus_decode(reader: &mut R) -> Result; } /// A variable-length unsigned integer @@ -378,14 +378,14 @@ macro_rules! impl_int_encodable { ($ty:ident, $meth_dec:ident, $meth_enc:ident) => { impl Decodable for $ty { #[inline] - fn consensus_decode(mut d: D) -> Result { - ReadExt::$meth_dec(&mut d) + fn consensus_decode(r: &mut R) -> Result { + ReadExt::$meth_dec(r) } } impl Encodable for $ty { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - s.$meth_enc(*self)?; + fn consensus_encode(&self, w: &mut W) -> Result { + w.$meth_enc(*self)?; Ok(mem::size_of::<$ty>()) } } @@ -419,25 +419,25 @@ impl VarInt { impl Encodable for VarInt { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { match self.0 { 0..=0xFC => { - (self.0 as u8).consensus_encode(s)?; + (self.0 as u8).consensus_encode(w)?; Ok(1) }, 0xFD..=0xFFFF => { - s.emit_u8(0xFD)?; - (self.0 as u16).consensus_encode(s)?; + w.emit_u8(0xFD)?; + (self.0 as u16).consensus_encode(w)?; Ok(3) }, 0x10000..=0xFFFFFFFF => { - s.emit_u8(0xFE)?; - (self.0 as u32).consensus_encode(s)?; + w.emit_u8(0xFE)?; + (self.0 as u32).consensus_encode(w)?; Ok(5) }, _ => { - s.emit_u8(0xFF)?; - (self.0 as u64).consensus_encode(s)?; + w.emit_u8(0xFF)?; + (self.0 as u64).consensus_encode(w)?; Ok(9) }, } @@ -446,11 +446,11 @@ impl Encodable for VarInt { impl Decodable for VarInt { #[inline] - fn consensus_decode(mut d: D) -> Result { - let n = ReadExt::read_u8(&mut d)?; + fn consensus_decode(r: &mut R) -> Result { + let n = ReadExt::read_u8(r)?; match n { 0xFF => { - let x = ReadExt::read_u64(&mut d)?; + let x = ReadExt::read_u64(r)?; if x < 0x100000000 { Err(self::Error::NonMinimalVarInt) } else { @@ -458,7 +458,7 @@ impl Decodable for VarInt { } } 0xFE => { - let x = ReadExt::read_u32(&mut d)?; + let x = ReadExt::read_u32(r)?; if x < 0x10000 { Err(self::Error::NonMinimalVarInt) } else { @@ -466,7 +466,7 @@ impl Decodable for VarInt { } } 0xFD => { - let x = ReadExt::read_u16(&mut d)?; + let x = ReadExt::read_u16(r)?; if x < 0xFD { Err(self::Error::NonMinimalVarInt) } else { @@ -481,34 +481,34 @@ impl Decodable for VarInt { // Booleans impl Encodable for bool { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - s.emit_bool(*self)?; + fn consensus_encode(&self, w: &mut W) -> Result { + w.emit_bool(*self)?; Ok(1) } } impl Decodable for bool { #[inline] - fn consensus_decode(mut d: D) -> Result { - ReadExt::read_bool(&mut d) + fn consensus_decode(r: &mut R) -> Result { + ReadExt::read_bool(r) } } // Strings impl Encodable for String { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let b = self.as_bytes(); - let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?; - s.emit_slice(b)?; + let vi_len = VarInt(b.len() as u64).consensus_encode(w)?; + w.emit_slice(b)?; Ok(vi_len + b.len()) } } impl Decodable for String { #[inline] - fn consensus_decode(d: D) -> Result { - String::from_utf8(Decodable::consensus_decode(d)?) + fn consensus_decode(r: &mut R) -> Result { + String::from_utf8(Decodable::consensus_decode(r)?) .map_err(|_| self::Error::ParseFailed("String was not valid UTF8")) } } @@ -516,18 +516,18 @@ impl Decodable for String { // Cow<'static, str> impl Encodable for Cow<'static, str> { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let b = self.as_bytes(); - let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?; - s.emit_slice(b)?; + let vi_len = VarInt(b.len() as u64).consensus_encode(w)?; + w.emit_slice(b)?; Ok(vi_len + b.len()) } } impl Decodable for Cow<'static, str> { #[inline] - fn consensus_decode(d: D) -> Result, Error> { - String::from_utf8(Decodable::consensus_decode(d)?) + fn consensus_decode(r: &mut R) -> Result, Error> { + String::from_utf8(Decodable::consensus_decode(r)?) .map_err(|_| self::Error::ParseFailed("String was not valid UTF8")) .map(Cow::Owned) } @@ -539,17 +539,17 @@ macro_rules! impl_array { ( $size:expr ) => { impl Encodable for [u8; $size] { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - s.emit_slice(&self[..])?; + fn consensus_encode(&self, w: &mut W) -> Result { + w.emit_slice(&self[..])?; Ok(self.len()) } } impl Decodable for [u8; $size] { #[inline] - fn consensus_decode(mut d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { let mut ret = [0; $size]; - d.read_slice(&mut ret)?; + r.read_slice(&mut ret)?; Ok(ret) } } @@ -567,10 +567,10 @@ impl_array!(33); impl Decodable for [u16; 8] { #[inline] - fn consensus_decode(mut d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { let mut res = [0; 8]; for item in &mut res { - *item = Decodable::consensus_decode(&mut d)?; + *item = Decodable::consensus_decode(r)?; } Ok(res) } @@ -578,8 +578,8 @@ impl Decodable for [u16; 8] { impl Encodable for [u16; 8] { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - for c in self.iter() { c.consensus_encode(&mut s)?; } + fn consensus_encode(&self, w: &mut W) -> Result { + for c in self.iter() { c.consensus_encode(w)?; } Ok(16) } } @@ -589,11 +589,11 @@ macro_rules! impl_vec { ($type: ty) => { impl Encodable for Vec<$type> { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += VarInt(self.len() as u64).consensus_encode(&mut s)?; + len += VarInt(self.len() as u64).consensus_encode(w)?; for c in self.iter() { - len += c.consensus_encode(&mut s)?; + len += c.consensus_encode(w)?; } Ok(len) } @@ -601,8 +601,8 @@ macro_rules! impl_vec { impl Decodable for Vec<$type> { #[inline] - fn consensus_decode_from_finite_reader(mut d: D) -> Result { - let len = VarInt::consensus_decode_from_finite_reader(&mut d)?.0; + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + let len = VarInt::consensus_decode_from_finite_reader(r)?.0; // Do not allocate upfront more items than if the sequnce of type // occupied roughly quarter a block. This should never be the case // for normal data, but even if that's not true - `push` will just @@ -612,14 +612,14 @@ macro_rules! impl_vec { let max_capacity = MAX_VEC_SIZE / 4 / mem::size_of::<$type>(); let mut ret = Vec::with_capacity(core::cmp::min(len as usize, max_capacity)); for _ in 0..len { - ret.push(Decodable::consensus_decode_from_finite_reader(&mut d)?); + ret.push(Decodable::consensus_decode_from_finite_reader(r)?); } Ok(ret) } #[inline] - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64)) + fn consensus_decode(d: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut d.take(MAX_VEC_SIZE as u64)) } } } @@ -675,41 +675,41 @@ fn read_bytes_from_finite_reader(mut d: D, mut opts: ReadBytesFromF impl Encodable for Vec { #[inline] - fn consensus_encode(&self, s: S) -> Result { - consensus_encode_with_size(self, s) + fn consensus_encode(&self, w: &mut W) -> Result { + consensus_encode_with_size(self, w) } } impl Decodable for Vec { #[inline] - fn consensus_decode_from_finite_reader(mut d: D) -> Result { - let len = VarInt::consensus_decode(&mut d)?.0 as usize; + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + let len = VarInt::consensus_decode(r)?.0 as usize; // most real-world vec of bytes data, wouldn't be larger than 128KiB - read_bytes_from_finite_reader(d, ReadBytesFromFiniteReaderOpts { len, chunk_size: 128 * 1024 }) + read_bytes_from_finite_reader(r, ReadBytesFromFiniteReaderOpts { len, chunk_size: 128 * 1024 }) } #[inline] - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64)) + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64)) } } impl Encodable for Box<[u8]> { #[inline] - fn consensus_encode(&self, s: S) -> Result { - consensus_encode_with_size(self, s) + fn consensus_encode(&self, w: &mut W) -> Result { + consensus_encode_with_size(self, w) } } impl Decodable for Box<[u8]> { #[inline] - fn consensus_decode_from_finite_reader(d: D) -> Result { - >::consensus_decode_from_finite_reader(d).map(From::from) + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + >::consensus_decode_from_finite_reader(r).map(From::from) } #[inline] - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64)) + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64)) } } @@ -723,21 +723,21 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { // Checked data impl Encodable for CheckedData { #[inline] - 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)?; + fn consensus_encode(&self, w: &mut W) -> Result { + (self.0.len() as u32).consensus_encode(w)?; + sha2_checksum(&self.0).consensus_encode(w)?; + w.emit_slice(&self.0)?; Ok(8 + self.0.len()) } } impl Decodable for CheckedData { #[inline] - fn consensus_decode_from_finite_reader(mut d: D) -> Result { - let len = u32::consensus_decode_from_finite_reader(&mut d)? as usize; + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + let len = u32::consensus_decode_from_finite_reader(r)? as usize; - let checksum = <[u8; 4]>::consensus_decode_from_finite_reader(&mut d)?; - let ret = read_bytes_from_finite_reader(d, ReadBytesFromFiniteReaderOpts { len, chunk_size: MAX_VEC_SIZE })?; + let checksum = <[u8; 4]>::consensus_decode_from_finite_reader(r)?; + let ret = read_bytes_from_finite_reader(r, ReadBytesFromFiniteReaderOpts { len, chunk_size: MAX_VEC_SIZE })?; let expected_checksum = sha2_checksum(&ret); if expected_checksum != checksum { Err(self::Error::InvalidChecksum { @@ -749,33 +749,33 @@ impl Decodable for CheckedData { } } - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64)) + fn consensus_decode(d: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut d.take(MAX_VEC_SIZE as u64)) } } // References impl<'a, T: Encodable> Encodable for &'a T { - fn consensus_encode(&self, s: S) -> Result { - (&**self).consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + (&**self).consensus_encode(w) } } impl<'a, T: Encodable> Encodable for &'a mut T { - fn consensus_encode(&self, s: S) -> Result { - (&**self).consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + (&**self).consensus_encode(w) } } impl Encodable for rc::Rc { - fn consensus_encode(&self, s: S) -> Result { - (&**self).consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + (&**self).consensus_encode(w) } } impl Encodable for sync::Arc { - fn consensus_encode(&self, s: S) -> Result { - (&**self).consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + (&**self).consensus_encode(w) } } @@ -785,13 +785,13 @@ macro_rules! tuple_encode { impl <$($x: Encodable),*> Encodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_encode( + fn consensus_encode( &self, - mut s: S, + w: &mut W, ) -> Result { let &($(ref $x),*) = self; let mut len = 0; - $(len += $x.consensus_encode(&mut s)?;)* + $(len += $x.consensus_encode(w)?;)* Ok(len) } } @@ -799,8 +799,8 @@ macro_rules! tuple_encode { impl<$($x: Decodable),*> Decodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_decode(mut d: D) -> Result { - Ok(($({let $x = Decodable::consensus_decode(&mut d)?; $x }),*)) + fn consensus_decode(r: &mut R) -> Result { + Ok(($({let $x = Decodable::consensus_decode(r)?; $x }),*)) } } }; @@ -815,38 +815,38 @@ tuple_encode!(T0, T1, T2, T3, T4, T5, T6); tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); impl Encodable for sha256d::Hash { - fn consensus_encode(&self, s: S) -> Result { - self.into_inner().consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + self.into_inner().consensus_encode(w) } } impl Decodable for sha256d::Hash { - fn consensus_decode(d: D) -> Result { - Ok(Self::from_inner(<::Inner>::consensus_decode(d)?)) + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_inner(<::Inner>::consensus_decode(r)?)) } } impl Encodable for sha256::Hash { - fn consensus_encode(&self, s: S) -> Result { - self.into_inner().consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + self.into_inner().consensus_encode(w) } } impl Decodable for sha256::Hash { - fn consensus_decode(d: D) -> Result { - Ok(Self::from_inner(<::Inner>::consensus_decode(d)?)) + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_inner(<::Inner>::consensus_decode(r)?)) } } impl Encodable for TapLeafHash { - fn consensus_encode(&self, s: S) -> Result { - self.into_inner().consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + self.into_inner().consensus_encode(w) } } impl Decodable for TapLeafHash { - fn consensus_decode(d: D) -> Result { - Ok(Self::from_inner(<::Inner>::consensus_decode(d)?)) + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_inner(<::Inner>::consensus_decode(r)?)) } } diff --git a/src/hash_types.rs b/src/hash_types.rs index 49bc52c3..f28d0863 100644 --- a/src/hash_types.rs +++ b/src/hash_types.rs @@ -25,15 +25,15 @@ use crate::hashes::{Hash, sha256, sha256d, hash160, hash_newtype}; macro_rules! impl_hashencode { ($hashtype:ident) => { impl $crate::consensus::Encodable for $hashtype { - fn consensus_encode(&self, s: S) -> Result { - self.0.consensus_encode(s) + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) } } impl $crate::consensus::Decodable for $hashtype { - fn consensus_decode(d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { use $crate::hashes::Hash; - Ok(Self::from_inner(<<$hashtype as $crate::hashes::Hash>::Inner>::consensus_decode(d)?)) + Ok(Self::from_inner(<<$hashtype as $crate::hashes::Hash>::Inner>::consensus_decode(r)?)) } } } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index fd77908f..60aebda5 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -21,12 +21,12 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( impl $crate::consensus::Encodable for $thing { #[inline] - fn consensus_encode( + fn consensus_encode( &self, - mut s: S, + r: &mut R, ) -> Result { let mut len = 0; - $(len += self.$field.consensus_encode(&mut s)?;)+ + $(len += self.$field.consensus_encode(r)?;)+ Ok(len) } } @@ -34,21 +34,22 @@ macro_rules! impl_consensus_encoding { impl $crate::consensus::Decodable for $thing { #[inline] - fn consensus_decode_from_finite_reader( - mut d: D, + fn consensus_decode_from_finite_reader( + r: &mut R, ) -> Result<$thing, $crate::consensus::encode::Error> { Ok($thing { - $($field: $crate::consensus::Decodable::consensus_decode_from_finite_reader(&mut d)?),+ + $($field: $crate::consensus::Decodable::consensus_decode_from_finite_reader(r)?),+ }) } #[inline] - fn consensus_decode( - d: D, + fn consensus_decode( + r: &mut R, ) -> Result<$thing, $crate::consensus::encode::Error> { - let mut d = d.take($crate::consensus::encode::MAX_VEC_SIZE as u64); + use crate::io::Read as _; + let mut r = r.take($crate::consensus::encode::MAX_VEC_SIZE as u64); Ok($thing { - $($field: $crate::consensus::Decodable::consensus_decode(&mut d)?),+ + $($field: $crate::consensus::Decodable::consensus_decode(r.by_ref())?),+ }) } } diff --git a/src/network/address.rs b/src/network/address.rs index d7e1a92c..ca89c6c0 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -69,15 +69,15 @@ impl Address { impl Encodable for Address { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - let mut len = self.services.consensus_encode(&mut s)?; + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = self.services.consensus_encode(w)?; for word in &self.address { - s.write_all(&word.to_be_bytes())?; + w.write_all(&word.to_be_bytes())?; len += 2; } - s.write_all(&self.port.to_be_bytes())?; + w.write_all(&self.port.to_be_bytes())?; len += 2; Ok(len) @@ -86,22 +86,22 @@ impl Encodable for Address { impl Decodable for Address { #[inline] - fn consensus_decode(mut d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(Address { - services: Decodable::consensus_decode(&mut d)?, - address: read_be_address(&mut d)?, - port: u16::swap_bytes(Decodable::consensus_decode(d)?) + services: Decodable::consensus_decode(r)?, + address: read_be_address(r)?, + port: u16::swap_bytes(Decodable::consensus_decode(r)?) }) } } /// Read a big-endian address from reader. -fn read_be_address(mut r: R) -> Result<[u16; 8], encode::Error> { +fn read_be_address(r: &mut R) -> Result<[u16; 8], encode::Error> { let mut address = [0u16; 8]; let mut buf = [0u8; 2]; for word in &mut address { - io::Read::read_exact(&mut r, &mut buf)?; + io::Read::read_exact(r, &mut buf)?; *word = u16::from_be_bytes(buf) } Ok(address) @@ -147,12 +147,12 @@ pub enum AddrV2 { } impl Encodable for AddrV2 { - fn consensus_encode(&self, e: W) -> Result { - fn encode_addr(mut e: W, network: u8, bytes: &[u8]) -> Result { - let len = network.consensus_encode(&mut e)? - + VarInt(bytes.len() as u64).consensus_encode(&mut e)? + fn consensus_encode(&self, e: &mut W) -> Result { + fn encode_addr(w: &mut W, network: u8, bytes: &[u8]) -> Result { + let len = network.consensus_encode(w)? + + VarInt(bytes.len() as u64).consensus_encode(w)? + bytes.len(); - e.emit_slice(bytes)?; + w.emit_slice(bytes)?; Ok(len) } Ok(match *self { @@ -168,9 +168,9 @@ impl Encodable for AddrV2 { } impl Decodable for AddrV2 { - fn consensus_decode(mut d: D) -> Result { - let network_id = u8::consensus_decode(&mut d)?; - let len = VarInt::consensus_decode(&mut d)?.0; + fn consensus_decode(r: &mut R) -> Result { + let network_id = u8::consensus_decode(r)?; + let len = VarInt::consensus_decode(r)?.0; if len > 512 { return Err(encode::Error::ParseFailed("IP must be <= 512 bytes")); } @@ -179,14 +179,14 @@ impl Decodable for AddrV2 { if len != 4 { return Err(encode::Error::ParseFailed("Invalid IPv4 address")); } - let addr: [u8; 4] = Decodable::consensus_decode(&mut d)?; + let addr: [u8; 4] = Decodable::consensus_decode(r)?; AddrV2::Ipv4(Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3])) }, 2 => { if len != 16 { return Err(encode::Error::ParseFailed("Invalid IPv6 address")); } - let addr: [u16; 8] = read_be_address(&mut d)?; + let addr: [u16; 8] = read_be_address(r)?; if addr[0..3] == ONION { return Err(encode::Error::ParseFailed("OnionCat address sent with IPv6 network id")); } @@ -199,28 +199,28 @@ impl Decodable for AddrV2 { if len != 10 { return Err(encode::Error::ParseFailed("Invalid TorV2 address")); } - let id = Decodable::consensus_decode(&mut d)?; + let id = Decodable::consensus_decode(r)?; AddrV2::TorV2(id) }, 4 => { if len != 32 { return Err(encode::Error::ParseFailed("Invalid TorV3 address")); } - let pubkey = Decodable::consensus_decode(&mut d)?; + let pubkey = Decodable::consensus_decode(r)?; AddrV2::TorV3(pubkey) }, 5 => { if len != 32 { return Err(encode::Error::ParseFailed("Invalid I2P address")); } - let hash = Decodable::consensus_decode(&mut d)?; + let hash = Decodable::consensus_decode(r)?; AddrV2::I2p(hash) }, 6 => { if len != 16 { return Err(encode::Error::ParseFailed("Invalid CJDNS address")); } - let addr: [u16; 8] = read_be_address(&mut d)?; + let addr: [u16; 8] = read_be_address(r)?; // check the first byte for the CJDNS marker if addr[0] != u16::from_be_bytes([0xFC, 0x00]) { return Err(encode::Error::ParseFailed("Invalid CJDNS address")); @@ -230,7 +230,7 @@ impl Decodable for AddrV2 { _ => { // len already checked above to be <= 512 let mut addr = vec![0u8; len as usize]; - d.read_slice(&mut addr)?; + r.read_slice(&mut addr)?; AddrV2::Unknown(network_id, addr) } }) @@ -264,26 +264,26 @@ impl AddrV2Message { } impl Encodable for AddrV2Message { - fn consensus_encode(&self, mut e: W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += self.time.consensus_encode(&mut e)?; - len += VarInt(self.services.to_u64()).consensus_encode(&mut e)?; - len += self.addr.consensus_encode(&mut e)?; + len += self.time.consensus_encode(w)?; + len += VarInt(self.services.to_u64()).consensus_encode(w)?; + len += self.addr.consensus_encode(w)?; // consensus_encode always encodes in LE, and we want to encode in BE. - //TODO `len += io::Write::write(&mut e, &self.port.to_be_bytes())?;` when MSRV >= 1.32 - len += self.port.swap_bytes().consensus_encode(e)?; + //TODO `len += io::Write::write(w, &self.port.to_be_bytes())?;` when MSRV >= 1.32 + len += self.port.swap_bytes().consensus_encode(w)?; Ok(len) } } impl Decodable for AddrV2Message { - fn consensus_decode(mut d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(AddrV2Message { - time: Decodable::consensus_decode(&mut d)?, - services: ServiceFlags::from(VarInt::consensus_decode(&mut d)?.0), - addr: Decodable::consensus_decode(&mut d)?, - port: u16::swap_bytes(Decodable::consensus_decode(d)?), + time: Decodable::consensus_decode(r)?, + services: ServiceFlags::from(VarInt::consensus_decode(r)?.0), + addr: Decodable::consensus_decode(r)?, + port: u16::swap_bytes(Decodable::consensus_decode(r)?), }) } } diff --git a/src/network/constants.rs b/src/network/constants.rs index 97fead78..5dab75eb 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -280,15 +280,15 @@ impl ops::BitXorAssign for ServiceFlags { impl Encodable for ServiceFlags { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - self.0.consensus_encode(&mut s) + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) } } impl Decodable for ServiceFlags { #[inline] - fn consensus_decode(mut d: D) -> Result { - Ok(ServiceFlags(Decodable::consensus_decode(&mut d)?)) + fn consensus_decode(r: &mut R) -> Result { + Ok(ServiceFlags(Decodable::consensus_decode(r)?)) } } diff --git a/src/network/message.rs b/src/network/message.rs index 7d095c40..4046df92 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -23,6 +23,7 @@ use crate::prelude::*; use core::{fmt, iter}; use crate::io; +use io::Read as _; use crate::blockdata::block; use crate::blockdata::transaction; use crate::network::address::{Address, AddrV2Message}; @@ -79,19 +80,19 @@ impl AsRef for CommandString { impl Encodable for CommandString { #[inline] - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut rawbytes = [0u8; 12]; let strbytes = self.0.as_bytes(); debug_assert!(strbytes.len() <= 12); rawbytes[..strbytes.len()].copy_from_slice(strbytes); - rawbytes.consensus_encode(s) + rawbytes.consensus_encode(w) } } impl Decodable for CommandString { #[inline] - fn consensus_decode(d: D) -> Result { - let rawbytes: [u8; 12] = Decodable::consensus_decode(d)?; + fn consensus_decode(r: &mut R) -> Result { + let rawbytes: [u8; 12] = Decodable::consensus_decode(r)?; let rv = iter::FromIterator::from_iter( rawbytes .iter() @@ -286,22 +287,22 @@ struct HeaderSerializationWrapper<'a>(&'a Vec); impl<'a> Encodable for HeaderSerializationWrapper<'a> { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += VarInt(self.0.len() as u64).consensus_encode(&mut s)?; + len += VarInt(self.0.len() as u64).consensus_encode(w)?; for header in self.0.iter() { - len += header.consensus_encode(&mut s)?; - len += 0u8.consensus_encode(&mut s)?; + len += header.consensus_encode(w)?; + len += 0u8.consensus_encode(w)?; } Ok(len) } } impl Encodable for RawNetworkMessage { - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += self.magic.consensus_encode(&mut s)?; - len += self.command().consensus_encode(&mut s)?; + len += self.magic.consensus_encode(w)?; + len += self.command().consensus_encode(w)?; len += CheckedData(match self.payload { NetworkMessage::Version(ref dat) => serialize(dat), NetworkMessage::Addr(ref dat) => serialize(dat), @@ -336,7 +337,7 @@ impl Encodable for RawNetworkMessage { | NetworkMessage::FilterClear | NetworkMessage::SendAddrV2 => vec![], NetworkMessage::Unknown { payload: ref data, .. } => serialize(data), - }).consensus_encode(&mut s)?; + }).consensus_encode(w)?; Ok(len) } } @@ -345,14 +346,14 @@ struct HeaderDeserializationWrapper(Vec); impl Decodable for HeaderDeserializationWrapper { #[inline] - fn consensus_decode_from_finite_reader(mut d: D) -> Result { - let len = VarInt::consensus_decode(&mut d)?.0; + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + let len = VarInt::consensus_decode(r)?.0; // should be above usual number of items to avoid // allocation let mut ret = Vec::with_capacity(core::cmp::min(1024 * 16, len as usize)); for _ in 0..len { - ret.push(Decodable::consensus_decode(&mut d)?); - if u8::consensus_decode(&mut d)? != 0u8 { + ret.push(Decodable::consensus_decode(r)?); + if u8::consensus_decode(r)? != 0u8 { return Err(encode::Error::ParseFailed("Headers message should not contain transactions")); } } @@ -360,16 +361,16 @@ impl Decodable for HeaderDeserializationWrapper { } #[inline] - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_MSG_SIZE as u64)) + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref()) } } impl Decodable for RawNetworkMessage { - fn consensus_decode_from_finite_reader(mut d: D) -> Result { - let magic = Decodable::consensus_decode_from_finite_reader(&mut d)?; - let cmd = CommandString::consensus_decode_from_finite_reader(&mut d)?; - let raw_payload = CheckedData::consensus_decode_from_finite_reader(&mut d)?.0; + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + let magic = Decodable::consensus_decode_from_finite_reader(r)?; + let cmd = CommandString::consensus_decode_from_finite_reader(r)?; + let raw_payload = CheckedData::consensus_decode_from_finite_reader(r)?.0; let mut mem_d = io::Cursor::new(raw_payload); let payload = match &cmd.0[..] { @@ -419,8 +420,8 @@ impl Decodable for RawNetworkMessage { } #[inline] - fn consensus_decode(d: D) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_MSG_SIZE as u64)) + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref()) } } diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 37af36ea..dcd72be6 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -54,10 +54,10 @@ pub enum Inventory { impl Encodable for Inventory { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { macro_rules! encode_inv { ($code:expr, $item:expr) => { - u32::consensus_encode(&$code, &mut s)? + $item.consensus_encode(&mut s)? + u32::consensus_encode(&$code, w)? + $item.consensus_encode(w)? } } Ok(match *self { @@ -74,18 +74,18 @@ impl Encodable for Inventory { impl Decodable for Inventory { #[inline] - fn consensus_decode(mut d: D) -> Result { - let inv_type: u32 = Decodable::consensus_decode(&mut d)?; + fn consensus_decode(r: &mut R) -> Result { + let inv_type: u32 = Decodable::consensus_decode(r)?; Ok(match inv_type { 0 => Inventory::Error, - 1 => Inventory::Transaction(Decodable::consensus_decode(&mut d)?), - 2 => Inventory::Block(Decodable::consensus_decode(&mut d)?), - 5 => Inventory::WTx(Decodable::consensus_decode(&mut d)?), - 0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(&mut d)?), - 0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(&mut d)?), + 1 => Inventory::Transaction(Decodable::consensus_decode(r)?), + 2 => Inventory::Block(Decodable::consensus_decode(r)?), + 5 => Inventory::WTx(Decodable::consensus_decode(r)?), + 0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(r)?), + 0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(r)?), tp => Inventory::Unknown { inv_type: tp, - hash: Decodable::consensus_decode(&mut d)?, + hash: Decodable::consensus_decode(r)?, } }) } diff --git a/src/network/message_bloom.rs b/src/network/message_bloom.rs index daae4d14..5d0df82e 100644 --- a/src/network/message_bloom.rs +++ b/src/network/message_bloom.rs @@ -34,8 +34,8 @@ pub enum BloomFlags { } impl Encodable for BloomFlags { - fn consensus_encode(&self, mut e: W) -> Result { - e.write_all(&[match self { + fn consensus_encode(&self, w: &mut W) -> Result { + w.write_all(&[match self { BloomFlags::None => 0, BloomFlags::All => 1, BloomFlags::PubkeyOnly => 2, @@ -45,8 +45,8 @@ impl Encodable for BloomFlags { } impl Decodable for BloomFlags { - fn consensus_decode(mut d: D) -> Result { - Ok(match d.read_u8()? { + fn consensus_decode(r: &mut R) -> Result { + Ok(match r.read_u8()? { 0 => BloomFlags::None, 1 => BloomFlags::All, 2 => BloomFlags::PubkeyOnly, diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 0e884c97..f9ee2223 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -106,15 +106,15 @@ pub enum RejectReason { } impl Encodable for RejectReason { - fn consensus_encode(&self, mut e: W) -> Result { - e.write_all(&[*self as u8])?; + fn consensus_encode(&self, w: &mut W) -> Result { + w.write_all(&[*self as u8])?; Ok(1) } } impl Decodable for RejectReason { - fn consensus_decode(mut d: D) -> Result { - Ok(match d.read_u8()? { + fn consensus_decode(r: &mut R) -> Result { + Ok(match r.read_u8()? { 0x01 => RejectReason::Malformed, 0x10 => RejectReason::Invalid, 0x11 => RejectReason::Obsolete, diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 5e3c3478..2f42e301 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -355,23 +355,23 @@ impl PartialMerkleTree { } 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)?; + fn consensus_encode(&self, w: &mut W) -> Result { + let ret = self.num_transactions.consensus_encode(w)? + + self.hashes.consensus_encode(w)?; 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; } - Ok(ret + bytes.consensus_encode(s)?) + Ok(ret + bytes.consensus_encode(w)?) } } 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)?; + fn consensus_decode(r: &mut R) -> Result { + let num_transactions: u32 = Decodable::consensus_decode(r)?; + let hashes: Vec = Decodable::consensus_decode(r)?; - let bytes: Vec = Decodable::consensus_decode(d)?; + let bytes: Vec = Decodable::consensus_decode(r)?; let mut bits: Vec = vec![false; bytes.len() * 8]; for (p, bit) in bits.iter_mut().enumerate() { @@ -506,18 +506,18 @@ impl MerkleBlock { } 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)?; + fn consensus_encode(&self, w: &mut W) -> Result { + let len = self.header.consensus_encode(w)? + + self.txn.consensus_encode(w)?; Ok(len) } } impl Decodable for MerkleBlock { - fn consensus_decode(mut d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(MerkleBlock { - header: Decodable::consensus_decode(&mut d)?, - txn: Decodable::consensus_decode(d)?, + header: Decodable::consensus_decode(r)?, + txn: Decodable::consensus_decode(r)?, }) } } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 542ff1df..bb2afbb4 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -55,11 +55,11 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { impl $crate::consensus::Encodable for $thing { - fn consensus_encode( + fn consensus_encode( &self, - s: S, + w: &mut W, ) -> Result { - self.consensus_encode_map(s) + self.consensus_encode_map(w) } } }; @@ -68,13 +68,13 @@ macro_rules! impl_psbtmap_consensus_encoding { macro_rules! impl_psbtmap_consensus_decoding { ($thing:ty) => { impl $crate::consensus::Decodable for $thing { - fn consensus_decode( - mut d: D, + fn consensus_decode( + r: &mut R, ) -> Result { let mut rv: Self = ::core::default::Default::default(); loop { - match $crate::consensus::Decodable::consensus_decode(&mut d) { + match $crate::consensus::Decodable::consensus_decode(r) { Ok(pair) => rv.insert_pair(pair)?, Err($crate::consensus::encode::Error::Psbt($crate::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 77288ce1..52c3a410 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -100,8 +100,8 @@ impl Map for PartiallySignedTransaction { } impl PartiallySignedTransaction { - pub(crate) fn consensus_decode_global(d: D) -> Result { - let mut d = d.take(MAX_VEC_SIZE as u64); + pub(crate) fn consensus_decode_global(r: &mut R) -> Result { + let mut r = r.take(MAX_VEC_SIZE as u64); let mut tx: Option = None; let mut version: Option = None; let mut unknowns: BTreeMap> = Default::default(); @@ -109,7 +109,7 @@ impl PartiallySignedTransaction { let mut proprietary: BTreeMap> = Default::default(); loop { - match raw::Pair::consensus_decode(&mut d) { + match raw::Pair::consensus_decode(&mut r) { Ok(pair) => { match pair.key.type_value { PSBT_GLOBAL_UNSIGNED_TX => { diff --git a/src/util/psbt/map/mod.rs b/src/util/psbt/map/mod.rs index 8e67d0d7..8a512cf1 100644 --- a/src/util/psbt/map/mod.rs +++ b/src/util/psbt/map/mod.rs @@ -32,12 +32,12 @@ pub(super) trait Map { fn get_pairs(&self) -> Result, io::Error>; /// Encodes map data with bitcoin consensus encoding. - fn consensus_encode_map(&self, mut s: S) -> Result { + fn consensus_encode_map(&self, w: &mut W) -> Result { let mut len = 0; for pair in Map::get_pairs(self)? { - len += encode::Encodable::consensus_encode(&pair, &mut s)?; + len += encode::Encodable::consensus_encode(&pair, w)?; } - Ok(len + encode::Encodable::consensus_encode(&0x00_u8, s)?) + Ok(len + encode::Encodable::consensus_encode(&0x00_u8, w)?) } } diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 2b56ca71..b750671e 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -23,13 +23,14 @@ use core::cmp; use crate::blockdata::script::Script; use crate::blockdata::transaction::{ TxOut, Transaction}; -use crate::consensus::{encode, Encodable, Decodable}; use crate::consensus::encode::MAX_VEC_SIZE; +use crate::consensus::{encode, Encodable, Decodable}; pub use crate::util::sighash::Prevouts; use crate::prelude::*; use crate::io; +use io::Read as _; mod error; pub use self::error::Error; @@ -278,20 +279,20 @@ mod display_from_str { pub use self::display_from_str::PsbtParseError; impl Encodable for PartiallySignedTransaction { - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += b"psbt".consensus_encode(&mut s)?; + len += b"psbt".consensus_encode(w)?; - len += 0xff_u8.consensus_encode(&mut s)?; + len += 0xff_u8.consensus_encode(w)?; - len += self.consensus_encode_map(&mut s)?; + len += self.consensus_encode_map(w)?; for i in &self.inputs { - len += i.consensus_encode(&mut s)?; + len += i.consensus_encode(w)?; } for i in &self.outputs { - len += i.consensus_encode(&mut s)?; + len += i.consensus_encode(w)?; } Ok(len) @@ -299,19 +300,18 @@ impl Encodable for PartiallySignedTransaction { } impl Decodable for PartiallySignedTransaction { - fn consensus_decode(d: D) -> Result { - let mut d = d.take(MAX_VEC_SIZE as u64); - let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?; + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + let magic: [u8; 4] = Decodable::consensus_decode(r)?; if *b"psbt" != magic { return Err(Error::InvalidMagic.into()); } - if 0xff_u8 != u8::consensus_decode(&mut d)? { + if 0xff_u8 != u8::consensus_decode(r)? { return Err(Error::InvalidSeparator.into()); } - let mut global = PartiallySignedTransaction::consensus_decode_global(&mut d)?; + let mut global = PartiallySignedTransaction::consensus_decode_global(r)?; global.unsigned_tx_checks()?; let inputs: Vec = { @@ -320,7 +320,7 @@ impl Decodable for PartiallySignedTransaction { let mut inputs: Vec = Vec::with_capacity(inputs_len); for _ in 0..inputs_len { - inputs.push(Decodable::consensus_decode(&mut d)?); + inputs.push(Decodable::consensus_decode(r)?); } inputs @@ -332,7 +332,7 @@ impl Decodable for PartiallySignedTransaction { let mut outputs: Vec = Vec::with_capacity(outputs_len); for _ in 0..outputs_len { - outputs.push(Decodable::consensus_decode(&mut d)?); + outputs.push(Decodable::consensus_decode(r)?); } outputs @@ -342,6 +342,11 @@ impl Decodable for PartiallySignedTransaction { global.outputs = outputs; Ok(global) } + + #[inline] + fn consensus_decode(d: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64).by_ref()) + } } #[cfg(test)] diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 64522b1e..eb6272da 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -79,8 +79,8 @@ impl fmt::Display for Key { } impl Decodable for Key { - fn consensus_decode(mut d: D) -> Result { - let VarInt(byte_size): VarInt = Decodable::consensus_decode(&mut d)?; + fn consensus_decode(r: &mut R) -> Result { + let VarInt(byte_size): VarInt = Decodable::consensus_decode(r)?; if byte_size == 0 { return Err(Error::NoMorePairs.into()); @@ -95,11 +95,11 @@ impl Decodable for Key { }) } - let type_value: u8 = Decodable::consensus_decode(&mut d)?; + let type_value: u8 = Decodable::consensus_decode(r)?; let mut key = Vec::with_capacity(key_byte_size as usize); for _ in 0..key_byte_size { - key.push(Decodable::consensus_decode(&mut d)?); + key.push(Decodable::consensus_decode(r)?); } Ok(Key { type_value, key }) @@ -107,14 +107,14 @@ impl Decodable for Key { } impl Encodable for Key { - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; - len += VarInt((self.key.len() + 1) as u64).consensus_encode(&mut s)?; + len += VarInt((self.key.len() + 1) as u64).consensus_encode(w)?; - len += self.type_value.consensus_encode(&mut s)?; + len += self.type_value.consensus_encode(w)?; for key in &self.key { - len += key.consensus_encode(&mut s)? + len += key.consensus_encode(w)? } Ok(len) @@ -122,36 +122,36 @@ impl Encodable for Key { } 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)?) + fn consensus_encode(&self, w: &mut W) -> Result { + let len = self.key.consensus_encode(w)?; + Ok(len + self.value.consensus_encode(w)?) } } impl Decodable for Pair { - fn consensus_decode(mut d: D) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(Pair { - key: Decodable::consensus_decode(&mut d)?, - value: Decodable::consensus_decode(d)?, + key: Decodable::consensus_decode(r)?, + value: Decodable::consensus_decode(r)?, }) } } impl Encodable for ProprietaryKey where Subtype: Copy + From + Into { - fn consensus_encode(&self, mut e: W) -> Result { - let mut len = self.prefix.consensus_encode(&mut e)? + 1; - e.emit_u8(self.subtype.into())?; - e.write_all(&self.key)?; + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = self.prefix.consensus_encode(w)? + 1; + w.emit_u8(self.subtype.into())?; + w.write_all(&self.key)?; len += self.key.len(); Ok(len) } } impl Decodable for ProprietaryKey where Subtype: Copy + From + Into { - fn consensus_decode(mut d: D) -> Result { - let prefix = Vec::::consensus_decode(&mut d)?; - let subtype = Subtype::from(d.read_u8()?); - let key = read_to_end(d)?; + fn consensus_decode(r: &mut R) -> Result { + let prefix = Vec::::consensus_decode(r)?; + let subtype = Subtype::from(r.read_u8()?); + let key = read_to_end(r)?; Ok(ProprietaryKey { prefix, subtype, key }) } diff --git a/src/util/sighash.rs b/src/util/sighash.rs index fa83383a..e89127d9 100644 --- a/src/util/sighash.rs +++ b/src/util/sighash.rs @@ -794,8 +794,8 @@ impl<'a> Annex<'a> { } impl<'a> Encodable for Annex<'a> { - fn consensus_encode(&self, writer: W) -> Result { - encode::consensus_encode_with_size(self.0, writer) + fn consensus_encode(&self, w: &mut W) -> Result { + encode::consensus_encode_with_size(self.0, w) } } diff --git a/src/util/uint.rs b/src/util/uint.rs index ccb702e7..9b2c6928 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -419,27 +419,27 @@ macro_rules! construct_uint { impl $crate::consensus::Encodable for $name { #[inline] - fn consensus_encode( + fn consensus_encode( &self, - mut s: S, + w: &mut W, ) -> Result { let &$name(ref data) = self; let mut len = 0; for word in data.iter() { - len += word.consensus_encode(&mut s)?; + len += word.consensus_encode(w)?; } Ok(len) } } impl $crate::consensus::Decodable for $name { - fn consensus_decode( - mut d: D, + fn consensus_decode( + r: &mut R, ) -> Result<$name, $crate::consensus::encode::Error> { use $crate::consensus::Decodable; let mut ret: [u64; $n_words] = [0; $n_words]; for i in 0..$n_words { - ret[i] = Decodable::consensus_decode(&mut d)?; + ret[i] = Decodable::consensus_decode(r)?; } Ok($name(ret)) } From a24a3b01941b6661e30ef910b5d6e9699752b313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Mon, 30 May 2022 18:14:09 -0700 Subject: [PATCH 2/3] Forward `consensus_decode` to `consensus_decode_from_finite_reader` --- src/blockdata/script.rs | 7 ------- src/blockdata/transaction.rs | 11 ----------- src/consensus/encode.rs | 34 +++++++++++++--------------------- src/util/psbt/mod.rs | 7 ------- 4 files changed, 13 insertions(+), 46 deletions(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index bb6e757f..16b9fcae 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -23,11 +23,9 @@ //! This module provides the structures and functions needed to support scripts. //! -use crate::consensus::encode::MAX_VEC_SIZE; use crate::prelude::*; use crate::io; -use io::Read as _; use core::{fmt, default::Default}; use core::ops::Index; @@ -1103,11 +1101,6 @@ impl Decodable for Script { fn consensus_decode_from_finite_reader(r: &mut R) -> Result { Ok(Script(Decodable::consensus_decode_from_finite_reader(r)?)) } - - #[inline] - fn consensus_decode(r: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(r.take(MAX_VEC_SIZE as u64).by_ref()) - } } #[cfg(test)] diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 105ff285..1311d175 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -26,7 +26,6 @@ use crate::prelude::*; use crate::io; -use io::Read as _; use core::{fmt, str, default::Default}; use crate::hashes::{self, Hash, sha256d}; @@ -38,7 +37,6 @@ use crate::blockdata::constants::WITNESS_SCALE_FACTOR; use crate::blockdata::script::Script; use crate::blockdata::witness::Witness; use crate::consensus::{encode, Decodable, Encodable}; -use crate::consensus::encode::MAX_VEC_SIZE; use crate::hash_types::{Sighash, Txid, Wtxid}; use crate::VarInt; @@ -687,11 +685,6 @@ impl Decodable for TxIn { witness: Witness::default(), }) } - - #[inline] - fn consensus_decode(r: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(r.take(MAX_VEC_SIZE as u64).by_ref()) - } } impl Encodable for Transaction { @@ -763,10 +756,6 @@ impl Decodable for Transaction { }) } } - - fn consensus_decode(r: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64)) - } } /// This type is consensus valid but an input including it would prevent the transaction from diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index b2b254c9..0ddcd46a 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -353,6 +353,7 @@ pub trait Decodable: Sized { /// should also implement it applying same rules, and in addition make sure to call /// `consensus_decode_from_finite_reader` on all members, to avoid creating redundant /// `Take` wrappers. Failure to do so might result only in a tiny performance hit. + #[inline] fn consensus_decode_from_finite_reader(reader: &mut R) -> Result { // This method is always strictly less general than, `consensus_decode`, // so it's safe and make sense to default to just calling it. @@ -361,8 +362,18 @@ pub trait Decodable: Sized { Self::consensus_decode(reader) } - /// Decode an object with a well-defined format - fn consensus_decode(reader: &mut R) -> Result; + /// Decode an object with a well-defined format. + /// + /// This is the method that should be implemented for a typical, fixed sized type + /// implementing this trait. Default implementation is wrapping the reader + /// in [`crate::io::Take`] to limit the input size to [`MAX_VEC_SIZE`], and forwards the call to + /// [`Self::consensus_decode_from_finite_reader`], which is convenient + /// for types that override [`Self::consensus_decode_from_finite_reader`] + /// instead. + #[inline] + fn consensus_decode(reader: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(reader.take(MAX_VEC_SIZE as u64).by_ref()) + } } /// A variable-length unsigned integer @@ -616,11 +627,6 @@ macro_rules! impl_vec { } Ok(ret) } - - #[inline] - fn consensus_decode(d: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(&mut d.take(MAX_VEC_SIZE as u64)) - } } } } @@ -687,11 +693,6 @@ impl Decodable for Vec { // most real-world vec of bytes data, wouldn't be larger than 128KiB read_bytes_from_finite_reader(r, ReadBytesFromFiniteReaderOpts { len, chunk_size: 128 * 1024 }) } - - #[inline] - fn consensus_decode(r: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64)) - } } impl Encodable for Box<[u8]> { @@ -706,11 +707,6 @@ impl Decodable for Box<[u8]> { fn consensus_decode_from_finite_reader(r: &mut R) -> Result { >::consensus_decode_from_finite_reader(r).map(From::from) } - - #[inline] - fn consensus_decode(r: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64)) - } } @@ -748,10 +744,6 @@ impl Decodable for CheckedData { Ok(CheckedData(ret)) } } - - fn consensus_decode(d: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(&mut d.take(MAX_VEC_SIZE as u64)) - } } // References diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index b750671e..f874c55b 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -23,14 +23,12 @@ use core::cmp; use crate::blockdata::script::Script; use crate::blockdata::transaction::{ TxOut, Transaction}; -use crate::consensus::encode::MAX_VEC_SIZE; use crate::consensus::{encode, Encodable, Decodable}; pub use crate::util::sighash::Prevouts; use crate::prelude::*; use crate::io; -use io::Read as _; mod error; pub use self::error::Error; @@ -342,11 +340,6 @@ impl Decodable for PartiallySignedTransaction { global.outputs = outputs; Ok(global) } - - #[inline] - fn consensus_decode(d: &mut R) -> Result { - Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64).by_ref()) - } } #[cfg(test)] From 1fea098dfb916d64f2ecbfb9a13b8d264020bc1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Tue, 28 Jun 2022 18:22:12 -0700 Subject: [PATCH 3/3] Support unsized `R` and `W` in consensus encode/decode --- src/blockdata/script.rs | 4 +- src/blockdata/transaction.rs | 25 +++++++--- src/blockdata/witness.rs | 4 +- src/consensus/encode.rs | 82 ++++++++++++++++---------------- src/hash_types.rs | 4 +- src/internal_macros.rs | 6 +-- src/network/address.rs | 16 +++---- src/network/constants.rs | 4 +- src/network/message.rs | 16 +++---- src/network/message_blockdata.rs | 4 +- src/network/message_bloom.rs | 4 +- src/network/message_network.rs | 4 +- src/util/merkleblock.rs | 8 ++-- src/util/psbt/macros.rs | 4 +- src/util/psbt/map/global.rs | 2 +- src/util/psbt/map/mod.rs | 2 +- src/util/psbt/mod.rs | 4 +- src/util/psbt/raw.rs | 12 ++--- src/util/sighash.rs | 2 +- src/util/uint.rs | 4 +- 20 files changed, 112 insertions(+), 99 deletions(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 16b9fcae..e07da70c 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -1091,14 +1091,14 @@ impl serde::Serialize for Script { impl Encodable for Script { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { self.0.consensus_encode(w) } } impl Decodable for Script { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { Ok(Script(Decodable::consensus_decode_from_finite_reader(r)?)) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 1311d175..2ae5adf9 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -652,13 +652,13 @@ impl Transaction { impl_consensus_encoding!(TxOut, value, script_pubkey); impl Encodable for OutPoint { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let len = self.txid.consensus_encode(w)?; Ok(len + self.vout.consensus_encode(w)?) } } impl Decodable for OutPoint { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(OutPoint { txid: Decodable::consensus_decode(r)?, vout: Decodable::consensus_decode(r)?, @@ -667,7 +667,7 @@ impl Decodable for OutPoint { } impl Encodable for TxIn { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += self.previous_output.consensus_encode(w)?; len += self.script_sig.consensus_encode(w)?; @@ -677,7 +677,7 @@ impl Encodable for TxIn { } impl Decodable for TxIn { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { Ok(TxIn { previous_output: Decodable::consensus_decode_from_finite_reader(r)?, script_sig: Decodable::consensus_decode_from_finite_reader(r)?, @@ -688,7 +688,7 @@ impl Decodable for TxIn { } impl Encodable for Transaction { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += self.version.consensus_encode(w)?; // To avoid serialization ambiguity, no inputs means we use BIP141 serialization (see @@ -718,7 +718,7 @@ impl Encodable for Transaction { } impl Decodable for Transaction { - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let version = i32::consensus_decode_from_finite_reader(r)?; let input = Vec::::consensus_decode_from_finite_reader(r)?; // segwit @@ -953,6 +953,19 @@ mod tests { use super::EcdsaSighashType; use crate::util::sighash::SighashCache; + const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; + + #[test] + fn encode_to_unsized_writer() { + let mut buf = [0u8; 1024]; + let raw_tx = Vec::from_hex(SOME_TX).unwrap(); + let tx: Transaction = Decodable::consensus_decode(&mut raw_tx.as_slice()).unwrap(); + + let size = tx.consensus_encode(&mut &mut buf[..]).unwrap(); + assert_eq!(size, SOME_TX.len() / 2); + assert_eq!(raw_tx, &buf[..size]); + } + #[test] fn test_outpoint() { assert_eq!(OutPoint::from_str("i don't care"), diff --git a/src/blockdata/witness.rs b/src/blockdata/witness.rs index 2339162e..860112b6 100644 --- a/src/blockdata/witness.rs +++ b/src/blockdata/witness.rs @@ -49,7 +49,7 @@ pub struct Iter<'a> { } impl Decodable for Witness { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let witness_elements = VarInt::consensus_decode(r)?.0 as usize; if witness_elements == 0 { Ok(Witness::default()) @@ -116,7 +116,7 @@ fn resize_if_needed(vec: &mut Vec, required_len: usize) { } impl Encodable for Witness { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let len = VarInt(self.witness_elements as u64); len.consensus_encode(w)?; w.emit_slice(&self.content[..])?; diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 0ddcd46a..97043e5d 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -176,7 +176,7 @@ pub fn deserialize_partial(data: &[u8]) -> Result<(T, usize), Erro /// Extensions of `Write` to encode data as per Bitcoin consensus -pub trait WriteExt { +pub trait WriteExt : io::Write { /// Output a 64-bit uint fn emit_u64(&mut self, v: u64) -> Result<(), io::Error>; /// Output a 32-bit uint @@ -203,7 +203,7 @@ pub trait WriteExt { } /// Extensions of `Read` to decode data as per Bitcoin consensus -pub trait ReadExt { +pub trait ReadExt : io::Read { /// Read a 64-bit uint fn read_u64(&mut self) -> Result; /// Read a 32-bit uint @@ -250,7 +250,7 @@ macro_rules! decoder_fn { } } -impl WriteExt for W { +impl WriteExt for W { encoder_fn!(emit_u64, u64, u64_to_array_le); encoder_fn!(emit_u32, u32, u32_to_array_le); encoder_fn!(emit_u16, u16, u16_to_array_le); @@ -276,7 +276,7 @@ impl WriteExt for W { } } -impl ReadExt for R { +impl ReadExt for R { decoder_fn!(read_u64, u64, slice_to_u64_le, 8); decoder_fn!(read_u32, u32, slice_to_u32_le, 4); decoder_fn!(read_u16, u16, slice_to_u16_le, 2); @@ -315,7 +315,7 @@ pub trait Encodable { /// Returns the number of bytes written on success. /// /// The only errors returned are errors propagated from the writer. - fn consensus_encode(&self, writer: &mut W) -> Result; + fn consensus_encode(&self, writer: &mut W) -> Result; } /// Data which can be encoded in a consensus-consistent way @@ -354,7 +354,7 @@ pub trait Decodable: Sized { /// `consensus_decode_from_finite_reader` on all members, to avoid creating redundant /// `Take` wrappers. Failure to do so might result only in a tiny performance hit. #[inline] - fn consensus_decode_from_finite_reader(reader: &mut R) -> Result { + fn consensus_decode_from_finite_reader(reader: &mut R) -> Result { // This method is always strictly less general than, `consensus_decode`, // so it's safe and make sense to default to just calling it. // This way most types, that don't care about protecting against @@ -371,7 +371,7 @@ pub trait Decodable: Sized { /// for types that override [`Self::consensus_decode_from_finite_reader`] /// instead. #[inline] - fn consensus_decode(reader: &mut R) -> Result { + fn consensus_decode(reader: &mut R) -> Result { Self::consensus_decode_from_finite_reader(reader.take(MAX_VEC_SIZE as u64).by_ref()) } } @@ -389,13 +389,13 @@ macro_rules! impl_int_encodable { ($ty:ident, $meth_dec:ident, $meth_enc:ident) => { impl Decodable for $ty { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { ReadExt::$meth_dec(r) } } impl Encodable for $ty { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { w.$meth_enc(*self)?; Ok(mem::size_of::<$ty>()) } @@ -430,7 +430,7 @@ impl VarInt { impl Encodable for VarInt { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { match self.0 { 0..=0xFC => { (self.0 as u8).consensus_encode(w)?; @@ -457,7 +457,7 @@ impl Encodable for VarInt { impl Decodable for VarInt { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let n = ReadExt::read_u8(r)?; match n { 0xFF => { @@ -492,7 +492,7 @@ impl Decodable for VarInt { // Booleans impl Encodable for bool { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { w.emit_bool(*self)?; Ok(1) } @@ -500,7 +500,7 @@ impl Encodable for bool { impl Decodable for bool { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { ReadExt::read_bool(r) } } @@ -508,7 +508,7 @@ impl Decodable for bool { // Strings impl Encodable for String { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let b = self.as_bytes(); let vi_len = VarInt(b.len() as u64).consensus_encode(w)?; w.emit_slice(b)?; @@ -518,7 +518,7 @@ impl Encodable for String { impl Decodable for String { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { String::from_utf8(Decodable::consensus_decode(r)?) .map_err(|_| self::Error::ParseFailed("String was not valid UTF8")) } @@ -527,7 +527,7 @@ impl Decodable for String { // Cow<'static, str> impl Encodable for Cow<'static, str> { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let b = self.as_bytes(); let vi_len = VarInt(b.len() as u64).consensus_encode(w)?; w.emit_slice(b)?; @@ -537,7 +537,7 @@ impl Encodable for Cow<'static, str> { impl Decodable for Cow<'static, str> { #[inline] - fn consensus_decode(r: &mut R) -> Result, Error> { + fn consensus_decode(r: &mut R) -> Result, Error> { String::from_utf8(Decodable::consensus_decode(r)?) .map_err(|_| self::Error::ParseFailed("String was not valid UTF8")) .map(Cow::Owned) @@ -550,7 +550,7 @@ macro_rules! impl_array { ( $size:expr ) => { impl Encodable for [u8; $size] { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { w.emit_slice(&self[..])?; Ok(self.len()) } @@ -558,7 +558,7 @@ macro_rules! impl_array { impl Decodable for [u8; $size] { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let mut ret = [0; $size]; r.read_slice(&mut ret)?; Ok(ret) @@ -578,7 +578,7 @@ impl_array!(33); impl Decodable for [u16; 8] { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let mut res = [0; 8]; for item in &mut res { *item = Decodable::consensus_decode(r)?; @@ -589,7 +589,7 @@ impl Decodable for [u16; 8] { impl Encodable for [u16; 8] { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { for c in self.iter() { c.consensus_encode(w)?; } Ok(16) } @@ -600,7 +600,7 @@ macro_rules! impl_vec { ($type: ty) => { impl Encodable for Vec<$type> { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += VarInt(self.len() as u64).consensus_encode(w)?; for c in self.iter() { @@ -612,7 +612,7 @@ macro_rules! impl_vec { impl Decodable for Vec<$type> { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let len = VarInt::consensus_decode_from_finite_reader(r)?.0; // Do not allocate upfront more items than if the sequnce of type // occupied roughly quarter a block. This should never be the case @@ -681,14 +681,14 @@ fn read_bytes_from_finite_reader(mut d: D, mut opts: ReadBytesFromF impl Encodable for Vec { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { consensus_encode_with_size(self, w) } } impl Decodable for Vec { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let len = VarInt::consensus_decode(r)?.0 as usize; // most real-world vec of bytes data, wouldn't be larger than 128KiB read_bytes_from_finite_reader(r, ReadBytesFromFiniteReaderOpts { len, chunk_size: 128 * 1024 }) @@ -697,14 +697,14 @@ impl Decodable for Vec { impl Encodable for Box<[u8]> { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { consensus_encode_with_size(self, w) } } impl Decodable for Box<[u8]> { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { >::consensus_decode_from_finite_reader(r).map(From::from) } } @@ -719,7 +719,7 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { // Checked data impl Encodable for CheckedData { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { (self.0.len() as u32).consensus_encode(w)?; sha2_checksum(&self.0).consensus_encode(w)?; w.emit_slice(&self.0)?; @@ -729,7 +729,7 @@ impl Encodable for CheckedData { impl Decodable for CheckedData { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let len = u32::consensus_decode_from_finite_reader(r)? as usize; let checksum = <[u8; 4]>::consensus_decode_from_finite_reader(r)?; @@ -748,25 +748,25 @@ impl Decodable for CheckedData { // References impl<'a, T: Encodable> Encodable for &'a T { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { (&**self).consensus_encode(w) } } impl<'a, T: Encodable> Encodable for &'a mut T { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { (&**self).consensus_encode(w) } } impl Encodable for rc::Rc { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { (&**self).consensus_encode(w) } } impl Encodable for sync::Arc { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { (&**self).consensus_encode(w) } } @@ -777,7 +777,7 @@ macro_rules! tuple_encode { impl <$($x: Encodable),*> Encodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_encode( + fn consensus_encode( &self, w: &mut W, ) -> Result { @@ -791,7 +791,7 @@ macro_rules! tuple_encode { impl<$($x: Decodable),*> Decodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(($({let $x = Decodable::consensus_decode(r)?; $x }),*)) } } @@ -807,37 +807,37 @@ tuple_encode!(T0, T1, T2, T3, T4, T5, T6); tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); impl Encodable for sha256d::Hash { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { self.into_inner().consensus_encode(w) } } impl Decodable for sha256d::Hash { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(Self::from_inner(<::Inner>::consensus_decode(r)?)) } } impl Encodable for sha256::Hash { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { self.into_inner().consensus_encode(w) } } impl Decodable for sha256::Hash { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(Self::from_inner(<::Inner>::consensus_decode(r)?)) } } impl Encodable for TapLeafHash { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { self.into_inner().consensus_encode(w) } } impl Decodable for TapLeafHash { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(Self::from_inner(<::Inner>::consensus_decode(r)?)) } } diff --git a/src/hash_types.rs b/src/hash_types.rs index f28d0863..84462dd8 100644 --- a/src/hash_types.rs +++ b/src/hash_types.rs @@ -25,13 +25,13 @@ use crate::hashes::{Hash, sha256, sha256d, hash160, hash_newtype}; macro_rules! impl_hashencode { ($hashtype:ident) => { impl $crate::consensus::Encodable for $hashtype { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { self.0.consensus_encode(w) } } impl $crate::consensus::Decodable for $hashtype { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { use $crate::hashes::Hash; Ok(Self::from_inner(<<$hashtype as $crate::hashes::Hash>::Inner>::consensus_decode(r)?)) } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 60aebda5..12fc77a2 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -21,7 +21,7 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( impl $crate::consensus::Encodable for $thing { #[inline] - fn consensus_encode( + fn consensus_encode( &self, r: &mut R, ) -> Result { @@ -34,7 +34,7 @@ macro_rules! impl_consensus_encoding { impl $crate::consensus::Decodable for $thing { #[inline] - fn consensus_decode_from_finite_reader( + fn consensus_decode_from_finite_reader( r: &mut R, ) -> Result<$thing, $crate::consensus::encode::Error> { Ok($thing { @@ -43,7 +43,7 @@ macro_rules! impl_consensus_encoding { } #[inline] - fn consensus_decode( + fn consensus_decode( r: &mut R, ) -> Result<$thing, $crate::consensus::encode::Error> { use crate::io::Read as _; diff --git a/src/network/address.rs b/src/network/address.rs index ca89c6c0..b62f18aa 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -69,7 +69,7 @@ impl Address { impl Encodable for Address { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = self.services.consensus_encode(w)?; for word in &self.address { @@ -86,7 +86,7 @@ impl Encodable for Address { impl Decodable for Address { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(Address { services: Decodable::consensus_decode(r)?, address: read_be_address(r)?, @@ -96,7 +96,7 @@ impl Decodable for Address { } /// Read a big-endian address from reader. -fn read_be_address(r: &mut R) -> Result<[u16; 8], encode::Error> { +fn read_be_address(r: &mut R) -> Result<[u16; 8], encode::Error> { let mut address = [0u16; 8]; let mut buf = [0u8; 2]; @@ -147,8 +147,8 @@ pub enum AddrV2 { } impl Encodable for AddrV2 { - fn consensus_encode(&self, e: &mut W) -> Result { - fn encode_addr(w: &mut W, network: u8, bytes: &[u8]) -> Result { + fn consensus_encode(&self, e: &mut W) -> Result { + fn encode_addr(w: &mut W, network: u8, bytes: &[u8]) -> Result { let len = network.consensus_encode(w)? + VarInt(bytes.len() as u64).consensus_encode(w)? + bytes.len(); @@ -168,7 +168,7 @@ impl Encodable for AddrV2 { } impl Decodable for AddrV2 { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let network_id = u8::consensus_decode(r)?; let len = VarInt::consensus_decode(r)?.0; if len > 512 { @@ -264,7 +264,7 @@ impl AddrV2Message { } impl Encodable for AddrV2Message { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += self.time.consensus_encode(w)?; len += VarInt(self.services.to_u64()).consensus_encode(w)?; @@ -278,7 +278,7 @@ impl Encodable for AddrV2Message { } impl Decodable for AddrV2Message { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(AddrV2Message { time: Decodable::consensus_decode(r)?, services: ServiceFlags::from(VarInt::consensus_decode(r)?.0), diff --git a/src/network/constants.rs b/src/network/constants.rs index 5dab75eb..573cdabf 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -280,14 +280,14 @@ impl ops::BitXorAssign for ServiceFlags { impl Encodable for ServiceFlags { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { self.0.consensus_encode(w) } } impl Decodable for ServiceFlags { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(ServiceFlags(Decodable::consensus_decode(r)?)) } } diff --git a/src/network/message.rs b/src/network/message.rs index 4046df92..5a0fe2dc 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -80,7 +80,7 @@ impl AsRef for CommandString { impl Encodable for CommandString { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut rawbytes = [0u8; 12]; let strbytes = self.0.as_bytes(); debug_assert!(strbytes.len() <= 12); @@ -91,7 +91,7 @@ impl Encodable for CommandString { impl Decodable for CommandString { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let rawbytes: [u8; 12] = Decodable::consensus_decode(r)?; let rv = iter::FromIterator::from_iter( rawbytes @@ -287,7 +287,7 @@ struct HeaderSerializationWrapper<'a>(&'a Vec); impl<'a> Encodable for HeaderSerializationWrapper<'a> { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += VarInt(self.0.len() as u64).consensus_encode(w)?; for header in self.0.iter() { @@ -299,7 +299,7 @@ impl<'a> Encodable for HeaderSerializationWrapper<'a> { } impl Encodable for RawNetworkMessage { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += self.magic.consensus_encode(w)?; len += self.command().consensus_encode(w)?; @@ -346,7 +346,7 @@ struct HeaderDeserializationWrapper(Vec); impl Decodable for HeaderDeserializationWrapper { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let len = VarInt::consensus_decode(r)?.0; // should be above usual number of items to avoid // allocation @@ -361,13 +361,13 @@ impl Decodable for HeaderDeserializationWrapper { } #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref()) } } impl Decodable for RawNetworkMessage { - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let magic = Decodable::consensus_decode_from_finite_reader(r)?; let cmd = CommandString::consensus_decode_from_finite_reader(r)?; let raw_payload = CheckedData::consensus_decode_from_finite_reader(r)?.0; @@ -420,7 +420,7 @@ impl Decodable for RawNetworkMessage { } #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref()) } } diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index dcd72be6..37e22588 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -54,7 +54,7 @@ pub enum Inventory { impl Encodable for Inventory { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { macro_rules! encode_inv { ($code:expr, $item:expr) => { u32::consensus_encode(&$code, w)? + $item.consensus_encode(w)? @@ -74,7 +74,7 @@ impl Encodable for Inventory { impl Decodable for Inventory { #[inline] - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let inv_type: u32 = Decodable::consensus_decode(r)?; Ok(match inv_type { 0 => Inventory::Error, diff --git a/src/network/message_bloom.rs b/src/network/message_bloom.rs index 5d0df82e..e25e50de 100644 --- a/src/network/message_bloom.rs +++ b/src/network/message_bloom.rs @@ -34,7 +34,7 @@ pub enum BloomFlags { } impl Encodable for BloomFlags { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { w.write_all(&[match self { BloomFlags::None => 0, BloomFlags::All => 1, @@ -45,7 +45,7 @@ impl Encodable for BloomFlags { } impl Decodable for BloomFlags { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(match r.read_u8()? { 0 => BloomFlags::None, 1 => BloomFlags::All, diff --git a/src/network/message_network.rs b/src/network/message_network.rs index f9ee2223..bcb36227 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -106,14 +106,14 @@ pub enum RejectReason { } impl Encodable for RejectReason { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { w.write_all(&[*self as u8])?; Ok(1) } } impl Decodable for RejectReason { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(match r.read_u8()? { 0x01 => RejectReason::Malformed, 0x10 => RejectReason::Invalid, diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 2f42e301..54107e2e 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -355,7 +355,7 @@ impl PartialMerkleTree { } impl Encodable for PartialMerkleTree { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let ret = self.num_transactions.consensus_encode(w)? + self.hashes.consensus_encode(w)?; let mut bytes: Vec = vec![0; (self.bits.len() + 7) / 8]; @@ -367,7 +367,7 @@ impl Encodable for PartialMerkleTree { } impl Decodable for PartialMerkleTree { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let num_transactions: u32 = Decodable::consensus_decode(r)?; let hashes: Vec = Decodable::consensus_decode(r)?; @@ -506,7 +506,7 @@ impl MerkleBlock { } impl Encodable for MerkleBlock { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let len = self.header.consensus_encode(w)? + self.txn.consensus_encode(w)?; Ok(len) @@ -514,7 +514,7 @@ impl Encodable for MerkleBlock { } impl Decodable for MerkleBlock { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(MerkleBlock { header: Decodable::consensus_decode(r)?, txn: Decodable::consensus_decode(r)?, diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index bb2afbb4..eb38f7b4 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -55,7 +55,7 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { impl $crate::consensus::Encodable for $thing { - fn consensus_encode( + fn consensus_encode( &self, w: &mut W, ) -> Result { @@ -68,7 +68,7 @@ macro_rules! impl_psbtmap_consensus_encoding { macro_rules! impl_psbtmap_consensus_decoding { ($thing:ty) => { impl $crate::consensus::Decodable for $thing { - fn consensus_decode( + fn consensus_decode( r: &mut R, ) -> Result { let mut rv: Self = ::core::default::Default::default(); diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index 52c3a410..c8651397 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -100,7 +100,7 @@ impl Map for PartiallySignedTransaction { } impl PartiallySignedTransaction { - pub(crate) fn consensus_decode_global(r: &mut R) -> Result { + pub(crate) fn consensus_decode_global(r: &mut R) -> Result { let mut r = r.take(MAX_VEC_SIZE as u64); let mut tx: Option = None; let mut version: Option = None; diff --git a/src/util/psbt/map/mod.rs b/src/util/psbt/map/mod.rs index 8a512cf1..39b4c74d 100644 --- a/src/util/psbt/map/mod.rs +++ b/src/util/psbt/map/mod.rs @@ -32,7 +32,7 @@ pub(super) trait Map { fn get_pairs(&self) -> Result, io::Error>; /// Encodes map data with bitcoin consensus encoding. - fn consensus_encode_map(&self, w: &mut W) -> Result { + fn consensus_encode_map(&self, w: &mut W) -> Result { let mut len = 0; for pair in Map::get_pairs(self)? { len += encode::Encodable::consensus_encode(&pair, w)?; diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index f874c55b..94fbfda7 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -277,7 +277,7 @@ mod display_from_str { pub use self::display_from_str::PsbtParseError; impl Encodable for PartiallySignedTransaction { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += b"psbt".consensus_encode(w)?; @@ -298,7 +298,7 @@ impl Encodable for PartiallySignedTransaction { } impl Decodable for PartiallySignedTransaction { - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let magic: [u8; 4] = Decodable::consensus_decode(r)?; if *b"psbt" != magic { diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index eb6272da..8222f0b7 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -79,7 +79,7 @@ impl fmt::Display for Key { } impl Decodable for Key { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let VarInt(byte_size): VarInt = Decodable::consensus_decode(r)?; if byte_size == 0 { @@ -107,7 +107,7 @@ impl Decodable for Key { } impl Encodable for Key { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = 0; len += VarInt((self.key.len() + 1) as u64).consensus_encode(w)?; @@ -122,14 +122,14 @@ impl Encodable for Key { } impl Encodable for Pair { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let len = self.key.consensus_encode(w)?; Ok(len + self.value.consensus_encode(w)?) } } impl Decodable for Pair { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { Ok(Pair { key: Decodable::consensus_decode(r)?, value: Decodable::consensus_decode(r)?, @@ -138,7 +138,7 @@ impl Decodable for Pair { } impl Encodable for ProprietaryKey where Subtype: Copy + From + Into { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { let mut len = self.prefix.consensus_encode(w)? + 1; w.emit_u8(self.subtype.into())?; w.write_all(&self.key)?; @@ -148,7 +148,7 @@ impl Encodable for ProprietaryKey where Subtype: Copy + From Decodable for ProprietaryKey where Subtype: Copy + From + Into { - fn consensus_decode(r: &mut R) -> Result { + fn consensus_decode(r: &mut R) -> Result { let prefix = Vec::::consensus_decode(r)?; let subtype = Subtype::from(r.read_u8()?); let key = read_to_end(r)?; diff --git a/src/util/sighash.rs b/src/util/sighash.rs index e89127d9..202933c4 100644 --- a/src/util/sighash.rs +++ b/src/util/sighash.rs @@ -794,7 +794,7 @@ impl<'a> Annex<'a> { } impl<'a> Encodable for Annex<'a> { - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode(&self, w: &mut W) -> Result { encode::consensus_encode_with_size(self.0, w) } } diff --git a/src/util/uint.rs b/src/util/uint.rs index 9b2c6928..ca9e4ed3 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -419,7 +419,7 @@ macro_rules! construct_uint { impl $crate::consensus::Encodable for $name { #[inline] - fn consensus_encode( + fn consensus_encode( &self, w: &mut W, ) -> Result { @@ -433,7 +433,7 @@ macro_rules! construct_uint { } impl $crate::consensus::Decodable for $name { - fn consensus_decode( + fn consensus_decode( r: &mut R, ) -> Result<$name, $crate::consensus::encode::Error> { use $crate::consensus::Decodable;