Skip to content

Commit

Permalink
Merge 43bcb53 into b95dcfa
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat committed Jul 29, 2020
2 parents b95dcfa + 43bcb53 commit bf346f9
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 53 deletions.
2 changes: 1 addition & 1 deletion sigma-tree/src/chain/json.rs
Expand Up @@ -140,6 +140,6 @@ mod tests {
{"boxId":"dd4e69ae683d7c2d1de2b3174182e6c443fd68abbcc24002ddc99adb599e0193","value":1000000,"ergoTree":"0008cd03f1102eb87a4166bf9fbd6247d087e92e1412b0e819dbb5fbc4e716091ec4e4ec","assets":[],"creationHeight":268539,"additionalRegisters":{},"transactionId":"8204d2bbaabf946f89a27b366d1356eb10241dc1619a70b4e4a4a38b520926ce","index":0}
"#;
let b: ergo_box::ErgoBoxFromJson = serde_json::from_str(json).unwrap();
assert!(b.ergo_tree.proposition().is_err())
assert!(b.ergo_tree.proposition().is_ok())
}
}
128 changes: 76 additions & 52 deletions sigma-tree/src/ergo_tree.rs
Expand Up @@ -30,6 +30,14 @@ pub struct ErgoTree {
#[derive(PartialEq, Eq, Debug, Clone)]
struct ErgoTreeHeader(u8);

impl ErgoTreeHeader {
const CONSTANT_SEGREGATION_FLAG: u8 = 0x10;

pub fn is_constant_segregation(&self) -> bool {
self.0 & ErgoTreeHeader::CONSTANT_SEGREGATION_FLAG != 0
}
}

/// Whole ErgoTree parsing (deserialization) error
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ErgoTreeConstantsParsingError {
Expand Down Expand Up @@ -99,13 +107,15 @@ impl SigmaSerializable for ErgoTree {
self.header.sigma_serialize(w)?;
match &self.tree {
Ok(ParsedTree { constants, root }) => {
w.put_usize_as_u32(constants.len())?;
assert!(
constants.is_empty(),
"separate constants serialization is not yet supported"
);
if self.header.is_constant_segregation() {
w.put_usize_as_u32(constants.len())?;
assert!(
constants.is_empty(),
"separate constants serialization is not yet supported"
);
}
match root {
Ok(tree) => tree.sigma_serialize(w)?,
Ok(expr) => expr.sigma_serialize(w)?,
Err(ErgoTreeRootParsingError { bytes, .. }) => w.write_all(&bytes[..])?,
}
}
Expand All @@ -116,71 +126,73 @@ impl SigmaSerializable for ErgoTree {

fn sigma_parse<R: ReadSigmaVlqExt>(r: &mut R) -> Result<Self, SerializationError> {
let header = ErgoTreeHeader::sigma_parse(r)?;
let constants_len = r.get_u32()?;
if constants_len != 0 {
Err(SerializationError::NotImplementedYet(
"separate constants serialization is not yet supported".to_string(),
))
} else {
let constants = Vec::new();
let root = Expr::sigma_parse(r)?;
Ok(ErgoTree {
header,
tree: Ok(ParsedTree {
constants,
root: Ok(Rc::new(root)),
}),
})
if header.is_constant_segregation() {
let constants_len = r.get_u32()?;
if constants_len != 0 {
return Err(SerializationError::NotImplementedYet(
"separate constants serialization is not yet supported".to_string(),
));
}
}
let constants = Vec::new();
let root = Expr::sigma_parse(r)?;
Ok(ErgoTree {
header,
tree: Ok(ParsedTree {
constants,
root: Ok(Rc::new(root)),
}),
})
}

fn sigma_parse_bytes(mut bytes: Vec<u8>) -> Result<Self, SerializationError> {
let cursor = Cursor::new(&mut bytes[..]);
let mut r = PeekableReader::new(cursor);
let header = ErgoTreeHeader::sigma_parse(&mut r)?;
let constants_len = r.get_u32()?;
if constants_len != 0 {
Ok(ErgoTree {
header,
tree: Err(ErgoTreeConstantsParsingError {
bytes: bytes[1..].to_vec(),
error: SerializationError::NotImplementedYet(
"separate constants serialization is not yet supported".to_string(),
),
}),
})
} else {
let constants = Vec::new();
let mut rest_of_the_bytes = Vec::new();
let _ = r.read_to_end(&mut rest_of_the_bytes);
let rest_of_the_bytes_copy = rest_of_the_bytes.clone();
match Expr::sigma_parse_bytes(rest_of_the_bytes) {
Ok(parsed) => Ok(ErgoTree {
if header.is_constant_segregation() {
let constants_len = r.get_u32()?;
if constants_len != 0 {
return Ok(ErgoTree {
header,
tree: Ok(ParsedTree {
constants,
root: Ok(Rc::new(parsed)),
tree: Err(ErgoTreeConstantsParsingError {
bytes: bytes[1..].to_vec(),
error: SerializationError::NotImplementedYet(
"separate constants serialization is not yet supported".to_string(),
),
}),
});
}
}
let constants = Vec::new();
let mut rest_of_the_bytes = Vec::new();
let _ = r.read_to_end(&mut rest_of_the_bytes);
let rest_of_the_bytes_copy = rest_of_the_bytes.clone();
match Expr::sigma_parse_bytes(rest_of_the_bytes) {
Ok(parsed) => Ok(ErgoTree {
header,
tree: Ok(ParsedTree {
constants,
root: Ok(Rc::new(parsed)),
}),
Err(err) => Ok(ErgoTree {
header,
tree: Ok(ParsedTree {
constants,
root: Err(ErgoTreeRootParsingError {
bytes: rest_of_the_bytes_copy,
error: err,
}),
}),
Err(err) => Ok(ErgoTree {
header,
tree: Ok(ParsedTree {
constants,
root: Err(ErgoTreeRootParsingError {
bytes: rest_of_the_bytes_copy,
error: err,
}),
}),
}
}),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{ast::ConstantVal, sigma_protocol::SigmaProp};
use crate::{ast::ConstantVal, chain, sigma_protocol::SigmaProp};
use proptest::prelude::*;
use sigma_ser::test_helpers::*;

Expand Down Expand Up @@ -219,4 +231,16 @@ mod tests {
// constants length is zero, but Expr is invalid
assert!(ErgoTree::sigma_parse_bytes(vec![0, 0, 1]).is_ok());
}

#[test]
fn test_constant_segregation_header_flag_support() {
let encoder = chain::AddressEncoder::new(chain::NetworkPrefix::Mainnet);
let address = encoder
.parse_address_from_str("9hzP24a2q8KLPVCUk7gdMDXYc7vinmGuxmLp5KU7k9UwptgYBYV")
.unwrap();

let contract = chain::Contract::pay_to_address(address).unwrap();
let bytes = &contract.get_ergo_tree().sigma_serialise_bytes();
assert_eq!(&bytes[..2], vec![0u8, 8u8].as_slice());
}
}

0 comments on commit bf346f9

Please sign in to comment.