Skip to content

Commit

Permalink
Network serialization basics; RGB commitments refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Jan 22, 2020
1 parent bd74ee0 commit 532f590
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 103 deletions.
32 changes: 2 additions & 30 deletions src/csv/serialize/commitment/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,11 @@ pub use macros::*;
pub use primitives::*;
pub use collections::*;

use std::{
io, str,
convert::From,
};
use std::io;

use bitcoin::consensus::encode as consensus;
use super::Error;


#[derive(Debug, Display)]
#[display_from(Debug)]
pub enum Error {
BitcoinConsensus(consensus::Error),
EnumValueUnknown(u8),
EnumValueOverflow,
Utf8Error(str::Utf8Error),
ValueOutOfRange,
WrongOptionalEncoding,
ParseFailed(&'static str),
}

impl From<str::Utf8Error> for Error {
fn from(err: str::Utf8Error) -> Self {
Self::Utf8Error(err)
}
}

impl From<consensus::Error> for Error {
#[inline]
fn from(err: consensus::Error) -> Self {
Error::BitcoinConsensus(err)
}
}

pub trait Commitment: Sized {
fn commitment_serialize<E: io::Write>(&self, e: E) -> Result<usize, Error>;
fn commitment_deserialize<D: io::Read>(d: D) -> Result<Self, Error>;
Expand Down
29 changes: 29 additions & 0 deletions src/csv/serialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,38 @@

#[macro_use]
pub mod commitment;
#[macro_use]
pub mod network;
pub mod storage;

pub use commitment::*;
pub use network::*;
pub use storage::*;


use std::{str, convert::From};

#[derive(Debug, Display)]
#[display_from(Debug)]
pub enum Error {
BitcoinConsensus(bitcoin::consensus::encode::Error),
EnumValueUnknown(u8),
EnumValueOverflow,
Utf8Error(str::Utf8Error),
ValueOutOfRange,
WrongOptionalEncoding,
ParseFailed(&'static str),
}

impl From<str::Utf8Error> for Error {
fn from(err: str::Utf8Error) -> Self {
Self::Utf8Error(err)
}
}

impl From<bitcoin::consensus::encode::Error> for Error {
#[inline]
fn from(err: bitcoin::consensus::encode::Error) -> Self {
Error::BitcoinConsensus(err)
}
}
50 changes: 36 additions & 14 deletions src/csv/serialize/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,53 @@
// If not, see <https://opensource.org/licenses/MIT>.

use std::io;
use super::commitment::*;

use super::Error;

pub trait Network: Sized {
fn network_serialize<E: io::Write>(&self, e: E) -> Result<usize, Error>;
fn network_deserialize<D: io::Read>(d: D) -> Result<Self, Error>;
}

impl<T> Network for T where T: Commitment {
#[inline]
fn network_serialize<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
self.commitment_serialize(&mut e)
}
/* We have to use custom implementations due to rust language limitations on default trait
implementations */
// TODO: Re-implement it as a proc macro
#[macro_export]
macro_rules! network_serialize_from_commitment {
($type:ty) => {
impl $crate::csv::serialize::network::Network for $type {
#[inline]
fn network_serialize<E: ::std::io::Write>(&self, mut e: E) -> Result<usize, $crate::csv::serialize::Error> {
use $crate::csv::serialize::commitment::Commitment;
self.commitment_serialize(&mut e)
}

#[inline]
fn network_deserialize<D: io::Read>(d: D) -> Result<Self, Error> {
Self::commitment_deserialize(d)
}
#[inline]
fn network_deserialize<D: ::std::io::Read>(d: D) -> Result<Self, $crate::csv::serialize::Error> {
use $crate::csv::serialize::commitment::Commitment;
Self::commitment_deserialize(d)
}
}
};
}

#[inline]
pub fn network_serialize<T: Commitment + Network>(data: &T) -> Result<Vec<u8>, Error> {
commitment_serialize(data)
pub fn network_serialize<T: Network>(data: &T) -> Result<Vec<u8>, Error> {
let mut encoder = io::Cursor::new(vec![]);
data.network_serialize(&mut encoder)?;
Ok(encoder.into_inner())
}

#[inline]
pub fn network_deserialize<T: Commitment + Network>(data: &[u8]) -> Result<T, Error> {
T::commitment_deserialize(data)
pub fn network_deserialize<T: Network>(data: &[u8]) -> Result<T, Error> {
let mut decoder = io::Cursor::new(data);
let rv = T::network_deserialize(&mut decoder)?;
let consumed = decoder.position() as usize;

// Fail if data are not consumed entirely.
if consumed == data.len() {
Ok(rv)
} else {
Err(Error::ParseFailed("data not consumed entirely when explicitly deserializing"))
}
}
2 changes: 1 addition & 1 deletion src/csv/serialize/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// If not, see <https://opensource.org/licenses/MIT>.

use std::io;
use super::{network::*, commitment::*};
use super::{network::*, commitment::*, Error};

pub trait Storage: Sized {
fn storage_serialize<E: io::Write>(&self, e: E) -> Result<usize, Error>;
Expand Down
47 changes: 5 additions & 42 deletions src/rgb/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ use bitcoin::{
use crate::{bp, cmt, csv, rgb};


const HASHTAG_MERKLESTATE: &'static str = "RGB:state:1";

/// Midstate for RGB state commitment. Corresponds to "RGB:state:1" tag with
/// `23fadcc399c645274f9c884ff997f88168d6fe5739593114bb3e3851d3ed3406` hex value
const MIDSTATE_STATE: [u8; 32] = [
Expand Down Expand Up @@ -90,33 +88,21 @@ impl From<bp::MerkleNode> for MetadataRootCommitment {
}


pub trait Identifiable {
pub trait Identifiable: csv::Commitment {
type HashId: cmt::StandaloneCommitment<Vec<u8>> + Hash;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error>;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error> {
use cmt::Committable;
Ok(csv::serialize::commitment_serialize(self)?.commit())
}
}


// TODO: Do this with proc macro to derive commitment from commitment_serialize
impl Identifiable for rgb::metadata::Field {
type HashId = MetadataCommitment;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error> {
use crate::cmt::committable::Committable;
Ok(csv::serialize::commitment_serialize(self)?.commit())
}
}

impl Identifiable for rgb::Metadata {
type HashId = MetadataRootCommitment;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error> {
let data = self.as_ref().iter().try_fold(
Vec::<bp::MerkleNode>::with_capacity(self.len()),
|mut data, field| -> Result<Vec<bp::MerkleNode>, csv::serialize::Error> {
data.push(bp::MerkleNode::from_inner(field.commitment()?.into_inner()));
Ok(data)
}
)?;
Ok(bp::merklize(HASHTAG_MERKLESTATE, &data[..], 0).into())
}
}

impl Identifiable for rgb::state::Partial {
Expand All @@ -129,41 +115,18 @@ impl Identifiable for rgb::state::Partial {
}
}

// TODO: Do this with proc macro to derive commitment from commitment_serialize
impl Identifiable for rgb::state::Bound {
type HashId = StateCommitment;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error> {
use crate::cmt::committable::Committable;
Ok(csv::serialize::commitment_serialize(self)?.commit())
}
}

impl Identifiable for rgb::State {
type HashId = StateRootCommitment;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error> {
let data = self.as_ref().iter().try_fold(
Vec::<bp::MerkleNode>::with_capacity(self.len()),
|mut data, state| -> Result<Vec<bp::MerkleNode>, csv::serialize::Error> {
data.push(bp::MerkleNode::from_inner(state.commitment()?.into_inner()));
Ok(data)
}
)?;
Ok(bp::merklize(HASHTAG_MERKLESTATE, &data[..], 0).into())
}
}

impl Identifiable for Option<rgb::Script> {
type HashId = ScriptCommitment;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error> {
use crate::cmt::committable::Committable;
Ok(csv::serialize::commitment_serialize(self)?.commit())
}
}

impl Identifiable for rgb::Transition {
type HashId = TransitionCommitment;
fn commitment(&self) -> Result<Self::HashId, csv::serialize::Error> {
use crate::cmt::committable::Committable;
Ok(csv::serialize::commitment_serialize(self)?.commit())
}
}
Loading

0 comments on commit 532f590

Please sign in to comment.