stacks_common/deps_common/bitcoin/network/
serialize.rsuse std::io::{Cursor, Read, Write};
use std::{error, fmt, io};
use crate::address;
use crate::deps_common::bitcoin::network::encodable::{ConsensusDecodable, ConsensusEncodable};
use crate::deps_common::bitcoin::util::hash::Sha256dHash;
use crate::util::hash::to_hex as hex_encode;
#[derive(Debug)]
pub enum Error {
Io(io::Error),
Base58(address::Error),
UnexpectedNetworkMagic {
expected: u32,
actual: u32,
},
OversizedVectorAllocation {
requested: usize,
max: usize,
},
InvalidChecksum {
expected: [u8; 4],
actual: [u8; 4],
},
UnknownNetworkMagic(u32),
ParseFailed(&'static str),
UnsupportedWitnessVersion(u8),
UnsupportedSegwitFlag(u8),
UnrecognizedNetworkCommand(String),
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::UnexpectedNetworkMagic {
expected: ref e,
actual: ref a,
} => write!(f, "unexpected network magic: expected {}, actual {}", e, a),
Error::OversizedVectorAllocation {
requested: ref r,
max: ref m,
} => write!(
f,
"allocation of oversized vector requested: requested {}, maximum {}",
r, m
),
Error::InvalidChecksum {
expected: ref e,
actual: ref a,
} => write!(
f,
"invalid checksum: expected {}, actual {}",
hex_encode(e),
hex_encode(a)
),
Error::UnknownNetworkMagic(ref m) => write!(f, "unknown network magic: {}", m),
Error::ParseFailed(ref e) => write!(f, "parse failed: {}", e),
Error::UnsupportedWitnessVersion(ref wver) => {
write!(f, "unsupported witness version: {}", wver)
}
Error::UnsupportedSegwitFlag(ref swflag) => {
write!(f, "unsupported segwit version: {}", swflag)
}
Error::UnrecognizedNetworkCommand(ref nwcmd) => {
write!(f, "unrecognized network command: {}", nwcmd)
}
Error::UnexpectedHexDigit(ref d) => write!(f, "unexpected hex digit: {}", d),
}
}
}
impl error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
Error::Io(ref e) => Some(e),
Error::Base58(ref e) => Some(e),
Error::UnexpectedNetworkMagic { .. }
| Error::OversizedVectorAllocation { .. }
| Error::InvalidChecksum { .. }
| Error::UnknownNetworkMagic(..)
| Error::ParseFailed(..)
| Error::UnsupportedWitnessVersion(..)
| Error::UnsupportedSegwitFlag(..)
| Error::UnrecognizedNetworkCommand(..)
| Error::UnexpectedHexDigit(..) => None,
}
}
}
#[doc(hidden)]
impl From<address::Error> for Error {
fn from(e: address::Error) -> Error {
Error::Base58(e)
}
}
#[doc(hidden)]
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error::Io(error)
}
}
pub trait BitcoinHash {
fn bitcoin_hash(&self) -> Sha256dHash;
}
impl BitcoinHash for Vec<u8> {
#[inline]
fn bitcoin_hash(&self) -> Sha256dHash {
Sha256dHash::from_data(&self[..])
}
}
pub fn serialize<T: ?Sized>(data: &T) -> Result<Vec<u8>, Error>
where
T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>,
{
let mut encoder = RawEncoder::new(Cursor::new(vec![]));
data.consensus_encode(&mut encoder)?;
Ok(encoder.into_inner().into_inner())
}
pub fn serialize_hex<T: ?Sized>(data: &T) -> Result<String, Error>
where
T: ConsensusEncodable<RawEncoder<Cursor<Vec<u8>>>>,
{
let serial = serialize(data)?;
Ok(hex_encode(&serial[..]))
}
pub fn deserialize<'a, T>(data: &'a [u8]) -> Result<T, Error>
where
T: ConsensusDecodable<RawDecoder<Cursor<&'a [u8]>>>,
{
let mut decoder = RawDecoder::new(Cursor::new(data));
let rv = ConsensusDecodable::consensus_decode(&mut decoder)?;
if decoder.into_inner().position() == data.len() as u64 {
Ok(rv)
} else {
Err(Error::ParseFailed(
"data not consumed entirely when explicitly deserializing",
))
}
}
pub struct RawEncoder<W> {
writer: W,
}
pub struct RawDecoder<R> {
reader: R,
}
impl<W: Write> RawEncoder<W> {
pub fn new(writer: W) -> RawEncoder<W> {
RawEncoder { writer }
}
pub fn into_inner(self) -> W {
self.writer
}
}
impl<R: Read> RawDecoder<R> {
pub fn new(reader: R) -> RawDecoder<R> {
RawDecoder { reader }
}
pub fn into_inner(self) -> R {
self.reader
}
}
pub trait SimpleEncoder {
fn emit_u64(&mut self, v: u64) -> Result<(), Error>;
fn emit_u32(&mut self, v: u32) -> Result<(), Error>;
fn emit_u16(&mut self, v: u16) -> Result<(), Error>;
fn emit_u8(&mut self, v: u8) -> Result<(), Error>;
fn emit_i64(&mut self, v: i64) -> Result<(), Error>;
fn emit_i32(&mut self, v: i32) -> Result<(), Error>;
fn emit_i16(&mut self, v: i16) -> Result<(), Error>;
fn emit_i8(&mut self, v: i8) -> Result<(), Error>;
fn emit_bool(&mut self, v: bool) -> Result<(), Error>;
}
pub trait SimpleDecoder {
fn read_u64(&mut self) -> Result<u64, Error>;
fn read_u32(&mut self) -> Result<u32, Error>;
fn read_u16(&mut self) -> Result<u16, Error>;
fn read_u8(&mut self) -> Result<u8, Error>;
fn read_i64(&mut self) -> Result<i64, Error>;
fn read_i32(&mut self) -> Result<i32, Error>;
fn read_i16(&mut self) -> Result<i16, Error>;
fn read_i8(&mut self) -> Result<i8, Error>;
fn read_bool(&mut self) -> Result<bool, Error>;
}
macro_rules! encoder_fn {
($name:ident, $val_type:ty) => {
#[inline]
fn $name(&mut self, v: $val_type) -> Result<(), Error> {
self.writer.write_all(&v.to_le_bytes()).map_err(Error::Io)
}
};
}
macro_rules! decoder_fn {
($name:ident, $val_type:ty, $type_size:literal) => {
#[inline]
fn $name(&mut self) -> Result<$val_type, Error> {
let mut buff = [0; $type_size];
self.reader.read_exact(&mut buff).map_err(Error::Io)?;
Ok(<$val_type>::from_le_bytes(buff))
}
};
}
impl<W: Write> SimpleEncoder for RawEncoder<W> {
encoder_fn!(emit_u64, u64);
encoder_fn!(emit_u32, u32);
encoder_fn!(emit_u16, u16);
encoder_fn!(emit_i64, i64);
encoder_fn!(emit_i32, i32);
encoder_fn!(emit_i16, i16);
encoder_fn!(emit_i8, i8);
encoder_fn!(emit_u8, u8);
#[inline]
fn emit_bool(&mut self, v: bool) -> Result<(), Error> {
self.emit_i8(if v { 1 } else { 0 })
}
}
impl<R: Read> SimpleDecoder for RawDecoder<R> {
decoder_fn!(read_u64, u64, 8);
decoder_fn!(read_u32, u32, 4);
decoder_fn!(read_u16, u16, 2);
decoder_fn!(read_i64, i64, 8);
decoder_fn!(read_i32, i32, 4);
decoder_fn!(read_i16, i16, 2);
decoder_fn!(read_u8, u8, 1);
decoder_fn!(read_i8, i8, 1);
#[inline]
fn read_bool(&mut self) -> Result<bool, Error> {
self.read_i8().map(|bit| bit != 0)
}
}