Merge pull request #137 from dongcarl/2018-8-better-errors
Fix Error type for SimpleDecoder and SimpleEncoder
This commit is contained in:
commit
a61ad5d382
|
@ -1,7 +1,7 @@
|
||||||
extern crate bitcoin;
|
extern crate bitcoin;
|
||||||
type BResult = Result<bitcoin::blockdata::block::Block, bitcoin::util::Error>;
|
|
||||||
fn do_test(data: &[u8]) {
|
fn do_test(data: &[u8]) {
|
||||||
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
let _: Result<bitcoin::blockdata::block::Block, _>= bitcoin::network::serialize::deserialize(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
extern crate bitcoin;
|
extern crate bitcoin;
|
||||||
type BResult = Result<bitcoin::blockdata::script::Script, bitcoin::util::Error>;
|
|
||||||
fn do_test(data: &[u8]) {
|
fn do_test(data: &[u8]) {
|
||||||
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
let _: Result<bitcoin::blockdata::script::Script, _> = bitcoin::network::serialize::deserialize(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
extern crate bitcoin;
|
extern crate bitcoin;
|
||||||
type BResult = Result<bitcoin::blockdata::transaction::Transaction, bitcoin::util::Error>;
|
|
||||||
fn do_test(data: &[u8]) {
|
fn do_test(data: &[u8]) {
|
||||||
let tx_result: BResult = bitcoin::network::serialize::deserialize(data);
|
let tx_result: Result<bitcoin::blockdata::transaction::Transaction, _> = bitcoin::network::serialize::deserialize(data);
|
||||||
match tx_result {
|
match tx_result {
|
||||||
Err(_) => {},
|
Err(_) => {},
|
||||||
Ok(mut tx) => {
|
Ok(mut tx) => {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
// Heavy stick to translate between opcode types
|
// Heavy stick to translate between opcode types
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
|
|
||||||
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
use network::serialize::{self, SimpleDecoder, SimpleEncoder};
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
|
|
||||||
// Note: I am deliberately not implementing PartialOrd or Ord on the
|
// Note: I am deliberately not implementing PartialOrd or Ord on the
|
||||||
|
@ -608,14 +608,14 @@ display_from_debug!(All);
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for All {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for All {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<All, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<All, serialize::Error> {
|
||||||
Ok(All::from(d.read_u8()?))
|
Ok(All::from(d.read_u8()?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for All {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for All {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
s.emit_u8(*self as u8)
|
s.emit_u8(*self as u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ use crypto::digest::Digest;
|
||||||
|
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
use network::serialize::{self, SimpleDecoder, SimpleEncoder};
|
||||||
use util::hash::Hash160;
|
use util::hash::Hash160;
|
||||||
#[cfg(feature="bitcoinconsensus")] use bitcoinconsensus;
|
#[cfg(feature="bitcoinconsensus")] use bitcoinconsensus;
|
||||||
#[cfg(feature="bitcoinconsensus")] use std::convert;
|
#[cfg(feature="bitcoinconsensus")] use std::convert;
|
||||||
|
@ -621,14 +621,14 @@ impl serde::Serialize for Script {
|
||||||
// Network serialization
|
// Network serialization
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for Script {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for Script {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
self.0.consensus_encode(s)
|
self.0.consensus_encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for Script {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for Script {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Script, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Script, serialize::Error> {
|
||||||
Ok(Script(ConsensusDecodable::consensus_decode(d)?))
|
Ok(Script(ConsensusDecodable::consensus_decode(d)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ use std::fmt;
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
#[cfg(feature="bitcoinconsensus")] use blockdata::script;
|
#[cfg(feature="bitcoinconsensus")] use blockdata::script;
|
||||||
use blockdata::script::Script;
|
use blockdata::script::Script;
|
||||||
use network::serialize::{serialize, BitcoinHash, SimpleEncoder, SimpleDecoder};
|
use network::serialize::{self, serialize, BitcoinHash, SimpleEncoder, SimpleDecoder};
|
||||||
use network::encodable::{ConsensusEncodable, ConsensusDecodable, VarInt};
|
use network::encodable::{ConsensusEncodable, ConsensusDecodable, VarInt};
|
||||||
|
|
||||||
/// A reference to a transaction output
|
/// A reference to a transaction output
|
||||||
|
@ -326,13 +326,13 @@ impl BitcoinHash for Transaction {
|
||||||
impl_consensus_encoding!(TxOut, value, script_pubkey);
|
impl_consensus_encoding!(TxOut, value, script_pubkey);
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for OutPoint {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for OutPoint {
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result <(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result <(), serialize::Error> {
|
||||||
self.txid.consensus_encode(s)?;
|
self.txid.consensus_encode(s)?;
|
||||||
self.vout.consensus_encode(s)
|
self.vout.consensus_encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for OutPoint {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for OutPoint {
|
||||||
fn consensus_decode(d: &mut D) -> Result<OutPoint, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<OutPoint, serialize::Error> {
|
||||||
Ok(OutPoint {
|
Ok(OutPoint {
|
||||||
txid: ConsensusDecodable::consensus_decode(d)?,
|
txid: ConsensusDecodable::consensus_decode(d)?,
|
||||||
vout: ConsensusDecodable::consensus_decode(d)?,
|
vout: ConsensusDecodable::consensus_decode(d)?,
|
||||||
|
@ -341,14 +341,14 @@ impl<D: SimpleDecoder> ConsensusDecodable<D> for OutPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for TxIn {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for TxIn {
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result <(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result <(), serialize::Error> {
|
||||||
self.previous_output.consensus_encode(s)?;
|
self.previous_output.consensus_encode(s)?;
|
||||||
self.script_sig.consensus_encode(s)?;
|
self.script_sig.consensus_encode(s)?;
|
||||||
self.sequence.consensus_encode(s)
|
self.sequence.consensus_encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for TxIn {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for TxIn {
|
||||||
fn consensus_decode(d: &mut D) -> Result<TxIn, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<TxIn, serialize::Error> {
|
||||||
Ok(TxIn {
|
Ok(TxIn {
|
||||||
previous_output: ConsensusDecodable::consensus_decode(d)?,
|
previous_output: ConsensusDecodable::consensus_decode(d)?,
|
||||||
script_sig: ConsensusDecodable::consensus_decode(d)?,
|
script_sig: ConsensusDecodable::consensus_decode(d)?,
|
||||||
|
@ -359,7 +359,7 @@ impl<D: SimpleDecoder> ConsensusDecodable<D> for TxIn {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for Transaction {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for Transaction {
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result <(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result <(), serialize::Error> {
|
||||||
self.version.consensus_encode(s)?;
|
self.version.consensus_encode(s)?;
|
||||||
let mut have_witness = false;
|
let mut have_witness = false;
|
||||||
for input in &self.input {
|
for input in &self.input {
|
||||||
|
@ -385,7 +385,7 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for Transaction {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for Transaction {
|
||||||
fn consensus_decode(d: &mut D) -> Result<Transaction, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Transaction, serialize::Error> {
|
||||||
let version: u32 = ConsensusDecodable::consensus_decode(d)?;
|
let version: u32 = ConsensusDecodable::consensus_decode(d)?;
|
||||||
let input: Vec<TxIn> = ConsensusDecodable::consensus_decode(d)?;
|
let input: Vec<TxIn> = ConsensusDecodable::consensus_decode(d)?;
|
||||||
// segwit
|
// segwit
|
||||||
|
@ -417,7 +417,7 @@ impl<D: SimpleDecoder> ConsensusDecodable<D> for Transaction {
|
||||||
}
|
}
|
||||||
// We don't support anything else
|
// We don't support anything else
|
||||||
x => {
|
x => {
|
||||||
Err(d.error(format!("segwit flag {:02x} not understood", x)))
|
Err(serialize::Error::UnsupportedSegwitFlag(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// non-segwit
|
// non-segwit
|
||||||
|
|
|
@ -16,7 +16,7 @@ macro_rules! impl_consensus_encoding {
|
||||||
($thing:ident, $($field:ident),+) => (
|
($thing:ident, $($field:ident),+) => (
|
||||||
impl<S: ::network::serialize::SimpleEncoder> ::network::encodable::ConsensusEncodable<S> for $thing {
|
impl<S: ::network::serialize::SimpleEncoder> ::network::encodable::ConsensusEncodable<S> for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), ::network::serialize::Error> {
|
||||||
$( self.$field.consensus_encode(s)?; )+
|
$( self.$field.consensus_encode(s)?; )+
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ macro_rules! impl_consensus_encoding {
|
||||||
|
|
||||||
impl<D: ::network::serialize::SimpleDecoder> ::network::encodable::ConsensusDecodable<D> for $thing {
|
impl<D: ::network::serialize::SimpleDecoder> ::network::encodable::ConsensusDecodable<D> for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<$thing, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<$thing, ::network::serialize::Error> {
|
||||||
use network::encodable::ConsensusDecodable;
|
use network::encodable::ConsensusDecodable;
|
||||||
Ok($thing {
|
Ok($thing {
|
||||||
$( $field: ConsensusDecodable::consensus_decode(d)?, )+
|
$( $field: ConsensusDecodable::consensus_decode(d)?, )+
|
||||||
|
@ -38,7 +38,7 @@ macro_rules! impl_newtype_consensus_encoding {
|
||||||
($thing:ident) => (
|
($thing:ident) => (
|
||||||
impl<S: ::network::serialize::SimpleEncoder> ::network::encodable::ConsensusEncodable<S> for $thing {
|
impl<S: ::network::serialize::SimpleEncoder> ::network::encodable::ConsensusEncodable<S> for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), ::network::serialize::Error> {
|
||||||
let &$thing(ref data) = self;
|
let &$thing(ref data) = self;
|
||||||
data.consensus_encode(s)
|
data.consensus_encode(s)
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ macro_rules! impl_newtype_consensus_encoding {
|
||||||
|
|
||||||
impl<D: ::network::serialize::SimpleDecoder> ::network::encodable::ConsensusDecodable<D> for $thing {
|
impl<D: ::network::serialize::SimpleDecoder> ::network::encodable::ConsensusDecodable<D> for $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<$thing, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<$thing, ::network::serialize::Error> {
|
||||||
Ok($thing(ConsensusDecodable::consensus_decode(d)?))
|
Ok($thing(ConsensusDecodable::consensus_decode(d)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use std::io;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
use std::net::{SocketAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||||
|
|
||||||
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
use network::serialize::{self, SimpleEncoder, SimpleDecoder};
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
|
|
||||||
/// A message which can be sent on the Bitcoin network
|
/// A message which can be sent on the Bitcoin network
|
||||||
|
@ -74,7 +74,7 @@ fn addr_to_be(addr: [u16; 8]) -> [u16; 8] {
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for Address {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for Address {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
self.services.consensus_encode(s)?;
|
self.services.consensus_encode(s)?;
|
||||||
addr_to_be(self.address).consensus_encode(s)?;
|
addr_to_be(self.address).consensus_encode(s)?;
|
||||||
self.port.to_be().consensus_encode(s)
|
self.port.to_be().consensus_encode(s)
|
||||||
|
@ -83,7 +83,7 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for Address {
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for Address {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for Address {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Address, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Address, serialize::Error> {
|
||||||
Ok(Address {
|
Ok(Address {
|
||||||
services: ConsensusDecodable::consensus_decode(d)?,
|
services: ConsensusDecodable::consensus_decode(d)?,
|
||||||
address: addr_to_be(ConsensusDecodable::consensus_decode(d)?),
|
address: addr_to_be(ConsensusDecodable::consensus_decode(d)?),
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
use network::serialize::{self, SimpleEncoder, SimpleDecoder};
|
||||||
|
|
||||||
/// Version of the protocol as appearing in network message headers
|
/// Version of the protocol as appearing in network message headers
|
||||||
pub const PROTOCOL_VERSION: u32 = 70001;
|
pub const PROTOCOL_VERSION: u32 = 70001;
|
||||||
|
@ -105,7 +105,7 @@ impl Network {
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for Network {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for Network {
|
||||||
/// Encodes the magic bytes of `Network`.
|
/// Encodes the magic bytes of `Network`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
self.magic().consensus_encode(s)
|
self.magic().consensus_encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,11 +113,11 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for Network {
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for Network {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for Network {
|
||||||
/// Decodes the magic bytes of `Network`.
|
/// Decodes the magic bytes of `Network`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Network, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Network, serialize::Error> {
|
||||||
u32::consensus_decode(d)
|
u32::consensus_decode(d)
|
||||||
.and_then(|m| {
|
.and_then(|m| {
|
||||||
Network::from_magic(m)
|
Network::from_magic(m)
|
||||||
.ok_or(d.error(format!("Unknown network (magic {:x})", m)))
|
.ok_or(serialize::Error::UnknownNetworkMagic(m))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ use std::hash::Hash;
|
||||||
use std::{mem, u32};
|
use std::{mem, u32};
|
||||||
|
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
use network::serialize::{self, SimpleDecoder, SimpleEncoder};
|
||||||
|
|
||||||
/// Maximum size, in bytes, of a vector we are allowed to decode
|
/// Maximum size, in bytes, of a vector we are allowed to decode
|
||||||
pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024;
|
pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024;
|
||||||
|
@ -42,13 +42,13 @@ pub const MAX_VEC_SIZE: usize = 32 * 1024 * 1024;
|
||||||
/// Data which can be encoded in a consensus-consistent way
|
/// Data which can be encoded in a consensus-consistent way
|
||||||
pub trait ConsensusEncodable<S: SimpleEncoder> {
|
pub trait ConsensusEncodable<S: SimpleEncoder> {
|
||||||
/// Encode an object with a well-defined format
|
/// Encode an object with a well-defined format
|
||||||
fn consensus_encode(&self, e: &mut S) -> Result<(), S::Error>;
|
fn consensus_encode(&self, e: &mut S) -> Result<(), serialize::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data which can be encoded in a consensus-consistent way
|
/// Data which can be encoded in a consensus-consistent way
|
||||||
pub trait ConsensusDecodable<D: SimpleDecoder>: Sized {
|
pub trait ConsensusDecodable<D: SimpleDecoder>: Sized {
|
||||||
/// Decode an object with a well-defined format
|
/// Decode an object with a well-defined format
|
||||||
fn consensus_decode(d: &mut D) -> Result<Self, D::Error>;
|
fn consensus_decode(d: &mut D) -> Result<Self, serialize::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A variable-length unsigned integer
|
/// A variable-length unsigned integer
|
||||||
|
@ -64,12 +64,12 @@ macro_rules! impl_int_encodable{
|
||||||
($ty:ident, $meth_dec:ident, $meth_enc:ident) => (
|
($ty:ident, $meth_dec:ident, $meth_enc:ident) => (
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for $ty {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<$ty, D::Error> { d.$meth_dec().map($ty::from_le) }
|
fn consensus_decode(d: &mut D) -> Result<$ty, serialize::Error> { d.$meth_dec().map($ty::from_le) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for $ty {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.$meth_enc(self.to_le()) }
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> { s.$meth_enc(self.to_le()) }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl VarInt {
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for VarInt {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for VarInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
0...0xFC => { (self.0 as u8).consensus_encode(s) }
|
0...0xFC => { (self.0 as u8).consensus_encode(s) }
|
||||||
0xFD...0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s) }
|
0xFD...0xFFFF => { s.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(s) }
|
||||||
|
@ -112,7 +112,7 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for VarInt {
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for VarInt {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for VarInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<VarInt, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<VarInt, serialize::Error> {
|
||||||
let n = d.read_u8()?;
|
let n = d.read_u8()?;
|
||||||
match n {
|
match n {
|
||||||
0xFF => d.read_u64().map(|n| VarInt(u64::from_le(n))),
|
0xFF => d.read_u64().map(|n| VarInt(u64::from_le(n))),
|
||||||
|
@ -126,27 +126,27 @@ impl<D: SimpleDecoder> ConsensusDecodable<D> for VarInt {
|
||||||
// Booleans
|
// Booleans
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for bool {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u8(if *self {1} else {0}) }
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> { s.emit_u8(if *self {1} else {0}) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for bool {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<bool, D::Error> { d.read_u8().map(|n| n != 0) }
|
fn consensus_decode(d: &mut D) -> Result<bool, serialize::Error> { d.read_u8().map(|n| n != 0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strings
|
// Strings
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for String {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
self.as_bytes().consensus_encode(s)
|
self.as_bytes().consensus_encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for String {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<String, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<String, serialize::Error> {
|
||||||
String::from_utf8(ConsensusDecodable::consensus_decode(d)?)
|
String::from_utf8(ConsensusDecodable::consensus_decode(d)?)
|
||||||
.map_err(|_| d.error("String was not valid UTF8".to_owned()))
|
.map_err(|_| serialize::Error::ParseFailed("String was not valid UTF8"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ macro_rules! impl_array {
|
||||||
( $size:expr ) => (
|
( $size:expr ) => (
|
||||||
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for [T; $size] {
|
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for [T; $size] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
for i in self.iter() { i.consensus_encode(s)?; }
|
for i in self.iter() { i.consensus_encode(s)?; }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ macro_rules! impl_array {
|
||||||
|
|
||||||
impl<D: SimpleDecoder, T:ConsensusDecodable<D> + Copy> ConsensusDecodable<D> for [T; $size] {
|
impl<D: SimpleDecoder, T:ConsensusDecodable<D> + Copy> ConsensusDecodable<D> for [T; $size] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<[T; $size], D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<[T; $size], serialize::Error> {
|
||||||
// Set everything to the first decode
|
// Set everything to the first decode
|
||||||
let mut ret = [ConsensusDecodable::consensus_decode(d)?; $size];
|
let mut ret = [ConsensusDecodable::consensus_decode(d)?; $size];
|
||||||
// Set the rest
|
// Set the rest
|
||||||
|
@ -184,7 +184,7 @@ impl_array!(32);
|
||||||
|
|
||||||
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for [T] {
|
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for [T] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
VarInt(self.len() as u64).consensus_encode(s)?;
|
VarInt(self.len() as u64).consensus_encode(s)?;
|
||||||
for c in self.iter() { c.consensus_encode(s)?; }
|
for c in self.iter() { c.consensus_encode(s)?; }
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -196,18 +196,18 @@ impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for [T] {
|
||||||
// Vectors
|
// Vectors
|
||||||
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Vec<T> {
|
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { (&self[..]).consensus_encode(s) }
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> { (&self[..]).consensus_encode(s) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Vec<T> {
|
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Vec<T>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Vec<T>, serialize::Error> {
|
||||||
let VarInt(len): VarInt = ConsensusDecodable::consensus_decode(d)?;
|
let VarInt(len): VarInt = ConsensusDecodable::consensus_decode(d)?;
|
||||||
let byte_size = (len as usize)
|
let byte_size = (len as usize)
|
||||||
.checked_mul(mem::size_of::<T>())
|
.checked_mul(mem::size_of::<T>())
|
||||||
.ok_or(d.error("Invalid length".to_owned()))?;
|
.ok_or(serialize::Error::ParseFailed("Invalid length"))?;
|
||||||
if byte_size > MAX_VEC_SIZE {
|
if byte_size > MAX_VEC_SIZE {
|
||||||
return Err(d.error(format!("tried to allocate vec of size {} (max {})", byte_size, MAX_VEC_SIZE)));
|
return Err(serialize::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE })
|
||||||
}
|
}
|
||||||
let mut ret = Vec::with_capacity(len as usize);
|
let mut ret = Vec::with_capacity(len as usize);
|
||||||
for _ in 0..len { ret.push(ConsensusDecodable::consensus_decode(d)?); }
|
for _ in 0..len { ret.push(ConsensusDecodable::consensus_decode(d)?); }
|
||||||
|
@ -217,16 +217,16 @@ impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Vec<T
|
||||||
|
|
||||||
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Box<[T]> {
|
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Box<[T]> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { (&self[..]).consensus_encode(s) }
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> { (&self[..]).consensus_encode(s) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<[T]> {
|
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<[T]> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Box<[T]>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Box<[T]>, serialize::Error> {
|
||||||
let VarInt(len): VarInt = ConsensusDecodable::consensus_decode(d)?;
|
let VarInt(len): VarInt = ConsensusDecodable::consensus_decode(d)?;
|
||||||
let len = len as usize;
|
let len = len as usize;
|
||||||
if len > MAX_VEC_SIZE {
|
if len > MAX_VEC_SIZE {
|
||||||
return Err(d.error(format!("tried to allocate vec of size {} (max {})", len, MAX_VEC_SIZE)));
|
return Err(serialize::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE })
|
||||||
}
|
}
|
||||||
let mut ret = Vec::with_capacity(len);
|
let mut ret = Vec::with_capacity(len);
|
||||||
for _ in 0..len { ret.push(ConsensusDecodable::consensus_decode(d)?); }
|
for _ in 0..len { ret.push(ConsensusDecodable::consensus_decode(d)?); }
|
||||||
|
@ -237,7 +237,7 @@ impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<[
|
||||||
// Options (encoded as vectors of length 0 or 1)
|
// Options (encoded as vectors of length 0 or 1)
|
||||||
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Option<T> {
|
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Option<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
Some(ref data) => {
|
Some(ref data) => {
|
||||||
1u8.consensus_encode(s)?;
|
1u8.consensus_encode(s)?;
|
||||||
|
@ -251,7 +251,7 @@ impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Optio
|
||||||
|
|
||||||
impl<D: SimpleDecoder, T:ConsensusDecodable<D>> ConsensusDecodable<D> for Option<T> {
|
impl<D: SimpleDecoder, T:ConsensusDecodable<D>> ConsensusDecodable<D> for Option<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Option<T>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Option<T>, serialize::Error> {
|
||||||
let bit: u8 = ConsensusDecodable::consensus_decode(d)?;
|
let bit: u8 = ConsensusDecodable::consensus_decode(d)?;
|
||||||
Ok(if bit != 0 {
|
Ok(if bit != 0 {
|
||||||
Some(ConsensusDecodable::consensus_decode(d)?)
|
Some(ConsensusDecodable::consensus_decode(d)?)
|
||||||
|
@ -271,7 +271,7 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] {
|
||||||
// Checked data
|
// Checked data
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for CheckedData {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for CheckedData {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
(self.0.len() as u32).consensus_encode(s)?;
|
(self.0.len() as u32).consensus_encode(s)?;
|
||||||
sha2_checksum(&self.0).consensus_encode(s)?;
|
sha2_checksum(&self.0).consensus_encode(s)?;
|
||||||
// We can't just pass to the slice encoder since it'll insert a length
|
// We can't just pass to the slice encoder since it'll insert a length
|
||||||
|
@ -284,14 +284,17 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for CheckedData {
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for CheckedData {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for CheckedData {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<CheckedData, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<CheckedData, serialize::Error> {
|
||||||
let len: u32 = ConsensusDecodable::consensus_decode(d)?;
|
let len: u32 = ConsensusDecodable::consensus_decode(d)?;
|
||||||
let checksum: [u8; 4] = ConsensusDecodable::consensus_decode(d)?;
|
let checksum: [u8; 4] = ConsensusDecodable::consensus_decode(d)?;
|
||||||
let mut ret = Vec::with_capacity(len as usize);
|
let mut ret = Vec::with_capacity(len as usize);
|
||||||
for _ in 0..len { ret.push(ConsensusDecodable::consensus_decode(d)?); }
|
for _ in 0..len { ret.push(ConsensusDecodable::consensus_decode(d)?); }
|
||||||
let expected_checksum = sha2_checksum(&ret);
|
let expected_checksum = sha2_checksum(&ret);
|
||||||
if expected_checksum != checksum {
|
if expected_checksum != checksum {
|
||||||
Err(d.error(format!("bad checksum {:?} (expected {:?})", checksum, expected_checksum)))
|
Err(serialize::Error::InvalidChecksum {
|
||||||
|
expected: expected_checksum,
|
||||||
|
actual: checksum,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(CheckedData(ret))
|
Ok(CheckedData(ret))
|
||||||
}
|
}
|
||||||
|
@ -304,7 +307,7 @@ macro_rules! tuple_encode {
|
||||||
impl <S: SimpleEncoder, $($x: ConsensusEncodable<S>),*> ConsensusEncodable<S> for ($($x),*) {
|
impl <S: SimpleEncoder, $($x: ConsensusEncodable<S>),*> ConsensusEncodable<S> for ($($x),*) {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
let &($(ref $x),*) = self;
|
let &($(ref $x),*) = self;
|
||||||
$( $x.consensus_encode(s)?; )*
|
$( $x.consensus_encode(s)?; )*
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -314,7 +317,7 @@ macro_rules! tuple_encode {
|
||||||
impl<D: SimpleDecoder, $($x: ConsensusDecodable<D>),*> ConsensusDecodable<D> for ($($x),*) {
|
impl<D: SimpleDecoder, $($x: ConsensusDecodable<D>),*> ConsensusDecodable<D> for ($($x),*) {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn consensus_decode(d: &mut D) -> Result<($($x),*), D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<($($x),*), serialize::Error> {
|
||||||
Ok(($({let $x = ConsensusDecodable::consensus_decode(d)?; $x }),*))
|
Ok(($({let $x = ConsensusDecodable::consensus_decode(d)?; $x }),*))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,12 +332,12 @@ tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7);
|
||||||
// References
|
// References
|
||||||
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Box<T> {
|
impl<S: SimpleEncoder, T: ConsensusEncodable<S>> ConsensusEncodable<S> for Box<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).consensus_encode(s) }
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> { (**self).consensus_encode(s) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<T> {
|
impl<D: SimpleDecoder, T: ConsensusDecodable<D>> ConsensusDecodable<D> for Box<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Box<T>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Box<T>, serialize::Error> {
|
||||||
ConsensusDecodable::consensus_decode(d).map(Box::new)
|
ConsensusDecodable::consensus_decode(d).map(Box::new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +349,7 @@ impl<S, K, V> ConsensusEncodable<S> for HashMap<K, V>
|
||||||
V: ConsensusEncodable<S>
|
V: ConsensusEncodable<S>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
VarInt(self.len() as u64).consensus_encode(s)?;
|
VarInt(self.len() as u64).consensus_encode(s)?;
|
||||||
for (key, value) in self.iter() {
|
for (key, value) in self.iter() {
|
||||||
key.consensus_encode(s)?;
|
key.consensus_encode(s)?;
|
||||||
|
@ -362,7 +365,7 @@ impl<D, K, V> ConsensusDecodable<D> for HashMap<K, V>
|
||||||
V: ConsensusDecodable<D>
|
V: ConsensusDecodable<D>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<HashMap<K, V>, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<HashMap<K, V>, serialize::Error> {
|
||||||
let VarInt(len): VarInt = ConsensusDecodable::consensus_decode(d)?;
|
let VarInt(len): VarInt = ConsensusDecodable::consensus_decode(d)?;
|
||||||
|
|
||||||
let mut ret = HashMap::with_capacity(len as usize);
|
let mut ret = HashMap::with_capacity(len as usize);
|
||||||
|
|
|
@ -39,9 +39,7 @@ pub trait Listener {
|
||||||
fn start(&self) -> Result<(Receiver<message::SocketResponse>, Socket), util::Error> {
|
fn start(&self) -> Result<(Receiver<message::SocketResponse>, Socket), util::Error> {
|
||||||
// Open socket
|
// Open socket
|
||||||
let mut ret_sock = Socket::new(self.network());
|
let mut ret_sock = Socket::new(self.network());
|
||||||
if let Err(e) = ret_sock.connect(self.peer(), self.port()) {
|
ret_sock.connect(self.peer(), self.port())?;
|
||||||
return Err(util::Error::Detail("listener".to_owned(), Box::new(e)));
|
|
||||||
}
|
|
||||||
let mut sock = ret_sock.clone();
|
let mut sock = ret_sock.clone();
|
||||||
|
|
||||||
let (recv_tx, recv_rx) = channel();
|
let (recv_tx, recv_rx) = channel();
|
||||||
|
|
|
@ -30,8 +30,8 @@ use network::message_network;
|
||||||
use network::message_blockdata;
|
use network::message_blockdata;
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::encodable::CheckedData;
|
use network::encodable::CheckedData;
|
||||||
use network::serialize::{serialize, RawDecoder, SimpleEncoder, SimpleDecoder};
|
use network::serialize::{self, serialize, RawDecoder, SimpleEncoder, SimpleDecoder};
|
||||||
use util::{self, propagate_err};
|
use util;
|
||||||
|
|
||||||
/// Serializer for command string
|
/// Serializer for command string
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
@ -39,7 +39,7 @@ pub struct CommandString(pub String);
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for CommandString {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for CommandString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
let &CommandString(ref inner_str) = self;
|
let &CommandString(ref inner_str) = self;
|
||||||
let mut rawbytes = [0u8; 12];
|
let mut rawbytes = [0u8; 12];
|
||||||
let strbytes = inner_str.as_bytes();
|
let strbytes = inner_str.as_bytes();
|
||||||
|
@ -55,7 +55,7 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for CommandString {
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for CommandString {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for CommandString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<CommandString, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<CommandString, serialize::Error> {
|
||||||
let rawbytes: [u8; 12] = ConsensusDecodable::consensus_decode(d)?;
|
let rawbytes: [u8; 12] = ConsensusDecodable::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))
|
Ok(CommandString(rv))
|
||||||
|
@ -147,7 +147,7 @@ impl RawNetworkMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for RawNetworkMessage {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for RawNetworkMessage {
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
self.magic.consensus_encode(s)?;
|
self.magic.consensus_encode(s)?;
|
||||||
CommandString(self.command()).consensus_encode(s)?;
|
CommandString(self.command()).consensus_encode(s)?;
|
||||||
CheckedData(match self.payload {
|
CheckedData(match self.payload {
|
||||||
|
@ -172,33 +172,31 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for RawNetworkMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: restriction on D::Error is so that `propagate_err` will work;
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for RawNetworkMessage {
|
||||||
// is there a more generic way to handle this?
|
fn consensus_decode(d: &mut D) -> Result<RawNetworkMessage, serialize::Error> {
|
||||||
impl<D: SimpleDecoder<Error=util::Error>> ConsensusDecodable<D> for RawNetworkMessage {
|
|
||||||
fn consensus_decode(d: &mut D) -> Result<RawNetworkMessage, D::Error> {
|
|
||||||
let magic = ConsensusDecodable::consensus_decode(d)?;
|
let magic = ConsensusDecodable::consensus_decode(d)?;
|
||||||
let CommandString(cmd): CommandString= ConsensusDecodable::consensus_decode(d)?;
|
let CommandString(cmd): CommandString= ConsensusDecodable::consensus_decode(d)?;
|
||||||
let CheckedData(raw_payload): CheckedData = ConsensusDecodable::consensus_decode(d)?;
|
let CheckedData(raw_payload): CheckedData = ConsensusDecodable::consensus_decode(d)?;
|
||||||
|
|
||||||
let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
|
let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
|
||||||
let payload = match &cmd[..] {
|
let payload = match &cmd[..] {
|
||||||
"version" => NetworkMessage::Version(propagate_err("version".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"version" => NetworkMessage::Version(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"verack" => NetworkMessage::Verack,
|
"verack" => NetworkMessage::Verack,
|
||||||
"addr" => NetworkMessage::Addr(propagate_err("addr".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"addr" => NetworkMessage::Addr(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"inv" => NetworkMessage::Inv(propagate_err("inv".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"inv" => NetworkMessage::Inv(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"getdata" => NetworkMessage::GetData(propagate_err("getdata".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"getdata" => NetworkMessage::GetData(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"notfound" => NetworkMessage::NotFound(propagate_err("notfound".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"notfound" => NetworkMessage::NotFound(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"getblocks" => NetworkMessage::GetBlocks(propagate_err("getblocks".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"getblocks" => NetworkMessage::GetBlocks(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"getheaders" => NetworkMessage::GetHeaders(propagate_err("getheaders".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"getheaders" => NetworkMessage::GetHeaders(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"mempool" => NetworkMessage::MemPool,
|
"mempool" => NetworkMessage::MemPool,
|
||||||
"block" => NetworkMessage::Block(propagate_err("block".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"block" => NetworkMessage::Block(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"headers" => NetworkMessage::Headers(propagate_err("headers".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"headers" => NetworkMessage::Headers(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"getaddr" => NetworkMessage::GetAddr,
|
"getaddr" => NetworkMessage::GetAddr,
|
||||||
"ping" => NetworkMessage::Ping(propagate_err("ping".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"ping" => NetworkMessage::Ping(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"pong" => NetworkMessage::Pong(propagate_err("pong".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"pong" => NetworkMessage::Pong(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"tx" => NetworkMessage::Tx(propagate_err("tx".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"tx" => NetworkMessage::Tx(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
"alert" => NetworkMessage::Alert(propagate_err("alert".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d))?),
|
"alert" => NetworkMessage::Alert(ConsensusDecodable::consensus_decode(&mut mem_d)?),
|
||||||
cmd => return Err(d.error(format!("unrecognized network command `{}`", cmd)))
|
_ => return Err(serialize::Error::UnrecognizedNetworkCommand(cmd)),
|
||||||
};
|
};
|
||||||
Ok(RawNetworkMessage {
|
Ok(RawNetworkMessage {
|
||||||
magic: magic,
|
magic: magic,
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
use network::constants;
|
use network::constants;
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleDecoder, SimpleEncoder};
|
use network::serialize::{self, SimpleDecoder, SimpleEncoder};
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
@ -103,7 +103,7 @@ impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash);
|
||||||
|
|
||||||
impl<S: SimpleEncoder> ConsensusEncodable<S> for Inventory {
|
impl<S: SimpleEncoder> ConsensusEncodable<S> for Inventory {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
match self.inv_type {
|
match self.inv_type {
|
||||||
InvType::Error => 0u32,
|
InvType::Error => 0u32,
|
||||||
InvType::Transaction => 1,
|
InvType::Transaction => 1,
|
||||||
|
@ -117,7 +117,7 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for Inventory {
|
||||||
|
|
||||||
impl<D: SimpleDecoder> ConsensusDecodable<D> for Inventory {
|
impl<D: SimpleDecoder> ConsensusDecodable<D> for Inventory {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode(d: &mut D) -> Result<Inventory, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<Inventory, serialize::Error> {
|
||||||
let int_type: u32 = ConsensusDecodable::consensus_decode(d)?;
|
let int_type: u32 = ConsensusDecodable::consensus_decode(d)?;
|
||||||
Ok(Inventory {
|
Ok(Inventory {
|
||||||
inv_type: match int_type {
|
inv_type: match int_type {
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
//! of Bitcoin data and network messages.
|
//! of Bitcoin data and network messages.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
|
use std::error;
|
||||||
|
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
pub mod consensus_params;
|
pub mod consensus_params;
|
||||||
pub mod encodable;
|
pub mod encodable;
|
||||||
|
@ -30,3 +34,39 @@ pub mod message;
|
||||||
pub mod message_blockdata;
|
pub mod message_blockdata;
|
||||||
pub mod message_network;
|
pub mod message_network;
|
||||||
|
|
||||||
|
/// Network error
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// And I/O error
|
||||||
|
Io(io::Error),
|
||||||
|
/// Socket mutex was poisoned
|
||||||
|
SocketMutexPoisoned,
|
||||||
|
/// Not connected to peer
|
||||||
|
SocketNotConnectedToPeer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Error::Io(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Error::SocketMutexPoisoned | Error::SocketNotConnectedToPeer => f.write_str(error::Error::description(self)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for Error {
|
||||||
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
|
match *self {
|
||||||
|
Error::Io(ref e) => Some(e),
|
||||||
|
Error::SocketMutexPoisoned | Error::SocketNotConnectedToPeer => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
Error::Io(ref e) => e.description(),
|
||||||
|
Error::SocketMutexPoisoned => "socket mutex was poisoned",
|
||||||
|
Error::SocketNotConnectedToPeer => "not connected to peer",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,13 +19,144 @@
|
||||||
//! It also defines (de)serialization routines for many primitives.
|
//! It also defines (de)serialization routines for many primitives.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
use std::io::{Cursor, Read, Write};
|
use std::io::{Cursor, Read, Write};
|
||||||
use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt};
|
use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt};
|
||||||
use hex::encode as hex_encode;
|
use hex::encode as hex_encode;
|
||||||
|
|
||||||
|
use bitcoin_bech32;
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
|
use util::base58;
|
||||||
use util::hash::Sha256dHash;
|
use util::hash::Sha256dHash;
|
||||||
use util;
|
|
||||||
|
/// Serialization error
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// And I/O error
|
||||||
|
Io(io::Error),
|
||||||
|
/// Base58 encoding error
|
||||||
|
Base58(base58::Error),
|
||||||
|
/// Bech32 encoding error
|
||||||
|
Bech32(bitcoin_bech32::Error),
|
||||||
|
/// Error from the `byteorder` crate
|
||||||
|
ByteOrder(io::Error),
|
||||||
|
/// Network magic was not expected
|
||||||
|
UnexpectedNetworkMagic {
|
||||||
|
/// The expected network magic
|
||||||
|
expected: u32,
|
||||||
|
/// The unexpected network magic
|
||||||
|
actual: u32,
|
||||||
|
},
|
||||||
|
/// Tried to allocate an oversized vector
|
||||||
|
OversizedVectorAllocation{
|
||||||
|
/// The capacity requested
|
||||||
|
requested: usize,
|
||||||
|
/// The maximum capacity
|
||||||
|
max: usize,
|
||||||
|
},
|
||||||
|
/// Checksum was invalid
|
||||||
|
InvalidChecksum {
|
||||||
|
/// The expected checksum
|
||||||
|
expected: [u8; 4],
|
||||||
|
/// The invalid checksum
|
||||||
|
actual: [u8; 4],
|
||||||
|
},
|
||||||
|
/// Network magic was unknown
|
||||||
|
UnknownNetworkMagic(u32),
|
||||||
|
/// Parsing error
|
||||||
|
ParseFailed(&'static str),
|
||||||
|
/// Unsupported witness version
|
||||||
|
UnsupportedWitnessVersion(u8),
|
||||||
|
/// Unsupported Segwit flag
|
||||||
|
UnsupportedSegwitFlag(u8),
|
||||||
|
/// Unrecognized network command
|
||||||
|
UnrecognizedNetworkCommand(String),
|
||||||
|
/// Unexpected hex digit
|
||||||
|
UnexpectedHexDigit(char),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Error::Io(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Error::Base58(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Error::Bech32(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Error::ByteOrder(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e, a),
|
||||||
|
Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "{}: requested {}, maximum {}", error::Error::description(self), r, m),
|
||||||
|
Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), hex_encode(e), hex_encode(a)),
|
||||||
|
Error::UnknownNetworkMagic(ref m) => write!(f, "{}: {}", error::Error::description(self), m),
|
||||||
|
Error::ParseFailed(ref e) => write!(f, "{}: {}", error::Error::description(self), e),
|
||||||
|
Error::UnsupportedWitnessVersion(ref wver) => write!(f, "{}: {}", error::Error::description(self), wver),
|
||||||
|
Error::UnsupportedSegwitFlag(ref swflag) => write!(f, "{}: {}", error::Error::description(self), swflag),
|
||||||
|
Error::UnrecognizedNetworkCommand(ref nwcmd) => write!(f, "{}: {}", error::Error::description(self), nwcmd),
|
||||||
|
Error::UnexpectedHexDigit(ref d) => write!(f, "{}: {}", error::Error::description(self), d),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for Error {
|
||||||
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
|
match *self {
|
||||||
|
Error::Io(ref e) => Some(e),
|
||||||
|
Error::Base58(ref e) => Some(e),
|
||||||
|
Error::Bech32(ref e) => Some(e),
|
||||||
|
Error::ByteOrder(ref e) => Some(e),
|
||||||
|
Error::UnexpectedNetworkMagic { .. }
|
||||||
|
| Error::OversizedVectorAllocation { .. }
|
||||||
|
| Error::InvalidChecksum { .. }
|
||||||
|
| Error::UnknownNetworkMagic(..)
|
||||||
|
| Error::ParseFailed(..)
|
||||||
|
| Error::UnsupportedWitnessVersion(..)
|
||||||
|
| Error::UnsupportedSegwitFlag(..)
|
||||||
|
| Error::UnrecognizedNetworkCommand(..)
|
||||||
|
| Error::UnexpectedHexDigit(..) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
Error::Io(ref e) => e.description(),
|
||||||
|
Error::Base58(ref e) => e.description(),
|
||||||
|
Error::Bech32(ref e) => e.description(),
|
||||||
|
Error::ByteOrder(ref e) => e.description(),
|
||||||
|
Error::UnexpectedNetworkMagic { .. } => "unexpected network magic",
|
||||||
|
Error::OversizedVectorAllocation { .. } => "allocation of oversized vector requested",
|
||||||
|
Error::InvalidChecksum { .. } => "invalid checksum",
|
||||||
|
Error::UnknownNetworkMagic(..) => "unknown network magic",
|
||||||
|
Error::ParseFailed(..) => "parse failed",
|
||||||
|
Error::UnsupportedWitnessVersion(..) => "unsupported witness version",
|
||||||
|
Error::UnsupportedSegwitFlag(..) => "unsupported segwit version",
|
||||||
|
Error::UnrecognizedNetworkCommand(..) => "unrecognized network command",
|
||||||
|
Error::UnexpectedHexDigit(..) => "unexpected hex digit",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl From<base58::Error> for Error {
|
||||||
|
fn from(e: base58::Error) -> Error {
|
||||||
|
Error::Base58(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl From<bitcoin_bech32::Error> for Error {
|
||||||
|
fn from(e: bitcoin_bech32::Error) -> Error {
|
||||||
|
Error::Bech32(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(error: io::Error) -> Self {
|
||||||
|
Error::Io(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Objects which are referred to by hash
|
/// Objects which are referred to by hash
|
||||||
pub trait BitcoinHash {
|
pub trait BitcoinHash {
|
||||||
|
@ -41,7 +172,7 @@ impl BitcoinHash for Vec<u8> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode an object into a vector
|
/// Encode an object into a vector
|
||||||
pub fn serialize<T: ?Sized>(data: &T) -> Result<Vec<u8>, util::Error>
|
pub fn serialize<T: ?Sized>(data: &T) -> Result<Vec<u8>, Error>
|
||||||
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>,
|
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>,
|
||||||
{
|
{
|
||||||
let mut encoder = RawEncoder::new(Cursor::new(vec![]));
|
let mut encoder = RawEncoder::new(Cursor::new(vec![]));
|
||||||
|
@ -50,7 +181,7 @@ pub fn serialize<T: ?Sized>(data: &T) -> Result<Vec<u8>, util::Error>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode an object into a hex-encoded string
|
/// Encode an object into a hex-encoded string
|
||||||
pub fn serialize_hex<T: ?Sized>(data: &T) -> Result<String, util::Error>
|
pub fn serialize_hex<T: ?Sized>(data: &T) -> Result<String, Error>
|
||||||
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>
|
where T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>
|
||||||
{
|
{
|
||||||
let serial = serialize(data)?;
|
let serial = serialize(data)?;
|
||||||
|
@ -59,7 +190,7 @@ pub fn serialize_hex<T: ?Sized>(data: &T) -> Result<String, util::Error>
|
||||||
|
|
||||||
/// Deserialize an object from a vector, will error if said deserialization
|
/// Deserialize an object from a vector, will error if said deserialization
|
||||||
/// doesn't consume the entire vector.
|
/// doesn't consume the entire vector.
|
||||||
pub fn deserialize<'a, T>(data: &'a [u8]) -> Result<T, util::Error>
|
pub fn deserialize<'a, T>(data: &'a [u8]) -> Result<T, Error>
|
||||||
where T: ConsensusDecodable<RawDecoder<Cursor<&'a [u8]>>>
|
where T: ConsensusDecodable<RawDecoder<Cursor<&'a [u8]>>>
|
||||||
{
|
{
|
||||||
let mut decoder = RawDecoder::new(Cursor::new(data));
|
let mut decoder = RawDecoder::new(Cursor::new(data));
|
||||||
|
@ -69,7 +200,7 @@ pub fn deserialize<'a, T>(data: &'a [u8]) -> Result<T, util::Error>
|
||||||
if decoder.into_inner().position() == data.len() as u64 {
|
if decoder.into_inner().position() == data.len() as u64 {
|
||||||
Ok(rv)
|
Ok(rv)
|
||||||
} else {
|
} else {
|
||||||
Err(util::Error::ParseFailed)
|
Err(Error::ParseFailed("data not consumed entirely when explicitly deserializing"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,66 +230,57 @@ impl<R: Read> RawDecoder<R> {
|
||||||
|
|
||||||
/// A simple Encoder trait
|
/// A simple Encoder trait
|
||||||
pub trait SimpleEncoder {
|
pub trait SimpleEncoder {
|
||||||
/// An encoding error
|
|
||||||
type Error;
|
|
||||||
|
|
||||||
/// Output a 64-bit uint
|
/// Output a 64-bit uint
|
||||||
fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
|
fn emit_u64(&mut self, v: u64) -> Result<(), Error>;
|
||||||
/// Output a 32-bit uint
|
/// Output a 32-bit uint
|
||||||
fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>;
|
fn emit_u32(&mut self, v: u32) -> Result<(), Error>;
|
||||||
/// Output a 16-bit uint
|
/// Output a 16-bit uint
|
||||||
fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>;
|
fn emit_u16(&mut self, v: u16) -> Result<(), Error>;
|
||||||
/// Output a 8-bit uint
|
/// Output a 8-bit uint
|
||||||
fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>;
|
fn emit_u8(&mut self, v: u8) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Output a 64-bit int
|
/// Output a 64-bit int
|
||||||
fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
|
fn emit_i64(&mut self, v: i64) -> Result<(), Error>;
|
||||||
/// Output a 32-bit int
|
/// Output a 32-bit int
|
||||||
fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>;
|
fn emit_i32(&mut self, v: i32) -> Result<(), Error>;
|
||||||
/// Output a 16-bit int
|
/// Output a 16-bit int
|
||||||
fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>;
|
fn emit_i16(&mut self, v: i16) -> Result<(), Error>;
|
||||||
/// Output a 8-bit int
|
/// Output a 8-bit int
|
||||||
fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>;
|
fn emit_i8(&mut self, v: i8) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Output a boolean
|
/// Output a boolean
|
||||||
fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>;
|
fn emit_bool(&mut self, v: bool) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple Decoder trait
|
/// A simple Decoder trait
|
||||||
pub trait SimpleDecoder {
|
pub trait SimpleDecoder {
|
||||||
/// A decoding error
|
|
||||||
type Error;
|
|
||||||
|
|
||||||
/// Read a 64-bit uint
|
/// Read a 64-bit uint
|
||||||
fn read_u64(&mut self) -> Result<u64, Self::Error>;
|
fn read_u64(&mut self) -> Result<u64, Error>;
|
||||||
/// Read a 32-bit uint
|
/// Read a 32-bit uint
|
||||||
fn read_u32(&mut self) -> Result<u32, Self::Error>;
|
fn read_u32(&mut self) -> Result<u32, Error>;
|
||||||
/// Read a 16-bit uint
|
/// Read a 16-bit uint
|
||||||
fn read_u16(&mut self) -> Result<u16, Self::Error>;
|
fn read_u16(&mut self) -> Result<u16, Error>;
|
||||||
/// Read a 8-bit uint
|
/// Read a 8-bit uint
|
||||||
fn read_u8(&mut self) -> Result<u8, Self::Error>;
|
fn read_u8(&mut self) -> Result<u8, Error>;
|
||||||
|
|
||||||
/// Read a 64-bit int
|
/// Read a 64-bit int
|
||||||
fn read_i64(&mut self) -> Result<i64, Self::Error>;
|
fn read_i64(&mut self) -> Result<i64, Error>;
|
||||||
/// Read a 32-bit int
|
/// Read a 32-bit int
|
||||||
fn read_i32(&mut self) -> Result<i32, Self::Error>;
|
fn read_i32(&mut self) -> Result<i32, Error>;
|
||||||
/// Read a 16-bit int
|
/// Read a 16-bit int
|
||||||
fn read_i16(&mut self) -> Result<i16, Self::Error>;
|
fn read_i16(&mut self) -> Result<i16, Error>;
|
||||||
/// Read a 8-bit int
|
/// Read a 8-bit int
|
||||||
fn read_i8(&mut self) -> Result<i8, Self::Error>;
|
fn read_i8(&mut self) -> Result<i8, Error>;
|
||||||
|
|
||||||
/// Read a boolean
|
/// Read a boolean
|
||||||
fn read_bool(&mut self) -> Result<bool, Self::Error>;
|
fn read_bool(&mut self) -> Result<bool, Error>;
|
||||||
|
|
||||||
/// Signal a decoding error
|
|
||||||
fn error(&mut self, err: String) -> Self::Error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! encoder_fn {
|
macro_rules! encoder_fn {
|
||||||
($name:ident, $val_type:ty, $writefn:ident) => {
|
($name:ident, $val_type:ty, $writefn:ident) => {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $name(&mut self, v: $val_type) -> Result<(), util::Error> {
|
fn $name(&mut self, v: $val_type) -> Result<(), Error> {
|
||||||
self.writer.$writefn::<LittleEndian>(v).map_err(util::Error::ByteOrder)
|
self.writer.$writefn::<LittleEndian>(v).map_err(Error::Io)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,15 +288,13 @@ macro_rules! encoder_fn {
|
||||||
macro_rules! decoder_fn {
|
macro_rules! decoder_fn {
|
||||||
($name:ident, $val_type:ty, $readfn:ident) => {
|
($name:ident, $val_type:ty, $readfn:ident) => {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $name(&mut self) -> Result<$val_type, util::Error> {
|
fn $name(&mut self) -> Result<$val_type, Error> {
|
||||||
self.reader.$readfn::<LittleEndian>().map_err(util::Error::ByteOrder)
|
self.reader.$readfn::<LittleEndian>().map_err(Error::Io)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write> SimpleEncoder for RawEncoder<W> {
|
impl<W: Write> SimpleEncoder for RawEncoder<W> {
|
||||||
type Error = util::Error;
|
|
||||||
|
|
||||||
encoder_fn!(emit_u64, u64, write_u64);
|
encoder_fn!(emit_u64, u64, write_u64);
|
||||||
encoder_fn!(emit_u32, u32, write_u32);
|
encoder_fn!(emit_u32, u32, write_u32);
|
||||||
encoder_fn!(emit_u16, u16, write_u16);
|
encoder_fn!(emit_u16, u16, write_u16);
|
||||||
|
@ -183,22 +303,20 @@ impl<W: Write> SimpleEncoder for RawEncoder<W> {
|
||||||
encoder_fn!(emit_i16, i16, write_i16);
|
encoder_fn!(emit_i16, i16, write_i16);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn emit_i8(&mut self, v: i8) -> Result<(), util::Error> {
|
fn emit_i8(&mut self, v: i8) -> Result<(), Error> {
|
||||||
self.writer.write_i8(v).map_err(util::Error::ByteOrder)
|
self.writer.write_i8(v).map_err(Error::Io)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn emit_u8(&mut self, v: u8) -> Result<(), util::Error> {
|
fn emit_u8(&mut self, v: u8) -> Result<(), Error> {
|
||||||
self.writer.write_u8(v).map_err(util::Error::ByteOrder)
|
self.writer.write_u8(v).map_err(Error::Io)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn emit_bool(&mut self, v: bool) -> Result<(), util::Error> {
|
fn emit_bool(&mut self, v: bool) -> Result<(), Error> {
|
||||||
self.writer.write_i8(if v {1} else {0}).map_err(util::Error::ByteOrder)
|
self.writer.write_i8(if v {1} else {0}).map_err(Error::Io)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read> SimpleDecoder for RawDecoder<R> {
|
impl<R: Read> SimpleDecoder for RawDecoder<R> {
|
||||||
type Error = util::Error;
|
|
||||||
|
|
||||||
decoder_fn!(read_u64, u64, read_u64);
|
decoder_fn!(read_u64, u64, read_u64);
|
||||||
decoder_fn!(read_u32, u32, read_u32);
|
decoder_fn!(read_u32, u32, read_u32);
|
||||||
decoder_fn!(read_u16, u16, read_u16);
|
decoder_fn!(read_u16, u16, read_u16);
|
||||||
|
@ -207,25 +325,20 @@ impl<R: Read> SimpleDecoder for RawDecoder<R> {
|
||||||
decoder_fn!(read_i16, i16, read_i16);
|
decoder_fn!(read_i16, i16, read_i16);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_u8(&mut self) -> Result<u8, util::Error> {
|
fn read_u8(&mut self) -> Result<u8, Error> {
|
||||||
self.reader.read_u8().map_err(util::Error::ByteOrder)
|
self.reader.read_u8().map_err(Error::Io)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_i8(&mut self) -> Result<i8, util::Error> {
|
fn read_i8(&mut self) -> Result<i8, Error> {
|
||||||
self.reader.read_i8().map_err(util::Error::ByteOrder)
|
self.reader.read_i8().map_err(Error::Io)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_bool(&mut self) -> Result<bool, util::Error> {
|
fn read_bool(&mut self) -> Result<bool, Error> {
|
||||||
match self.reader.read_i8() {
|
match self.reader.read_i8() {
|
||||||
Ok(bit) => Ok(bit != 0),
|
Ok(bit) => Ok(bit != 0),
|
||||||
Err(e) => Err(util::Error::ByteOrder(e))
|
Err(e) => Err(Error::Io(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn error(&mut self, err: String) -> util::Error {
|
|
||||||
util::Error::Detail(err, Box::new(util::Error::ParseFailed))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aren't really any tests here.. the main functions are serialize and
|
// Aren't really any tests here.. the main functions are serialize and
|
||||||
|
|
|
@ -19,18 +19,19 @@
|
||||||
|
|
||||||
use std::time::{UNIX_EPOCH, SystemTime};
|
use std::time::{UNIX_EPOCH, SystemTime};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use std::io::{self, Write};
|
use std::io::Write;
|
||||||
use std::net;
|
use std::net;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use network;
|
||||||
use network::constants;
|
use network::constants;
|
||||||
use network::address::Address;
|
use network::address::Address;
|
||||||
use network::encodable::{ConsensusEncodable, ConsensusDecodable};
|
use network::encodable::{ConsensusEncodable, ConsensusDecodable};
|
||||||
use network::message::{RawNetworkMessage, NetworkMessage};
|
use network::message::{RawNetworkMessage, NetworkMessage};
|
||||||
use network::message::NetworkMessage::Version;
|
use network::message::NetworkMessage::Version;
|
||||||
use network::message_network::VersionMessage;
|
use network::message_network::VersionMessage;
|
||||||
use network::serialize::{RawEncoder, RawDecoder};
|
use network::serialize::{self, RawEncoder, RawDecoder};
|
||||||
use util::{self, propagate_err};
|
use util;
|
||||||
|
|
||||||
/// Format an IP address in the 16-byte bitcoin protocol serialization
|
/// Format an IP address in the 16-byte bitcoin protocol serialization
|
||||||
fn ipaddr_to_bitcoin_addr(addr: &net::SocketAddr) -> [u16; 8] {
|
fn ipaddr_to_bitcoin_addr(addr: &net::SocketAddr) -> [u16; 8] {
|
||||||
|
@ -60,9 +61,7 @@ macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({
|
||||||
let sock_lock = $s.socket.lock();
|
let sock_lock = $s.socket.lock();
|
||||||
match sock_lock {
|
match sock_lock {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
Err(network::Error::SocketMutexPoisoned.into())
|
||||||
"socket: socket mutex was poisoned");
|
|
||||||
Err(util::Error::Io(io_err))
|
|
||||||
}
|
}
|
||||||
Ok(mut guard) => {
|
Ok(mut guard) => {
|
||||||
match *guard.deref_mut() {
|
match *guard.deref_mut() {
|
||||||
|
@ -70,16 +69,13 @@ macro_rules! with_socket(($s:ident, $sock:ident, $body:block) => ({
|
||||||
$body
|
$body
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let io_err = io::Error::new(io::ErrorKind::NotConnected,
|
Err(network::Error::SocketNotConnectedToPeer.into())
|
||||||
"socket: not connected to peer");
|
|
||||||
Err(util::Error::Io(io_err))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
impl Socket {
|
impl Socket {
|
||||||
// TODO: we fix services to 0
|
// TODO: we fix services to 0
|
||||||
/// Construct a new socket
|
/// Construct a new socket
|
||||||
|
@ -95,7 +91,7 @@ impl Socket {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// (Re)connect to the peer
|
/// (Re)connect to the peer
|
||||||
pub fn connect(&mut self, host: &str, port: u16) -> Result<(), util::Error> {
|
pub fn connect(&mut self, host: &str, port: u16) -> Result<(), network::Error> {
|
||||||
// Entirely replace the Mutex, in case it was poisoned;
|
// Entirely replace the Mutex, in case it was poisoned;
|
||||||
// this will also drop any preexisting socket that might be open
|
// this will also drop any preexisting socket that might be open
|
||||||
match net::TcpStream::connect((host, port)) {
|
match net::TcpStream::connect((host, port)) {
|
||||||
|
@ -105,13 +101,13 @@ impl Socket {
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.socket = Arc::new(Mutex::new(None));
|
self.socket = Arc::new(Mutex::new(None));
|
||||||
Err(util::Error::Io(e))
|
Err(network::Error::Io(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peer address
|
/// Peer address
|
||||||
pub fn receiver_address(&mut self) -> Result<Address, util::Error> {
|
pub fn receiver_address(&mut self) -> Result<Address, network::Error> {
|
||||||
with_socket!(self, sock, {
|
with_socket!(self, sock, {
|
||||||
match sock.peer_addr() {
|
match sock.peer_addr() {
|
||||||
Ok(addr) => {
|
Ok(addr) => {
|
||||||
|
@ -121,13 +117,13 @@ impl Socket {
|
||||||
port: addr.port()
|
port: addr.port()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Err(e) => Err(util::Error::Io(e))
|
Err(e) => Err(network::Error::Io(e))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Our own address
|
/// Our own address
|
||||||
pub fn sender_address(&mut self) -> Result<Address, util::Error> {
|
pub fn sender_address(&mut self) -> Result<Address, network::Error> {
|
||||||
with_socket!(self, sock, {
|
with_socket!(self, sock, {
|
||||||
match sock.local_addr() {
|
match sock.local_addr() {
|
||||||
Ok(addr) => {
|
Ok(addr) => {
|
||||||
|
@ -137,13 +133,13 @@ impl Socket {
|
||||||
port: addr.port()
|
port: addr.port()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Err(e) => Err(util::Error::Io(e))
|
Err(e) => Err(network::Error::Io(e))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a version message appropriate for this socket
|
/// Produce a version message appropriate for this socket
|
||||||
pub fn version_message(&mut self, start_height: i32) -> Result<NetworkMessage, util::Error> {
|
pub fn version_message(&mut self, start_height: i32) -> Result<NetworkMessage, network::Error> {
|
||||||
let recv_addr = self.receiver_address()?;
|
let recv_addr = self.receiver_address()?;
|
||||||
let send_addr = self.sender_address()?;
|
let send_addr = self.sender_address()?;
|
||||||
let timestamp = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
let timestamp = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||||
|
@ -169,7 +165,7 @@ impl Socket {
|
||||||
with_socket!(self, sock, {
|
with_socket!(self, sock, {
|
||||||
let message = RawNetworkMessage { magic: self.magic, payload: payload };
|
let message = RawNetworkMessage { magic: self.magic, payload: payload };
|
||||||
message.consensus_encode(&mut RawEncoder::new(&mut *sock))?;
|
message.consensus_encode(&mut RawEncoder::new(&mut *sock))?;
|
||||||
sock.flush().map_err(util::Error::Io)
|
sock.flush().map_err(network::Error::Io).map_err(util::Error::Network)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,21 +176,18 @@ impl Socket {
|
||||||
// We need a new scope since the closure in here borrows read_err,
|
// We need a new scope since the closure in here borrows read_err,
|
||||||
// and we try to read it afterward. Letting `iter` go out fixes it.
|
// and we try to read it afterward. Letting `iter` go out fixes it.
|
||||||
let mut decoder = RawDecoder::new(sock);
|
let mut decoder = RawDecoder::new(sock);
|
||||||
let decode: Result<RawNetworkMessage, _> = ConsensusDecodable::consensus_decode(&mut decoder);
|
|
||||||
match decode {
|
let decoded: RawNetworkMessage = ConsensusDecodable::consensus_decode(&mut decoder)?;
|
||||||
// Check for parse errors...
|
|
||||||
Err(e) => {
|
// Then for magic (this should come before parse error, but we can't
|
||||||
propagate_err("receive_message".to_owned(), Err(e))
|
// get to it if the deserialization failed). TODO restructure this
|
||||||
},
|
if decoded.magic != self.magic {
|
||||||
Ok(ret) => {
|
Err(serialize::Error::UnexpectedNetworkMagic {
|
||||||
// Then for magic (this should come before parse error, but we can't
|
expected: self.magic,
|
||||||
// get to it if the deserialization failed). TODO restructure this
|
actual: decoded.magic,
|
||||||
if ret.magic != self.magic {
|
}.into())
|
||||||
Err(util::Error::BadNetworkMagic(self.magic, ret.magic))
|
} else {
|
||||||
} else {
|
Ok(decoded.payload)
|
||||||
Ok(ret.payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@ use secp256k1::key::PublicKey;
|
||||||
use blockdata::script;
|
use blockdata::script;
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
|
use network::serialize;
|
||||||
use util::hash::Hash160;
|
use util::hash::Hash160;
|
||||||
use util::base58;
|
use util::base58;
|
||||||
use util::Error;
|
|
||||||
|
|
||||||
/// The method used to produce an address
|
/// The method used to produce an address
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
@ -243,9 +243,9 @@ impl Display for Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Address {
|
impl FromStr for Address {
|
||||||
type Err = Error;
|
type Err = serialize::Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Address, Error> {
|
fn from_str(s: &str) -> Result<Address, serialize::Error> {
|
||||||
// bech32 (note that upper or lowercase is allowed but NOT mixed case)
|
// bech32 (note that upper or lowercase is allowed but NOT mixed case)
|
||||||
if s.starts_with("bc1") || s.starts_with("BC1") ||
|
if s.starts_with("bc1") || s.starts_with("BC1") ||
|
||||||
s.starts_with("tb1") || s.starts_with("TB1") ||
|
s.starts_with("tb1") || s.starts_with("TB1") ||
|
||||||
|
@ -259,7 +259,7 @@ impl FromStr for Address {
|
||||||
_ => panic!("unknown network")
|
_ => panic!("unknown network")
|
||||||
};
|
};
|
||||||
if witprog.version().to_u8() != 0 {
|
if witprog.version().to_u8() != 0 {
|
||||||
return Err(Error::UnsupportedWitnessVersion(witprog.version().to_u8()));
|
return Err(serialize::Error::UnsupportedWitnessVersion(witprog.version().to_u8()));
|
||||||
}
|
}
|
||||||
return Ok(Address {
|
return Ok(Address {
|
||||||
network: network,
|
network: network,
|
||||||
|
@ -268,14 +268,14 @@ impl FromStr for Address {
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.len() > 50 {
|
if s.len() > 50 {
|
||||||
return Err(Error::Base58(base58::Error::InvalidLength(s.len() * 11 / 15)));
|
return Err(serialize::Error::Base58(base58::Error::InvalidLength(s.len() * 11 / 15)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base 58
|
// Base 58
|
||||||
let data = base58::from_check(s)?;
|
let data = base58::from_check(s)?;
|
||||||
|
|
||||||
if data.len() != 21 {
|
if data.len() != 21 {
|
||||||
return Err(Error::Base58(base58::Error::InvalidLength(data.len())));
|
return Err(serialize::Error::Base58(base58::Error::InvalidLength(data.len())));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (network, payload) = match data[0] {
|
let (network, payload) = match data[0] {
|
||||||
|
@ -295,7 +295,7 @@ impl FromStr for Address {
|
||||||
Network::Testnet,
|
Network::Testnet,
|
||||||
Payload::ScriptHash(Hash160::from(&data[1..]))
|
Payload::ScriptHash(Hash160::from(&data[1..]))
|
||||||
),
|
),
|
||||||
x => return Err(Error::Base58(base58::Error::InvalidVersion(vec![x])))
|
x => return Err(serialize::Error::Base58(base58::Error::InvalidVersion(vec![x])))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Address {
|
Ok(Address {
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crypto::digest::Digest;
|
||||||
use crypto::ripemd160::Ripemd160;
|
use crypto::ripemd160::Ripemd160;
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleEncoder, RawEncoder, BitcoinHash};
|
use network::serialize::{self, SimpleEncoder, RawEncoder, BitcoinHash};
|
||||||
use util::uint::Uint256;
|
use util::uint::Uint256;
|
||||||
|
|
||||||
#[cfg(feature="fuzztarget")] use util::sha2::Sha256;
|
#[cfg(feature="fuzztarget")] use util::sha2::Sha256;
|
||||||
|
@ -108,61 +108,59 @@ impl Sha256dEncoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimpleEncoder for Sha256dEncoder {
|
impl SimpleEncoder for Sha256dEncoder {
|
||||||
type Error = ();
|
fn emit_u64(&mut self, v: u64) -> Result<(), serialize::Error> {
|
||||||
|
|
||||||
fn emit_u64(&mut self, v: u64) -> Result<(), ()> {
|
|
||||||
let mut data = [0; 8];
|
let mut data = [0; 8];
|
||||||
(&mut data[..]).write_u64::<LittleEndian>(v).unwrap();
|
(&mut data[..]).write_u64::<LittleEndian>(v).unwrap();
|
||||||
self.0.input(&data);
|
self.0.input(&data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_u32(&mut self, v: u32) -> Result<(), ()> {
|
fn emit_u32(&mut self, v: u32) -> Result<(), serialize::Error> {
|
||||||
let mut data = [0; 4];
|
let mut data = [0; 4];
|
||||||
(&mut data[..]).write_u32::<LittleEndian>(v).unwrap();
|
(&mut data[..]).write_u32::<LittleEndian>(v).unwrap();
|
||||||
self.0.input(&data);
|
self.0.input(&data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_u16(&mut self, v: u16) -> Result<(), ()> {
|
fn emit_u16(&mut self, v: u16) -> Result<(), serialize::Error> {
|
||||||
let mut data = [0; 2];
|
let mut data = [0; 2];
|
||||||
(&mut data[..]).write_u16::<LittleEndian>(v).unwrap();
|
(&mut data[..]).write_u16::<LittleEndian>(v).unwrap();
|
||||||
self.0.input(&data);
|
self.0.input(&data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_i64(&mut self, v: i64) -> Result<(), ()> {
|
fn emit_i64(&mut self, v: i64) -> Result<(), serialize::Error> {
|
||||||
let mut data = [0; 8];
|
let mut data = [0; 8];
|
||||||
(&mut data[..]).write_i64::<LittleEndian>(v).unwrap();
|
(&mut data[..]).write_i64::<LittleEndian>(v).unwrap();
|
||||||
self.0.input(&data);
|
self.0.input(&data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_i32(&mut self, v: i32) -> Result<(), ()> {
|
fn emit_i32(&mut self, v: i32) -> Result<(), serialize::Error> {
|
||||||
let mut data = [0; 4];
|
let mut data = [0; 4];
|
||||||
(&mut data[..]).write_i32::<LittleEndian>(v).unwrap();
|
(&mut data[..]).write_i32::<LittleEndian>(v).unwrap();
|
||||||
self.0.input(&data);
|
self.0.input(&data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_i16(&mut self, v: i16) -> Result<(), ()> {
|
fn emit_i16(&mut self, v: i16) -> Result<(), serialize::Error> {
|
||||||
let mut data = [0; 2];
|
let mut data = [0; 2];
|
||||||
(&mut data[..]).write_i16::<LittleEndian>(v).unwrap();
|
(&mut data[..]).write_i16::<LittleEndian>(v).unwrap();
|
||||||
self.0.input(&data);
|
self.0.input(&data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_i8(&mut self, v: i8) -> Result<(), ()> {
|
fn emit_i8(&mut self, v: i8) -> Result<(), serialize::Error> {
|
||||||
self.0.input(&[v as u8]);
|
self.0.input(&[v as u8]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_u8(&mut self, v: u8) -> Result<(), ()> {
|
fn emit_u8(&mut self, v: u8) -> Result<(), serialize::Error> {
|
||||||
self.0.input(&[v]);
|
self.0.input(&[v]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_bool(&mut self, v: bool) -> Result<(), ()> {
|
fn emit_bool(&mut self, v: bool) -> Result<(), serialize::Error> {
|
||||||
self.0.input(&[if v {1} else {0}]);
|
self.0.input(&[if v {1} else {0}]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
//! Various utility functions
|
//! Various utility functions
|
||||||
|
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use util::Error;
|
|
||||||
use util::iter::Pairable;
|
use util::iter::Pairable;
|
||||||
|
use network::serialize;
|
||||||
|
|
||||||
/// Convert a hexadecimal-encoded string to its corresponding bytes
|
/// Convert a hexadecimal-encoded string to its corresponding bytes
|
||||||
pub fn hex_bytes(s: &str) -> Result<Vec<u8>, Error> {
|
pub fn hex_bytes(s: &str) -> Result<Vec<u8>, serialize::Error> {
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
let mut iter = s.chars().pair();
|
let mut iter = s.chars().pair();
|
||||||
// Do the parsing
|
// Do the parsing
|
||||||
|
@ -29,37 +29,19 @@ pub fn hex_bytes(s: &str) -> Result<Vec<u8>, Error> {
|
||||||
if e.is_err() { e }
|
if e.is_err() { e }
|
||||||
else {
|
else {
|
||||||
match (f.to_digit(16), s.to_digit(16)) {
|
match (f.to_digit(16), s.to_digit(16)) {
|
||||||
(None, _) => Err(Error::Detail(
|
(None, _) => Err(serialize::Error::UnexpectedHexDigit(f)),
|
||||||
format!("expected hex, got {:}", f),
|
(_, None) => Err(serialize::Error::UnexpectedHexDigit(s)),
|
||||||
Box::new(Error::ParseFailed)
|
|
||||||
)),
|
|
||||||
(_, None) => Err(Error::Detail(
|
|
||||||
format!("expected hex, got {:}", s),
|
|
||||||
Box::new(Error::ParseFailed)
|
|
||||||
)),
|
|
||||||
(Some(f), Some(s)) => { v.push((f * 0x10 + s) as u8); Ok(()) }
|
(Some(f), Some(s)) => { v.push((f * 0x10 + s) as u8); Ok(()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
// Check that there was no remainder
|
// Check that there was no remainder
|
||||||
match iter.remainder() {
|
match iter.remainder() {
|
||||||
Some(_) => Err(Error::Detail(
|
Some(_) => Err(serialize::Error::ParseFailed("hexstring of odd length")),
|
||||||
"hexstring of odd length".to_owned(),
|
|
||||||
Box::new(Error::ParseFailed)
|
|
||||||
)),
|
|
||||||
None => Ok(v)
|
None => Ok(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dump an error message to the screen
|
|
||||||
/// TODO all uses of this should be replaced with some sort of logging infrastructure
|
|
||||||
pub fn consume_err<T>(s: &str, res: Result<T, Error>) {
|
|
||||||
match res {
|
|
||||||
Ok(_) => {},
|
|
||||||
Err(e) => { println!("{}: {:?}", s, e); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Search for `needle` in the vector `haystack` and remove every
|
/// Search for `needle` in the vector `haystack` and remove every
|
||||||
/// instance of it, returning the number of instances removed.
|
/// instance of it, returning the number of instances removed.
|
||||||
/// Loops through the vector opcode by opcode, skipping pushed data.
|
/// Loops through the vector opcode by opcode, skipping pushed data.
|
||||||
|
|
109
src/util/mod.rs
109
src/util/mod.rs
|
@ -31,11 +31,13 @@ pub mod uint;
|
||||||
#[cfg(feature = "fuzztarget")]
|
#[cfg(feature = "fuzztarget")]
|
||||||
pub mod sha2;
|
pub mod sha2;
|
||||||
|
|
||||||
use std::{error, fmt, io};
|
use std::{error, fmt};
|
||||||
|
|
||||||
use bitcoin_bech32;
|
|
||||||
use secp256k1;
|
use secp256k1;
|
||||||
|
|
||||||
|
use network;
|
||||||
|
use network::serialize;
|
||||||
|
|
||||||
/// A trait which allows numbers to act as fixed-size bit arrays
|
/// A trait which allows numbers to act as fixed-size bit arrays
|
||||||
pub trait BitArray {
|
pub trait BitArray {
|
||||||
/// Is bit set?
|
/// Is bit set?
|
||||||
|
@ -57,53 +59,29 @@ pub trait BitArray {
|
||||||
fn one() -> Self;
|
fn one() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A general error code
|
/// A general error code, other errors should implement conversions to/from this
|
||||||
|
/// if appropriate.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// An I/O error
|
|
||||||
Io(io::Error),
|
|
||||||
/// Base58 encoding error
|
|
||||||
Base58(base58::Error),
|
|
||||||
/// Bech32 encoding error
|
|
||||||
Bech32(bitcoin_bech32::Error),
|
|
||||||
/// Error from the `byteorder` crate
|
|
||||||
ByteOrder(io::Error),
|
|
||||||
/// Network magic was not what we expected
|
|
||||||
BadNetworkMagic(u32, u32),
|
|
||||||
/// Network message was unrecognized
|
|
||||||
BadNetworkMessage(String),
|
|
||||||
/// An object was attempted to be added twice
|
|
||||||
DuplicateHash,
|
|
||||||
/// Some operation was attempted on a block (or blockheader) that doesn't exist
|
|
||||||
BlockNotFound,
|
|
||||||
/// Parsing error
|
|
||||||
ParseFailed,
|
|
||||||
/// An object was added but it does not link into existing history
|
|
||||||
PrevHashNotFound,
|
|
||||||
/// secp-related error
|
/// secp-related error
|
||||||
Secp256k1(secp256k1::Error),
|
Secp256k1(secp256k1::Error),
|
||||||
/// The `target` field of a block header did not match the expected difficulty
|
/// Serialization error
|
||||||
SpvBadTarget,
|
Serialize(serialize::Error),
|
||||||
|
/// Network error
|
||||||
|
Network(network::Error),
|
||||||
/// The header hash is not below the target
|
/// The header hash is not below the target
|
||||||
SpvBadProofOfWork,
|
SpvBadProofOfWork,
|
||||||
/// Error propagated from subsystem
|
/// The `target` field of a block header did not match the expected difficulty
|
||||||
Detail(String, Box<Error>),
|
SpvBadTarget,
|
||||||
/// Unsupported witness version
|
|
||||||
UnsupportedWitnessVersion(u8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Error::Io(ref e) => fmt::Display::fmt(e, f),
|
|
||||||
Error::Base58(ref e) => fmt::Display::fmt(e, f),
|
|
||||||
Error::Bech32(ref e) => fmt::Display::fmt(e, f),
|
|
||||||
Error::ByteOrder(ref e) => fmt::Display::fmt(e, f),
|
|
||||||
Error::BadNetworkMagic(exp, got) => write!(f, "expected network magic 0x{:x}, got 0x{:x}", exp, got),
|
|
||||||
Error::BadNetworkMessage(ref got) => write!(f, "incorrect network message {}", got),
|
|
||||||
Error::Detail(ref s, ref e) => write!(f, "{}: {}", s, e),
|
|
||||||
Error::Secp256k1(ref e) => fmt::Display::fmt(e, f),
|
Error::Secp256k1(ref e) => fmt::Display::fmt(e, f),
|
||||||
ref x => f.write_str(error::Error::description(x))
|
Error::Serialize(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Error::Network(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Error::SpvBadProofOfWork | Error::SpvBadTarget => f.write_str(error::Error::description(self)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,56 +89,24 @@ impl fmt::Display for Error {
|
||||||
impl error::Error for Error {
|
impl error::Error for Error {
|
||||||
fn cause(&self) -> Option<&error::Error> {
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
Error::Io(ref e) => Some(e),
|
|
||||||
Error::Base58(ref e) => Some(e),
|
|
||||||
Error::Bech32(ref e) => Some(e),
|
|
||||||
Error::ByteOrder(ref e) => Some(e),
|
|
||||||
Error::Detail(_, ref e) => Some(e),
|
|
||||||
Error::Secp256k1(ref e) => Some(e),
|
Error::Secp256k1(ref e) => Some(e),
|
||||||
_ => None
|
Error::Serialize(ref e) => Some(e),
|
||||||
|
Error::Network(ref e) => Some(e),
|
||||||
|
Error::SpvBadProofOfWork | Error::SpvBadTarget => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
Error::Io(ref e) => e.description(),
|
|
||||||
Error::Base58(ref e) => e.description(),
|
|
||||||
Error::Bech32(ref e) => e.description(),
|
|
||||||
Error::ByteOrder(ref e) => e.description(),
|
|
||||||
Error::BadNetworkMagic(_, _) => "incorrect network magic",
|
|
||||||
Error::BadNetworkMessage(_) => "incorrect/unexpected network message",
|
|
||||||
Error::DuplicateHash => "duplicate hash",
|
|
||||||
Error::BlockNotFound => "no such block",
|
|
||||||
Error::ParseFailed => "parsing error",
|
|
||||||
Error::PrevHashNotFound => "prevhash not found",
|
|
||||||
Error::Secp256k1(ref e) => e.description(),
|
Error::Secp256k1(ref e) => e.description(),
|
||||||
Error::SpvBadTarget => "target incorrect",
|
Error::Serialize(ref e) => e.description(),
|
||||||
|
Error::Network(ref e) => e.description(),
|
||||||
Error::SpvBadProofOfWork => "target correct but not attained",
|
Error::SpvBadProofOfWork => "target correct but not attained",
|
||||||
Error::Detail(_, ref e) => e.description(),
|
Error::SpvBadTarget => "target incorrect",
|
||||||
Error::UnsupportedWitnessVersion(_) => "unsupported witness version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepend the detail of an `IoResult`'s error with some text to get poor man's backtracing
|
|
||||||
pub fn propagate_err<T>(s: String, res: Result<T, Error>) -> Result<T, Error> {
|
|
||||||
res.map_err(|err| Error::Detail(s, Box::new(err)))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
impl From<base58::Error> for Error {
|
|
||||||
fn from(e: base58::Error) -> Error {
|
|
||||||
Error::Base58(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
impl From<bitcoin_bech32::Error> for Error {
|
|
||||||
fn from(e: bitcoin_bech32::Error) -> Error {
|
|
||||||
Error::Bech32(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl From<secp256k1::Error> for Error {
|
impl From<secp256k1::Error> for Error {
|
||||||
fn from(e: secp256k1::Error) -> Error {
|
fn from(e: secp256k1::Error) -> Error {
|
||||||
|
@ -168,3 +114,16 @@ impl From<secp256k1::Error> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl From<serialize::Error> for Error {
|
||||||
|
fn from(e: serialize::Error) -> Error {
|
||||||
|
Error::Serialize(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl From<network::Error> for Error {
|
||||||
|
fn from(e: network::Error) -> Error {
|
||||||
|
Error::Network(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use util::Error;
|
|
||||||
use secp256k1::{self, Secp256k1};
|
use secp256k1::{self, Secp256k1};
|
||||||
use secp256k1::key::{PublicKey, SecretKey};
|
use secp256k1::key::{PublicKey, SecretKey};
|
||||||
use util::address::Address;
|
use util::address::Address;
|
||||||
|
use network::serialize;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
use util::base58;
|
use util::base58;
|
||||||
|
|
||||||
|
@ -113,21 +113,21 @@ impl Display for Privkey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Privkey {
|
impl FromStr for Privkey {
|
||||||
type Err = Error;
|
type Err = serialize::Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Privkey, Error> {
|
fn from_str(s: &str) -> Result<Privkey, serialize::Error> {
|
||||||
let data = base58::from_check(s)?;
|
let data = base58::from_check(s)?;
|
||||||
|
|
||||||
let compressed = match data.len() {
|
let compressed = match data.len() {
|
||||||
33 => false,
|
33 => false,
|
||||||
34 => true,
|
34 => true,
|
||||||
_ => { return Err(Error::Base58(base58::Error::InvalidLength(data.len()))); }
|
_ => { return Err(serialize::Error::Base58(base58::Error::InvalidLength(data.len()))); }
|
||||||
};
|
};
|
||||||
|
|
||||||
let network = match data[0] {
|
let network = match data[0] {
|
||||||
128 => Network::Bitcoin,
|
128 => Network::Bitcoin,
|
||||||
239 => Network::Testnet,
|
239 => Network::Testnet,
|
||||||
x => { return Err(Error::Base58(base58::Error::InvalidVersion(vec![x]))); }
|
x => { return Err(serialize::Error::Base58(base58::Error::InvalidVersion(vec![x]))); }
|
||||||
};
|
};
|
||||||
|
|
||||||
let secp = Secp256k1::without_caps();
|
let secp = Secp256k1::without_caps();
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use network::serialize;
|
||||||
use util::BitArray;
|
use util::BitArray;
|
||||||
|
|
||||||
macro_rules! construct_uint {
|
macro_rules! construct_uint {
|
||||||
|
@ -337,7 +338,7 @@ macro_rules! construct_uint {
|
||||||
|
|
||||||
impl<S: ::network::serialize::SimpleEncoder> ::network::encodable::ConsensusEncodable<S> for $name {
|
impl<S: ::network::serialize::SimpleEncoder> ::network::encodable::ConsensusEncodable<S> for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
|
fn consensus_encode(&self, s: &mut S) -> Result<(), serialize::Error> {
|
||||||
let &$name(ref data) = self;
|
let &$name(ref data) = self;
|
||||||
for word in data.iter() { word.consensus_encode(s)?; }
|
for word in data.iter() { word.consensus_encode(s)?; }
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -345,7 +346,7 @@ macro_rules! construct_uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: ::network::serialize::SimpleDecoder> ::network::encodable::ConsensusDecodable<D> for $name {
|
impl<D: ::network::serialize::SimpleDecoder> ::network::encodable::ConsensusDecodable<D> for $name {
|
||||||
fn consensus_decode(d: &mut D) -> Result<$name, D::Error> {
|
fn consensus_decode(d: &mut D) -> Result<$name, serialize::Error> {
|
||||||
use network::encodable::ConsensusDecodable;
|
use network::encodable::ConsensusDecodable;
|
||||||
let ret: [u64; $n_words] = ConsensusDecodable::consensus_decode(d)?;
|
let ret: [u64; $n_words] = ConsensusDecodable::consensus_decode(d)?;
|
||||||
Ok($name(ret))
|
Ok($name(ret))
|
||||||
|
|
Loading…
Reference in New Issue