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.
This commit is contained in:
parent
cf5503af74
commit
9c754ca4de
|
@ -27,6 +27,7 @@ use crate::consensus::encode::MAX_VEC_SIZE;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use io::Read as _;
|
||||||
use core::{fmt, default::Default};
|
use core::{fmt, default::Default};
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
|
|
||||||
|
@ -1092,20 +1093,20 @@ impl serde::Serialize for Script {
|
||||||
|
|
||||||
impl Encodable for Script {
|
impl Encodable for Script {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
self.0.consensus_encode(s)
|
self.0.consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Script {
|
impl Decodable for Script {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(Script(Decodable::consensus_decode_from_finite_reader(d)?))
|
Ok(Script(Decodable::consensus_decode_from_finite_reader(r)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(r.take(MAX_VEC_SIZE as u64).by_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use io::Read as _;
|
||||||
use core::{fmt, str, default::Default};
|
use core::{fmt, str, default::Default};
|
||||||
|
|
||||||
use crate::hashes::{self, Hash, sha256d};
|
use crate::hashes::{self, Hash, sha256d};
|
||||||
|
@ -653,50 +654,50 @@ impl Transaction {
|
||||||
impl_consensus_encoding!(TxOut, value, script_pubkey);
|
impl_consensus_encoding!(TxOut, value, script_pubkey);
|
||||||
|
|
||||||
impl Encodable for OutPoint {
|
impl Encodable for OutPoint {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let len = self.txid.consensus_encode(&mut s)?;
|
let len = self.txid.consensus_encode(w)?;
|
||||||
Ok(len + self.vout.consensus_encode(s)?)
|
Ok(len + self.vout.consensus_encode(w)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Decodable for OutPoint {
|
impl Decodable for OutPoint {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(OutPoint {
|
Ok(OutPoint {
|
||||||
txid: Decodable::consensus_decode(&mut d)?,
|
txid: Decodable::consensus_decode(r)?,
|
||||||
vout: Decodable::consensus_decode(d)?,
|
vout: Decodable::consensus_decode(r)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for TxIn {
|
impl Encodable for TxIn {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
len += self.previous_output.consensus_encode(&mut s)?;
|
len += self.previous_output.consensus_encode(w)?;
|
||||||
len += self.script_sig.consensus_encode(&mut s)?;
|
len += self.script_sig.consensus_encode(w)?;
|
||||||
len += self.sequence.consensus_encode(s)?;
|
len += self.sequence.consensus_encode(w)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Decodable for TxIn {
|
impl Decodable for TxIn {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(TxIn {
|
Ok(TxIn {
|
||||||
previous_output: Decodable::consensus_decode_from_finite_reader(&mut d)?,
|
previous_output: Decodable::consensus_decode_from_finite_reader(r)?,
|
||||||
script_sig: Decodable::consensus_decode_from_finite_reader(&mut d)?,
|
script_sig: Decodable::consensus_decode_from_finite_reader(r)?,
|
||||||
sequence: Decodable::consensus_decode_from_finite_reader(d)?,
|
sequence: Decodable::consensus_decode_from_finite_reader(r)?,
|
||||||
witness: Witness::default(),
|
witness: Witness::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(r.take(MAX_VEC_SIZE as u64).by_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for Transaction {
|
impl Encodable for Transaction {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
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
|
// To avoid serialization ambiguity, no inputs means we use BIP141 serialization (see
|
||||||
// `Transaction` docs for full explanation).
|
// `Transaction` docs for full explanation).
|
||||||
let mut have_witness = self.input.is_empty();
|
let mut have_witness = self.input.is_empty();
|
||||||
|
@ -707,36 +708,36 @@ impl Encodable for Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !have_witness {
|
if !have_witness {
|
||||||
len += self.input.consensus_encode(&mut s)?;
|
len += self.input.consensus_encode(w)?;
|
||||||
len += self.output.consensus_encode(&mut s)?;
|
len += self.output.consensus_encode(w)?;
|
||||||
} else {
|
} else {
|
||||||
len += 0u8.consensus_encode(&mut s)?;
|
len += 0u8.consensus_encode(w)?;
|
||||||
len += 1u8.consensus_encode(&mut s)?;
|
len += 1u8.consensus_encode(w)?;
|
||||||
len += self.input.consensus_encode(&mut s)?;
|
len += self.input.consensus_encode(w)?;
|
||||||
len += self.output.consensus_encode(&mut s)?;
|
len += self.output.consensus_encode(w)?;
|
||||||
for input in &self.input {
|
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)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Transaction {
|
impl Decodable for Transaction {
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let version = i32::consensus_decode_from_finite_reader(&mut d)?;
|
let version = i32::consensus_decode_from_finite_reader(r)?;
|
||||||
let input = Vec::<TxIn>::consensus_decode_from_finite_reader(&mut d)?;
|
let input = Vec::<TxIn>::consensus_decode_from_finite_reader(r)?;
|
||||||
// segwit
|
// segwit
|
||||||
if input.is_empty() {
|
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 {
|
match segwit_flag {
|
||||||
// BIP144 input witnesses
|
// BIP144 input witnesses
|
||||||
1 => {
|
1 => {
|
||||||
let mut input = Vec::<TxIn>::consensus_decode_from_finite_reader(&mut d)?;
|
let mut input = Vec::<TxIn>::consensus_decode_from_finite_reader(r)?;
|
||||||
let output = Vec::<TxOut>::consensus_decode_from_finite_reader(&mut d)?;
|
let output = Vec::<TxOut>::consensus_decode_from_finite_reader(r)?;
|
||||||
for txin in input.iter_mut() {
|
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()) {
|
if !input.is_empty() && input.iter().all(|input| input.witness.is_empty()) {
|
||||||
Err(encode::Error::ParseFailed("witness flag set but no witnesses present"))
|
Err(encode::Error::ParseFailed("witness flag set but no witnesses present"))
|
||||||
|
@ -745,7 +746,7 @@ impl Decodable for Transaction {
|
||||||
version,
|
version,
|
||||||
input,
|
input,
|
||||||
output,
|
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 {
|
Ok(Transaction {
|
||||||
version,
|
version,
|
||||||
input,
|
input,
|
||||||
output: Decodable::consensus_decode_from_finite_reader(&mut d)?,
|
output: Decodable::consensus_decode_from_finite_reader(r)?,
|
||||||
lock_time: Decodable::consensus_decode_from_finite_reader(d)?,
|
lock_time: Decodable::consensus_decode_from_finite_reader(r)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,8 @@ pub struct Iter<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Witness {
|
impl Decodable for Witness {
|
||||||
fn consensus_decode<D: Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
let witness_elements = VarInt::consensus_decode(&mut d)?.0 as usize;
|
let witness_elements = VarInt::consensus_decode(r)?.0 as usize;
|
||||||
if witness_elements == 0 {
|
if witness_elements == 0 {
|
||||||
Ok(Witness::default())
|
Ok(Witness::default())
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,7 +65,7 @@ impl Decodable for Witness {
|
||||||
for _ in 0..witness_elements {
|
for _ in 0..witness_elements {
|
||||||
second_to_last = last;
|
second_to_last = last;
|
||||||
last = cursor;
|
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_varint_len = element_size_varint.len();
|
||||||
let element_size = element_size_varint.0 as usize;
|
let element_size = element_size_varint.0 as usize;
|
||||||
let required_len = cursor
|
let required_len = cursor
|
||||||
|
@ -89,9 +89,9 @@ impl Decodable for Witness {
|
||||||
|
|
||||||
resize_if_needed(&mut content, required_len);
|
resize_if_needed(&mut content, required_len);
|
||||||
element_size_varint
|
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;
|
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;
|
cursor += element_size;
|
||||||
}
|
}
|
||||||
content.truncate(cursor);
|
content.truncate(cursor);
|
||||||
|
@ -116,10 +116,10 @@ fn resize_if_needed(vec: &mut Vec<u8>, required_len: usize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for Witness {
|
impl Encodable for Witness {
|
||||||
fn consensus_encode<W: Write>(&self, mut writer: W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let len = VarInt(self.witness_elements as u64);
|
let len = VarInt(self.witness_elements as u64);
|
||||||
len.consensus_encode(&mut writer)?;
|
len.consensus_encode(w)?;
|
||||||
writer.emit_slice(&self.content[..])?;
|
w.emit_slice(&self.content[..])?;
|
||||||
Ok(self.content.len() + len.len())
|
Ok(self.content.len() + len.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ impl Witness {
|
||||||
last = cursor;
|
last = cursor;
|
||||||
let el_len_varint = VarInt(el.len() as u64);
|
let el_len_varint = VarInt(el.len() as u64);
|
||||||
el_len_varint
|
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");
|
.expect("writers on vec don't errors, space granted by content_size");
|
||||||
cursor += el_len_varint.len();
|
cursor += el_len_varint.len();
|
||||||
content[cursor..cursor + el.len()].copy_from_slice(&el);
|
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);
|
.resize(current_content_len + element_len_varint.len() + new_element.len(), 0);
|
||||||
let end_varint = current_content_len + element_len_varint.len();
|
let end_varint = current_content_len + element_len_varint.len();
|
||||||
element_len_varint
|
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");
|
.expect("writers on vec don't error, space granted through previous resize");
|
||||||
self.content[end_varint..].copy_from_slice(new_element);
|
self.content[end_varint..].copy_from_slice(new_element);
|
||||||
}
|
}
|
||||||
|
@ -228,7 +228,7 @@ impl Witness {
|
||||||
|
|
||||||
|
|
||||||
fn element_at(&self, index: usize) -> Option<&[u8]> {
|
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();
|
let start = index + varint.len();
|
||||||
Some(&self.content[start..start + varint.0 as usize])
|
Some(&self.content[start..start + varint.0 as usize])
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ impl<'a> Iterator for Iter<'a> {
|
||||||
type Item = &'a [u8];
|
type Item = &'a [u8];
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
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
|
self.inner.nth(varint.len() - 1)?; // VarInt::len returns at least 1
|
||||||
let len = varint.0 as usize;
|
let len = varint.0 as usize;
|
||||||
let slice = &self.inner.as_slice()[..len];
|
let slice = &self.inner.as_slice()[..len];
|
||||||
|
|
|
@ -315,7 +315,7 @@ pub trait Encodable {
|
||||||
/// Returns the number of bytes written on success.
|
/// Returns the number of bytes written on success.
|
||||||
///
|
///
|
||||||
/// The only errors returned are errors propagated from the writer.
|
/// The only errors returned are errors propagated from the writer.
|
||||||
fn consensus_encode<W: io::Write>(&self, writer: W) -> Result<usize, io::Error>;
|
fn consensus_encode<W: io::Write>(&self, writer: &mut W) -> Result<usize, io::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data which can be encoded in a consensus-consistent way
|
/// 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
|
/// 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
|
/// `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.
|
/// `Take` wrappers. Failure to do so might result only in a tiny performance hit.
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(reader: &mut R) -> Result<Self, Error> {
|
||||||
// This method is always strictly less general than, `consensus_decode`,
|
// This method is always strictly less general than, `consensus_decode`,
|
||||||
// so it's safe and make sense to default to just calling it.
|
// so it's safe and make sense to default to just calling it.
|
||||||
// This way most types, that don't care about protecting against
|
// This way most types, that don't care about protecting against
|
||||||
// resource exhaustion due to malicious input, can just ignore it.
|
// 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
|
/// Decode an object with a well-defined format
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error>;
|
fn consensus_decode<R: io::Read>(reader: &mut R) -> Result<Self, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A variable-length unsigned integer
|
/// A variable-length unsigned integer
|
||||||
|
@ -378,14 +378,14 @@ macro_rules! impl_int_encodable {
|
||||||
($ty:ident, $meth_dec:ident, $meth_enc:ident) => {
|
($ty:ident, $meth_dec:ident, $meth_enc:ident) => {
|
||||||
impl Decodable for $ty {
|
impl Decodable for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
ReadExt::$meth_dec(&mut d)
|
ReadExt::$meth_dec(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Encodable for $ty {
|
impl Encodable for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: WriteExt>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: WriteExt>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
s.$meth_enc(*self)?;
|
w.$meth_enc(*self)?;
|
||||||
Ok(mem::size_of::<$ty>())
|
Ok(mem::size_of::<$ty>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,25 +419,25 @@ impl VarInt {
|
||||||
|
|
||||||
impl Encodable for VarInt {
|
impl Encodable for VarInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
0..=0xFC => {
|
0..=0xFC => {
|
||||||
(self.0 as u8).consensus_encode(s)?;
|
(self.0 as u8).consensus_encode(w)?;
|
||||||
Ok(1)
|
Ok(1)
|
||||||
},
|
},
|
||||||
0xFD..=0xFFFF => {
|
0xFD..=0xFFFF => {
|
||||||
s.emit_u8(0xFD)?;
|
w.emit_u8(0xFD)?;
|
||||||
(self.0 as u16).consensus_encode(s)?;
|
(self.0 as u16).consensus_encode(w)?;
|
||||||
Ok(3)
|
Ok(3)
|
||||||
},
|
},
|
||||||
0x10000..=0xFFFFFFFF => {
|
0x10000..=0xFFFFFFFF => {
|
||||||
s.emit_u8(0xFE)?;
|
w.emit_u8(0xFE)?;
|
||||||
(self.0 as u32).consensus_encode(s)?;
|
(self.0 as u32).consensus_encode(w)?;
|
||||||
Ok(5)
|
Ok(5)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
s.emit_u8(0xFF)?;
|
w.emit_u8(0xFF)?;
|
||||||
(self.0 as u64).consensus_encode(s)?;
|
(self.0 as u64).consensus_encode(w)?;
|
||||||
Ok(9)
|
Ok(9)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -446,11 +446,11 @@ impl Encodable for VarInt {
|
||||||
|
|
||||||
impl Decodable for VarInt {
|
impl Decodable for VarInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
let n = ReadExt::read_u8(&mut d)?;
|
let n = ReadExt::read_u8(r)?;
|
||||||
match n {
|
match n {
|
||||||
0xFF => {
|
0xFF => {
|
||||||
let x = ReadExt::read_u64(&mut d)?;
|
let x = ReadExt::read_u64(r)?;
|
||||||
if x < 0x100000000 {
|
if x < 0x100000000 {
|
||||||
Err(self::Error::NonMinimalVarInt)
|
Err(self::Error::NonMinimalVarInt)
|
||||||
} else {
|
} else {
|
||||||
|
@ -458,7 +458,7 @@ impl Decodable for VarInt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0xFE => {
|
0xFE => {
|
||||||
let x = ReadExt::read_u32(&mut d)?;
|
let x = ReadExt::read_u32(r)?;
|
||||||
if x < 0x10000 {
|
if x < 0x10000 {
|
||||||
Err(self::Error::NonMinimalVarInt)
|
Err(self::Error::NonMinimalVarInt)
|
||||||
} else {
|
} else {
|
||||||
|
@ -466,7 +466,7 @@ impl Decodable for VarInt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0xFD => {
|
0xFD => {
|
||||||
let x = ReadExt::read_u16(&mut d)?;
|
let x = ReadExt::read_u16(r)?;
|
||||||
if x < 0xFD {
|
if x < 0xFD {
|
||||||
Err(self::Error::NonMinimalVarInt)
|
Err(self::Error::NonMinimalVarInt)
|
||||||
} else {
|
} else {
|
||||||
|
@ -481,34 +481,34 @@ impl Decodable for VarInt {
|
||||||
// Booleans
|
// Booleans
|
||||||
impl Encodable for bool {
|
impl Encodable for bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: WriteExt>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: WriteExt>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
s.emit_bool(*self)?;
|
w.emit_bool(*self)?;
|
||||||
Ok(1)
|
Ok(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for bool {
|
impl Decodable for bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<bool, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<bool, Error> {
|
||||||
ReadExt::read_bool(&mut d)
|
ReadExt::read_bool(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strings
|
// Strings
|
||||||
impl Encodable for String {
|
impl Encodable for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let b = self.as_bytes();
|
let b = self.as_bytes();
|
||||||
let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?;
|
let vi_len = VarInt(b.len() as u64).consensus_encode(w)?;
|
||||||
s.emit_slice(b)?;
|
w.emit_slice(b)?;
|
||||||
Ok(vi_len + b.len())
|
Ok(vi_len + b.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for String {
|
impl Decodable for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<String, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<String, Error> {
|
||||||
String::from_utf8(Decodable::consensus_decode(d)?)
|
String::from_utf8(Decodable::consensus_decode(r)?)
|
||||||
.map_err(|_| self::Error::ParseFailed("String was not valid UTF8"))
|
.map_err(|_| self::Error::ParseFailed("String was not valid UTF8"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,18 +516,18 @@ impl Decodable for String {
|
||||||
// Cow<'static, str>
|
// Cow<'static, str>
|
||||||
impl Encodable for Cow<'static, str> {
|
impl Encodable for Cow<'static, str> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let b = self.as_bytes();
|
let b = self.as_bytes();
|
||||||
let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?;
|
let vi_len = VarInt(b.len() as u64).consensus_encode(w)?;
|
||||||
s.emit_slice(b)?;
|
w.emit_slice(b)?;
|
||||||
Ok(vi_len + b.len())
|
Ok(vi_len + b.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Cow<'static, str> {
|
impl Decodable for Cow<'static, str> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Cow<'static, str>, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Cow<'static, str>, Error> {
|
||||||
String::from_utf8(Decodable::consensus_decode(d)?)
|
String::from_utf8(Decodable::consensus_decode(r)?)
|
||||||
.map_err(|_| self::Error::ParseFailed("String was not valid UTF8"))
|
.map_err(|_| self::Error::ParseFailed("String was not valid UTF8"))
|
||||||
.map(Cow::Owned)
|
.map(Cow::Owned)
|
||||||
}
|
}
|
||||||
|
@ -539,17 +539,17 @@ macro_rules! impl_array {
|
||||||
( $size:expr ) => {
|
( $size:expr ) => {
|
||||||
impl Encodable for [u8; $size] {
|
impl Encodable for [u8; $size] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: WriteExt>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: WriteExt>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
s.emit_slice(&self[..])?;
|
w.emit_slice(&self[..])?;
|
||||||
Ok(self.len())
|
Ok(self.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for [u8; $size] {
|
impl Decodable for [u8; $size] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
let mut ret = [0; $size];
|
let mut ret = [0; $size];
|
||||||
d.read_slice(&mut ret)?;
|
r.read_slice(&mut ret)?;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -567,10 +567,10 @@ impl_array!(33);
|
||||||
|
|
||||||
impl Decodable for [u16; 8] {
|
impl Decodable for [u16; 8] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
let mut res = [0; 8];
|
let mut res = [0; 8];
|
||||||
for item in &mut res {
|
for item in &mut res {
|
||||||
*item = Decodable::consensus_decode(&mut d)?;
|
*item = Decodable::consensus_decode(r)?;
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -578,8 +578,8 @@ impl Decodable for [u16; 8] {
|
||||||
|
|
||||||
impl Encodable for [u16; 8] {
|
impl Encodable for [u16; 8] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
for c in self.iter() { c.consensus_encode(&mut s)?; }
|
for c in self.iter() { c.consensus_encode(w)?; }
|
||||||
Ok(16)
|
Ok(16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,11 +589,11 @@ macro_rules! impl_vec {
|
||||||
($type: ty) => {
|
($type: ty) => {
|
||||||
impl Encodable for Vec<$type> {
|
impl Encodable for Vec<$type> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
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() {
|
for c in self.iter() {
|
||||||
len += c.consensus_encode(&mut s)?;
|
len += c.consensus_encode(w)?;
|
||||||
}
|
}
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
|
@ -601,8 +601,8 @@ macro_rules! impl_vec {
|
||||||
|
|
||||||
impl Decodable for Vec<$type> {
|
impl Decodable for Vec<$type> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
let len = VarInt::consensus_decode_from_finite_reader(&mut d)?.0;
|
let len = VarInt::consensus_decode_from_finite_reader(r)?.0;
|
||||||
// Do not allocate upfront more items than if the sequnce of type
|
// Do not allocate upfront more items than if the sequnce of type
|
||||||
// occupied roughly quarter a block. This should never be the case
|
// occupied roughly quarter a block. This should never be the case
|
||||||
// for normal data, but even if that's not true - `push` will just
|
// 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 max_capacity = MAX_VEC_SIZE / 4 / mem::size_of::<$type>();
|
||||||
let mut ret = Vec::with_capacity(core::cmp::min(len as usize, max_capacity));
|
let mut ret = Vec::with_capacity(core::cmp::min(len as usize, max_capacity));
|
||||||
for _ in 0..len {
|
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)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(d: &mut R) -> Result<Self, Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(&mut d.take(MAX_VEC_SIZE as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,41 +675,41 @@ fn read_bytes_from_finite_reader<D: io::Read>(mut d: D, mut opts: ReadBytesFromF
|
||||||
|
|
||||||
impl Encodable for Vec<u8> {
|
impl Encodable for Vec<u8> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
consensus_encode_with_size(self, s)
|
consensus_encode_with_size(self, w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Vec<u8> {
|
impl Decodable for Vec<u8> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
let len = VarInt::consensus_decode(&mut d)?.0 as usize;
|
let len = VarInt::consensus_decode(r)?.0 as usize;
|
||||||
// most real-world vec of bytes data, wouldn't be larger than 128KiB
|
// 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]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(&mut r.take(MAX_VEC_SIZE as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for Box<[u8]> {
|
impl Encodable for Box<[u8]> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
consensus_encode_with_size(self, s)
|
consensus_encode_with_size(self, w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Box<[u8]> {
|
impl Decodable for Box<[u8]> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
<Vec<u8>>::consensus_decode_from_finite_reader(d).map(From::from)
|
<Vec<u8>>::consensus_decode_from_finite_reader(r).map(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64))
|
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
|
// Checked data
|
||||||
impl Encodable for CheckedData {
|
impl Encodable for CheckedData {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
(self.0.len() as u32).consensus_encode(&mut s)?;
|
(self.0.len() as u32).consensus_encode(w)?;
|
||||||
sha2_checksum(&self.0).consensus_encode(&mut s)?;
|
sha2_checksum(&self.0).consensus_encode(w)?;
|
||||||
s.emit_slice(&self.0)?;
|
w.emit_slice(&self.0)?;
|
||||||
Ok(8 + self.0.len())
|
Ok(8 + self.0.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for CheckedData {
|
impl Decodable for CheckedData {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
let len = u32::consensus_decode_from_finite_reader(&mut d)? as usize;
|
let len = u32::consensus_decode_from_finite_reader(r)? as usize;
|
||||||
|
|
||||||
let checksum = <[u8; 4]>::consensus_decode_from_finite_reader(&mut d)?;
|
let checksum = <[u8; 4]>::consensus_decode_from_finite_reader(r)?;
|
||||||
let ret = read_bytes_from_finite_reader(d, ReadBytesFromFiniteReaderOpts { len, chunk_size: MAX_VEC_SIZE })?;
|
let ret = read_bytes_from_finite_reader(r, ReadBytesFromFiniteReaderOpts { len, chunk_size: MAX_VEC_SIZE })?;
|
||||||
let expected_checksum = sha2_checksum(&ret);
|
let expected_checksum = sha2_checksum(&ret);
|
||||||
if expected_checksum != checksum {
|
if expected_checksum != checksum {
|
||||||
Err(self::Error::InvalidChecksum {
|
Err(self::Error::InvalidChecksum {
|
||||||
|
@ -749,33 +749,33 @@ impl Decodable for CheckedData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(d: &mut R) -> Result<Self, Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(&mut d.take(MAX_VEC_SIZE as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// References
|
// References
|
||||||
impl<'a, T: Encodable> Encodable for &'a T {
|
impl<'a, T: Encodable> Encodable for &'a T {
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
(&**self).consensus_encode(s)
|
(&**self).consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Encodable> Encodable for &'a mut T {
|
impl<'a, T: Encodable> Encodable for &'a mut T {
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
(&**self).consensus_encode(s)
|
(&**self).consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Encodable> Encodable for rc::Rc<T> {
|
impl<T: Encodable> Encodable for rc::Rc<T> {
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
(&**self).consensus_encode(s)
|
(&**self).consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Encodable> Encodable for sync::Arc<T> {
|
impl<T: Encodable> Encodable for sync::Arc<T> {
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
(&**self).consensus_encode(s)
|
(&**self).consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,13 +785,13 @@ macro_rules! tuple_encode {
|
||||||
impl <$($x: Encodable),*> Encodable for ($($x),*) {
|
impl <$($x: Encodable),*> Encodable for ($($x),*) {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn consensus_encode<S: io::Write>(
|
fn consensus_encode<W: io::Write>(
|
||||||
&self,
|
&self,
|
||||||
mut s: S,
|
w: &mut W,
|
||||||
) -> Result<usize, io::Error> {
|
) -> Result<usize, io::Error> {
|
||||||
let &($(ref $x),*) = self;
|
let &($(ref $x),*) = self;
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
$(len += $x.consensus_encode(&mut s)?;)*
|
$(len += $x.consensus_encode(w)?;)*
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -799,8 +799,8 @@ macro_rules! tuple_encode {
|
||||||
impl<$($x: Decodable),*> Decodable for ($($x),*) {
|
impl<$($x: Decodable),*> Decodable for ($($x),*) {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
Ok(($({let $x = Decodable::consensus_decode(&mut d)?; $x }),*))
|
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);
|
tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7);
|
||||||
|
|
||||||
impl Encodable for sha256d::Hash {
|
impl Encodable for sha256d::Hash {
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
self.into_inner().consensus_encode(s)
|
self.into_inner().consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for sha256d::Hash {
|
impl Decodable for sha256d::Hash {
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
Ok(Self::from_inner(<<Self as Hash>::Inner>::consensus_decode(d)?))
|
Ok(Self::from_inner(<<Self as Hash>::Inner>::consensus_decode(r)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for sha256::Hash {
|
impl Encodable for sha256::Hash {
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
self.into_inner().consensus_encode(s)
|
self.into_inner().consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for sha256::Hash {
|
impl Decodable for sha256::Hash {
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
Ok(Self::from_inner(<<Self as Hash>::Inner>::consensus_decode(d)?))
|
Ok(Self::from_inner(<<Self as Hash>::Inner>::consensus_decode(r)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for TapLeafHash {
|
impl Encodable for TapLeafHash {
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
self.into_inner().consensus_encode(s)
|
self.into_inner().consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for TapLeafHash {
|
impl Decodable for TapLeafHash {
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, Error> {
|
||||||
Ok(Self::from_inner(<<Self as Hash>::Inner>::consensus_decode(d)?))
|
Ok(Self::from_inner(<<Self as Hash>::Inner>::consensus_decode(r)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,15 @@ use crate::hashes::{Hash, sha256, sha256d, hash160, hash_newtype};
|
||||||
macro_rules! impl_hashencode {
|
macro_rules! impl_hashencode {
|
||||||
($hashtype:ident) => {
|
($hashtype:ident) => {
|
||||||
impl $crate::consensus::Encodable for $hashtype {
|
impl $crate::consensus::Encodable for $hashtype {
|
||||||
fn consensus_encode<S: $crate::io::Write>(&self, s: S) -> Result<usize, $crate::io::Error> {
|
fn consensus_encode<W: $crate::io::Write>(&self, w: &mut W) -> Result<usize, $crate::io::Error> {
|
||||||
self.0.consensus_encode(s)
|
self.0.consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $crate::consensus::Decodable for $hashtype {
|
impl $crate::consensus::Decodable for $hashtype {
|
||||||
fn consensus_decode<D: $crate::io::Read>(d: D) -> Result<Self, $crate::consensus::encode::Error> {
|
fn consensus_decode<R: $crate::io::Read>(r: &mut R) -> Result<Self, $crate::consensus::encode::Error> {
|
||||||
use $crate::hashes::Hash;
|
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)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,12 @@ macro_rules! impl_consensus_encoding {
|
||||||
($thing:ident, $($field:ident),+) => (
|
($thing:ident, $($field:ident),+) => (
|
||||||
impl $crate::consensus::Encodable for $thing {
|
impl $crate::consensus::Encodable for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: $crate::io::Write>(
|
fn consensus_encode<R: $crate::io::Write>(
|
||||||
&self,
|
&self,
|
||||||
mut s: S,
|
r: &mut R,
|
||||||
) -> Result<usize, $crate::io::Error> {
|
) -> Result<usize, $crate::io::Error> {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
$(len += self.$field.consensus_encode(&mut s)?;)+
|
$(len += self.$field.consensus_encode(r)?;)+
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,21 +34,22 @@ macro_rules! impl_consensus_encoding {
|
||||||
impl $crate::consensus::Decodable for $thing {
|
impl $crate::consensus::Decodable for $thing {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: $crate::io::Read>(
|
fn consensus_decode_from_finite_reader<R: $crate::io::Read>(
|
||||||
mut d: D,
|
r: &mut R,
|
||||||
) -> Result<$thing, $crate::consensus::encode::Error> {
|
) -> Result<$thing, $crate::consensus::encode::Error> {
|
||||||
Ok($thing {
|
Ok($thing {
|
||||||
$($field: $crate::consensus::Decodable::consensus_decode_from_finite_reader(&mut d)?),+
|
$($field: $crate::consensus::Decodable::consensus_decode_from_finite_reader(r)?),+
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: $crate::io::Read>(
|
fn consensus_decode<R: $crate::io::Read>(
|
||||||
d: D,
|
r: &mut R,
|
||||||
) -> Result<$thing, $crate::consensus::encode::Error> {
|
) -> 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 {
|
Ok($thing {
|
||||||
$($field: $crate::consensus::Decodable::consensus_decode(&mut d)?),+
|
$($field: $crate::consensus::Decodable::consensus_decode(r.by_ref())?),+
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,15 +69,15 @@ impl Address {
|
||||||
|
|
||||||
impl Encodable for Address {
|
impl Encodable for Address {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = self.services.consensus_encode(&mut s)?;
|
let mut len = self.services.consensus_encode(w)?;
|
||||||
|
|
||||||
for word in &self.address {
|
for word in &self.address {
|
||||||
s.write_all(&word.to_be_bytes())?;
|
w.write_all(&word.to_be_bytes())?;
|
||||||
len += 2;
|
len += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
s.write_all(&self.port.to_be_bytes())?;
|
w.write_all(&self.port.to_be_bytes())?;
|
||||||
len += 2;
|
len += 2;
|
||||||
|
|
||||||
Ok(len)
|
Ok(len)
|
||||||
|
@ -86,22 +86,22 @@ impl Encodable for Address {
|
||||||
|
|
||||||
impl Decodable for Address {
|
impl Decodable for Address {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(Address {
|
Ok(Address {
|
||||||
services: Decodable::consensus_decode(&mut d)?,
|
services: Decodable::consensus_decode(r)?,
|
||||||
address: read_be_address(&mut d)?,
|
address: read_be_address(r)?,
|
||||||
port: u16::swap_bytes(Decodable::consensus_decode(d)?)
|
port: u16::swap_bytes(Decodable::consensus_decode(r)?)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a big-endian address from reader.
|
/// Read a big-endian address from reader.
|
||||||
fn read_be_address<R: io::Read>(mut r: R) -> Result<[u16; 8], encode::Error> {
|
fn read_be_address<R: io::Read>(r: &mut R) -> Result<[u16; 8], encode::Error> {
|
||||||
let mut address = [0u16; 8];
|
let mut address = [0u16; 8];
|
||||||
let mut buf = [0u8; 2];
|
let mut buf = [0u8; 2];
|
||||||
|
|
||||||
for word in &mut address {
|
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)
|
*word = u16::from_be_bytes(buf)
|
||||||
}
|
}
|
||||||
Ok(address)
|
Ok(address)
|
||||||
|
@ -147,12 +147,12 @@ pub enum AddrV2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for AddrV2 {
|
impl Encodable for AddrV2 {
|
||||||
fn consensus_encode<W: io::Write>(&self, e: W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, e: &mut W) -> Result<usize, io::Error> {
|
||||||
fn encode_addr<W: io::Write>(mut e: W, network: u8, bytes: &[u8]) -> Result<usize, io::Error> {
|
fn encode_addr<W: io::Write>(w: &mut W, network: u8, bytes: &[u8]) -> Result<usize, io::Error> {
|
||||||
let len = network.consensus_encode(&mut e)?
|
let len = network.consensus_encode(w)?
|
||||||
+ VarInt(bytes.len() as u64).consensus_encode(&mut e)?
|
+ VarInt(bytes.len() as u64).consensus_encode(w)?
|
||||||
+ bytes.len();
|
+ bytes.len();
|
||||||
e.emit_slice(bytes)?;
|
w.emit_slice(bytes)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
Ok(match *self {
|
Ok(match *self {
|
||||||
|
@ -168,9 +168,9 @@ impl Encodable for AddrV2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for AddrV2 {
|
impl Decodable for AddrV2 {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let network_id = u8::consensus_decode(&mut d)?;
|
let network_id = u8::consensus_decode(r)?;
|
||||||
let len = VarInt::consensus_decode(&mut d)?.0;
|
let len = VarInt::consensus_decode(r)?.0;
|
||||||
if len > 512 {
|
if len > 512 {
|
||||||
return Err(encode::Error::ParseFailed("IP must be <= 512 bytes"));
|
return Err(encode::Error::ParseFailed("IP must be <= 512 bytes"));
|
||||||
}
|
}
|
||||||
|
@ -179,14 +179,14 @@ impl Decodable for AddrV2 {
|
||||||
if len != 4 {
|
if len != 4 {
|
||||||
return Err(encode::Error::ParseFailed("Invalid IPv4 address"));
|
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]))
|
AddrV2::Ipv4(Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3]))
|
||||||
},
|
},
|
||||||
2 => {
|
2 => {
|
||||||
if len != 16 {
|
if len != 16 {
|
||||||
return Err(encode::Error::ParseFailed("Invalid IPv6 address"));
|
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 {
|
if addr[0..3] == ONION {
|
||||||
return Err(encode::Error::ParseFailed("OnionCat address sent with IPv6 network id"));
|
return Err(encode::Error::ParseFailed("OnionCat address sent with IPv6 network id"));
|
||||||
}
|
}
|
||||||
|
@ -199,28 +199,28 @@ impl Decodable for AddrV2 {
|
||||||
if len != 10 {
|
if len != 10 {
|
||||||
return Err(encode::Error::ParseFailed("Invalid TorV2 address"));
|
return Err(encode::Error::ParseFailed("Invalid TorV2 address"));
|
||||||
}
|
}
|
||||||
let id = Decodable::consensus_decode(&mut d)?;
|
let id = Decodable::consensus_decode(r)?;
|
||||||
AddrV2::TorV2(id)
|
AddrV2::TorV2(id)
|
||||||
},
|
},
|
||||||
4 => {
|
4 => {
|
||||||
if len != 32 {
|
if len != 32 {
|
||||||
return Err(encode::Error::ParseFailed("Invalid TorV3 address"));
|
return Err(encode::Error::ParseFailed("Invalid TorV3 address"));
|
||||||
}
|
}
|
||||||
let pubkey = Decodable::consensus_decode(&mut d)?;
|
let pubkey = Decodable::consensus_decode(r)?;
|
||||||
AddrV2::TorV3(pubkey)
|
AddrV2::TorV3(pubkey)
|
||||||
},
|
},
|
||||||
5 => {
|
5 => {
|
||||||
if len != 32 {
|
if len != 32 {
|
||||||
return Err(encode::Error::ParseFailed("Invalid I2P address"));
|
return Err(encode::Error::ParseFailed("Invalid I2P address"));
|
||||||
}
|
}
|
||||||
let hash = Decodable::consensus_decode(&mut d)?;
|
let hash = Decodable::consensus_decode(r)?;
|
||||||
AddrV2::I2p(hash)
|
AddrV2::I2p(hash)
|
||||||
},
|
},
|
||||||
6 => {
|
6 => {
|
||||||
if len != 16 {
|
if len != 16 {
|
||||||
return Err(encode::Error::ParseFailed("Invalid CJDNS address"));
|
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
|
// check the first byte for the CJDNS marker
|
||||||
if addr[0] != u16::from_be_bytes([0xFC, 0x00]) {
|
if addr[0] != u16::from_be_bytes([0xFC, 0x00]) {
|
||||||
return Err(encode::Error::ParseFailed("Invalid CJDNS address"));
|
return Err(encode::Error::ParseFailed("Invalid CJDNS address"));
|
||||||
|
@ -230,7 +230,7 @@ impl Decodable for AddrV2 {
|
||||||
_ => {
|
_ => {
|
||||||
// len already checked above to be <= 512
|
// len already checked above to be <= 512
|
||||||
let mut addr = vec![0u8; len as usize];
|
let mut addr = vec![0u8; len as usize];
|
||||||
d.read_slice(&mut addr)?;
|
r.read_slice(&mut addr)?;
|
||||||
AddrV2::Unknown(network_id, addr)
|
AddrV2::Unknown(network_id, addr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -264,26 +264,26 @@ impl AddrV2Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for AddrV2Message {
|
impl Encodable for AddrV2Message {
|
||||||
fn consensus_encode<W: io::Write>(&self, mut e: W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
len += self.time.consensus_encode(&mut e)?;
|
len += self.time.consensus_encode(w)?;
|
||||||
len += VarInt(self.services.to_u64()).consensus_encode(&mut e)?;
|
len += VarInt(self.services.to_u64()).consensus_encode(w)?;
|
||||||
len += self.addr.consensus_encode(&mut e)?;
|
len += self.addr.consensus_encode(w)?;
|
||||||
|
|
||||||
// consensus_encode always encodes in LE, and we want to encode in BE.
|
// 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
|
//TODO `len += io::Write::write(w, &self.port.to_be_bytes())?;` when MSRV >= 1.32
|
||||||
len += self.port.swap_bytes().consensus_encode(e)?;
|
len += self.port.swap_bytes().consensus_encode(w)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for AddrV2Message {
|
impl Decodable for AddrV2Message {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(AddrV2Message {
|
Ok(AddrV2Message {
|
||||||
time: Decodable::consensus_decode(&mut d)?,
|
time: Decodable::consensus_decode(r)?,
|
||||||
services: ServiceFlags::from(VarInt::consensus_decode(&mut d)?.0),
|
services: ServiceFlags::from(VarInt::consensus_decode(r)?.0),
|
||||||
addr: Decodable::consensus_decode(&mut d)?,
|
addr: Decodable::consensus_decode(r)?,
|
||||||
port: u16::swap_bytes(Decodable::consensus_decode(d)?),
|
port: u16::swap_bytes(Decodable::consensus_decode(r)?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,15 +280,15 @@ impl ops::BitXorAssign for ServiceFlags {
|
||||||
|
|
||||||
impl Encodable for ServiceFlags {
|
impl Encodable for ServiceFlags {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
self.0.consensus_encode(&mut s)
|
self.0.consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for ServiceFlags {
|
impl Decodable for ServiceFlags {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(ServiceFlags(Decodable::consensus_decode(&mut d)?))
|
Ok(ServiceFlags(Decodable::consensus_decode(r)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ use crate::prelude::*;
|
||||||
use core::{fmt, iter};
|
use core::{fmt, iter};
|
||||||
|
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use io::Read as _;
|
||||||
use crate::blockdata::block;
|
use crate::blockdata::block;
|
||||||
use crate::blockdata::transaction;
|
use crate::blockdata::transaction;
|
||||||
use crate::network::address::{Address, AddrV2Message};
|
use crate::network::address::{Address, AddrV2Message};
|
||||||
|
@ -79,19 +80,19 @@ impl AsRef<str> for CommandString {
|
||||||
|
|
||||||
impl Encodable for CommandString {
|
impl Encodable for CommandString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut rawbytes = [0u8; 12];
|
let mut rawbytes = [0u8; 12];
|
||||||
let strbytes = self.0.as_bytes();
|
let strbytes = self.0.as_bytes();
|
||||||
debug_assert!(strbytes.len() <= 12);
|
debug_assert!(strbytes.len() <= 12);
|
||||||
rawbytes[..strbytes.len()].copy_from_slice(strbytes);
|
rawbytes[..strbytes.len()].copy_from_slice(strbytes);
|
||||||
rawbytes.consensus_encode(s)
|
rawbytes.consensus_encode(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for CommandString {
|
impl Decodable for CommandString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let rawbytes: [u8; 12] = Decodable::consensus_decode(d)?;
|
let rawbytes: [u8; 12] = Decodable::consensus_decode(r)?;
|
||||||
let rv = iter::FromIterator::from_iter(
|
let rv = iter::FromIterator::from_iter(
|
||||||
rawbytes
|
rawbytes
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -286,22 +287,22 @@ struct HeaderSerializationWrapper<'a>(&'a Vec<block::BlockHeader>);
|
||||||
|
|
||||||
impl<'a> Encodable for HeaderSerializationWrapper<'a> {
|
impl<'a> Encodable for HeaderSerializationWrapper<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
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() {
|
for header in self.0.iter() {
|
||||||
len += header.consensus_encode(&mut s)?;
|
len += header.consensus_encode(w)?;
|
||||||
len += 0u8.consensus_encode(&mut s)?;
|
len += 0u8.consensus_encode(w)?;
|
||||||
}
|
}
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for RawNetworkMessage {
|
impl Encodable for RawNetworkMessage {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
len += self.magic.consensus_encode(&mut s)?;
|
len += self.magic.consensus_encode(w)?;
|
||||||
len += self.command().consensus_encode(&mut s)?;
|
len += self.command().consensus_encode(w)?;
|
||||||
len += CheckedData(match self.payload {
|
len += CheckedData(match self.payload {
|
||||||
NetworkMessage::Version(ref dat) => serialize(dat),
|
NetworkMessage::Version(ref dat) => serialize(dat),
|
||||||
NetworkMessage::Addr(ref dat) => serialize(dat),
|
NetworkMessage::Addr(ref dat) => serialize(dat),
|
||||||
|
@ -336,7 +337,7 @@ impl Encodable for RawNetworkMessage {
|
||||||
| NetworkMessage::FilterClear
|
| NetworkMessage::FilterClear
|
||||||
| NetworkMessage::SendAddrV2 => vec![],
|
| NetworkMessage::SendAddrV2 => vec![],
|
||||||
NetworkMessage::Unknown { payload: ref data, .. } => serialize(data),
|
NetworkMessage::Unknown { payload: ref data, .. } => serialize(data),
|
||||||
}).consensus_encode(&mut s)?;
|
}).consensus_encode(w)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,14 +346,14 @@ struct HeaderDeserializationWrapper(Vec<block::BlockHeader>);
|
||||||
|
|
||||||
impl Decodable for HeaderDeserializationWrapper {
|
impl Decodable for HeaderDeserializationWrapper {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let len = VarInt::consensus_decode(&mut d)?.0;
|
let len = VarInt::consensus_decode(r)?.0;
|
||||||
// should be above usual number of items to avoid
|
// should be above usual number of items to avoid
|
||||||
// allocation
|
// allocation
|
||||||
let mut ret = Vec::with_capacity(core::cmp::min(1024 * 16, len as usize));
|
let mut ret = Vec::with_capacity(core::cmp::min(1024 * 16, len as usize));
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
ret.push(Decodable::consensus_decode(&mut d)?);
|
ret.push(Decodable::consensus_decode(r)?);
|
||||||
if u8::consensus_decode(&mut d)? != 0u8 {
|
if u8::consensus_decode(r)? != 0u8 {
|
||||||
return Err(encode::Error::ParseFailed("Headers message should not contain transactions"));
|
return Err(encode::Error::ParseFailed("Headers message should not contain transactions"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,16 +361,16 @@ impl Decodable for HeaderDeserializationWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_MSG_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for RawNetworkMessage {
|
impl Decodable for RawNetworkMessage {
|
||||||
fn consensus_decode_from_finite_reader<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let magic = Decodable::consensus_decode_from_finite_reader(&mut d)?;
|
let magic = Decodable::consensus_decode_from_finite_reader(r)?;
|
||||||
let cmd = CommandString::consensus_decode_from_finite_reader(&mut d)?;
|
let cmd = CommandString::consensus_decode_from_finite_reader(r)?;
|
||||||
let raw_payload = CheckedData::consensus_decode_from_finite_reader(&mut d)?.0;
|
let raw_payload = CheckedData::consensus_decode_from_finite_reader(r)?.0;
|
||||||
|
|
||||||
let mut mem_d = io::Cursor::new(raw_payload);
|
let mut mem_d = io::Cursor::new(raw_payload);
|
||||||
let payload = match &cmd.0[..] {
|
let payload = match &cmd.0[..] {
|
||||||
|
@ -419,8 +420,8 @@ impl Decodable for RawNetworkMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Self::consensus_decode_from_finite_reader(d.take(MAX_MSG_SIZE as u64))
|
Self::consensus_decode_from_finite_reader(r.take(MAX_MSG_SIZE as u64).by_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,10 +54,10 @@ pub enum Inventory {
|
||||||
|
|
||||||
impl Encodable for Inventory {
|
impl Encodable for Inventory {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
macro_rules! encode_inv {
|
macro_rules! encode_inv {
|
||||||
($code:expr, $item:expr) => {
|
($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 {
|
Ok(match *self {
|
||||||
|
@ -74,18 +74,18 @@ impl Encodable for Inventory {
|
||||||
|
|
||||||
impl Decodable for Inventory {
|
impl Decodable for Inventory {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let inv_type: u32 = Decodable::consensus_decode(&mut d)?;
|
let inv_type: u32 = Decodable::consensus_decode(r)?;
|
||||||
Ok(match inv_type {
|
Ok(match inv_type {
|
||||||
0 => Inventory::Error,
|
0 => Inventory::Error,
|
||||||
1 => Inventory::Transaction(Decodable::consensus_decode(&mut d)?),
|
1 => Inventory::Transaction(Decodable::consensus_decode(r)?),
|
||||||
2 => Inventory::Block(Decodable::consensus_decode(&mut d)?),
|
2 => Inventory::Block(Decodable::consensus_decode(r)?),
|
||||||
5 => Inventory::WTx(Decodable::consensus_decode(&mut d)?),
|
5 => Inventory::WTx(Decodable::consensus_decode(r)?),
|
||||||
0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(&mut d)?),
|
0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(r)?),
|
||||||
0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(&mut d)?),
|
0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(r)?),
|
||||||
tp => Inventory::Unknown {
|
tp => Inventory::Unknown {
|
||||||
inv_type: tp,
|
inv_type: tp,
|
||||||
hash: Decodable::consensus_decode(&mut d)?,
|
hash: Decodable::consensus_decode(r)?,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,8 @@ pub enum BloomFlags {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for BloomFlags {
|
impl Encodable for BloomFlags {
|
||||||
fn consensus_encode<W: io::Write>(&self, mut e: W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
e.write_all(&[match self {
|
w.write_all(&[match self {
|
||||||
BloomFlags::None => 0,
|
BloomFlags::None => 0,
|
||||||
BloomFlags::All => 1,
|
BloomFlags::All => 1,
|
||||||
BloomFlags::PubkeyOnly => 2,
|
BloomFlags::PubkeyOnly => 2,
|
||||||
|
@ -45,8 +45,8 @@ impl Encodable for BloomFlags {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for BloomFlags {
|
impl Decodable for BloomFlags {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(match d.read_u8()? {
|
Ok(match r.read_u8()? {
|
||||||
0 => BloomFlags::None,
|
0 => BloomFlags::None,
|
||||||
1 => BloomFlags::All,
|
1 => BloomFlags::All,
|
||||||
2 => BloomFlags::PubkeyOnly,
|
2 => BloomFlags::PubkeyOnly,
|
||||||
|
|
|
@ -106,15 +106,15 @@ pub enum RejectReason {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for RejectReason {
|
impl Encodable for RejectReason {
|
||||||
fn consensus_encode<W: io::Write>(&self, mut e: W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
e.write_all(&[*self as u8])?;
|
w.write_all(&[*self as u8])?;
|
||||||
Ok(1)
|
Ok(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for RejectReason {
|
impl Decodable for RejectReason {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(match d.read_u8()? {
|
Ok(match r.read_u8()? {
|
||||||
0x01 => RejectReason::Malformed,
|
0x01 => RejectReason::Malformed,
|
||||||
0x10 => RejectReason::Invalid,
|
0x10 => RejectReason::Invalid,
|
||||||
0x11 => RejectReason::Obsolete,
|
0x11 => RejectReason::Obsolete,
|
||||||
|
|
|
@ -355,23 +355,23 @@ impl PartialMerkleTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for PartialMerkleTree {
|
impl Encodable for PartialMerkleTree {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let ret = self.num_transactions.consensus_encode(&mut s)?
|
let ret = self.num_transactions.consensus_encode(w)?
|
||||||
+ self.hashes.consensus_encode(&mut s)?;
|
+ self.hashes.consensus_encode(w)?;
|
||||||
let mut bytes: Vec<u8> = vec![0; (self.bits.len() + 7) / 8];
|
let mut bytes: Vec<u8> = vec![0; (self.bits.len() + 7) / 8];
|
||||||
for p in 0..self.bits.len() {
|
for p in 0..self.bits.len() {
|
||||||
bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8;
|
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 {
|
impl Decodable for PartialMerkleTree {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let num_transactions: u32 = Decodable::consensus_decode(&mut d)?;
|
let num_transactions: u32 = Decodable::consensus_decode(r)?;
|
||||||
let hashes: Vec<TxMerkleNode> = Decodable::consensus_decode(&mut d)?;
|
let hashes: Vec<TxMerkleNode> = Decodable::consensus_decode(r)?;
|
||||||
|
|
||||||
let bytes: Vec<u8> = Decodable::consensus_decode(d)?;
|
let bytes: Vec<u8> = Decodable::consensus_decode(r)?;
|
||||||
let mut bits: Vec<bool> = vec![false; bytes.len() * 8];
|
let mut bits: Vec<bool> = vec![false; bytes.len() * 8];
|
||||||
|
|
||||||
for (p, bit) in bits.iter_mut().enumerate() {
|
for (p, bit) in bits.iter_mut().enumerate() {
|
||||||
|
@ -506,18 +506,18 @@ impl MerkleBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for MerkleBlock {
|
impl Encodable for MerkleBlock {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let len = self.header.consensus_encode(&mut s)?
|
let len = self.header.consensus_encode(w)?
|
||||||
+ self.txn.consensus_encode(s)?;
|
+ self.txn.consensus_encode(w)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for MerkleBlock {
|
impl Decodable for MerkleBlock {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(MerkleBlock {
|
Ok(MerkleBlock {
|
||||||
header: Decodable::consensus_decode(&mut d)?,
|
header: Decodable::consensus_decode(r)?,
|
||||||
txn: Decodable::consensus_decode(d)?,
|
txn: Decodable::consensus_decode(r)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,11 +55,11 @@ macro_rules! impl_psbt_serialize {
|
||||||
macro_rules! impl_psbtmap_consensus_encoding {
|
macro_rules! impl_psbtmap_consensus_encoding {
|
||||||
($thing:ty) => {
|
($thing:ty) => {
|
||||||
impl $crate::consensus::Encodable for $thing {
|
impl $crate::consensus::Encodable for $thing {
|
||||||
fn consensus_encode<S: $crate::io::Write>(
|
fn consensus_encode<W: $crate::io::Write>(
|
||||||
&self,
|
&self,
|
||||||
s: S,
|
w: &mut W,
|
||||||
) -> Result<usize, $crate::io::Error> {
|
) -> Result<usize, $crate::io::Error> {
|
||||||
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 {
|
macro_rules! impl_psbtmap_consensus_decoding {
|
||||||
($thing:ty) => {
|
($thing:ty) => {
|
||||||
impl $crate::consensus::Decodable for $thing {
|
impl $crate::consensus::Decodable for $thing {
|
||||||
fn consensus_decode<D: $crate::io::Read>(
|
fn consensus_decode<R: $crate::io::Read>(
|
||||||
mut d: D,
|
r: &mut R,
|
||||||
) -> Result<Self, $crate::consensus::encode::Error> {
|
) -> Result<Self, $crate::consensus::encode::Error> {
|
||||||
let mut rv: Self = ::core::default::Default::default();
|
let mut rv: Self = ::core::default::Default::default();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match $crate::consensus::Decodable::consensus_decode(&mut d) {
|
match $crate::consensus::Decodable::consensus_decode(r) {
|
||||||
Ok(pair) => rv.insert_pair(pair)?,
|
Ok(pair) => rv.insert_pair(pair)?,
|
||||||
Err($crate::consensus::encode::Error::Psbt($crate::util::psbt::Error::NoMorePairs)) => return Ok(rv),
|
Err($crate::consensus::encode::Error::Psbt($crate::util::psbt::Error::NoMorePairs)) => return Ok(rv),
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
|
|
|
@ -100,8 +100,8 @@ impl Map for PartiallySignedTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartiallySignedTransaction {
|
impl PartiallySignedTransaction {
|
||||||
pub(crate) fn consensus_decode_global<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
pub(crate) fn consensus_decode_global<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let mut d = d.take(MAX_VEC_SIZE as u64);
|
let mut r = r.take(MAX_VEC_SIZE as u64);
|
||||||
let mut tx: Option<Transaction> = None;
|
let mut tx: Option<Transaction> = None;
|
||||||
let mut version: Option<u32> = None;
|
let mut version: Option<u32> = None;
|
||||||
let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default();
|
let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default();
|
||||||
|
@ -109,7 +109,7 @@ impl PartiallySignedTransaction {
|
||||||
let mut proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = Default::default();
|
let mut proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = Default::default();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match raw::Pair::consensus_decode(&mut d) {
|
match raw::Pair::consensus_decode(&mut r) {
|
||||||
Ok(pair) => {
|
Ok(pair) => {
|
||||||
match pair.key.type_value {
|
match pair.key.type_value {
|
||||||
PSBT_GLOBAL_UNSIGNED_TX => {
|
PSBT_GLOBAL_UNSIGNED_TX => {
|
||||||
|
|
|
@ -32,12 +32,12 @@ pub(super) trait Map {
|
||||||
fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error>;
|
fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error>;
|
||||||
|
|
||||||
/// Encodes map data with bitcoin consensus encoding.
|
/// Encodes map data with bitcoin consensus encoding.
|
||||||
fn consensus_encode_map<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode_map<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
for pair in Map::get_pairs(self)? {
|
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)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,14 @@ use core::cmp;
|
||||||
|
|
||||||
use crate::blockdata::script::Script;
|
use crate::blockdata::script::Script;
|
||||||
use crate::blockdata::transaction::{ TxOut, Transaction};
|
use crate::blockdata::transaction::{ TxOut, Transaction};
|
||||||
use crate::consensus::{encode, Encodable, Decodable};
|
|
||||||
use crate::consensus::encode::MAX_VEC_SIZE;
|
use crate::consensus::encode::MAX_VEC_SIZE;
|
||||||
|
use crate::consensus::{encode, Encodable, Decodable};
|
||||||
pub use crate::util::sighash::Prevouts;
|
pub use crate::util::sighash::Prevouts;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::io;
|
use crate::io;
|
||||||
|
use io::Read as _;
|
||||||
mod error;
|
mod error;
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
|
|
||||||
|
@ -278,20 +279,20 @@ mod display_from_str {
|
||||||
pub use self::display_from_str::PsbtParseError;
|
pub use self::display_from_str::PsbtParseError;
|
||||||
|
|
||||||
impl Encodable for PartiallySignedTransaction {
|
impl Encodable for PartiallySignedTransaction {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
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 {
|
for i in &self.inputs {
|
||||||
len += i.consensus_encode(&mut s)?;
|
len += i.consensus_encode(w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in &self.outputs {
|
for i in &self.outputs {
|
||||||
len += i.consensus_encode(&mut s)?;
|
len += i.consensus_encode(w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(len)
|
Ok(len)
|
||||||
|
@ -299,19 +300,18 @@ impl Encodable for PartiallySignedTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for PartiallySignedTransaction {
|
impl Decodable for PartiallySignedTransaction {
|
||||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode_from_finite_reader<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let mut d = d.take(MAX_VEC_SIZE as u64);
|
let magic: [u8; 4] = Decodable::consensus_decode(r)?;
|
||||||
let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?;
|
|
||||||
|
|
||||||
if *b"psbt" != magic {
|
if *b"psbt" != magic {
|
||||||
return Err(Error::InvalidMagic.into());
|
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());
|
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()?;
|
global.unsigned_tx_checks()?;
|
||||||
|
|
||||||
let inputs: Vec<Input> = {
|
let inputs: Vec<Input> = {
|
||||||
|
@ -320,7 +320,7 @@ impl Decodable for PartiallySignedTransaction {
|
||||||
let mut inputs: Vec<Input> = Vec::with_capacity(inputs_len);
|
let mut inputs: Vec<Input> = Vec::with_capacity(inputs_len);
|
||||||
|
|
||||||
for _ in 0..inputs_len {
|
for _ in 0..inputs_len {
|
||||||
inputs.push(Decodable::consensus_decode(&mut d)?);
|
inputs.push(Decodable::consensus_decode(r)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
inputs
|
inputs
|
||||||
|
@ -332,7 +332,7 @@ impl Decodable for PartiallySignedTransaction {
|
||||||
let mut outputs: Vec<Output> = Vec::with_capacity(outputs_len);
|
let mut outputs: Vec<Output> = Vec::with_capacity(outputs_len);
|
||||||
|
|
||||||
for _ in 0..outputs_len {
|
for _ in 0..outputs_len {
|
||||||
outputs.push(Decodable::consensus_decode(&mut d)?);
|
outputs.push(Decodable::consensus_decode(r)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputs
|
outputs
|
||||||
|
@ -342,6 +342,11 @@ impl Decodable for PartiallySignedTransaction {
|
||||||
global.outputs = outputs;
|
global.outputs = outputs;
|
||||||
Ok(global)
|
Ok(global)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn consensus_decode<R: io::Read>(d: &mut R) -> Result<Self, encode::Error> {
|
||||||
|
Self::consensus_decode_from_finite_reader(d.take(MAX_VEC_SIZE as u64).by_ref())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -79,8 +79,8 @@ impl fmt::Display for Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Key {
|
impl Decodable for Key {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let VarInt(byte_size): VarInt = Decodable::consensus_decode(&mut d)?;
|
let VarInt(byte_size): VarInt = Decodable::consensus_decode(r)?;
|
||||||
|
|
||||||
if byte_size == 0 {
|
if byte_size == 0 {
|
||||||
return Err(Error::NoMorePairs.into());
|
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);
|
let mut key = Vec::with_capacity(key_byte_size as usize);
|
||||||
for _ in 0..key_byte_size {
|
for _ in 0..key_byte_size {
|
||||||
key.push(Decodable::consensus_decode(&mut d)?);
|
key.push(Decodable::consensus_decode(r)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Key { type_value, key })
|
Ok(Key { type_value, key })
|
||||||
|
@ -107,14 +107,14 @@ impl Decodable for Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for Key {
|
impl Encodable for Key {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = 0;
|
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 {
|
for key in &self.key {
|
||||||
len += key.consensus_encode(&mut s)?
|
len += key.consensus_encode(w)?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(len)
|
Ok(len)
|
||||||
|
@ -122,36 +122,36 @@ impl Encodable for Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for Pair {
|
impl Encodable for Pair {
|
||||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let len = self.key.consensus_encode(&mut s)?;
|
let len = self.key.consensus_encode(w)?;
|
||||||
Ok(len + self.value.consensus_encode(s)?)
|
Ok(len + self.value.consensus_encode(w)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decodable for Pair {
|
impl Decodable for Pair {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
Ok(Pair {
|
Ok(Pair {
|
||||||
key: Decodable::consensus_decode(&mut d)?,
|
key: Decodable::consensus_decode(r)?,
|
||||||
value: Decodable::consensus_decode(d)?,
|
value: Decodable::consensus_decode(r)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Subtype> Encodable for ProprietaryKey<Subtype> where Subtype: Copy + From<u8> + Into<u8> {
|
impl<Subtype> Encodable for ProprietaryKey<Subtype> where Subtype: Copy + From<u8> + Into<u8> {
|
||||||
fn consensus_encode<W: io::Write>(&self, mut e: W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
let mut len = self.prefix.consensus_encode(&mut e)? + 1;
|
let mut len = self.prefix.consensus_encode(w)? + 1;
|
||||||
e.emit_u8(self.subtype.into())?;
|
w.emit_u8(self.subtype.into())?;
|
||||||
e.write_all(&self.key)?;
|
w.write_all(&self.key)?;
|
||||||
len += self.key.len();
|
len += self.key.len();
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Subtype> Decodable for ProprietaryKey<Subtype> where Subtype: Copy + From<u8> + Into<u8> {
|
impl<Subtype> Decodable for ProprietaryKey<Subtype> where Subtype: Copy + From<u8> + Into<u8> {
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
fn consensus_decode<R: io::Read>(r: &mut R) -> Result<Self, encode::Error> {
|
||||||
let prefix = Vec::<u8>::consensus_decode(&mut d)?;
|
let prefix = Vec::<u8>::consensus_decode(r)?;
|
||||||
let subtype = Subtype::from(d.read_u8()?);
|
let subtype = Subtype::from(r.read_u8()?);
|
||||||
let key = read_to_end(d)?;
|
let key = read_to_end(r)?;
|
||||||
|
|
||||||
Ok(ProprietaryKey { prefix, subtype, key })
|
Ok(ProprietaryKey { prefix, subtype, key })
|
||||||
}
|
}
|
||||||
|
|
|
@ -794,8 +794,8 @@ impl<'a> Annex<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Encodable for Annex<'a> {
|
impl<'a> Encodable for Annex<'a> {
|
||||||
fn consensus_encode<W: io::Write>(&self, writer: W) -> Result<usize, io::Error> {
|
fn consensus_encode<W: io::Write>(&self, w: &mut W) -> Result<usize, io::Error> {
|
||||||
encode::consensus_encode_with_size(self.0, writer)
|
encode::consensus_encode_with_size(self.0, w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -419,27 +419,27 @@ macro_rules! construct_uint {
|
||||||
|
|
||||||
impl $crate::consensus::Encodable for $name {
|
impl $crate::consensus::Encodable for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode<S: $crate::io::Write>(
|
fn consensus_encode<W: $crate::io::Write>(
|
||||||
&self,
|
&self,
|
||||||
mut s: S,
|
w: &mut W,
|
||||||
) -> Result<usize, $crate::io::Error> {
|
) -> Result<usize, $crate::io::Error> {
|
||||||
let &$name(ref data) = self;
|
let &$name(ref data) = self;
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
for word in data.iter() {
|
for word in data.iter() {
|
||||||
len += word.consensus_encode(&mut s)?;
|
len += word.consensus_encode(w)?;
|
||||||
}
|
}
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $crate::consensus::Decodable for $name {
|
impl $crate::consensus::Decodable for $name {
|
||||||
fn consensus_decode<D: $crate::io::Read>(
|
fn consensus_decode<R: $crate::io::Read>(
|
||||||
mut d: D,
|
r: &mut R,
|
||||||
) -> Result<$name, $crate::consensus::encode::Error> {
|
) -> Result<$name, $crate::consensus::encode::Error> {
|
||||||
use $crate::consensus::Decodable;
|
use $crate::consensus::Decodable;
|
||||||
let mut ret: [u64; $n_words] = [0; $n_words];
|
let mut ret: [u64; $n_words] = [0; $n_words];
|
||||||
for i in 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))
|
Ok($name(ret))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue