From 61918dfe8121138d70bb28b2f76f8ff713b5d0f4 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 9 Oct 2020 17:04:10 +0200 Subject: [PATCH] Change the signature of consensus_encode to return io::Error's This is instead of encode::Errors because the encoders should not be allowed to return errors that don't originate in the writer they are writing into. This is a part of the method definition that has been relied upon for a while already. --- src/blockdata/script.rs | 2 +- src/blockdata/transaction.rs | 6 +-- src/consensus/encode.rs | 85 ++++++++++++++++---------------- src/hash_types.rs | 2 +- src/internal_macros.rs | 2 +- src/network/address.rs | 8 +-- src/network/constants.rs | 2 +- src/network/message.rs | 6 +-- src/network/message_blockdata.rs | 2 +- src/network/message_network.rs | 2 +- src/util/merkleblock.rs | 4 +- src/util/psbt/macros.rs | 2 +- src/util/psbt/map/global.rs | 2 +- src/util/psbt/map/input.rs | 9 ++-- src/util/psbt/map/mod.rs | 4 +- src/util/psbt/map/output.rs | 3 +- src/util/psbt/mod.rs | 2 +- src/util/psbt/raw.rs | 6 +-- src/util/uint.rs | 2 +- 19 files changed, 78 insertions(+), 73 deletions(-) diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 84f1b97c..86151f35 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -831,7 +831,7 @@ impl Encodable for Script { fn consensus_encode( &self, s: S, - ) -> Result { + ) -> Result { self.0.consensus_encode(s) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 0af5a172..07f07364 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -490,7 +490,7 @@ impl Encodable for OutPoint { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let len = self.txid.consensus_encode(&mut s)?; Ok(len + self.vout.consensus_encode(s)?) } @@ -508,7 +508,7 @@ impl Encodable for TxIn { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; len += self.previous_output.consensus_encode(&mut s)?; len += self.script_sig.consensus_encode(&mut s)?; @@ -531,7 +531,7 @@ impl Encodable for Transaction { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; len += self.version.consensus_encode(&mut s)?; let mut have_witness = self.input.is_empty(); diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index d422cd65..54c8366f 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -176,28 +176,28 @@ pub fn deserialize_partial( /// Extensions of `Write` to encode data as per Bitcoin consensus pub trait WriteExt { /// Output a 64-bit uint - fn emit_u64(&mut self, v: u64) -> Result<(), Error>; + fn emit_u64(&mut self, v: u64) -> Result<(), io::Error>; /// Output a 32-bit uint - fn emit_u32(&mut self, v: u32) -> Result<(), Error>; + fn emit_u32(&mut self, v: u32) -> Result<(), io::Error>; /// Output a 16-bit uint - fn emit_u16(&mut self, v: u16) -> Result<(), Error>; + fn emit_u16(&mut self, v: u16) -> Result<(), io::Error>; /// Output a 8-bit uint - fn emit_u8(&mut self, v: u8) -> Result<(), Error>; + fn emit_u8(&mut self, v: u8) -> Result<(), io::Error>; /// Output a 64-bit int - fn emit_i64(&mut self, v: i64) -> Result<(), Error>; + fn emit_i64(&mut self, v: i64) -> Result<(), io::Error>; /// Output a 32-bit int - fn emit_i32(&mut self, v: i32) -> Result<(), Error>; + fn emit_i32(&mut self, v: i32) -> Result<(), io::Error>; /// Output a 16-bit int - fn emit_i16(&mut self, v: i16) -> Result<(), Error>; + fn emit_i16(&mut self, v: i16) -> Result<(), io::Error>; /// Output a 8-bit int - fn emit_i8(&mut self, v: i8) -> Result<(), Error>; + fn emit_i8(&mut self, v: i8) -> Result<(), io::Error>; /// Output a boolean - fn emit_bool(&mut self, v: bool) -> Result<(), Error>; + fn emit_bool(&mut self, v: bool) -> Result<(), io::Error>; /// Output a byte slice - fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error>; + fn emit_slice(&mut self, v: &[u8]) -> Result<(), io::Error>; } /// Extensions of `Read` to decode data as per Bitcoin consensus @@ -230,8 +230,8 @@ pub trait ReadExt { macro_rules! encoder_fn { ($name:ident, $val_type:ty, $writefn:ident) => { #[inline] - fn $name(&mut self, v: $val_type) -> Result<(), Error> { - self.write_all(&endian::$writefn(v)).map_err(Error::Io) + fn $name(&mut self, v: $val_type) -> Result<(), io::Error> { + self.write_all(&endian::$writefn(v)) } } } @@ -257,20 +257,20 @@ impl WriteExt for W { encoder_fn!(emit_i16, i16, i16_to_array_le); #[inline] - fn emit_i8(&mut self, v: i8) -> Result<(), Error> { - self.write_all(&[v as u8]).map_err(Error::Io) + fn emit_i8(&mut self, v: i8) -> Result<(), io::Error> { + self.write_all(&[v as u8]) } #[inline] - fn emit_u8(&mut self, v: u8) -> Result<(), Error> { - self.write_all(&[v]).map_err(Error::Io) + fn emit_u8(&mut self, v: u8) -> Result<(), io::Error> { + self.write_all(&[v]) } #[inline] - fn emit_bool(&mut self, v: bool) -> Result<(), Error> { - self.write_all(&[v as u8]).map_err(Error::Io) + fn emit_bool(&mut self, v: bool) -> Result<(), io::Error> { + self.write_all(&[v as u8]) } #[inline] - fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error> { - self.write_all(v).map_err(Error::Io) + fn emit_slice(&mut self, v: &[u8]) -> Result<(), io::Error> { + self.write_all(v) } } @@ -309,10 +309,11 @@ pub const MAX_VEC_SIZE: usize = 4_000_000; /// Data which can be encoded in a consensus-consistent way pub trait Encodable { - /// Encode an object with a well-defined format, should only ever error if - /// the underlying `Write` errors. Returns the number of bytes written on - /// success - fn consensus_encode(&self, e: W) -> Result; + /// Encode an object with a well-defined format. + /// 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; } /// Data which can be encoded in a consensus-consistent way @@ -343,7 +344,7 @@ macro_rules! impl_int_encodable{ fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { s.$meth_enc(self.to_le())?; Ok(mem::size_of::<$ty>()) } @@ -377,7 +378,7 @@ impl VarInt { impl Encodable for VarInt { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, mut s: S) -> Result { match self.0 { 0..=0xFC => { (self.0 as u8).consensus_encode(s)?; @@ -440,7 +441,7 @@ impl Decodable for VarInt { // Booleans impl Encodable for bool { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, mut s: S) -> Result { s.emit_bool(*self)?; Ok(1) } @@ -456,7 +457,7 @@ impl Decodable for bool { // Strings impl Encodable for String { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, mut s: S) -> Result { let b = self.as_bytes(); let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?; s.emit_slice(&b)?; @@ -475,7 +476,7 @@ 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, mut s: S) -> Result { let b = self.as_bytes(); let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?; s.emit_slice(&b)?; @@ -501,7 +502,7 @@ macro_rules! impl_array { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { s.emit_slice(&self[..])?; Ok(self.len()) } @@ -540,7 +541,7 @@ impl Decodable for [u16; 8] { impl Encodable for [u16; 8] { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + fn consensus_encode(&self, mut s: S) -> Result { for c in self.iter() { c.consensus_encode(&mut s)?; } Ok(16) } @@ -554,7 +555,7 @@ macro_rules! impl_vec { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; len += VarInt(self.len() as u64).consensus_encode(&mut s)?; for c in self.iter() { @@ -595,7 +596,7 @@ impl_vec!((u32, Address)); impl_vec!(u64); impl_vec!(AddrV2Message); -fn consensus_encode_with_size(data: &[u8], mut s: S) -> Result { +fn consensus_encode_with_size(data: &[u8], mut s: S) -> Result { let vi_len = VarInt(data.len() as u64).consensus_encode(&mut s)?; s.emit_slice(&data)?; Ok(vi_len + data.len()) @@ -604,7 +605,7 @@ fn consensus_encode_with_size(data: &[u8], mut s: S) -> Result { #[inline] - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, s: S) -> Result { consensus_encode_with_size(self, s) } } @@ -624,7 +625,7 @@ impl Decodable for Vec { impl Encodable for Box<[u8]> { #[inline] - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, s: S) -> Result { consensus_encode_with_size(self, s) } } @@ -646,7 +647,7 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { // Checked data impl Encodable for CheckedData { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { + 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)?; @@ -681,25 +682,25 @@ impl Decodable for CheckedData { // References impl<'a, T: Encodable> Encodable for &'a T { - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, s: S) -> Result { (&**self).consensus_encode(s) } } impl<'a, T: Encodable> Encodable for &'a mut T { - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, s: S) -> Result { (&**self).consensus_encode(s) } } impl Encodable for ::std::rc::Rc { - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, s: S) -> Result { (&**self).consensus_encode(s) } } impl Encodable for ::std::sync::Arc { - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, s: S) -> Result { (&**self).consensus_encode(s) } } @@ -713,7 +714,7 @@ macro_rules! tuple_encode { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let &($(ref $x),*) = self; let mut len = 0; $(len += $x.consensus_encode(&mut s)?;)* @@ -740,7 +741,7 @@ 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 { + fn consensus_encode(&self, s: S) -> Result { self.into_inner().consensus_encode(s) } } diff --git a/src/hash_types.rs b/src/hash_types.rs index f50be4bd..f55ded05 100644 --- a/src/hash_types.rs +++ b/src/hash_types.rs @@ -21,7 +21,7 @@ use hashes::{Hash, sha256, sha256d, hash160}; macro_rules! impl_hashencode { ($hashtype:ident) => { impl $crate::consensus::Encodable for $hashtype { - fn consensus_encode(&self, s: S) -> Result { + fn consensus_encode(&self, s: S) -> Result { self.0.consensus_encode(s) } } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index e0f9247a..dc66ec60 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -23,7 +23,7 @@ macro_rules! impl_consensus_encoding { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; $(len += self.$field.consensus_encode(&mut s)?;)+ Ok(len) diff --git a/src/network/address.rs b/src/network/address.rs index 3c4b7a6d..1ee27bb2 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -77,7 +77,7 @@ impl Encodable for Address { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let len = self.services.consensus_encode(&mut s)? + addr_to_be(self.address).consensus_encode(&mut s)? + self.port.to_be().consensus_encode(s)?; @@ -136,8 +136,8 @@ 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 { + 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)? + @@ -261,7 +261,7 @@ impl AddrV2Message { } impl Encodable for AddrV2Message { - fn consensus_encode(&self, mut e: W) -> Result { + fn consensus_encode(&self, mut e: W) -> Result { let mut len = 0; len += self.time.consensus_encode(&mut e)?; len += VarInt(self.services.as_u64()).consensus_encode(&mut e)?; diff --git a/src/network/constants.rs b/src/network/constants.rs index ce858b36..f29ba79c 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -276,7 +276,7 @@ impl Encodable for ServiceFlags { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { self.0.consensus_encode(&mut s) } } diff --git a/src/network/message.rs b/src/network/message.rs index 43df567c..1ca3a839 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -78,7 +78,7 @@ impl Encodable for CommandString { fn consensus_encode( &self, s: S, - ) -> Result { + ) -> Result { let mut rawbytes = [0u8; 12]; let strbytes = self.0.as_bytes(); debug_assert!(strbytes.len() <= 12); @@ -255,7 +255,7 @@ impl<'a> Encodable for HeaderSerializationWrapper<'a> { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; len += VarInt(self.0.len() as u64).consensus_encode(&mut s)?; for header in self.0.iter() { @@ -270,7 +270,7 @@ impl Encodable for RawNetworkMessage { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; len += self.magic.consensus_encode(&mut s)?; len += self.command().consensus_encode(&mut s)?; diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index ef82552d..909c6c05 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -55,7 +55,7 @@ impl Encodable for Inventory { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { macro_rules! encode_inv { ($code:expr, $item:expr) => { u32::consensus_encode(&$code, &mut s)? + diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 5f033004..76a9f4da 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -106,7 +106,7 @@ pub enum RejectReason { } impl Encodable for RejectReason { - fn consensus_encode(&self, mut e: W) -> Result { + fn consensus_encode(&self, mut e: W) -> Result { e.write_all(&[*self as u8])?; Ok(1) } diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index f4edaeb0..528514f3 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -350,7 +350,7 @@ impl Encodable for PartialMerkleTree { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let ret = self.num_transactions.consensus_encode(&mut s)? + self.hashes.consensus_encode(&mut s)?; let mut bytes: Vec = vec![0; (self.bits.len() + 7) / 8]; @@ -478,7 +478,7 @@ impl Encodable for MerkleBlock { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let len = self.header.consensus_encode(&mut s)? + self.txn.consensus_encode(s)?; Ok(len) diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 9b3987a7..11c47bef 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -58,7 +58,7 @@ macro_rules! impl_psbtmap_consensus_encoding { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; for pair in $crate::util::psbt::Map::get_pairs(self)? { len += $crate::consensus::Encodable::consensus_encode( diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index 44a7fc3a..bc4464c2 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -100,7 +100,7 @@ impl Map for Global { Ok(()) } - fn get_pairs(&self) -> Result, encode::Error> { + fn get_pairs(&self) -> Result, io::Error> { let mut rv: Vec = Default::default(); rv.push(raw::Pair { diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 208f1ce0..ab114e0c 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -12,7 +12,8 @@ // If not, see . // -use std::collections::btree_map::{Entry, BTreeMap}; +use std::io; +use std::collections::btree_map::{BTreeMap, Entry}; use blockdata::script::Script; use blockdata::transaction::{SigHashType, Transaction, TxOut}; @@ -180,10 +181,10 @@ impl Map for Input { ::std::collections::btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()), } _ => match self.unknown.entry(raw_key) { - ::std::collections::btree_map::Entry::Vacant(empty_key) => { + Entry::Vacant(empty_key) => { empty_key.insert(raw_value); } - ::std::collections::btree_map::Entry::Occupied(k) => { + Entry::Occupied(k) => { return Err(Error::DuplicateKey(k.key().clone()).into()) } }, @@ -192,7 +193,7 @@ impl Map for Input { Ok(()) } - fn get_pairs(&self) -> Result, encode::Error> { + fn get_pairs(&self) -> Result, io::Error> { let mut rv: Vec = Default::default(); impl_psbt_get_pair! { diff --git a/src/util/psbt/map/mod.rs b/src/util/psbt/map/mod.rs index a84cf8a3..6cde3653 100644 --- a/src/util/psbt/map/mod.rs +++ b/src/util/psbt/map/mod.rs @@ -12,6 +12,8 @@ // If not, see . // +use std::io; + use consensus::encode; use util::psbt; use util::psbt::raw; @@ -22,7 +24,7 @@ pub trait Map { fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error>; /// Attempt to get all key-value pairs. - fn get_pairs(&self) -> Result, encode::Error>; + fn get_pairs(&self) -> Result, io::Error>; /// Attempt to merge with another key-value map of the same type. fn merge(&mut self, other: Self) -> Result<(), psbt::Error>; diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 18511949..1c40ec1b 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -12,6 +12,7 @@ // If not, see . // +use std::io; use std::collections::BTreeMap; use std::collections::btree_map::Entry; @@ -90,7 +91,7 @@ impl Map for Output { Ok(()) } - fn get_pairs(&self) -> Result, encode::Error> { + fn get_pairs(&self) -> Result, io::Error> { let mut rv: Vec = Default::default(); impl_psbt_get_pair! { diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 0bb430d1..d54f523d 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -95,7 +95,7 @@ impl Encodable for PartiallySignedTransaction { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; len += b"psbt".consensus_encode(&mut s)?; diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 74290b31..44f80d03 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -106,7 +106,7 @@ impl Encodable for Key { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let mut len = 0; len += VarInt((self.key.len() + 1) as u64).consensus_encode(&mut s)?; @@ -124,7 +124,7 @@ impl Encodable for Pair { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let len = self.key.consensus_encode(&mut s)?; Ok(len + self.value.consensus_encode(s)?) } @@ -140,7 +140,7 @@ impl Decodable for Pair { } impl Encodable for ProprietaryKey where Subtype: Copy + From + Into { - fn consensus_encode(&self, mut e: W) -> Result { + fn consensus_encode(&self, mut e: W) -> Result { let mut len = self.prefix.consensus_encode(&mut e)? + 1; e.emit_u8(self.subtype.into())?; len += e.write(&self.key)?; diff --git a/src/util/uint.rs b/src/util/uint.rs index 376dc7d2..314ac6b0 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -381,7 +381,7 @@ macro_rules! construct_uint { fn consensus_encode( &self, mut s: S, - ) -> Result { + ) -> Result { let &$name(ref data) = self; let mut len = 0; for word in data.iter() {