From b734d6488a22519f7248e4fdd39a3ce2f55d5255 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 23 May 2019 20:28:10 +0000 Subject: [PATCH] make consensus_encode return the encoded length --- src/blockdata/opcodes.rs | 20 -------- src/blockdata/script.rs | 2 +- src/blockdata/transaction.rs | 38 ++++++++------- src/consensus/encode.rs | 80 +++++++++++++++++++------------- src/internal_macros.rs | 7 +-- src/network/address.rs | 10 ++-- src/network/constants.rs | 67 ++++++++++++-------------- src/network/message.rs | 25 +++++----- src/network/message_blockdata.rs | 6 +-- src/util/merkleblock.rs | 13 +++--- src/util/psbt/macros.rs | 7 +-- src/util/psbt/mod.rs | 15 +++--- src/util/psbt/raw.rs | 17 +++---- src/util/uint.rs | 9 ++-- 14 files changed, 160 insertions(+), 156 deletions(-) diff --git a/src/blockdata/opcodes.rs b/src/blockdata/opcodes.rs index a79081a3..96da7673 100644 --- a/src/blockdata/opcodes.rs +++ b/src/blockdata/opcodes.rs @@ -24,8 +24,6 @@ use std::fmt; -use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; - // Note: I am deliberately not implementing PartialOrd or Ord on the // opcode enum. If you want to check ranges of opcodes, etc., // write an #[inline] helper function which casts to u8s. @@ -714,20 +712,6 @@ impl From for All { display_from_debug!(All); -impl Decodable for All { - #[inline] - fn consensus_decode(d: &mut D) -> Result { - Ok(All::from(d.read_u8()?)) - } -} - -impl Encodable for All { - #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - s.emit_u8(self.code) - } -} - #[cfg(feature = "serde")] impl serde::Serialize for All { fn serialize(&self, serializer: S) -> Result @@ -834,7 +818,6 @@ impl Ordinary { mod tests { use std::collections::HashSet; - use consensus::encode::{serialize, deserialize}; use super::*; macro_rules! roundtrip { @@ -846,9 +829,6 @@ mod tests { assert_eq!(s1, s2); assert_eq!(s1, stringify!($op)); assert!($unique.insert(s1)); - - let enc = serialize(&all::$op); - assert_eq!(all::$op, deserialize(&enc).unwrap()); } } diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 845fb8f8..ec1ae8b1 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -727,7 +727,7 @@ impl serde::Serialize for Script { // Network serialization impl Encodable for Script { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { self.0.consensus_encode(s) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index f79b3069..e7c4675f 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -440,9 +440,9 @@ impl BitcoinHash for Transaction { impl_consensus_encoding!(TxOut, value, script_pubkey); impl Encodable for OutPoint { - fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { - self.txid.consensus_encode(s)?; - self.vout.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let len = self.txid.consensus_encode(s)?; + Ok(len + self.vout.consensus_encode(s)?) } } impl Decodable for OutPoint { @@ -455,10 +455,12 @@ impl Decodable for OutPoint { } impl Encodable for TxIn { - fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { - self.previous_output.consensus_encode(s)?; - self.script_sig.consensus_encode(s)?; - self.sequence.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.previous_output.consensus_encode(s)?; + len += self.script_sig.consensus_encode(s)?; + len += self.sequence.consensus_encode(s)?; + Ok(len) } } impl Decodable for TxIn { @@ -473,8 +475,9 @@ impl Decodable for TxIn { } impl Encodable for Transaction { - fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> { - self.version.consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.version.consensus_encode(s)?; let mut have_witness = self.input.is_empty(); for input in &self.input { if !input.witness.is_empty() { @@ -483,18 +486,19 @@ impl Encodable for Transaction { } } if !have_witness { - self.input.consensus_encode(s)?; - self.output.consensus_encode(s)?; + len += self.input.consensus_encode(s)?; + len += self.output.consensus_encode(s)?; } else { - 0u8.consensus_encode(s)?; - 1u8.consensus_encode(s)?; - self.input.consensus_encode(s)?; - self.output.consensus_encode(s)?; + len += 0u8.consensus_encode(s)?; + len += 1u8.consensus_encode(s)?; + len += self.input.consensus_encode(s)?; + len += self.output.consensus_encode(s)?; for input in &self.input { - input.witness.consensus_encode(s)?; + len += input.witness.consensus_encode(s)?; } } - self.lock_time.consensus_encode(s) + len += self.lock_time.consensus_encode(s)?; + Ok(len) } } diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index fba5cf53..02cf6af6 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -372,8 +372,9 @@ pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024; /// Data which can be encoded in a consensus-consistent way pub trait Encodable { /// Encode an object with a well-defined format, should only ever error if - /// the underlying WriteExt errors. - fn consensus_encode(&self, e: &mut S) -> Result<(), self::Error>; + /// the underlying WriteExt errors. Returns the number of bytes written on + /// success + fn consensus_encode(&self, e: &mut S) -> Result; } /// Data which can be encoded in a consensus-consistent way @@ -400,7 +401,10 @@ macro_rules! impl_int_encodable{ impl Encodable for $ty { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.$meth_enc(self.to_le()) } + fn consensus_encode(&self, s: &mut S) -> Result { + s.$meth_enc(self.to_le())?; + Ok(mem::size_of::<$ty>()) + } } ) } @@ -431,12 +435,12 @@ impl VarInt { impl Encodable for VarInt { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { match self.0 { - 0...0xFC => { (self.0 as u8).consensus_encode(s) } - 0xFD...0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s) } - 0x10000...0xFFFFFFFF => { s.emit_u8(0xFE)?; (self.0 as u32).consensus_encode(s) } - _ => { s.emit_u8(0xFF)?; (self.0 as u64).consensus_encode(s) } + 0...0xFC => { (self.0 as u8).consensus_encode(s)?; Ok(1) } + 0xFD...0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s)?; Ok(3) } + 0x10000...0xFFFFFFFF => { s.emit_u8(0xFE)?; (self.0 as u32).consensus_encode(s)?; Ok(5) } + _ => { s.emit_u8(0xFF)?; (self.0 as u64).consensus_encode(s)?; Ok(9) } } } } @@ -479,7 +483,10 @@ impl Decodable for VarInt { // Booleans impl Encodable for bool { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.emit_u8(if *self {1} else {0}) } + fn consensus_encode(&self, s: &mut S) -> Result { + s.emit_u8(if *self {1} else {0})?; + Ok(1) + } } impl Decodable for bool { @@ -490,10 +497,11 @@ impl Decodable for bool { // Strings impl Encodable for String { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let b = self.as_bytes(); - VarInt(b.len() as u64).consensus_encode(s)?; - s.emit_slice(&b) + let vi_len = VarInt(b.len() as u64).consensus_encode(s)?; + s.emit_slice(&b)?; + Ok(vi_len + b.len()) } } @@ -511,8 +519,9 @@ macro_rules! impl_array { ( $size:expr ) => ( impl Encodable for [u8; $size] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - s.emit_slice(&self[..]) + fn consensus_encode(&self, s: &mut S) -> Result { + s.emit_slice(&self[..])?; + Ok(self.len()) } } @@ -548,9 +557,9 @@ impl Decodable for [u16; 8] { impl Encodable for [u16; 8] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { for c in self.iter() { c.consensus_encode(s)?; } - Ok(()) + Ok(16) } } @@ -559,10 +568,13 @@ macro_rules! impl_vec { ($type: ty) => { impl Encodable for Vec<$type> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - VarInt(self.len() as u64).consensus_encode(s)?; - for c in self.iter() { c.consensus_encode(s)?; } - Ok(()) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).consensus_encode(s)?; + for c in self.iter() { + len += c.consensus_encode(s)?; + } + Ok(len) } } @@ -594,9 +606,10 @@ impl_vec!(u64); impl Encodable for Vec { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - VarInt(self.len() as u64).consensus_encode(s)?; - s.emit_slice(&self) + fn consensus_encode(&self, s: &mut S) -> Result { + let vi_len = VarInt(self.len() as u64).consensus_encode(s)?; + s.emit_slice(&self)?; + Ok(vi_len + self.len()) } } @@ -617,9 +630,10 @@ impl Decodable for Vec { impl Encodable for Box<[u8]> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - VarInt(self.len() as u64).consensus_encode(s)?; - s.emit_slice(&self) + fn consensus_encode(&self, s: &mut S) -> Result { + let vi_len = VarInt(self.len() as u64).consensus_encode(s)?; + s.emit_slice(&self)?; + Ok(vi_len + self.len()) } } @@ -648,10 +662,11 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { // Checked data impl Encodable for CheckedData { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { (self.0.len() as u32).consensus_encode(s)?; sha2_checksum(&self.0).consensus_encode(s)?; - s.emit_slice(&self.0) + s.emit_slice(&self.0)?; + Ok(8 + self.0.len()) } } @@ -687,10 +702,11 @@ macro_rules! tuple_encode { impl ),*> Encodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let &($(ref $x),*) = self; - $( $x.consensus_encode(s)?; )* - Ok(()) + let mut len = 0; + $(len += $x.consensus_encode(s)?;)* + Ok(len) } } @@ -710,7 +726,7 @@ tuple_encode!(T0, T1, T2, T3, T4, T5); tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); impl Encodable for sha256d::Hash { - fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { self.into_inner().consensus_encode(s) } } diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 86cec029..27cbb5af 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -20,9 +20,10 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( impl ::consensus::Encodable for $thing { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> { - $( self.$field.consensus_encode(s)?; )+ - Ok(()) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + $(len += self.$field.consensus_encode(s)?;)+ + Ok(len) } } diff --git a/src/network/address.rs b/src/network/address.rs index 36531b2a..142ae41d 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -74,10 +74,12 @@ fn addr_to_be(addr: [u16; 8]) -> [u16; 8] { impl Encodable for Address { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.services.consensus_encode(s)?; - addr_to_be(self.address).consensus_encode(s)?; - self.port.to_be().consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.services.consensus_encode(s)?; + len += addr_to_be(self.address).consensus_encode(s)?; + len += self.port.to_be().consensus_encode(s)?; + Ok(len) } } diff --git a/src/network/constants.rs b/src/network/constants.rs index 7f44ff02..bd7b523b 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -32,13 +32,11 @@ //! use bitcoin::consensus::encode::serialize; //! //! let network = Network::Bitcoin; -//! let bytes = serialize(&network); +//! let bytes = serialize(&network.magic()); //! //! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]); //! ``` -use consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; - /// Version of the protocol as appearing in network message headers pub const PROTOCOL_VERSION: u32 = 70001; /// Bitfield of services provided by this node @@ -101,44 +99,39 @@ impl Network { } } -impl Encodable for Network { - /// Encodes the magic bytes of `Network`. - #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.magic().consensus_encode(s) - } -} - -impl Decodable for Network { - /// Decodes the magic bytes of `Network`. - #[inline] - fn consensus_decode(d: &mut D) -> Result { - u32::consensus_decode(d) - .and_then(|m| { - Network::from_magic(m) - .ok_or(encode::Error::UnknownNetworkMagic(m)) - }) - } -} - #[cfg(test)] mod tests { - use super::Network; - use consensus::encode::{deserialize, serialize}; + use super::Network; + use consensus::encode::{deserialize, serialize}; - #[test] - fn serialize_test() { - assert_eq!(serialize(&Network::Bitcoin), vec![0xf9, 0xbe, 0xb4, 0xd9]); - assert_eq!(serialize(&Network::Testnet), vec![0x0b, 0x11, 0x09, 0x07]); - assert_eq!(serialize(&Network::Regtest), vec![0xfa, 0xbf, 0xb5, 0xda]); + #[test] + fn serialize_test() { + assert_eq!( + serialize(&Network::Bitcoin.magic()), + &[0xf9, 0xbe, 0xb4, 0xd9] + ); + assert_eq!( + serialize(&Network::Testnet.magic()), + &[0x0b, 0x11, 0x09, 0x07] + ); + assert_eq!( + serialize(&Network::Regtest.magic()), + &[0xfa, 0xbf, 0xb5, 0xda] + ); - assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin)); - assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet)); - assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest)); - - let bad: Result = deserialize("fakenet".as_bytes()); - assert!(bad.is_err()); - } + assert_eq!( + deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), + Some(Network::Bitcoin.magic()) + ); + assert_eq!( + deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), + Some(Network::Testnet.magic()) + ); + assert_eq!( + deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), + Some(Network::Regtest.magic()) + ); + } #[test] fn string_test() { diff --git a/src/network/message.rs b/src/network/message.rs index 40d1e051..d8dcfd08 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -39,7 +39,7 @@ pub struct CommandString(pub String); impl Encodable for CommandString { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let &CommandString(ref inner_str) = self; let mut rawbytes = [0u8; 12]; let strbytes = inner_str.as_bytes(); @@ -162,21 +162,23 @@ impl RawNetworkMessage { struct HeaderSerializationWrapper<'a>(&'a Vec); impl <'a, S: WriteExt> Encodable for HeaderSerializationWrapper<'a> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - VarInt(self.0.len() as u64).consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.0.len() as u64).consensus_encode(s)?; for header in self.0.iter() { - header.consensus_encode(s)?; - 0u8.consensus_encode(s)?; + len += header.consensus_encode(s)?; + len += 0u8.consensus_encode(s)?; } - Ok(()) + Ok(len) } } impl Encodable for RawNetworkMessage { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.magic.consensus_encode(s)?; - CommandString(self.command()).consensus_encode(s)?; - CheckedData(match self.payload { + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.magic.consensus_encode(s)?; + len += CommandString(self.command()).consensus_encode(s)?; + len += CheckedData(match self.payload { NetworkMessage::Version(ref dat) => serialize(dat), NetworkMessage::Addr(ref dat) => serialize(dat), NetworkMessage::Inv(ref dat) => serialize(dat), @@ -200,7 +202,8 @@ impl Encodable for RawNetworkMessage { | NetworkMessage::SendHeaders | NetworkMessage::MemPool | NetworkMessage::GetAddr => vec![], - }).consensus_encode(s) + }).consensus_encode(s)?; + Ok(len) } } diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index b9f76b3b..c74c0543 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -103,15 +103,15 @@ impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); impl Encodable for Inventory { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - match self.inv_type { + fn consensus_encode(&self, s: &mut S) -> Result { + let inv_len = match self.inv_type { InvType::Error => 0u32, InvType::Transaction => 1, InvType::Block => 2, InvType::WitnessBlock => 0x40000002, InvType::WitnessTransaction => 0x40000001 }.consensus_encode(s)?; - self.hash.consensus_encode(s) + Ok(inv_len + self.hash.consensus_encode(s)?) } } diff --git a/src/util/merkleblock.rs b/src/util/merkleblock.rs index 6ae1512e..9eb551e5 100644 --- a/src/util/merkleblock.rs +++ b/src/util/merkleblock.rs @@ -354,14 +354,14 @@ impl PartialMerkleTree { } impl Encodable for PartialMerkleTree { - fn consensus_encode(&self, s: &mut S) -> Result<(), Error> { - self.num_transactions.consensus_encode(s)?; - self.hashes.consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let ret = self.num_transactions.consensus_encode(s)? + + self.hashes.consensus_encode(s)?; let mut bytes: Vec = vec![0; (self.bits.len() + 7) / 8]; for p in 0..self.bits.len() { bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8; } - bytes.consensus_encode(s) + Ok(ret + bytes.consensus_encode(s)?) } } @@ -472,9 +472,8 @@ impl MerkleBlock { } impl Encodable for MerkleBlock { - fn consensus_encode(&self, s: &mut S) -> Result<(), Error> { - self.header.consensus_encode(s)?; - self.txn.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + Ok(self.header.consensus_encode(s)? + self.txn.consensus_encode(s)?) } } diff --git a/src/util/psbt/macros.rs b/src/util/psbt/macros.rs index 50363f4b..5e652c54 100644 --- a/src/util/psbt/macros.rs +++ b/src/util/psbt/macros.rs @@ -55,12 +55,13 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_consensus_encoding { ($thing:ty) => { impl ::consensus::Encodable for $thing { - fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; for pair in ::util::psbt::Map::get_pairs(self)? { - ::consensus::Encodable::consensus_encode(&pair, s)? + len += ::consensus::Encodable::consensus_encode(&pair, s)?; } - ::consensus::Encodable::consensus_encode(&0x00_u8, s) + Ok(len + ::consensus::Encodable::consensus_encode(&0x00_u8, s)?) } } }; diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index e3299d09..088192bc 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -89,22 +89,23 @@ impl PartiallySignedTransaction { } impl Encodable for PartiallySignedTransaction { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - b"psbt".consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += b"psbt".consensus_encode(s)?; - 0xff_u8.consensus_encode(s)?; + len += 0xff_u8.consensus_encode(s)?; - self.global.consensus_encode(s)?; + len += self.global.consensus_encode(s)?; for i in &self.inputs { - i.consensus_encode(s)?; + len += i.consensus_encode(s)?; } for i in &self.outputs { - i.consensus_encode(s)?; + len += i.consensus_encode(s)?; } - Ok(()) + Ok(len) } } diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 1753cf1b..880b437f 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -81,23 +81,24 @@ impl Decodable for Key { } impl Encodable for Key { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - VarInt((self.key.len() + 1) as u64).consensus_encode(s)?; + fn consensus_encode(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt((self.key.len() + 1) as u64).consensus_encode(s)?; - self.type_value.consensus_encode(s)?; + len += self.type_value.consensus_encode(s)?; for key in &self.key { - key.consensus_encode(s)? + len += key.consensus_encode(s)? } - Ok(()) + Ok(len) } } impl Encodable for Pair { - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { - self.key.consensus_encode(s)?; - self.value.consensus_encode(s) + fn consensus_encode(&self, s: &mut S) -> Result { + let len = self.key.consensus_encode(s)?; + Ok(len + self.value.consensus_encode(s)?) } } diff --git a/src/util/uint.rs b/src/util/uint.rs index 42abdbfa..de98411f 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -338,10 +338,13 @@ macro_rules! construct_uint { impl ::consensus::Encodable for $name { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> { + fn consensus_encode(&self, s: &mut S) -> Result { let &$name(ref data) = self; - for word in data.iter() { word.consensus_encode(s)?; } - Ok(()) + let mut len = 0; + for word in data.iter() { + len += word.consensus_encode(s)?; + } + Ok(len) } }