mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
Merge pull request #11 from merope07/option-t
core: Clean up serialization and hashing
This commit is contained in:
commit
1008539048
10 changed files with 252 additions and 217 deletions
|
@ -26,7 +26,7 @@ use core::transaction::merkle_inputs_outputs;
|
||||||
use core::{PROOFSIZE, REWARD};
|
use core::{PROOFSIZE, REWARD};
|
||||||
use core::hash::{Hash, Hashed, ZERO_HASH};
|
use core::hash::{Hash, Hashed, ZERO_HASH};
|
||||||
use core::transaction::MAX_IN_OUT_LEN;
|
use core::transaction::MAX_IN_OUT_LEN;
|
||||||
use ser::{self, Readable, Reader, Writeable, Writer, ser_vec};
|
use ser::{self, Readable, Reader, Writeable, Writer};
|
||||||
|
|
||||||
/// Block header, fairly standard compared to other blockchains.
|
/// Block header, fairly standard compared to other blockchains.
|
||||||
pub struct BlockHeader {
|
pub struct BlockHeader {
|
||||||
|
@ -60,7 +60,7 @@ impl Default for BlockHeader {
|
||||||
// Only Writeable implementation is required for hashing, which is part of
|
// Only Writeable implementation is required for hashing, which is part of
|
||||||
// core. Readable is in the ser package.
|
// core. Readable is in the ser package.
|
||||||
impl Writeable for BlockHeader {
|
impl Writeable for BlockHeader {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
[write_u64, self.height],
|
[write_u64, self.height],
|
||||||
[write_fixed_bytes, &self.previous],
|
[write_fixed_bytes, &self.previous],
|
||||||
|
@ -70,22 +70,15 @@ impl Writeable for BlockHeader {
|
||||||
[write_u64, self.total_fees]);
|
[write_u64, self.total_fees]);
|
||||||
// make sure to not introduce any variable length data before the nonce to
|
// make sure to not introduce any variable length data before the nonce to
|
||||||
// avoid complicating PoW
|
// avoid complicating PoW
|
||||||
try_o!(writer.write_u64(self.nonce));
|
try!(writer.write_u64(self.nonce));
|
||||||
// cuckoo cycle of 42 nodes
|
// cuckoo cycle of 42 nodes
|
||||||
for n in 0..42 {
|
for n in 0..42 {
|
||||||
try_o!(writer.write_u32(self.pow.0[n]));
|
try!(writer.write_u32(self.pow.0[n]));
|
||||||
}
|
}
|
||||||
writer.write_u64(self.td)
|
writer.write_u64(self.td)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hashed for BlockHeader {
|
|
||||||
fn bytes(&self) -> Vec<u8> {
|
|
||||||
// no serialization errors are applicable in this specific case
|
|
||||||
ser_vec(self).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A block as expressed in the MimbleWimble protocol. The reward is
|
/// A block as expressed in the MimbleWimble protocol. The reward is
|
||||||
/// non-explicit, assumed to be deductible from block height (similar to
|
/// non-explicit, assumed to be deductible from block height (similar to
|
||||||
/// bitcoin's schedule) and expressed as a global transaction fee (added v.H),
|
/// bitcoin's schedule) and expressed as a global transaction fee (added v.H),
|
||||||
|
@ -101,23 +94,23 @@ pub struct Block {
|
||||||
/// Implementation of Writeable for a block, defines how to write the full
|
/// Implementation of Writeable for a block, defines how to write the full
|
||||||
/// block as binary.
|
/// block as binary.
|
||||||
impl Writeable for Block {
|
impl Writeable for Block {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
try_o!(self.header.write(writer));
|
try!(self.header.write(writer));
|
||||||
|
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
[write_u64, self.inputs.len() as u64],
|
[write_u64, self.inputs.len() as u64],
|
||||||
[write_u64, self.outputs.len() as u64],
|
[write_u64, self.outputs.len() as u64],
|
||||||
[write_u64, self.proofs.len() as u64]);
|
[write_u64, self.proofs.len() as u64]);
|
||||||
for inp in &self.inputs {
|
for inp in &self.inputs {
|
||||||
try_o!(inp.write(writer));
|
try!(inp.write(writer));
|
||||||
}
|
}
|
||||||
for out in &self.outputs {
|
for out in &self.outputs {
|
||||||
try_o!(out.write(writer));
|
try!(out.write(writer));
|
||||||
}
|
}
|
||||||
for proof in &self.proofs {
|
for proof in &self.proofs {
|
||||||
try_o!(proof.write(writer));
|
try!(proof.write(writer));
|
||||||
}
|
}
|
||||||
None
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
//! Primary hash function used in the protocol
|
//! Primary hash function used in the protocol
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
use byteorder::{ByteOrder, BigEndian};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use tiny_keccak::Keccak;
|
use tiny_keccak::Keccak;
|
||||||
|
|
||||||
|
use ser::{self, AsFixedBytes};
|
||||||
|
|
||||||
/// A hash to uniquely (or close enough) identify one of the main blockchain
|
/// A hash to uniquely (or close enough) identify one of the main blockchain
|
||||||
/// constructs. Used pervasively for blocks, transactions and ouputs.
|
/// constructs. Used pervasively for blocks, transactions and ouputs.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
@ -56,27 +58,58 @@ impl Hash {
|
||||||
|
|
||||||
pub const ZERO_HASH: Hash = Hash([0; 32]);
|
pub const ZERO_HASH: Hash = Hash([0; 32]);
|
||||||
|
|
||||||
/// A trait for types that get their hash (double SHA256) from their byte
|
/// Serializer that outputs a hash of the serialized object
|
||||||
/// serialzation.
|
pub struct HashWriter {
|
||||||
pub trait Hashed {
|
state: Keccak
|
||||||
fn hash(&self) -> Hash {
|
|
||||||
let data = self.bytes();
|
|
||||||
Hash(sha3(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bytes(&self) -> Vec<u8>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sha3(data: Vec<u8>) -> [u8; 32] {
|
impl HashWriter {
|
||||||
let mut sha3 = Keccak::new_sha3_256();
|
fn finalize(self, output: &mut [u8]) {
|
||||||
let mut buf = [0; 32];
|
self.state.finalize(output);
|
||||||
sha3.update(&data);
|
}
|
||||||
sha3.finalize(&mut buf);
|
}
|
||||||
buf
|
|
||||||
|
impl Default for HashWriter {
|
||||||
|
fn default() -> HashWriter {
|
||||||
|
HashWriter {
|
||||||
|
state: Keccak::new_sha3_256()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ser::Writer for HashWriter {
|
||||||
|
fn serialization_mode(&self) -> ser::SerializationMode {
|
||||||
|
ser::SerializationMode::Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fixed_bytes(&mut self, b32: &AsFixedBytes) -> Result<(), ser::Error> {
|
||||||
|
self.state.update(b32.as_fixed_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait for types that have a canonical hash
|
||||||
|
pub trait Hashed {
|
||||||
|
fn hash(&self) -> Hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: ser::Writeable> Hashed for W {
|
||||||
|
fn hash(&self) -> Hash {
|
||||||
|
let mut hasher = HashWriter::default();
|
||||||
|
ser::Writeable::write(self, &mut hasher).unwrap();
|
||||||
|
let mut ret = [0; 32];
|
||||||
|
hasher.finalize(&mut ret);
|
||||||
|
Hash(ret)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hashed for [u8] {
|
impl Hashed for [u8] {
|
||||||
fn bytes(&self) -> Vec<u8> {
|
fn hash(&self) -> Hash {
|
||||||
self.to_owned()
|
let mut hasher = HashWriter::default();
|
||||||
|
let mut ret = [0; 32];
|
||||||
|
ser::Writer::write_bytes(&mut hasher, &self).unwrap();
|
||||||
|
hasher.finalize(&mut ret);
|
||||||
|
Hash(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,25 +18,18 @@ pub mod block;
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[macro_use]
|
|
||||||
|
|
||||||
pub use self::block::{Block, BlockHeader};
|
pub use self::block::{Block, BlockHeader};
|
||||||
pub use self::transaction::{Transaction, Input, Output, TxProof};
|
pub use self::transaction::{Transaction, Input, Output, TxProof};
|
||||||
use self::hash::{Hash, Hashed, ZERO_HASH};
|
use self::hash::{Hash, Hashed, ZERO_HASH};
|
||||||
use ser::{Writeable, Writer, Error, ser_vec};
|
use ser::{Writeable, Writer, Error};
|
||||||
|
|
||||||
use time;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use secp;
|
use secp::{self, Secp256k1};
|
||||||
use secp::{Secp256k1, Signature, Message};
|
|
||||||
use secp::key::SecretKey;
|
|
||||||
use secp::pedersen::*;
|
use secp::pedersen::*;
|
||||||
|
|
||||||
use tiny_keccak::Keccak;
|
|
||||||
|
|
||||||
/// The block subsidy amount
|
/// The block subsidy amount
|
||||||
pub const REWARD: u64 = 1_000_000_000;
|
pub const REWARD: u64 = 1_000_000_000;
|
||||||
|
|
||||||
|
@ -154,12 +147,12 @@ impl Proof {
|
||||||
/// Two hashes that will get hashed together in a Merkle tree to build the next
|
/// Two hashes that will get hashed together in a Merkle tree to build the next
|
||||||
/// level up.
|
/// level up.
|
||||||
struct HPair(Hash, Hash);
|
struct HPair(Hash, Hash);
|
||||||
impl Hashed for HPair {
|
|
||||||
fn bytes(&self) -> Vec<u8> {
|
impl Writeable for HPair {
|
||||||
let mut data = Vec::with_capacity(64);
|
fn write(&self, writer: &mut Writer) -> Result<(), Error> {
|
||||||
data.extend_from_slice(self.0.to_slice());
|
try!(writer.write_bytes(&self.0.to_slice()));
|
||||||
data.extend_from_slice(self.1.to_slice());
|
try!(writer.write_bytes(&self.1.to_slice()));
|
||||||
return data;
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// An iterator over hashes in a vector that pairs them to build a row in a
|
/// An iterator over hashes in a vector that pairs them to build a row in a
|
||||||
|
@ -198,7 +191,7 @@ impl MerkleRow {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::hash::{Hash, Hashed, ZERO_HASH};
|
use core::hash::ZERO_HASH;
|
||||||
use secp;
|
use secp;
|
||||||
use secp::Secp256k1;
|
use secp::Secp256k1;
|
||||||
use secp::key::SecretKey;
|
use secp::key::SecretKey;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
use core::Committed;
|
use core::Committed;
|
||||||
use core::MerkleRow;
|
use core::MerkleRow;
|
||||||
use core::hash::{Hashed, Hash};
|
use core::hash::{Hash, Hashed};
|
||||||
use ser::{self, Reader, Writer, Readable, Writeable};
|
use ser::{self, Reader, Writer, Readable, Writeable};
|
||||||
|
|
||||||
use secp::{self, Secp256k1, Message, Signature};
|
use secp::{self, Secp256k1, Message, Signature};
|
||||||
|
@ -39,9 +39,9 @@ pub struct TxProof {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writeable for TxProof {
|
impl Writeable for TxProof {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
try_o!(writer.write_fixed_bytes(&self.remainder));
|
try!(writer.write_fixed_bytes(&self.remainder));
|
||||||
writer.write_vec(&mut self.sig.clone())
|
writer.write_bytes(&self.sig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,19 +68,19 @@ pub struct Transaction {
|
||||||
/// Implementation of Writeable for a fully blinded transaction, defines how to
|
/// Implementation of Writeable for a fully blinded transaction, defines how to
|
||||||
/// write the transaction as binary.
|
/// write the transaction as binary.
|
||||||
impl Writeable for Transaction {
|
impl Writeable for Transaction {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
[write_u64, self.fee],
|
[write_u64, self.fee],
|
||||||
[write_vec, &mut self.zerosig.clone()],
|
[write_bytes, &self.zerosig],
|
||||||
[write_u64, self.inputs.len() as u64],
|
[write_u64, self.inputs.len() as u64],
|
||||||
[write_u64, self.outputs.len() as u64]);
|
[write_u64, self.outputs.len() as u64]);
|
||||||
for inp in &self.inputs {
|
for inp in &self.inputs {
|
||||||
try_o!(inp.write(writer));
|
try!(inp.write(writer));
|
||||||
}
|
}
|
||||||
for out in &self.outputs {
|
for out in &self.outputs {
|
||||||
try_o!(out.write(writer));
|
try!(out.write(writer));
|
||||||
}
|
}
|
||||||
None
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ pub enum Input {
|
||||||
/// Implementation of Writeable for a transaction Input, defines how to write
|
/// Implementation of Writeable for a transaction Input, defines how to write
|
||||||
/// an Input as binary.
|
/// an Input as binary.
|
||||||
impl Writeable for Input {
|
impl Writeable for Input {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
writer.write_fixed_bytes(&self.output_hash())
|
writer.write_fixed_bytes(&self.output_hash())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,13 +283,6 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The hash of an input is the hash of the output hash it references.
|
|
||||||
impl Hashed for Input {
|
|
||||||
fn bytes(&self) -> Vec<u8> {
|
|
||||||
self.output_hash().to_vec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Output {
|
pub enum Output {
|
||||||
BlindOutput {
|
BlindOutput {
|
||||||
|
@ -302,9 +295,13 @@ pub enum Output {
|
||||||
/// Implementation of Writeable for a transaction Output, defines how to write
|
/// Implementation of Writeable for a transaction Output, defines how to write
|
||||||
/// an Output as binary.
|
/// an Output as binary.
|
||||||
impl Writeable for Output {
|
impl Writeable for Output {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
try_o!(writer.write_fixed_bytes(&self.commitment().unwrap()));
|
// The hash of an output is only the hash of its commitment.
|
||||||
writer.write_vec(&mut self.proof().unwrap().bytes().to_vec())
|
try!(writer.write_fixed_bytes(&self.commitment().unwrap()));
|
||||||
|
if writer.serialization_mode() == ser::SerializationMode::Full {
|
||||||
|
try!(writer.write_bytes(&self.proof().unwrap().bytes()))
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,17 +360,6 @@ impl Output {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The hash of an output is the hash of its commitment.
|
|
||||||
impl Hashed for Output {
|
|
||||||
fn bytes(&self) -> Vec<u8> {
|
|
||||||
if let &Output::BlindOutput { commit, .. } = self {
|
|
||||||
return commit.bytes().to_vec();
|
|
||||||
} else {
|
|
||||||
panic!("cannot hash an overt output");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Utility function to calculate the Merkle root of vectors of inputs and
|
/// Utility function to calculate the Merkle root of vectors of inputs and
|
||||||
/// outputs.
|
/// outputs.
|
||||||
pub fn merkle_inputs_outputs(inputs: &Vec<Input>, outputs: &Vec<Output>) -> Hash {
|
pub fn merkle_inputs_outputs(inputs: &Vec<Input>, outputs: &Vec<Output>) -> Hash {
|
||||||
|
@ -392,7 +378,6 @@ mod test {
|
||||||
|
|
||||||
use secp::{self, Secp256k1};
|
use secp::{self, Secp256k1};
|
||||||
use secp::key::SecretKey;
|
use secp::key::SecretKey;
|
||||||
use rand::Rng;
|
|
||||||
use rand::os::OsRng;
|
use rand::os::OsRng;
|
||||||
|
|
||||||
fn new_secp() -> Secp256k1 {
|
fn new_secp() -> Secp256k1 {
|
||||||
|
@ -407,9 +392,7 @@ mod test {
|
||||||
let tx = tx2i1o(secp, &mut rng);
|
let tx = tx2i1o(secp, &mut rng);
|
||||||
let btx = tx.blind(&secp).unwrap();
|
let btx = tx.blind(&secp).unwrap();
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
if let Some(e) = serialize(&mut vec, &btx) {
|
serialize(&mut vec, &btx).expect("serialized failed");
|
||||||
panic!(e);
|
|
||||||
}
|
|
||||||
assert!(vec.len() > 5320);
|
assert!(vec.len() > 5320);
|
||||||
assert!(vec.len() < 5340);
|
assert!(vec.len() < 5340);
|
||||||
}
|
}
|
||||||
|
@ -420,14 +403,12 @@ mod test {
|
||||||
let ref secp = new_secp();
|
let ref secp = new_secp();
|
||||||
|
|
||||||
let tx = tx2i1o(secp, &mut rng);
|
let tx = tx2i1o(secp, &mut rng);
|
||||||
let mut btx = tx.blind(&secp).unwrap();
|
let btx = tx.blind(&secp).unwrap();
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
if let Some(e) = serialize(&mut vec, &btx) {
|
serialize(&mut vec, &btx).expect("serialization failed");
|
||||||
panic!(e);
|
|
||||||
}
|
|
||||||
// let mut dtx = Transaction::read(&mut BinReader { source: &mut &vec[..]
|
// let mut dtx = Transaction::read(&mut BinReader { source: &mut &vec[..]
|
||||||
// }).unwrap();
|
// }).unwrap();
|
||||||
let mut dtx: Transaction = deserialize(&mut &vec[..]).unwrap();
|
let dtx: Transaction = deserialize(&mut &vec[..]).unwrap();
|
||||||
assert_eq!(dtx.fee, 1);
|
assert_eq!(dtx.fee, 1);
|
||||||
assert_eq!(dtx.inputs.len(), 2);
|
assert_eq!(dtx.inputs.len(), 2);
|
||||||
assert_eq!(dtx.outputs.len(), 1);
|
assert_eq!(dtx.outputs.len(), 1);
|
||||||
|
@ -441,15 +422,15 @@ mod test {
|
||||||
let ref secp = new_secp();
|
let ref secp = new_secp();
|
||||||
|
|
||||||
let tx = tx2i1o(secp, &mut rng);
|
let tx = tx2i1o(secp, &mut rng);
|
||||||
let mut btx = tx.blind(&secp).unwrap();
|
let btx = tx.blind(&secp).unwrap();
|
||||||
|
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
assert!(serialize(&mut vec, &btx).is_none());
|
assert!(serialize(&mut vec, &btx).is_ok());
|
||||||
let mut dtx: Transaction = deserialize(&mut &vec[..]).unwrap();
|
let dtx: Transaction = deserialize(&mut &vec[..]).unwrap();
|
||||||
|
|
||||||
let mut vec2 = Vec::new();
|
let mut vec2 = Vec::new();
|
||||||
assert!(serialize(&mut vec2, &btx).is_none());
|
assert!(serialize(&mut vec2, &btx).is_ok());
|
||||||
let mut dtx2: Transaction = deserialize(&mut &vec2[..]).unwrap();
|
let dtx2: Transaction = deserialize(&mut &vec2[..]).unwrap();
|
||||||
|
|
||||||
assert_eq!(btx.hash(), dtx.hash());
|
assert_eq!(btx.hash(), dtx.hash());
|
||||||
assert_eq!(dtx.hash(), dtx2.hash());
|
assert_eq!(dtx.hash(), dtx2.hash());
|
||||||
|
@ -536,10 +517,10 @@ mod test {
|
||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
|
|
||||||
let tx1 = tx2i1o(secp, &mut rng);
|
let tx1 = tx2i1o(secp, &mut rng);
|
||||||
let mut btx1 = tx1.blind(&secp).unwrap();
|
let btx1 = tx1.blind(&secp).unwrap();
|
||||||
|
|
||||||
let tx2 = tx1i1o(secp, &mut rng);
|
let tx2 = tx1i1o(secp, &mut rng);
|
||||||
let mut btx2 = tx2.blind(&secp).unwrap();
|
let btx2 = tx2.blind(&secp).unwrap();
|
||||||
|
|
||||||
if btx1.hash() == btx2.hash() {
|
if btx1.hash() == btx2.hash() {
|
||||||
panic!("diff txs have same hash")
|
panic!("diff txs have same hash")
|
||||||
|
|
|
@ -61,19 +61,6 @@ macro_rules! tee {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simple equivalent of try! but for an Option<Error>. Motivated mostly by the
|
|
||||||
/// io package and our serialization as an alternative to silly Result<(),
|
|
||||||
/// Error>.
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! try_o {
|
|
||||||
($trying:expr) => {
|
|
||||||
let tried = $trying;
|
|
||||||
if let Some(_) = tried {
|
|
||||||
return tried;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! try_to_o {
|
macro_rules! try_to_o {
|
||||||
($trying:expr) => {{
|
($trying:expr) => {{
|
||||||
|
@ -109,6 +96,6 @@ macro_rules! ser_multiread {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! ser_multiwrite {
|
macro_rules! ser_multiwrite {
|
||||||
($wrtr:ident, $([ $write_call:ident, $val:expr ]),* ) => {
|
($wrtr:ident, $([ $write_call:ident, $val:expr ]),* ) => {
|
||||||
$( try_o!($wrtr.$write_call($val)) );*
|
$( try!($wrtr.$write_call($val)) );*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha2::Sha256;
|
use crypto::sha2::Sha256;
|
||||||
|
|
|
@ -27,12 +27,12 @@ mod cuckoo;
|
||||||
|
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
use core::{Block, BlockHeader, Proof, PROOFSIZE};
|
use core::{Block, Proof, PROOFSIZE};
|
||||||
use core::hash::{Hash, Hashed};
|
use core::hash::{Hash, Hashed};
|
||||||
use pow::cuckoo::{Cuckoo, Miner, Error};
|
use pow::cuckoo::{Cuckoo, Miner, Error};
|
||||||
|
|
||||||
use ser;
|
use ser;
|
||||||
use ser::{Writeable, Writer, ser_vec};
|
use ser::{Writeable, Writer};
|
||||||
|
|
||||||
/// Default Cuckoo Cycle size shift used is 28. We may decide to increase it.
|
/// Default Cuckoo Cycle size shift used is 28. We may decide to increase it.
|
||||||
/// when difficuty increases.
|
/// when difficuty increases.
|
||||||
|
@ -71,27 +71,20 @@ struct PowHeader {
|
||||||
/// the data that gets hashed for PoW calculation. The nonce is written first
|
/// the data that gets hashed for PoW calculation. The nonce is written first
|
||||||
/// to make incrementing from the serialized form trivial.
|
/// to make incrementing from the serialized form trivial.
|
||||||
impl Writeable for PowHeader {
|
impl Writeable for PowHeader {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
try_o!(writer.write_u64(self.nonce));
|
try!(writer.write_u64(self.nonce));
|
||||||
try_o!(writer.write_u64(self.height));
|
try!(writer.write_u64(self.height));
|
||||||
try_o!(writer.write_fixed_bytes(&self.previous));
|
try!(writer.write_fixed_bytes(&self.previous));
|
||||||
try_o!(writer.write_i64(self.timestamp.to_timespec().sec));
|
try!(writer.write_i64(self.timestamp.to_timespec().sec));
|
||||||
try_o!(writer.write_fixed_bytes(&self.utxo_merkle));
|
try!(writer.write_fixed_bytes(&self.utxo_merkle));
|
||||||
try_o!(writer.write_fixed_bytes(&self.tx_merkle));
|
try!(writer.write_fixed_bytes(&self.tx_merkle));
|
||||||
try_o!(writer.write_u64(self.total_fees));
|
try!(writer.write_u64(self.total_fees));
|
||||||
try_o!(writer.write_u64(self.n_in));
|
try!(writer.write_u64(self.n_in));
|
||||||
try_o!(writer.write_u64(self.n_out));
|
try!(writer.write_u64(self.n_out));
|
||||||
writer.write_u64(self.n_proofs)
|
writer.write_u64(self.n_proofs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hashed for PowHeader {
|
|
||||||
fn bytes(&self) -> Vec<u8> {
|
|
||||||
// no serialization errors are applicable in this specific case
|
|
||||||
ser_vec(self).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PowHeader {
|
impl PowHeader {
|
||||||
fn from_block(b: &Block) -> PowHeader {
|
fn from_block(b: &Block) -> PowHeader {
|
||||||
let ref h = b.header;
|
let ref h = b.header;
|
||||||
|
@ -176,9 +169,7 @@ fn pow_size(b: &Block, target: Proof, sizeshift: u32) -> Result<(Proof, u64), Er
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use core::{BlockHeader, Proof};
|
use core::Proof;
|
||||||
use core::hash::Hash;
|
|
||||||
use std::time::Instant;
|
|
||||||
use genesis;
|
use genesis;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
152
core/src/ser.rs
152
core/src/ser.rs
|
@ -19,9 +19,9 @@
|
||||||
//! To use it simply implement `Writeable` or `Readable` and then use the
|
//! To use it simply implement `Writeable` or `Readable` and then use the
|
||||||
//! `serialize` or `deserialize` functions on them as appropriate.
|
//! `serialize` or `deserialize` functions on them as appropriate.
|
||||||
|
|
||||||
use std::io;
|
use std::{error, fmt};
|
||||||
use std::io::{Write, Read};
|
use std::io::{self, Write, Read};
|
||||||
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
|
use byteorder::{ByteOrder, ReadBytesExt, BigEndian};
|
||||||
|
|
||||||
/// Possible errors deriving from serializing or deserializing.
|
/// Possible errors deriving from serializing or deserializing.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -33,12 +33,47 @@ pub enum Error {
|
||||||
expected: Vec<u8>,
|
expected: Vec<u8>,
|
||||||
received: Vec<u8>,
|
received: Vec<u8>,
|
||||||
},
|
},
|
||||||
/// Data wasn't in a consumable format
|
/// Data wasn't in a consumable format
|
||||||
CorruptedData,
|
CorruptedData,
|
||||||
/// When asked to read too much data
|
/// When asked to read too much data
|
||||||
TooLargeReadErr(String),
|
TooLargeReadErr(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(e: io::Error) -> Error {
|
||||||
|
Error::IOErr(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Error::IOErr(ref e) => write!(f, "{}", e),
|
||||||
|
Error::UnexpectedData { expected: ref e, received: ref r } => write!(f, "expected {:?}, got {:?}", e, r),
|
||||||
|
Error::CorruptedData => f.write_str("corrupted data"),
|
||||||
|
Error::TooLargeReadErr(ref s) => f.write_str(&s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for Error {
|
||||||
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
|
match *self {
|
||||||
|
Error::IOErr(ref e) => Some(e),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
Error::IOErr(ref e) => error::Error::description(e),
|
||||||
|
Error::UnexpectedData { expected: _, received: _ } => "unexpected data",
|
||||||
|
Error::CorruptedData => "corrupted data",
|
||||||
|
Error::TooLargeReadErr(ref s) => s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Useful trait to implement on types that can be translated to byte slices
|
/// Useful trait to implement on types that can be translated to byte slices
|
||||||
/// directly. Allows the use of `write_fixed_bytes` on them.
|
/// directly. Allows the use of `write_fixed_bytes` on them.
|
||||||
pub trait AsFixedBytes {
|
pub trait AsFixedBytes {
|
||||||
|
@ -46,25 +81,67 @@ pub trait AsFixedBytes {
|
||||||
fn as_fixed_bytes(&self) -> &[u8];
|
fn as_fixed_bytes(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Signal to a serializable object how much of its data should be serialized
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum SerializationMode {
|
||||||
|
/// Serialize everything sufficiently to fully reconstruct the object
|
||||||
|
Full,
|
||||||
|
/// Serialize the data that defines the object
|
||||||
|
Hash,
|
||||||
|
/// Serialize everything that a signer of the object should know
|
||||||
|
SigHash
|
||||||
|
}
|
||||||
|
|
||||||
/// Implementations defined how different numbers and binary structures are
|
/// Implementations defined how different numbers and binary structures are
|
||||||
/// written to an underlying stream or container (depending on implementation).
|
/// written to an underlying stream or container (depending on implementation).
|
||||||
pub trait Writer {
|
pub trait Writer {
|
||||||
|
/// The mode this serializer is writing in
|
||||||
|
fn serialization_mode(&self) -> SerializationMode;
|
||||||
|
|
||||||
/// Writes a u8 as bytes
|
/// Writes a u8 as bytes
|
||||||
fn write_u8(&mut self, n: u8) -> Option<Error>;
|
fn write_u8(&mut self, n: u8) -> Result<(), Error> {
|
||||||
|
self.write_fixed_bytes(&[n])
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes a u16 as bytes
|
/// Writes a u16 as bytes
|
||||||
fn write_u16(&mut self, n: u16) -> Option<Error>;
|
fn write_u16(&mut self, n: u16) -> Result<(), Error> {
|
||||||
|
let mut bytes = [0; 2];
|
||||||
|
BigEndian::write_u16(&mut bytes, n);
|
||||||
|
self.write_fixed_bytes(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes a u32 as bytes
|
/// Writes a u32 as bytes
|
||||||
fn write_u32(&mut self, n: u32) -> Option<Error>;
|
fn write_u32(&mut self, n: u32) -> Result<(), Error> {
|
||||||
|
let mut bytes = [0; 4];
|
||||||
|
BigEndian::write_u32(&mut bytes, n);
|
||||||
|
self.write_fixed_bytes(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes a u64 as bytes
|
/// Writes a u64 as bytes
|
||||||
fn write_u64(&mut self, n: u64) -> Option<Error>;
|
fn write_u64(&mut self, n: u64) -> Result<(), Error> {
|
||||||
|
let mut bytes = [0; 8];
|
||||||
|
BigEndian::write_u64(&mut bytes, n);
|
||||||
|
self.write_fixed_bytes(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes a i64 as bytes
|
/// Writes a i64 as bytes
|
||||||
fn write_i64(&mut self, n: i64) -> Option<Error>;
|
fn write_i64(&mut self, n: i64) -> Result<(), Error> {
|
||||||
/// Writes a variable length `Vec`, the length of the `Vec` is encoded as a
|
let mut bytes = [0; 8];
|
||||||
|
BigEndian::write_i64(&mut bytes, n);
|
||||||
|
self.write_fixed_bytes(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes a variable number of bytes. The length is encoded as a 64-bit
|
||||||
/// prefix.
|
/// prefix.
|
||||||
fn write_vec(&mut self, vec: &mut Vec<u8>) -> Option<Error>;
|
fn write_bytes(&mut self, bytes: &AsFixedBytes) -> Result<(), Error> {
|
||||||
|
try!(self.write_u64(bytes.as_fixed_bytes().len() as u64));
|
||||||
|
self.write_fixed_bytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes a fixed number of bytes from something that can turn itself into
|
/// Writes a fixed number of bytes from something that can turn itself into
|
||||||
/// a `&[u8]`. The reader is expected to know the actual length on read.
|
/// a `&[u8]`. The reader is expected to know the actual length on read.
|
||||||
fn write_fixed_bytes(&mut self, b32: &AsFixedBytes) -> Option<Error>;
|
fn write_fixed_bytes(&mut self, fixed: &AsFixedBytes) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementations defined how different numbers and binary structures are
|
/// Implementations defined how different numbers and binary structures are
|
||||||
|
@ -98,7 +175,7 @@ pub trait Reader {
|
||||||
/// underlying Write implementation.
|
/// underlying Write implementation.
|
||||||
pub trait Writeable {
|
pub trait Writeable {
|
||||||
/// Write the data held by this Writeable to the provided writer
|
/// Write the data held by this Writeable to the provided writer
|
||||||
fn write(&self, writer: &mut Writer) -> Option<Error>;
|
fn write(&self, writer: &mut Writer) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait that every type that can be deserialized from binary must implement.
|
/// Trait that every type that can be deserialized from binary must implement.
|
||||||
|
@ -116,7 +193,7 @@ pub fn deserialize<T: Readable<T>>(mut source: &mut Read) -> Result<T, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes a Writeable into any std::io::Write implementation.
|
/// Serializes a Writeable into any std::io::Write implementation.
|
||||||
pub fn serialize(mut sink: &mut Write, thing: &Writeable) -> Option<Error> {
|
pub fn serialize(mut sink: &mut Write, thing: &Writeable) -> Result<(), Error> {
|
||||||
let mut writer = BinWriter { sink: sink };
|
let mut writer = BinWriter { sink: sink };
|
||||||
thing.write(&mut writer)
|
thing.write(&mut writer)
|
||||||
}
|
}
|
||||||
|
@ -125,9 +202,7 @@ pub fn serialize(mut sink: &mut Write, thing: &Writeable) -> Option<Error> {
|
||||||
/// Vec<u8>.
|
/// Vec<u8>.
|
||||||
pub fn ser_vec(thing: &Writeable) -> Result<Vec<u8>, Error> {
|
pub fn ser_vec(thing: &Writeable) -> Result<Vec<u8>, Error> {
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
if let Some(err) = serialize(&mut vec, thing) {
|
try!(serialize(&mut vec, thing));
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,33 +267,14 @@ struct BinWriter<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Writer for BinWriter<'a> {
|
impl<'a> Writer for BinWriter<'a> {
|
||||||
fn write_u8(&mut self, n: u8) -> Option<Error> {
|
fn serialization_mode(&self) -> SerializationMode {
|
||||||
self.sink.write_u8(n).err().map(Error::IOErr)
|
SerializationMode::Full
|
||||||
}
|
|
||||||
fn write_u16(&mut self, n: u16) -> Option<Error> {
|
|
||||||
self.sink.write_u16::<BigEndian>(n).err().map(Error::IOErr)
|
|
||||||
}
|
|
||||||
fn write_u32(&mut self, n: u32) -> Option<Error> {
|
|
||||||
self.sink.write_u32::<BigEndian>(n).err().map(Error::IOErr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_u64(&mut self, n: u64) -> Option<Error> {
|
fn write_fixed_bytes(&mut self, fixed: &AsFixedBytes) -> Result<(), Error> {
|
||||||
self.sink.write_u64::<BigEndian>(n).err().map(Error::IOErr)
|
let bs = fixed.as_fixed_bytes();
|
||||||
}
|
try!(self.sink.write_all(bs));
|
||||||
|
Ok(())
|
||||||
fn write_i64(&mut self, n: i64) -> Option<Error> {
|
|
||||||
self.sink.write_i64::<BigEndian>(n).err().map(Error::IOErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn write_vec(&mut self, vec: &mut Vec<u8>) -> Option<Error> {
|
|
||||||
try_o!(self.write_u64(vec.len() as u64));
|
|
||||||
self.sink.write_all(vec).err().map(Error::IOErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_fixed_bytes(&mut self, b32: &AsFixedBytes) -> Option<Error> {
|
|
||||||
let bs = b32.as_fixed_bytes();
|
|
||||||
self.sink.write_all(bs).err().map(Error::IOErr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,6 +292,16 @@ impl_slice_bytes!(::secp::key::SecretKey);
|
||||||
impl_slice_bytes!(::secp::Signature);
|
impl_slice_bytes!(::secp::Signature);
|
||||||
impl_slice_bytes!(::secp::pedersen::Commitment);
|
impl_slice_bytes!(::secp::pedersen::Commitment);
|
||||||
impl_slice_bytes!(Vec<u8>);
|
impl_slice_bytes!(Vec<u8>);
|
||||||
|
impl_slice_bytes!([u8; 1]);
|
||||||
|
impl_slice_bytes!([u8; 2]);
|
||||||
|
impl_slice_bytes!([u8; 4]);
|
||||||
|
impl_slice_bytes!([u8; 8]);
|
||||||
|
|
||||||
|
impl<'a> AsFixedBytes for &'a [u8] {
|
||||||
|
fn as_fixed_bytes(&self) -> &[u8] {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsFixedBytes for ::core::hash::Hash {
|
impl AsFixedBytes for ::core::hash::Hash {
|
||||||
fn as_fixed_bytes(&self) -> &[u8] {
|
fn as_fixed_bytes(&self) -> &[u8] {
|
||||||
|
|
|
@ -51,19 +51,15 @@ impl Handshake {
|
||||||
// send the first part of the handshake
|
// send the first part of the handshake
|
||||||
let sender_addr = conn.local_addr().unwrap();
|
let sender_addr = conn.local_addr().unwrap();
|
||||||
let receiver_addr = conn.peer_addr().unwrap();
|
let receiver_addr = conn.peer_addr().unwrap();
|
||||||
let opt_err = serialize(&mut conn,
|
try!(serialize(&mut conn,
|
||||||
&Hand {
|
&Hand {
|
||||||
version: PROTOCOL_VERSION,
|
version: PROTOCOL_VERSION,
|
||||||
capabilities: FULL_SYNC,
|
capabilities: FULL_SYNC,
|
||||||
nonce: nonce,
|
nonce: nonce,
|
||||||
sender_addr: SockAddr(sender_addr),
|
sender_addr: SockAddr(sender_addr),
|
||||||
receiver_addr: SockAddr(receiver_addr),
|
receiver_addr: SockAddr(receiver_addr),
|
||||||
user_agent: USER_AGENT.to_string(),
|
user_agent: USER_AGENT.to_string(),
|
||||||
});
|
}));
|
||||||
match opt_err {
|
|
||||||
Some(err) => return Err(err),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deserialize the handshake response and do version negotiation
|
// deserialize the handshake response and do version negotiation
|
||||||
let shake = try!(deserialize::<Shake>(&mut conn));
|
let shake = try!(deserialize::<Shake>(&mut conn));
|
||||||
|
@ -127,16 +123,12 @@ impl Handshake {
|
||||||
};
|
};
|
||||||
|
|
||||||
// send our reply with our info
|
// send our reply with our info
|
||||||
let opt_err = serialize(&mut conn,
|
try!(serialize(&mut conn,
|
||||||
&Shake {
|
&Shake {
|
||||||
version: PROTOCOL_VERSION,
|
version: PROTOCOL_VERSION,
|
||||||
capabilities: FULL_SYNC,
|
capabilities: FULL_SYNC,
|
||||||
user_agent: USER_AGENT.to_string(),
|
user_agent: USER_AGENT.to_string(),
|
||||||
});
|
}));
|
||||||
match opt_err {
|
|
||||||
Some(err) => return Err(err),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("Received connection from peer {:?}", peer_info);
|
info!("Received connection from peer {:?}", peer_info);
|
||||||
// when more than one protocol version is supported, choosing should go here
|
// when more than one protocol version is supported, choosing should go here
|
||||||
|
|
|
@ -18,7 +18,7 @@ use std::net::*;
|
||||||
|
|
||||||
use num::FromPrimitive;
|
use num::FromPrimitive;
|
||||||
|
|
||||||
use core::ser::{self, Writeable, Readable, Writer, Reader, Error};
|
use core::ser::{self, Writeable, Readable, Writer, Reader};
|
||||||
|
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
|
@ -72,12 +72,12 @@ impl MsgHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writeable for MsgHeader {
|
impl Writeable for MsgHeader {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
[write_u8, self.magic[0]],
|
[write_u8, self.magic[0]],
|
||||||
[write_u8, self.magic[1]],
|
[write_u8, self.magic[1]],
|
||||||
[write_u8, self.msg_type as u8]);
|
[write_u8, self.msg_type as u8]);
|
||||||
None
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,14 +111,14 @@ pub struct Hand {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writeable for Hand {
|
impl Writeable for Hand {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
[write_u32, self.version],
|
[write_u32, self.version],
|
||||||
[write_u32, self.capabilities.bits()],
|
[write_u32, self.capabilities.bits()],
|
||||||
[write_u64, self.nonce]);
|
[write_u64, self.nonce]);
|
||||||
self.sender_addr.write(writer);
|
self.sender_addr.write(writer);
|
||||||
self.receiver_addr.write(writer);
|
self.receiver_addr.write(writer);
|
||||||
writer.write_vec(&mut self.user_agent.clone().into_bytes())
|
writer.write_bytes(self.user_agent.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +153,12 @@ pub struct Shake {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writeable for Shake {
|
impl Writeable for Shake {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
[write_u32, self.version],
|
[write_u32, self.version],
|
||||||
[write_u32, self.capabilities.bits()],
|
[write_u32, self.capabilities.bits()],
|
||||||
[write_vec, &mut self.user_agent.as_bytes().to_vec()]);
|
[write_bytes, self.user_agent.as_bytes()]);
|
||||||
None
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,11 +233,11 @@ pub struct PeerError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writeable for PeerError {
|
impl Writeable for PeerError {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
[write_u32, self.code],
|
[write_u32, self.code],
|
||||||
[write_vec, &mut self.message.clone().into_bytes()]);
|
[write_bytes, self.message.as_bytes()]);
|
||||||
None
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ impl Readable<PeerError> for PeerError {
|
||||||
pub struct SockAddr(pub SocketAddr);
|
pub struct SockAddr(pub SocketAddr);
|
||||||
|
|
||||||
impl Writeable for SockAddr {
|
impl Writeable for SockAddr {
|
||||||
fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
SocketAddr::V4(sav4) => {
|
SocketAddr::V4(sav4) => {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
|
@ -267,14 +267,14 @@ impl Writeable for SockAddr {
|
||||||
[write_u16, sav4.port()]);
|
[write_u16, sav4.port()]);
|
||||||
}
|
}
|
||||||
SocketAddr::V6(sav6) => {
|
SocketAddr::V6(sav6) => {
|
||||||
try_o!(writer.write_u8(1));
|
try!(writer.write_u8(1));
|
||||||
for seg in &sav6.ip().segments() {
|
for seg in &sav6.ip().segments() {
|
||||||
try_o!(writer.write_u16(*seg));
|
try!(writer.write_u16(*seg));
|
||||||
}
|
}
|
||||||
try_o!(writer.write_u16(sav6.port()));
|
try!(writer.write_u16(sav6.port()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue