Merge pull request #265 from apoelstra/2019-05-enc-dec-cleanup
clean up encoding/decoding traits
This commit is contained in:
commit
a041168205
|
@ -7,12 +7,12 @@ fn do_test(data: &[u8]) {
|
|||
Ok(mut tx) => {
|
||||
let ser = bitcoin::consensus::encode::serialize(&tx);
|
||||
assert_eq!(&ser[..], data);
|
||||
let len = ser.len() as u64;
|
||||
let len = ser.len();
|
||||
let calculated_weight = tx.get_weight();
|
||||
for input in &mut tx.input {
|
||||
input.witness = vec![];
|
||||
}
|
||||
let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len() as u64;
|
||||
let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len();
|
||||
// For 0-input transactions, `no_witness_len` will be incorrect because
|
||||
// we serialize as segwit even after "stripping the witnesses". We need
|
||||
// to drop two bytes (i.e. eight weight)
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use consensus::encode::{self, Decoder, Encoder};
|
||||
use consensus::encode::{Decodable, Encodable};
|
||||
|
||||
// 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.
|
||||
|
@ -715,20 +712,6 @@ impl From<u8> for All {
|
|||
|
||||
display_from_debug!(All);
|
||||
|
||||
impl<D: Decoder> Decodable<D> for All {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<All, encode::Error> {
|
||||
Ok(All::from(d.read_u8()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
@ -835,7 +818,6 @@ impl Ordinary {
|
|||
mod tests {
|
||||
use std::collections::HashSet;
|
||||
|
||||
use consensus::encode::{serialize, deserialize};
|
||||
use super::*;
|
||||
|
||||
macro_rules! roundtrip {
|
||||
|
@ -847,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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,12 @@
|
|||
//!
|
||||
|
||||
use std::default::Default;
|
||||
use std::{error, fmt};
|
||||
use std::{error, fmt, io};
|
||||
|
||||
#[cfg(feature = "serde")] use serde;
|
||||
|
||||
use blockdata::opcodes;
|
||||
use consensus::encode::{Decodable, Encodable};
|
||||
use consensus::encode::{self, Decoder, Encoder};
|
||||
use consensus::{encode, Decodable, Encodable};
|
||||
use bitcoin_hashes::{hash160, sha256, Hash};
|
||||
#[cfg(feature="bitcoinconsensus")] use bitcoinconsensus;
|
||||
#[cfg(feature="bitcoinconsensus")] use std::convert;
|
||||
|
@ -726,16 +725,19 @@ impl serde::Serialize for Script {
|
|||
}
|
||||
|
||||
// Network serialization
|
||||
impl<S: Encoder> Encodable<S> for Script {
|
||||
impl Encodable for Script {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
self.0.consensus_encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Script {
|
||||
impl Decodable for Script {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<Script, encode::Error> {
|
||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
||||
Ok(Script(Decodable::consensus_decode(d)?))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use std::default::Default;
|
||||
use std::fmt;
|
||||
use std::{fmt, io};
|
||||
#[cfg(feature="bitcoinconsensus")] use std::collections::HashMap;
|
||||
|
||||
use bitcoin_hashes::{self, sha256d, Hash};
|
||||
|
@ -34,8 +34,8 @@ use bitcoin_hashes::hex::FromHex;
|
|||
use util::hash::BitcoinHash;
|
||||
#[cfg(feature="bitcoinconsensus")] use blockdata::script;
|
||||
use blockdata::script::Script;
|
||||
use consensus::encode::{self, serialize, Encoder, Decoder};
|
||||
use consensus::encode::{Encodable, Decodable, VarInt};
|
||||
use consensus::{encode, serialize, Decodable, Encodable};
|
||||
use VarInt;
|
||||
|
||||
/// A reference to a transaction output
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||
|
@ -368,40 +368,40 @@ impl Transaction {
|
|||
/// witness, this is the non-witness consensus-serialized size multiplied by 3 plus the
|
||||
/// with-witness consensus-serialized size.
|
||||
#[inline]
|
||||
pub fn get_weight(&self) -> u64 {
|
||||
pub fn get_weight(&self) -> usize {
|
||||
let mut input_weight = 0;
|
||||
let mut inputs_with_witnesses = 0;
|
||||
for input in &self.input {
|
||||
input_weight += 4*(32 + 4 + 4 + // outpoint (32+4) + nSequence
|
||||
VarInt(input.script_sig.len() as u64).encoded_length() +
|
||||
input.script_sig.len() as u64);
|
||||
VarInt(input.script_sig.len() as u64).len() +
|
||||
input.script_sig.len());
|
||||
if !input.witness.is_empty() {
|
||||
inputs_with_witnesses += 1;
|
||||
input_weight += VarInt(input.witness.len() as u64).encoded_length();
|
||||
input_weight += VarInt(input.witness.len() as u64).len();
|
||||
for elem in &input.witness {
|
||||
input_weight += VarInt(elem.len() as u64).encoded_length() + elem.len() as u64;
|
||||
input_weight += VarInt(elem.len() as u64).len() + elem.len();
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut output_size = 0;
|
||||
for output in &self.output {
|
||||
output_size += 8 + // value
|
||||
VarInt(output.script_pubkey.len() as u64).encoded_length() +
|
||||
output.script_pubkey.len() as u64;
|
||||
VarInt(output.script_pubkey.len() as u64).len() +
|
||||
output.script_pubkey.len();
|
||||
}
|
||||
let non_input_size =
|
||||
// version:
|
||||
4 +
|
||||
// count varints:
|
||||
VarInt(self.input.len() as u64).encoded_length() +
|
||||
VarInt(self.output.len() as u64).encoded_length() +
|
||||
VarInt(self.input.len() as u64).len() +
|
||||
VarInt(self.output.len() as u64).len() +
|
||||
output_size +
|
||||
// lock_time
|
||||
4;
|
||||
if inputs_with_witnesses == 0 {
|
||||
non_input_size * 4 + input_weight
|
||||
} else {
|
||||
non_input_size * 4 + input_weight + self.input.len() as u64 - inputs_with_witnesses + 2
|
||||
non_input_size * 4 + input_weight + self.input.len() - inputs_with_witnesses + 2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,42 +439,54 @@ impl BitcoinHash for Transaction {
|
|||
|
||||
impl_consensus_encoding!(TxOut, value, script_pubkey);
|
||||
|
||||
impl<S: Encoder> Encodable<S> for OutPoint {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> {
|
||||
self.txid.consensus_encode(s)?;
|
||||
self.vout.consensus_encode(s)
|
||||
impl Encodable for OutPoint {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let len = self.txid.consensus_encode(&mut s)?;
|
||||
Ok(len + self.vout.consensus_encode(s)?)
|
||||
}
|
||||
}
|
||||
impl<D: Decoder> Decodable<D> for OutPoint {
|
||||
fn consensus_decode(d: &mut D) -> Result<OutPoint, encode::Error> {
|
||||
impl Decodable for OutPoint {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
Ok(OutPoint {
|
||||
txid: Decodable::consensus_decode(d)?,
|
||||
txid: Decodable::consensus_decode(&mut d)?,
|
||||
vout: Decodable::consensus_decode(d)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for TxIn {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> {
|
||||
self.previous_output.consensus_encode(s)?;
|
||||
self.script_sig.consensus_encode(s)?;
|
||||
self.sequence.consensus_encode(s)
|
||||
impl Encodable for TxIn {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let mut len = 0;
|
||||
len += self.previous_output.consensus_encode(&mut s)?;
|
||||
len += self.script_sig.consensus_encode(&mut s)?;
|
||||
len += self.sequence.consensus_encode(s)?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
impl<D: Decoder> Decodable<D> for TxIn {
|
||||
fn consensus_decode(d: &mut D) -> Result<TxIn, encode::Error> {
|
||||
impl Decodable for TxIn {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
Ok(TxIn {
|
||||
previous_output: Decodable::consensus_decode(d)?,
|
||||
script_sig: Decodable::consensus_decode(d)?,
|
||||
previous_output: Decodable::consensus_decode(&mut d)?,
|
||||
script_sig: Decodable::consensus_decode(&mut d)?,
|
||||
sequence: Decodable::consensus_decode(d)?,
|
||||
witness: vec![],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Transaction {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result <(), encode::Error> {
|
||||
self.version.consensus_encode(s)?;
|
||||
impl Encodable for Transaction {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let mut len = 0;
|
||||
len += self.version.consensus_encode(&mut s)?;
|
||||
let mut have_witness = self.input.is_empty();
|
||||
for input in &self.input {
|
||||
if !input.witness.is_empty() {
|
||||
|
@ -483,35 +495,36 @@ impl<S: Encoder> Encodable<S> for Transaction {
|
|||
}
|
||||
}
|
||||
if !have_witness {
|
||||
self.input.consensus_encode(s)?;
|
||||
self.output.consensus_encode(s)?;
|
||||
len += self.input.consensus_encode(&mut s)?;
|
||||
len += self.output.consensus_encode(&mut s)?;
|
||||
} else {
|
||||
0u8.consensus_encode(s)?;
|
||||
1u8.consensus_encode(s)?;
|
||||
self.input.consensus_encode(s)?;
|
||||
self.output.consensus_encode(s)?;
|
||||
len += 0u8.consensus_encode(&mut s)?;
|
||||
len += 1u8.consensus_encode(&mut s)?;
|
||||
len += self.input.consensus_encode(&mut s)?;
|
||||
len += self.output.consensus_encode(&mut s)?;
|
||||
for input in &self.input {
|
||||
input.witness.consensus_encode(s)?;
|
||||
len += input.witness.consensus_encode(&mut s)?;
|
||||
}
|
||||
}
|
||||
self.lock_time.consensus_encode(s)
|
||||
len += self.lock_time.consensus_encode(s)?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Transaction {
|
||||
fn consensus_decode(d: &mut D) -> Result<Transaction, encode::Error> {
|
||||
let version: u32 = Decodable::consensus_decode(d)?;
|
||||
let input: Vec<TxIn> = Decodable::consensus_decode(d)?;
|
||||
impl Decodable for Transaction {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let version = u32::consensus_decode(&mut d)?;
|
||||
let input = Vec::<TxIn>::consensus_decode(&mut d)?;
|
||||
// segwit
|
||||
if input.is_empty() {
|
||||
let segwit_flag: u8 = Decodable::consensus_decode(d)?;
|
||||
let segwit_flag = u8::consensus_decode(&mut d)?;
|
||||
match segwit_flag {
|
||||
// BIP144 input witnesses
|
||||
1 => {
|
||||
let mut input: Vec<TxIn> = Decodable::consensus_decode(d)?;
|
||||
let output: Vec<TxOut> = Decodable::consensus_decode(d)?;
|
||||
let mut input = Vec::<TxIn>::consensus_decode(&mut d)?;
|
||||
let output = Vec::<TxOut>::consensus_decode(&mut d)?;
|
||||
for txin in input.iter_mut() {
|
||||
txin.witness = Decodable::consensus_decode(d)?;
|
||||
txin.witness = Decodable::consensus_decode(&mut d)?;
|
||||
}
|
||||
if !input.is_empty() && input.iter().all(|input| input.witness.is_empty()) {
|
||||
Err(encode::Error::ParseFailed("witness flag set but no witnesses present"))
|
||||
|
@ -534,7 +547,7 @@ impl<D: Decoder> Decodable<D> for Transaction {
|
|||
Ok(Transaction {
|
||||
version: version,
|
||||
input: input,
|
||||
output: Decodable::consensus_decode(d)?,
|
||||
output: Decodable::consensus_decode(&mut d)?,
|
||||
lock_time: Decodable::consensus_decode(d)?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -199,26 +199,20 @@ impl From<psbt::Error> for Error {
|
|||
}
|
||||
|
||||
/// Encode an object into a vector
|
||||
pub fn serialize<T: ?Sized>(data: &T) -> Vec<u8>
|
||||
where T: Encodable<Cursor<Vec<u8>>>,
|
||||
{
|
||||
pub fn serialize<T: Encodable + ?Sized>(data: &T) -> Vec<u8> {
|
||||
let mut encoder = Cursor::new(vec![]);
|
||||
data.consensus_encode(&mut encoder).unwrap();
|
||||
encoder.into_inner()
|
||||
}
|
||||
|
||||
/// Encode an object into a hex-encoded string
|
||||
pub fn serialize_hex<T: ?Sized>(data: &T) -> String
|
||||
where T: Encodable<Cursor<Vec<u8>>>
|
||||
{
|
||||
pub fn serialize_hex<T: Encodable + ?Sized>(data: &T) -> String {
|
||||
hex_encode(serialize(data))
|
||||
}
|
||||
|
||||
/// Deserialize an object from a vector, will error if said deserialization
|
||||
/// doesn't consume the entire vector.
|
||||
pub fn deserialize<'a, T>(data: &'a [u8]) -> Result<T, Error>
|
||||
where T: Decodable<Cursor<&'a [u8]>>
|
||||
{
|
||||
pub fn deserialize<'a, T: Decodable>(data: &'a [u8]) -> Result<T, Error> {
|
||||
let (rv, consumed) = deserialize_partial(data)?;
|
||||
|
||||
// Fail if data are not consumed entirely.
|
||||
|
@ -231,9 +225,9 @@ pub fn deserialize<'a, T>(data: &'a [u8]) -> Result<T, Error>
|
|||
|
||||
/// Deserialize an object from a vector, but will not report an error if said deserialization
|
||||
/// doesn't consume the entire vector.
|
||||
pub fn deserialize_partial<'a, T>(data: &'a [u8]) -> Result<(T, usize), Error>
|
||||
where T: Decodable<Cursor<&'a [u8]>>
|
||||
{
|
||||
pub fn deserialize_partial<'a, T: Decodable>(
|
||||
data: &'a [u8],
|
||||
) -> Result<(T, usize), Error> {
|
||||
let mut decoder = Cursor::new(data);
|
||||
let rv = Decodable::consensus_decode(&mut decoder)?;
|
||||
let consumed = decoder.position() as usize;
|
||||
|
@ -242,8 +236,8 @@ pub fn deserialize_partial<'a, T>(data: &'a [u8]) -> Result<(T, usize), Error>
|
|||
}
|
||||
|
||||
|
||||
/// A simple Encoder trait
|
||||
pub trait Encoder {
|
||||
/// Extensions of `Write` to encode data as per Bitcoin consensus
|
||||
pub trait WriteExt {
|
||||
/// Output a 64-bit uint
|
||||
fn emit_u64(&mut self, v: u64) -> Result<(), Error>;
|
||||
/// Output a 32-bit uint
|
||||
|
@ -269,8 +263,8 @@ pub trait Encoder {
|
|||
fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// A simple Decoder trait
|
||||
pub trait Decoder {
|
||||
/// Extensions of `Read` to decode data as per Bitcoin consensus
|
||||
pub trait ReadExt {
|
||||
/// Read a 64-bit uint
|
||||
fn read_u64(&mut self) -> Result<u64, Error>;
|
||||
/// Read a 32-bit uint
|
||||
|
@ -314,7 +308,7 @@ macro_rules! decoder_fn {
|
|||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Encoder for W {
|
||||
impl<W: Write> WriteExt for W {
|
||||
encoder_fn!(emit_u64, u64, write_u64);
|
||||
encoder_fn!(emit_u32, u32, write_u32);
|
||||
encoder_fn!(emit_u16, u16, write_u16);
|
||||
|
@ -340,7 +334,7 @@ impl<W: Write> Encoder for W {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Decoder for R {
|
||||
impl<R: Read> ReadExt for R {
|
||||
decoder_fn!(read_u64, u64, read_u64);
|
||||
decoder_fn!(read_u32, u32, read_u32);
|
||||
decoder_fn!(read_u16, u16, read_u16);
|
||||
|
@ -358,7 +352,7 @@ impl<R: Read> Decoder for R {
|
|||
}
|
||||
#[inline]
|
||||
fn read_bool(&mut self) -> Result<bool, Error> {
|
||||
Decoder::read_i8(self).map(|bit| bit != 0)
|
||||
ReadExt::read_i8(self).map(|bit| bit != 0)
|
||||
}
|
||||
#[inline]
|
||||
fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error> {
|
||||
|
@ -370,16 +364,17 @@ impl<R: Read> Decoder for R {
|
|||
pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024;
|
||||
|
||||
/// Data which can be encoded in a consensus-consistent way
|
||||
pub trait Encodable<S: Encoder> {
|
||||
pub trait Encodable {
|
||||
/// Encode an object with a well-defined format, should only ever error if
|
||||
/// the underlying Encoder errors.
|
||||
fn consensus_encode(&self, e: &mut S) -> Result<(), self::Error>;
|
||||
/// the underlying `Write` errors. Returns the number of bytes written on
|
||||
/// success
|
||||
fn consensus_encode<W: io::Write>(&self, e: W) -> Result<usize, Error>;
|
||||
}
|
||||
|
||||
/// Data which can be encoded in a consensus-consistent way
|
||||
pub trait Decodable<D: Decoder>: Sized {
|
||||
pub trait Decodable: Sized {
|
||||
/// Decode an object with a well-defined format
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, self::Error>;
|
||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error>;
|
||||
}
|
||||
|
||||
/// A variable-length unsigned integer
|
||||
|
@ -393,14 +388,22 @@ pub struct CheckedData(pub Vec<u8>);
|
|||
// Primitive types
|
||||
macro_rules! impl_int_encodable{
|
||||
($ty:ident, $meth_dec:ident, $meth_enc:ident) => (
|
||||
impl<D: Decoder> Decodable<D> for $ty {
|
||||
impl Decodable for $ty {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<$ty, self::Error> { d.$meth_dec().map($ty::from_le) }
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
ReadExt::$meth_dec(&mut d).map($ty::from_le)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for $ty {
|
||||
impl Encodable for $ty {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.$meth_enc(self.to_le()) }
|
||||
fn consensus_encode<S: WriteExt>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, self::Error> {
|
||||
s.$meth_enc(self.to_le())?;
|
||||
Ok(mem::size_of::<$ty>())
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -419,7 +422,7 @@ impl VarInt {
|
|||
/// Returns 1 for 0...0xFC, 3 for 0xFD...(2^16-1), 5 for 0x10000...(2^32-1),
|
||||
/// and 9 otherwise.
|
||||
#[inline]
|
||||
pub fn encoded_length(&self) -> u64 {
|
||||
pub fn len(&self) -> usize {
|
||||
match self.0 {
|
||||
0...0xFC => { 1 }
|
||||
0xFD...0xFFFF => { 3 }
|
||||
|
@ -429,25 +432,40 @@ impl VarInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for VarInt {
|
||||
impl Encodable for VarInt {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, Error> {
|
||||
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)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for VarInt {
|
||||
impl Decodable for VarInt {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<VarInt, self::Error> {
|
||||
let n = d.read_u8()?;
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
let n = ReadExt::read_u8(&mut d)?;
|
||||
match n {
|
||||
0xFF => {
|
||||
let x = d.read_u64()?;
|
||||
let x = ReadExt::read_u64(&mut d)?;
|
||||
if x < 0x100000000 {
|
||||
Err(self::Error::ParseFailed("non-minimal varint"))
|
||||
} else {
|
||||
|
@ -455,7 +473,7 @@ impl<D: Decoder> Decodable<D> for VarInt {
|
|||
}
|
||||
}
|
||||
0xFE => {
|
||||
let x = d.read_u32()?;
|
||||
let x = ReadExt::read_u32(&mut d)?;
|
||||
if x < 0x10000 {
|
||||
Err(self::Error::ParseFailed("non-minimal varint"))
|
||||
} else {
|
||||
|
@ -463,7 +481,7 @@ impl<D: Decoder> Decodable<D> for VarInt {
|
|||
}
|
||||
}
|
||||
0xFD => {
|
||||
let x = d.read_u16()?;
|
||||
let x = ReadExt::read_u16(&mut d)?;
|
||||
if x < 0xFD {
|
||||
Err(self::Error::ParseFailed("non-minimal varint"))
|
||||
} else {
|
||||
|
@ -477,29 +495,35 @@ impl<D: Decoder> Decodable<D> for VarInt {
|
|||
|
||||
|
||||
// Booleans
|
||||
impl<S: Encoder> Encodable<S> for bool {
|
||||
impl Encodable for bool {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { s.emit_u8(if *self {1} else {0}) }
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for bool {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<bool, self::Error> { d.read_u8().map(|n| n != 0) }
|
||||
}
|
||||
|
||||
// Strings
|
||||
impl<S: Encoder> Encodable<S> for String {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
let b = self.as_bytes();
|
||||
VarInt(b.len() as u64).consensus_encode(s)?;
|
||||
s.emit_slice(&b)
|
||||
fn consensus_encode<S: WriteExt>(&self, mut s: S) -> Result<usize, Error> {
|
||||
s.emit_u8(if *self {1} else {0})?;
|
||||
Ok(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for String {
|
||||
impl Decodable for bool {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<String, self::Error> {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<bool, Error> {
|
||||
ReadExt::read_u8(&mut d).map(|n| n != 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Strings
|
||||
impl Encodable for String {
|
||||
#[inline]
|
||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, Error> {
|
||||
let b = self.as_bytes();
|
||||
let vi_len = VarInt(b.len() as u64).consensus_encode(&mut s)?;
|
||||
s.emit_slice(&b)?;
|
||||
Ok(vi_len + b.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for String {
|
||||
#[inline]
|
||||
fn consensus_decode<D: io::Read>(d: D) -> Result<String, Error> {
|
||||
String::from_utf8(Decodable::consensus_decode(d)?)
|
||||
.map_err(|_| self::Error::ParseFailed("String was not valid UTF8"))
|
||||
}
|
||||
|
@ -509,16 +533,20 @@ impl<D: Decoder> Decodable<D> for String {
|
|||
// Arrays
|
||||
macro_rules! impl_array {
|
||||
( $size:expr ) => (
|
||||
impl<S: Encoder> Encodable<S> for [u8; $size] {
|
||||
impl Encodable for [u8; $size] {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
s.emit_slice(&self[..])
|
||||
fn consensus_encode<S: WriteExt>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, Error> {
|
||||
s.emit_slice(&self[..])?;
|
||||
Ok(self.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for [u8; $size] {
|
||||
impl Decodable for [u8; $size] {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<[u8; $size], self::Error> {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
let mut ret = [0; $size];
|
||||
d.read_slice(&mut ret)?;
|
||||
Ok(ret)
|
||||
|
@ -535,41 +563,47 @@ impl_array!(16);
|
|||
impl_array!(32);
|
||||
impl_array!(33);
|
||||
|
||||
impl<D: Decoder> Decodable<D> for [u16; 8] {
|
||||
impl Decodable for [u16; 8] {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<[u16; 8], self::Error> {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
let mut res = [0; 8];
|
||||
for i in 0..8 {
|
||||
res[i] = Decodable::consensus_decode(d)?;
|
||||
res[i] = Decodable::consensus_decode(&mut d)?;
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for [u16; 8] {
|
||||
impl Encodable for [u16; 8] {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
for c in self.iter() { c.consensus_encode(s)?; }
|
||||
Ok(())
|
||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, Error> {
|
||||
for c in self.iter() { c.consensus_encode(&mut s)?; }
|
||||
Ok(16)
|
||||
}
|
||||
}
|
||||
|
||||
// Vectors
|
||||
macro_rules! impl_vec {
|
||||
($type: ty) => {
|
||||
impl<S: Encoder> Encodable<S> for Vec<$type> {
|
||||
impl Encodable for Vec<$type> {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
VarInt(self.len() as u64).consensus_encode(s)?;
|
||||
for c in self.iter() { c.consensus_encode(s)?; }
|
||||
Ok(())
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, Error> {
|
||||
let mut len = 0;
|
||||
len += VarInt(self.len() as u64).consensus_encode(&mut s)?;
|
||||
for c in self.iter() {
|
||||
len += c.consensus_encode(&mut s)?;
|
||||
}
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Vec<$type> {
|
||||
impl Decodable for Vec<$type> {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<Vec<$type>, self::Error> {
|
||||
let len = VarInt::consensus_decode(d)?.0;
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
let len = VarInt::consensus_decode(&mut d)?.0;
|
||||
let byte_size = (len as usize)
|
||||
.checked_mul(mem::size_of::<$type>())
|
||||
.ok_or(self::Error::ParseFailed("Invalid length"))?;
|
||||
|
@ -577,7 +611,9 @@ macro_rules! impl_vec {
|
|||
return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE })
|
||||
}
|
||||
let mut ret = Vec::with_capacity(len as usize);
|
||||
for _ in 0..len { ret.push(Decodable::consensus_decode(d)?); }
|
||||
for _ in 0..len {
|
||||
ret.push(Decodable::consensus_decode(&mut d)?);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
@ -592,19 +628,19 @@ impl_vec!(Vec<u8>);
|
|||
impl_vec!((u32, Address));
|
||||
impl_vec!(u64);
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Vec<u8> {
|
||||
impl Encodable for Vec<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<S: io::Write>(&self, mut s: S) -> Result<usize, Error> {
|
||||
let vi_len = VarInt(self.len() as u64).consensus_encode(&mut s)?;
|
||||
s.emit_slice(&self)?;
|
||||
Ok(vi_len + self.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Vec<u8> {
|
||||
impl Decodable for Vec<u8> {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<Vec<u8>, self::Error> {
|
||||
let len = VarInt::consensus_decode(d)?.0;
|
||||
let len = len as usize;
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
let len = VarInt::consensus_decode(&mut d)?.0 as usize;
|
||||
if len > MAX_VEC_SIZE {
|
||||
return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE })
|
||||
}
|
||||
|
@ -615,18 +651,19 @@ impl<D: Decoder> Decodable<D> for Vec<u8> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Box<[u8]> {
|
||||
impl Encodable for Box<[u8]> {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
VarInt(self.len() as u64).consensus_encode(s)?;
|
||||
s.emit_slice(&self)
|
||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, Error> {
|
||||
let vi_len = VarInt(self.len() as u64).consensus_encode(&mut s)?;
|
||||
s.emit_slice(&self)?;
|
||||
Ok(vi_len + self.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Box<[u8]> {
|
||||
impl Decodable for Box<[u8]> {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<Box<[u8]>, self::Error> {
|
||||
let len = VarInt::consensus_decode(d)?.0;
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
let len = VarInt::consensus_decode(&mut d)?.0;
|
||||
let len = len as usize;
|
||||
if len > MAX_VEC_SIZE {
|
||||
return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE })
|
||||
|
@ -646,26 +683,27 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] {
|
|||
}
|
||||
|
||||
// Checked data
|
||||
impl<S: Encoder> Encodable<S> for CheckedData {
|
||||
impl Encodable for CheckedData {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
(self.0.len() as u32).consensus_encode(s)?;
|
||||
sha2_checksum(&self.0).consensus_encode(s)?;
|
||||
s.emit_slice(&self.0)
|
||||
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, Error> {
|
||||
(self.0.len() as u32).consensus_encode(&mut s)?;
|
||||
sha2_checksum(&self.0).consensus_encode(&mut s)?;
|
||||
s.emit_slice(&self.0)?;
|
||||
Ok(8 + self.0.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for CheckedData {
|
||||
impl Decodable for CheckedData {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<CheckedData, self::Error> {
|
||||
let len: u32 = Decodable::consensus_decode(d)?;
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
let len = u32::consensus_decode(&mut d)?;
|
||||
if len > MAX_VEC_SIZE as u32 {
|
||||
return Err(self::Error::OversizedVectorAllocation {
|
||||
requested: len as usize,
|
||||
max: MAX_VEC_SIZE
|
||||
});
|
||||
}
|
||||
let checksum: [u8; 4] = Decodable::consensus_decode(d)?;
|
||||
let checksum = <[u8; 4]>::consensus_decode(&mut d)?;
|
||||
let mut ret = Vec::with_capacity(len as usize);
|
||||
ret.resize(len as usize, 0);
|
||||
d.read_slice(&mut ret)?;
|
||||
|
@ -684,21 +722,25 @@ impl<D: Decoder> Decodable<D> for CheckedData {
|
|||
// Tuples
|
||||
macro_rules! tuple_encode {
|
||||
($($x:ident),*) => (
|
||||
impl <S: Encoder, $($x: Encodable<S>),*> Encodable<S> for ($($x),*) {
|
||||
impl <$($x: Encodable),*> Encodable for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, self::Error> {
|
||||
let &($(ref $x),*) = self;
|
||||
$( $x.consensus_encode(s)?; )*
|
||||
Ok(())
|
||||
let mut len = 0;
|
||||
$(len += $x.consensus_encode(&mut s)?;)*
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder, $($x: Decodable<D>),*> Decodable<D> for ($($x),*) {
|
||||
impl<$($x: Decodable),*> Decodable for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn consensus_decode(d: &mut D) -> Result<($($x),*), self::Error> {
|
||||
Ok(($({let $x = Decodable::consensus_decode(d)?; $x }),*))
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||
Ok(($({let $x = Decodable::consensus_decode(&mut d)?; $x }),*))
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -709,15 +751,15 @@ tuple_encode!(T0, T1, T2, T3);
|
|||
tuple_encode!(T0, T1, T2, T3, T4, T5);
|
||||
tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7);
|
||||
|
||||
impl<S: Encoder> Encodable<S> for sha256d::Hash {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
|
||||
impl Encodable for sha256d::Hash {
|
||||
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, Error> {
|
||||
self.into_inner().consensus_encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for sha256d::Hash {
|
||||
fn consensus_decode(d: &mut D) -> Result<sha256d::Hash, self::Error> {
|
||||
let inner: [u8; 32] = Decodable::consensus_decode(d)?;
|
||||
impl Decodable for sha256d::Hash {
|
||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
|
||||
let inner = <[u8; 32]>::consensus_decode(d)?;
|
||||
Ok(sha256d::Hash::from_slice(&inner).unwrap())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
pub mod encode;
|
||||
pub mod params;
|
||||
|
||||
pub use self::encode::{Encodable, Decodable, Encoder, Decoder,
|
||||
serialize, deserialize, deserialize_partial};
|
||||
pub use self::encode::{Encodable, Decodable, WriteExt, ReadExt};
|
||||
pub use self::encode::{serialize, deserialize, deserialize_partial};
|
||||
pub use self::params::Params;
|
||||
|
|
|
@ -18,20 +18,25 @@
|
|||
|
||||
macro_rules! impl_consensus_encoding {
|
||||
($thing:ident, $($field:ident),+) => (
|
||||
impl<S: ::consensus::encode::Encoder> ::consensus::encode::Encodable<S> for $thing {
|
||||
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<S: ::std::io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, ::consensus::encode::Error> {
|
||||
let mut len = 0;
|
||||
$(len += self.$field.consensus_encode(&mut s)?;)+
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: ::consensus::encode::Decoder> ::consensus::encode::Decodable<D> for $thing {
|
||||
impl ::consensus::Decodable for $thing {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<$thing, ::consensus::encode::Error> {
|
||||
use consensus::encode::Decodable;
|
||||
fn consensus_decode<D: ::std::io::Read>(
|
||||
mut d: D,
|
||||
) -> Result<$thing, ::consensus::encode::Error> {
|
||||
Ok($thing {
|
||||
$( $field: Decodable::consensus_decode(d)?, )+
|
||||
$($field: ::consensus::Decodable::consensus_decode(&mut d)?),+
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,9 @@ extern crate secp256k1;
|
|||
#[cfg(all(test, feature = "unstable"))] extern crate test;
|
||||
#[cfg(feature="bitcoinconsensus")] extern crate bitcoinconsensus;
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
compile_error!("rust-bitcoin cannot be used on 16-bit architectures");
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod test_macros;
|
||||
|
|
|
@ -22,8 +22,7 @@ use std::io;
|
|||
use std::fmt;
|
||||
use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||
|
||||
use consensus::encode::{self, Encoder, Decoder};
|
||||
use consensus::encode::{Decodable, Encodable};
|
||||
use consensus::encode::{self, Decodable, Encodable};
|
||||
|
||||
/// A message which can be sent on the Bitcoin network
|
||||
pub struct Address {
|
||||
|
@ -72,21 +71,25 @@ fn addr_to_be(addr: [u16; 8]) -> [u16; 8] {
|
|||
addr[4].to_be(), addr[5].to_be(), addr[6].to_be(), addr[7].to_be()]
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Address {
|
||||
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<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let len = self.services.consensus_encode(&mut s)?
|
||||
+ addr_to_be(self.address).consensus_encode(&mut s)?
|
||||
+ self.port.to_be().consensus_encode(s)?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Address {
|
||||
impl Decodable for Address {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<Address, encode::Error> {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
Ok(Address {
|
||||
services: Decodable::consensus_decode(d)?,
|
||||
address: addr_to_be(Decodable::consensus_decode(d)?),
|
||||
services: Decodable::consensus_decode(&mut d)?,
|
||||
address: addr_to_be(Decodable::consensus_decode(&mut d)?),
|
||||
port: u16::from_be(Decodable::consensus_decode(d)?)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -32,14 +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};
|
||||
use consensus::encode::{self, Encoder, Decoder};
|
||||
|
||||
/// Version of the protocol as appearing in network message headers
|
||||
pub const PROTOCOL_VERSION: u32 = 70001;
|
||||
/// Bitfield of services provided by this node
|
||||
|
@ -102,26 +99,6 @@ impl Network {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> 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<D: Decoder> Decodable<D> for Network {
|
||||
/// Decodes the magic bytes of `Network`.
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<Network, encode::Error> {
|
||||
u32::consensus_decode(d)
|
||||
.and_then(|m| {
|
||||
Network::from_magic(m)
|
||||
.ok_or(encode::Error::UnknownNetworkMagic(m))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Network;
|
||||
|
@ -129,16 +106,31 @@ mod tests {
|
|||
|
||||
#[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]);
|
||||
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<Network, _> = 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]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
//! also defines (de)serialization routines for many primitives.
|
||||
//!
|
||||
|
||||
use std::{iter, mem};
|
||||
use std::{io, iter, mem};
|
||||
use std::io::Cursor;
|
||||
|
||||
use blockdata::block;
|
||||
|
@ -28,18 +28,20 @@ use network::address::Address;
|
|||
use network::message_network;
|
||||
use network::message_blockdata;
|
||||
use network::message_filter;
|
||||
use consensus::encode::{Decodable, Encodable};
|
||||
use consensus::encode::{CheckedData, VarInt};
|
||||
use consensus::encode::{self, serialize, Encoder, Decoder};
|
||||
use consensus::encode::{CheckedData, Decodable, Encodable, VarInt};
|
||||
use consensus::{encode, serialize};
|
||||
use consensus::encode::MAX_VEC_SIZE;
|
||||
|
||||
/// Serializer for command string
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct CommandString(pub String);
|
||||
|
||||
impl<S: Encoder> Encodable<S> for CommandString {
|
||||
impl Encodable for CommandString {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let &CommandString(ref inner_str) = self;
|
||||
let mut rawbytes = [0u8; 12];
|
||||
let strbytes = inner_str.as_bytes();
|
||||
|
@ -53,11 +55,15 @@ impl<S: Encoder> Encodable<S> for CommandString {
|
|||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for CommandString {
|
||||
impl Decodable for CommandString {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<CommandString, encode::Error> {
|
||||
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
|
||||
let rawbytes: [u8; 12] = Decodable::consensus_decode(d)?;
|
||||
let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
|
||||
let rv = iter::FromIterator::from_iter(
|
||||
rawbytes
|
||||
.iter()
|
||||
.filter_map(|&u| if u > 0 { Some(u as char) } else { None })
|
||||
);
|
||||
Ok(CommandString(rv))
|
||||
}
|
||||
}
|
||||
|
@ -160,23 +166,32 @@ impl RawNetworkMessage {
|
|||
}
|
||||
|
||||
struct HeaderSerializationWrapper<'a>(&'a Vec<block::BlockHeader>);
|
||||
impl <'a, S: Encoder> Encodable<S> for HeaderSerializationWrapper<'a> {
|
||||
|
||||
impl<'a> 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<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let mut len = 0;
|
||||
len += VarInt(self.0.len() as u64).consensus_encode(&mut s)?;
|
||||
for header in self.0.iter() {
|
||||
header.consensus_encode(s)?;
|
||||
0u8.consensus_encode(s)?;
|
||||
len += header.consensus_encode(&mut s)?;
|
||||
len += 0u8.consensus_encode(&mut s)?;
|
||||
}
|
||||
Ok(())
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> 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 {
|
||||
impl Encodable for RawNetworkMessage {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let mut len = 0;
|
||||
len += self.magic.consensus_encode(&mut s)?;
|
||||
len += CommandString(self.command()).consensus_encode(&mut s)?;
|
||||
len += CheckedData(match self.payload {
|
||||
NetworkMessage::Version(ref dat) => serialize(dat),
|
||||
NetworkMessage::Addr(ref dat) => serialize(dat),
|
||||
NetworkMessage::Inv(ref dat) => serialize(dat),
|
||||
|
@ -200,15 +215,17 @@ impl<S: Encoder> Encodable<S> for RawNetworkMessage {
|
|||
| NetworkMessage::SendHeaders
|
||||
| NetworkMessage::MemPool
|
||||
| NetworkMessage::GetAddr => vec![],
|
||||
}).consensus_encode(s)
|
||||
}).consensus_encode(&mut s)?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
struct HeaderDeserializationWrapper(Vec<block::BlockHeader>);
|
||||
impl<D: Decoder> Decodable<D> for HeaderDeserializationWrapper {
|
||||
|
||||
impl Decodable for HeaderDeserializationWrapper {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<HeaderDeserializationWrapper, encode::Error> {
|
||||
let len = VarInt::consensus_decode(d)?.0;
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let len = VarInt::consensus_decode(&mut d)?.0;
|
||||
let byte_size = (len as usize)
|
||||
.checked_mul(mem::size_of::<block::BlockHeader>())
|
||||
.ok_or(encode::Error::ParseFailed("Invalid length"))?;
|
||||
|
@ -217,8 +234,8 @@ impl<D: Decoder> Decodable<D> for HeaderDeserializationWrapper {
|
|||
}
|
||||
let mut ret = Vec::with_capacity(len as usize);
|
||||
for _ in 0..len {
|
||||
ret.push(Decodable::consensus_decode(d)?);
|
||||
if <u8 as Decodable<D>>::consensus_decode(d)? != 0u8 {
|
||||
ret.push(Decodable::consensus_decode(&mut d)?);
|
||||
if u8::consensus_decode(&mut d)? != 0u8 {
|
||||
return Err(encode::Error::ParseFailed("Headers message should not contain transactions"));
|
||||
}
|
||||
}
|
||||
|
@ -226,11 +243,11 @@ impl<D: Decoder> Decodable<D> for HeaderDeserializationWrapper {
|
|||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for RawNetworkMessage {
|
||||
fn consensus_decode(d: &mut D) -> Result<RawNetworkMessage, encode::Error> {
|
||||
let magic = Decodable::consensus_decode(d)?;
|
||||
let CommandString(cmd): CommandString= Decodable::consensus_decode(d)?;
|
||||
let CheckedData(raw_payload): CheckedData = Decodable::consensus_decode(d)?;
|
||||
impl Decodable for RawNetworkMessage {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let magic = Decodable::consensus_decode(&mut d)?;
|
||||
let cmd = CommandString::consensus_decode(&mut d)?.0;
|
||||
let raw_payload = CheckedData::consensus_decode(&mut d)?.0;
|
||||
|
||||
let mut mem_d = Cursor::new(raw_payload);
|
||||
let payload = match &cmd[..] {
|
||||
|
@ -244,9 +261,9 @@ impl<D: Decoder> Decodable<D> for RawNetworkMessage {
|
|||
"getheaders" => NetworkMessage::GetHeaders(Decodable::consensus_decode(&mut mem_d)?),
|
||||
"mempool" => NetworkMessage::MemPool,
|
||||
"block" => NetworkMessage::Block(Decodable::consensus_decode(&mut mem_d)?),
|
||||
"headers" =>
|
||||
NetworkMessage::Headers(<HeaderDeserializationWrapper as Decodable<Cursor<Vec<u8>>>>
|
||||
::consensus_decode(&mut mem_d)?.0),
|
||||
"headers" => NetworkMessage::Headers(
|
||||
HeaderDeserializationWrapper::consensus_decode(&mut mem_d)?.0
|
||||
),
|
||||
"sendheaders" => NetworkMessage::SendHeaders,
|
||||
"getaddr" => NetworkMessage::GetAddr,
|
||||
"ping" => NetworkMessage::Ping(Decodable::consensus_decode(&mut mem_d)?),
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
//!
|
||||
|
||||
use network::constants;
|
||||
use consensus::encode::{Decodable, Encodable};
|
||||
use consensus::encode::{self, Decoder, Encoder};
|
||||
use consensus::encode::{self, Decodable, Encodable};
|
||||
use bitcoin_hashes::sha256d;
|
||||
|
||||
use std::io;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
/// The type of an inventory object
|
||||
pub enum InvType {
|
||||
|
@ -101,24 +102,27 @@ impl GetHeadersMessage {
|
|||
|
||||
impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash);
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Inventory {
|
||||
impl Encodable for Inventory {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
|
||||
match self.inv_type {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
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)
|
||||
}.consensus_encode(&mut s)?;
|
||||
Ok(inv_len + self.hash.consensus_encode(&mut s)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Inventory {
|
||||
impl Decodable for Inventory {
|
||||
#[inline]
|
||||
fn consensus_decode(d: &mut D) -> Result<Inventory, encode::Error> {
|
||||
let int_type: u32 = Decodable::consensus_decode(d)?;
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let int_type: u32 = Decodable::consensus_decode(&mut d)?;
|
||||
Ok(Inventory {
|
||||
inv_type: match int_type {
|
||||
0 => InvType::Error,
|
||||
|
|
|
@ -137,7 +137,6 @@ impl Address {
|
|||
/// Create a witness pay to script hash address
|
||||
pub fn p2wsh (script: &script::Script, network: Network) -> Address {
|
||||
use bitcoin_hashes::sha256;
|
||||
use bitcoin_hashes::Hash;
|
||||
|
||||
Address {
|
||||
network: network,
|
||||
|
@ -156,8 +155,6 @@ impl Address {
|
|||
/// This is a segwit address type that looks familiar (as p2sh) to legacy clients
|
||||
pub fn p2shwsh (script: &script::Script, network: Network) -> Address {
|
||||
use bitcoin_hashes::sha256;
|
||||
use bitcoin_hashes::Hash;
|
||||
use bitcoin_hashes::hash160;
|
||||
|
||||
let ws = script::Builder::new().push_int(0)
|
||||
.push_slice(&sha256::Hash::hash(&script[..])[..])
|
||||
|
@ -430,7 +427,6 @@ mod tests {
|
|||
assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_p2wsh () {
|
||||
// stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667
|
||||
|
@ -439,7 +435,6 @@ mod tests {
|
|||
assert_eq!(&addr.to_string(), "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_bip173_vectors() {
|
||||
let addrstr = "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4";
|
||||
|
|
|
@ -57,12 +57,12 @@
|
|||
//! ```
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::io;
|
||||
|
||||
use bitcoin_hashes::{sha256d, Hash};
|
||||
|
||||
use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
|
||||
use consensus::encode::{Encodable, Error};
|
||||
use consensus::{Decodable, Decoder, Encoder};
|
||||
use consensus::encode::{self, Decodable, Encodable};
|
||||
use util::hash::BitcoinHash;
|
||||
use util::merkleblock::MerkleBlockError::*;
|
||||
use {Block, BlockHeader};
|
||||
|
@ -353,22 +353,25 @@ impl PartialMerkleTree {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for PartialMerkleTree {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), Error> {
|
||||
self.num_transactions.consensus_encode(s)?;
|
||||
self.hashes.consensus_encode(s)?;
|
||||
impl Encodable for PartialMerkleTree {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let ret = self.num_transactions.consensus_encode(&mut s)?
|
||||
+ self.hashes.consensus_encode(&mut s)?;
|
||||
let mut bytes: Vec<u8> = 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)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for PartialMerkleTree {
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, Error> {
|
||||
let num_transactions: u32 = Decodable::consensus_decode(d)?;
|
||||
let hashes: Vec<sha256d::Hash> = Decodable::consensus_decode(d)?;
|
||||
impl Decodable for PartialMerkleTree {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let num_transactions: u32 = Decodable::consensus_decode(&mut d)?;
|
||||
let hashes: Vec<sha256d::Hash> = Decodable::consensus_decode(&mut d)?;
|
||||
|
||||
let bytes: Vec<u8> = Decodable::consensus_decode(d)?;
|
||||
let mut bits: Vec<bool> = vec![false; bytes.len() * 8];
|
||||
|
@ -471,17 +474,21 @@ impl MerkleBlock {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for MerkleBlock {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), Error> {
|
||||
self.header.consensus_encode(s)?;
|
||||
self.txn.consensus_encode(s)
|
||||
impl Encodable for MerkleBlock {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let len = self.header.consensus_encode(&mut s)?
|
||||
+ self.txn.consensus_encode(s)?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for MerkleBlock {
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, Error> {
|
||||
impl Decodable for MerkleBlock {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
Ok(MerkleBlock {
|
||||
header: Decodable::consensus_decode(d)?,
|
||||
header: Decodable::consensus_decode(&mut d)?,
|
||||
txn: Decodable::consensus_decode(d)?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! hex_psbt {
|
||||
($s:expr) => { ::consensus::encode::deserialize(&::hex::decode($s).unwrap()) };
|
||||
($s:expr) => { ::consensus::deserialize(&::hex::decode($s).unwrap()) };
|
||||
}
|
||||
|
||||
macro_rules! merge {
|
||||
|
@ -36,7 +36,7 @@ macro_rules! impl_psbt_deserialize {
|
|||
($thing:ty) => {
|
||||
impl ::util::psbt::serialize::Deserialize for $thing {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, ::consensus::encode::Error> {
|
||||
::consensus::encode::deserialize(&bytes[..])
|
||||
::consensus::deserialize(&bytes[..])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ macro_rules! impl_psbt_serialize {
|
|||
($thing:ty) => {
|
||||
impl ::util::psbt::serialize::Serialize for $thing {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
::consensus::encode::serialize(self)
|
||||
::consensus::serialize(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -54,13 +54,20 @@ macro_rules! impl_psbt_serialize {
|
|||
|
||||
macro_rules! impl_psbtmap_consensus_encoding {
|
||||
($thing:ty) => {
|
||||
impl<S: ::consensus::encode::Encoder> ::consensus::encode::Encodable<S> for $thing {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), ::consensus::encode::Error> {
|
||||
impl ::consensus::Encodable for $thing {
|
||||
fn consensus_encode<S: ::std::io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, ::consensus::encode::Error> {
|
||||
let mut len = 0;
|
||||
for pair in ::util::psbt::Map::get_pairs(self)? {
|
||||
::consensus::encode::Encodable::consensus_encode(&pair, s)?
|
||||
len += ::consensus::Encodable::consensus_encode(
|
||||
&pair,
|
||||
&mut s,
|
||||
)?;
|
||||
}
|
||||
|
||||
::consensus::encode::Encodable::consensus_encode(&0x00_u8, s)
|
||||
Ok(len + ::consensus::Encodable::consensus_encode(&0x00_u8, s)?)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -68,12 +75,14 @@ macro_rules! impl_psbtmap_consensus_encoding {
|
|||
|
||||
macro_rules! impl_psbtmap_consensus_decoding {
|
||||
($thing:ty) => {
|
||||
impl<D: ::consensus::encode::Decoder> ::consensus::encode::Decodable<D> for $thing {
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, ::consensus::encode::Error> {
|
||||
impl ::consensus::Decodable for $thing {
|
||||
fn consensus_decode<D: ::std::io::Read>(
|
||||
mut d: D,
|
||||
) -> Result<Self, ::consensus::encode::Error> {
|
||||
let mut rv: Self = ::std::default::Default::default();
|
||||
|
||||
loop {
|
||||
match ::consensus::encode::Decodable::consensus_decode(d) {
|
||||
match ::consensus::Decodable::consensus_decode(&mut d) {
|
||||
Ok(pair) => ::util::psbt::Map::insert_pair(&mut rv, pair)?,
|
||||
Err(::consensus::encode::Error::Psbt(::util::psbt::Error::NoMorePairs)) => return Ok(rv),
|
||||
Err(e) => return Err(e),
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
use std::io::{self, Cursor};
|
||||
|
||||
use blockdata::transaction::Transaction;
|
||||
use consensus::encode::{self, Encodable, Decodable, Decoder};
|
||||
use consensus::{encode, Encodable, Decodable};
|
||||
use util::psbt::map::Map;
|
||||
use util::psbt::raw;
|
||||
use util::psbt;
|
||||
|
@ -120,14 +120,14 @@ impl Map for Global {
|
|||
|
||||
impl_psbtmap_consensus_encoding!(Global);
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Global {
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, encode::Error> {
|
||||
impl Decodable for Global {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
|
||||
let mut tx: Option<Transaction> = None;
|
||||
let mut unknowns: HashMap<raw::Key, Vec<u8>> = Default::default();
|
||||
|
||||
loop {
|
||||
match raw::Pair::consensus_decode(d) {
|
||||
match raw::Pair::consensus_decode(&mut d) {
|
||||
Ok(pair) => {
|
||||
match pair.key.type_value {
|
||||
0u8 => {
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
use blockdata::script::Script;
|
||||
use blockdata::transaction::Transaction;
|
||||
use consensus::encode::{self, Encodable, Decodable, Encoder, Decoder};
|
||||
use consensus::{encode, Encodable, Decodable};
|
||||
|
||||
use std::io;
|
||||
|
||||
mod error;
|
||||
pub use self::error::Error;
|
||||
|
@ -88,39 +90,43 @@ impl PartiallySignedTransaction {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for PartiallySignedTransaction {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
|
||||
b"psbt".consensus_encode(s)?;
|
||||
impl Encodable for PartiallySignedTransaction {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let mut len = 0;
|
||||
len += b"psbt".consensus_encode(&mut s)?;
|
||||
|
||||
0xff_u8.consensus_encode(s)?;
|
||||
len += 0xff_u8.consensus_encode(&mut s)?;
|
||||
|
||||
self.global.consensus_encode(s)?;
|
||||
len += self.global.consensus_encode(&mut s)?;
|
||||
|
||||
for i in &self.inputs {
|
||||
i.consensus_encode(s)?;
|
||||
len += i.consensus_encode(&mut s)?;
|
||||
}
|
||||
|
||||
for i in &self.outputs {
|
||||
i.consensus_encode(s)?;
|
||||
len += i.consensus_encode(&mut s)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for PartiallySignedTransaction {
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, encode::Error> {
|
||||
let magic: [u8; 4] = Decodable::consensus_decode(d)?;
|
||||
impl Decodable for PartiallySignedTransaction {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?;
|
||||
|
||||
if *b"psbt" != magic {
|
||||
return Err(Error::InvalidMagic.into());
|
||||
}
|
||||
|
||||
if 0xff_u8 != u8::consensus_decode(d)? {
|
||||
if 0xff_u8 != u8::consensus_decode(&mut d)? {
|
||||
return Err(Error::InvalidSeparator.into());
|
||||
}
|
||||
|
||||
let global: Global = Decodable::consensus_decode(d)?;
|
||||
let global: Global = Decodable::consensus_decode(&mut d)?;
|
||||
|
||||
let inputs: Vec<Input> = {
|
||||
let inputs_len: usize = (&global.unsigned_tx.input).len();
|
||||
|
@ -128,7 +134,7 @@ impl<D: Decoder> Decodable<D> for PartiallySignedTransaction {
|
|||
let mut inputs: Vec<Input> = Vec::with_capacity(inputs_len);
|
||||
|
||||
for _ in 0..inputs_len {
|
||||
inputs.push(Decodable::consensus_decode(d)?);
|
||||
inputs.push(Decodable::consensus_decode(&mut d)?);
|
||||
}
|
||||
|
||||
inputs
|
||||
|
@ -140,7 +146,7 @@ impl<D: Decoder> Decodable<D> for PartiallySignedTransaction {
|
|||
let mut outputs: Vec<Output> = Vec::with_capacity(outputs_len);
|
||||
|
||||
for _ in 0..outputs_len {
|
||||
outputs.push(Decodable::consensus_decode(d)?);
|
||||
outputs.push(Decodable::consensus_decode(&mut d)?);
|
||||
}
|
||||
|
||||
outputs
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
//! Raw PSBT key-value pairs as defined at
|
||||
//! https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki.
|
||||
|
||||
use std::fmt;
|
||||
use std::{fmt, io};
|
||||
|
||||
use consensus::encode::{Decodable, Encodable, VarInt, MAX_VEC_SIZE};
|
||||
use consensus::encode::{self, Decoder, Encoder};
|
||||
use consensus::encode::{self, Decodable, Encodable, VarInt, MAX_VEC_SIZE};
|
||||
use util::psbt::Error;
|
||||
|
||||
/// A PSBT key in its raw byte form.
|
||||
|
@ -43,15 +42,18 @@ pub struct Pair {
|
|||
|
||||
impl fmt::Display for Key {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use hex;
|
||||
|
||||
write!(f, "type: {:#x}, key: {}", self.type_value, hex::encode(&self.key))
|
||||
write!(
|
||||
f,
|
||||
"type: {:#x}, key: {}",
|
||||
self.type_value,
|
||||
::hex::encode(&self.key)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Key {
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, encode::Error> {
|
||||
let VarInt(byte_size): VarInt = Decodable::consensus_decode(d)?;
|
||||
impl Decodable for Key {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let VarInt(byte_size): VarInt = Decodable::consensus_decode(&mut d)?;
|
||||
|
||||
if byte_size == 0 {
|
||||
return Err(Error::NoMorePairs.into());
|
||||
|
@ -60,14 +62,17 @@ impl<D: Decoder> Decodable<D> for Key {
|
|||
let key_byte_size: u64 = byte_size - 1;
|
||||
|
||||
if key_byte_size > MAX_VEC_SIZE as u64 {
|
||||
return Err(encode::Error::OversizedVectorAllocation { requested: key_byte_size as usize, max: MAX_VEC_SIZE } )
|
||||
return Err(encode::Error::OversizedVectorAllocation {
|
||||
requested: key_byte_size as usize,
|
||||
max: MAX_VEC_SIZE,
|
||||
})
|
||||
}
|
||||
|
||||
let type_value: u8 = Decodable::consensus_decode(d)?;
|
||||
let type_value: u8 = Decodable::consensus_decode(&mut d)?;
|
||||
|
||||
let mut key = Vec::with_capacity(key_byte_size as usize);
|
||||
for _ in 0..key_byte_size {
|
||||
key.push(Decodable::consensus_decode(d)?);
|
||||
key.push(Decodable::consensus_decode(&mut d)?);
|
||||
}
|
||||
|
||||
Ok(Key {
|
||||
|
@ -77,31 +82,38 @@ impl<D: Decoder> Decodable<D> for Key {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Key {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
|
||||
VarInt((self.key.len() + 1) as u64).consensus_encode(s)?;
|
||||
impl Encodable for Key {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let mut len = 0;
|
||||
len += VarInt((self.key.len() + 1) as u64).consensus_encode(&mut s)?;
|
||||
|
||||
self.type_value.consensus_encode(s)?;
|
||||
len += self.type_value.consensus_encode(&mut s)?;
|
||||
|
||||
for key in &self.key {
|
||||
key.consensus_encode(s)?
|
||||
len += key.consensus_encode(&mut s)?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Pair {
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
|
||||
self.key.consensus_encode(s)?;
|
||||
self.value.consensus_encode(s)
|
||||
impl Encodable for Pair {
|
||||
fn consensus_encode<S: io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
let len = self.key.consensus_encode(&mut s)?;
|
||||
Ok(len + self.value.consensus_encode(s)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for Pair {
|
||||
fn consensus_decode(d: &mut D) -> Result<Self, encode::Error> {
|
||||
impl Decodable for Pair {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
Ok(Pair {
|
||||
key: Decodable::consensus_decode(d)?,
|
||||
key: Decodable::consensus_decode(&mut d)?,
|
||||
value: Decodable::consensus_decode(d)?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
//! Defines traits used for (de)serializing PSBT values into/from raw
|
||||
//! bytes in PSBT key-value pairs.
|
||||
|
||||
use std::io::{self, Cursor};
|
||||
use std::io;
|
||||
|
||||
use blockdata::script::Script;
|
||||
use blockdata::transaction::{SigHashType, Transaction, TxOut};
|
||||
|
@ -93,16 +93,10 @@ impl Deserialize for (Fingerprint, DerivationPath) {
|
|||
let fprint: Fingerprint = Fingerprint::from(&bytes[0..4]);
|
||||
let mut dpath: Vec<ChildNumber> = Default::default();
|
||||
|
||||
let d = &mut Cursor::new(&bytes[4..]);
|
||||
loop {
|
||||
match Decodable::consensus_decode(d) {
|
||||
Ok(index) => {
|
||||
dpath.push(<ChildNumber as From<u32>>::from(index));
|
||||
|
||||
if d.position() == (bytes.len() - 4) as u64 {
|
||||
break;
|
||||
}
|
||||
},
|
||||
let mut d = &bytes[4..];
|
||||
while !d.is_empty() {
|
||||
match u32::consensus_decode(&mut d) {
|
||||
Ok(index) => dpath.push(index.into()),
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -336,21 +336,29 @@ macro_rules! construct_uint {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: ::consensus::encode::Encoder> ::consensus::encode::Encodable<S> for $name {
|
||||
impl ::consensus::Encodable for $name {
|
||||
#[inline]
|
||||
fn consensus_encode(&self, s: &mut S) -> Result<(), encode::Error> {
|
||||
fn consensus_encode<S: ::std::io::Write>(
|
||||
&self,
|
||||
mut s: S,
|
||||
) -> Result<usize, encode::Error> {
|
||||
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(&mut s)?;
|
||||
}
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: ::consensus::encode::Decoder> ::consensus::encode::Decodable<D> for $name {
|
||||
fn consensus_decode(d: &mut D) -> Result<$name, encode::Error> {
|
||||
use consensus::encode::Decodable;
|
||||
impl ::consensus::Decodable for $name {
|
||||
fn consensus_decode<D: ::std::io::Read>(
|
||||
mut d: D,
|
||||
) -> Result<$name, encode::Error> {
|
||||
use consensus::Decodable;
|
||||
let mut ret: [u64; $n_words] = [0; $n_words];
|
||||
for i in 0..$n_words {
|
||||
ret[i] = Decodable::consensus_decode(d)?;
|
||||
ret[i] = Decodable::consensus_decode(&mut d)?;
|
||||
}
|
||||
Ok($name(ret))
|
||||
}
|
||||
|
@ -388,7 +396,7 @@ impl Uint256 {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use consensus::encode::{deserialize, serialize};
|
||||
use consensus::{deserialize, serialize};
|
||||
use util::uint::Uint256;
|
||||
use util::BitArray;
|
||||
|
||||
|
|
Loading…
Reference in New Issue