Skip to content

Commit

Permalink
introduce SigmaByteWrite trait and the writer impl;
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat committed Aug 7, 2020
1 parent ec43531 commit b886dab
Show file tree
Hide file tree
Showing 23 changed files with 182 additions and 85 deletions.
17 changes: 16 additions & 1 deletion sigma-tree/src/ast/constant.rs
@@ -1,7 +1,7 @@
use crate::chain::{Base16DecodedBytes, Base16EncodedBytes};
use crate::{
chain::ErgoBox,
serialization::{SerializationError, SigmaSerializable},
serialization::{op_code::OpCode, SerializationError, SigmaSerializable},
sigma_protocol::{dlog_group::EcPoint, SigmaProp},
types::{LiftIntoSType, SType},
};
Expand Down Expand Up @@ -260,6 +260,21 @@ impl Into<Constant> for Vec<i8> {
}
}

/// Placeholder for a constant in ErgoTree.
pub struct ConstantPlaceholder {
/// Zero based index in ErgoTree.constants array.
pub id: u32,
/// Type of the constant value
pub tpe: SType,
}

impl ConstantPlaceholder {
/// OpCode for the serialization
pub fn op_code(&self) -> OpCode {
OpCode::CONSTANT_PLACEHOLDER
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
6 changes: 3 additions & 3 deletions sigma-tree/src/chain/box_id.rs
Expand Up @@ -6,11 +6,11 @@ use serde::{Deserialize, Serialize};

use super::digest32::Digest32;
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
sigma_byte_reader::SigmaByteRead, sigma_byte_writer::SigmaByteWrite, SerializationError,
SigmaSerializable,
};
#[cfg(test)]
use proptest_derive::Arbitrary;
use sigma_ser::vlq_encode;

/// newtype for box ids
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
Expand Down Expand Up @@ -42,7 +42,7 @@ impl Into<String> for BoxId {
}

impl SigmaSerializable for BoxId {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.0.sigma_serialize(w)?;
Ok(())
}
Expand Down
6 changes: 3 additions & 3 deletions sigma-tree/src/chain/data_input.rs
@@ -1,11 +1,11 @@
//! DataInput type

use sigma_ser::vlq_encode;
use std::io;

use super::box_id::BoxId;
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
sigma_byte_reader::SigmaByteRead, sigma_byte_writer::SigmaByteWrite, SerializationError,
SigmaSerializable,
};
#[cfg(test)]
use proptest::prelude::*;
Expand All @@ -25,7 +25,7 @@ pub struct DataInput {
}

impl SigmaSerializable for DataInput {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.box_id.sigma_serialize(w)?;
Ok(())
}
Expand Down
8 changes: 4 additions & 4 deletions sigma-tree/src/chain/ergo_box.rs
Expand Up @@ -15,6 +15,7 @@ use crate::{
serialization::{
ergo_box::{parse_box_with_indexed_digests, serialize_box_with_indexed_digests},
sigma_byte_reader::SigmaByteRead,
sigma_byte_writer::SigmaByteWrite,
SerializationError, SigmaSerializable,
},
};
Expand All @@ -23,7 +24,6 @@ use indexmap::IndexSet;
use register::NonMandatoryRegisters;
#[cfg(feature = "with-serde")]
use serde::{Deserialize, Serialize};
use sigma_ser::vlq_encode;
#[cfg(feature = "with-serde")]
use std::convert::TryFrom;
use std::io;
Expand Down Expand Up @@ -184,7 +184,7 @@ impl TryFrom<json::ergo_box::ErgoBoxFromJson> for ErgoBox {
}

impl SigmaSerializable for ErgoBox {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
let ergo_tree_bytes = self.ergo_tree.sigma_serialise_bytes();
serialize_box_with_indexed_digests(
&self.value,
Expand Down Expand Up @@ -239,7 +239,7 @@ impl ErgoBoxCandidate {

/// Box serialization with token ids optionally saved in transaction
/// (in this case only token index is saved)
pub fn serialize_body_with_indexed_digests<W: vlq_encode::WriteSigmaVlqExt>(
pub fn serialize_body_with_indexed_digests<W: SigmaByteWrite>(
&self,
token_ids_in_tx: Option<&IndexSet<TokenId>>,
w: &mut W,
Expand All @@ -265,7 +265,7 @@ impl ErgoBoxCandidate {
}

impl SigmaSerializable for ErgoBoxCandidate {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.serialize_body_with_indexed_digests(None, w)
}
fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SerializationError> {
Expand Down
6 changes: 3 additions & 3 deletions sigma-tree/src/chain/input.rs
@@ -1,10 +1,10 @@
//! Transaction input
use sigma_ser::vlq_encode;
use std::io;

use super::{box_id::BoxId, prover_result::ProverResult};
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
sigma_byte_reader::SigmaByteRead, sigma_byte_writer::SigmaByteWrite, SerializationError,
SigmaSerializable,
};
#[cfg(feature = "with-serde")]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -36,7 +36,7 @@ impl Input {
}

impl SigmaSerializable for Input {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.box_id.sigma_serialize(w)?;
self.spending_proof.sigma_serialize(w)?;
Ok(())
Expand Down
6 changes: 3 additions & 3 deletions sigma-tree/src/chain/prover_result.rs
@@ -1,10 +1,10 @@
//! ProverResult
use sigma_ser::vlq_encode;
use std::io;

use super::context_extension::ContextExtension;
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
sigma_byte_reader::SigmaByteRead, sigma_byte_writer::SigmaByteWrite, SerializationError,
SigmaSerializable,
};
#[cfg(feature = "with-serde")]
use serde::{Deserialize, Serialize};
Expand All @@ -22,7 +22,7 @@ pub struct ProverResult {
}

impl SigmaSerializable for ProverResult {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
w.put_u16(self.proof.len() as u16)?;
w.write_all(&self.proof)?;
self.extension.sigma_serialize(w)?;
Expand Down
6 changes: 3 additions & 3 deletions sigma-tree/src/chain/token.rs
@@ -1,9 +1,9 @@
//! Token related types

use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
sigma_byte_reader::SigmaByteRead, sigma_byte_writer::SigmaByteWrite, SerializationError,
SigmaSerializable,
};
use sigma_ser::vlq_encode;
use std::io;

use super::digest32::Digest32;
Expand All @@ -24,7 +24,7 @@ impl TokenId {
}

impl SigmaSerializable for TokenId {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.0.sigma_serialize(w)?;
Ok(())
}
Expand Down
9 changes: 5 additions & 4 deletions sigma-tree/src/chain/transaction.rs
Expand Up @@ -11,14 +11,15 @@ use super::{
ErgoBox,
};
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
sigma_byte_reader::SigmaByteRead, sigma_byte_writer::SigmaByteWrite, SerializationError,
SigmaSerializable,
};
use indexmap::IndexSet;
#[cfg(test)]
use proptest_derive::Arbitrary;
#[cfg(feature = "with-serde")]
use serde::{Deserialize, Serialize};
use sigma_ser::vlq_encode;

use std::convert::TryFrom;
use std::io;
use std::iter::FromIterator;
Expand All @@ -39,7 +40,7 @@ impl TxId {
}

impl SigmaSerializable for TxId {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.0.sigma_serialize(w)?;
Ok(())
}
Expand Down Expand Up @@ -134,7 +135,7 @@ impl Transaction {
}

impl SigmaSerializable for Transaction {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
// reference implementation - https://github.com/ScorexFoundation/sigmastate-interpreter/blob/9b20cb110effd1987ff76699d637174a4b2fb441/sigmastate/src/main/scala/org/ergoplatform/ErgoLikeTransaction.scala#L112-L112
w.put_usize_as_u16(self.inputs.len())?;
self.inputs.iter().try_for_each(|i| i.sigma_serialize(w))?;
Expand Down
7 changes: 4 additions & 3 deletions sigma-tree/src/ergo_tree.rs
@@ -1,6 +1,7 @@
//! ErgoTree
use crate::serialization::{
sigma_byte_reader::{SigmaByteRead, SigmaByteReader},
sigma_byte_writer::SigmaByteWrite,
SerializationError, SigmaSerializable,
};
use crate::{
Expand All @@ -12,7 +13,7 @@ use io::{Cursor, Read};
use sigma_ser::{peekable_reader::PeekableReader, vlq_encode};
use std::io;
use std::rc::Rc;
use vlq_encode::{ReadSigmaVlqExt, WriteSigmaVlqExt};
use vlq_encode::ReadSigmaVlqExt;

#[derive(PartialEq, Eq, Debug, Clone)]
struct ParsedTree {
Expand Down Expand Up @@ -105,7 +106,7 @@ impl From<Rc<Expr>> for ErgoTree {
}
}
impl SigmaSerializable for ErgoTreeHeader {
fn sigma_serialize<W: WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
w.put_u8(self.0)?;
Ok(())
}
Expand All @@ -116,7 +117,7 @@ impl SigmaSerializable for ErgoTreeHeader {
}

impl SigmaSerializable for ErgoTree {
fn sigma_serialize<W: WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.header.sigma_serialize(w)?;
match &self.tree {
Ok(ParsedTree { constants, root }) => {
Expand Down
2 changes: 2 additions & 0 deletions sigma-tree/src/serialization.rs
@@ -1,6 +1,7 @@
//! Serializers

mod constant;
mod constant_placeholder;
mod constant_store;
mod data;
mod expr;
Expand All @@ -11,6 +12,7 @@ mod sigmaboolean;
pub mod ergo_box;
pub mod op_code;
pub mod sigma_byte_reader;
pub mod sigma_byte_writer;
pub mod types;

pub use serializable::*;
5 changes: 2 additions & 3 deletions sigma-tree/src/serialization/constant.rs
@@ -1,14 +1,13 @@
use super::data::DataSerializer;
use super::{data::DataSerializer, sigma_byte_writer::SigmaByteWrite};
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
};
use crate::{ast::Constant, types::SType};

use sigma_ser::vlq_encode::WriteSigmaVlqExt;
use std::io;

impl SigmaSerializable for Constant {
fn sigma_serialize<W: WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
self.tpe.sigma_serialize(w)?;
DataSerializer::sigma_serialize(&self.v, w)
}
Expand Down
40 changes: 40 additions & 0 deletions sigma-tree/src/serialization/constant_placeholder.rs
@@ -0,0 +1,40 @@
use super::sigma_byte_writer::SigmaByteWrite;
use crate::ast::ConstantPlaceholder;
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
};

use std::io;

impl SigmaSerializable for ConstantPlaceholder {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), io::Error> {
w.put_u32(self.id)
}

fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SerializationError> {
let id = r.get_u32()?;
if let Some(c) = r.constant_store().get(id) {
Ok(ConstantPlaceholder {
id,
tpe: c.tpe.clone(),
})
} else {
Err(SerializationError::ConstantForPlaceholderNotFound(id))
}
}
}

// #[cfg(test)]
// mod tests {
// use super::*;
// use crate::serialization::sigma_serialize_roundtrip;
// use proptest::prelude::*;

// proptest! {

// #[test]
// fn ser_roundtrip(v in any::<ConstantPlaceholder>()) {
// prop_assert_eq![sigma_serialize_roundtrip(&v), v];
// }
// }
// }
16 changes: 11 additions & 5 deletions sigma-tree/src/serialization/constant_store.rs
@@ -1,23 +1,29 @@
//! Constant store for Sigma byte reader

use crate::ast::Constant;
use crate::ast::{Constant, ConstantPlaceholder};

/// Storage for constants used in ErgoTree constant segregation
pub struct ConstantStore {
constants: Vec<Constant>,
}

pub struct ConstantPlaceholder();

impl ConstantStore {
/// empty store(no constants)
pub fn empty() -> Self {
ConstantStore { constants: vec![] }
}

pub fn get(&self, index: u32) -> Option<&Constant> {
self.constants.get(index as usize)
}

pub fn put(&mut self, c: Constant) -> ConstantPlaceholder {
self.constants.push(c);
ConstantPlaceholder()
self.constants.push(c.clone());
assert!(self.constants.len() <= u32::MAX as usize);
ConstantPlaceholder {
id: (self.constants.len() - 1) as u32,
tpe: c.tpe,
}
}

pub fn get_all(&self) -> Vec<Constant> {
Expand Down
7 changes: 2 additions & 5 deletions sigma-tree/src/serialization/data.rs
Expand Up @@ -11,16 +11,13 @@ use crate::{
};
use sigma_protocol::{dlog_group::EcPoint, SigmaBoolean, SigmaProp};

use sigma_ser::vlq_encode::WriteSigmaVlqExt;
use super::sigma_byte_writer::SigmaByteWrite;
use std::io;

pub struct DataSerializer {}

impl DataSerializer {
pub fn sigma_serialize<W: WriteSigmaVlqExt>(
c: &ConstantVal,
w: &mut W,
) -> Result<(), io::Error> {
pub fn sigma_serialize<W: SigmaByteWrite>(c: &ConstantVal, w: &mut W) -> Result<(), io::Error> {
// for reference see http://github.com/ScorexFoundation/sigmastate-interpreter/blob/25251c1313b0131835f92099f02cef8a5d932b5e/sigmastate/src/main/scala/sigmastate/serialization/DataSerializer.scala#L26-L26
match c {
Boolean(v) => w.put_u8(if *v { 1 } else { 0 }),
Expand Down

0 comments on commit b886dab

Please sign in to comment.