Skip to content

Commit

Permalink
Merge pull request #98 from RGB-WG/richdata
Browse files Browse the repository at this point in the history
Refactoring data types and their strict encoding
  • Loading branch information
dr-orlovsky authored Jun 9, 2022
2 parents 29645cd + 7c445fc commit cb747a3
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 1,556 deletions.
14 changes: 0 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ bitcoin = { version = "~0.28.1", features = ["rand"] }
bitcoin_hashes = "~0.10.0" # we need macro from here
electrum-client = { version = "0.10.0", optional = true }
bech32 = "~0.9.0"
# Used only as a part of RGB for encoding Ed25519 key data (for instance as
# a part of Tor address)
ed25519-dalek = "~1.0.1"
# Core rust projects
# ------------------
# This strange naming is a workaround for cargo inability to define required
Expand All @@ -77,11 +74,6 @@ chrono = "~0.4.19"
# updates w/o checking them manually. Should Elements Project secpk256k-zkp
# accept bulletproofs code, we will switch to it
grin_secp256k1zkp = { version = "=0.7.11" }
# 2. We use these to simplify enum strict encoding, but once the required
# functionality will become part of either amplify_derive or lnpbp_derive
# crates they should be removed
num-traits = "~0.2.11"
num-derive = "~0.3.0"
# Optional features used only by a binary
clap = { version = "3.1", optional = true, features = ["derive"] }
serde_yaml = { version = "0.8", optional = true }
Expand Down
50 changes: 0 additions & 50 deletions src/bech32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,26 +57,6 @@ pub enum Bech32 {
)]
Bulletproof(secp256k1zkp::pedersen::RangeProof),

/// Curve25519 public key
///
/// HRP: `curve25519pk`
#[from]
#[cfg_attr(
feature = "serde",
serde(serialize_with = "to_bech32_str", deserialize_with = "from_bech32_str")
)]
Curve25519Pk(ed25519_dalek::PublicKey),

/// Ed25519 signature
///
/// HRP: `ed25519sign`
#[from]
#[cfg_attr(
feature = "serde",
serde(serialize_with = "to_bech32_str", deserialize_with = "from_bech32_str")
)]
Ed25519Sign(ed25519_dalek::Signature),

/// Blinded UTXO for assigning RGB state to.
///
/// HRP: `utxob`
Expand Down Expand Up @@ -167,10 +147,6 @@ impl Bech32 {
pub const HRP_PEDERSEN: &'static str = "pedersen";
/// HRP for a Bech32-encoded blinded bulletproof range proof data
pub const HRP_BULLETPROOF: &'static str = "bulletproof";
/// HRP for a Bech32-encoded blinded bulletproof range proof data
pub const HRP_CURVE25519OPK: &'static str = "curve25519pk";
/// HRP for a Bech32-encoded blinded bulletproof range proof data
pub const HRP_ED25519OSIGN: &'static str = "ed25519sign";
/// HRP for a Bech32-encoded blinded UTXO data
pub const HRP_OUTPOINT: &'static str = "utxob";

Expand Down Expand Up @@ -318,28 +294,6 @@ impl TryFrom<Bech32> for secp256k1zkp::pedersen::RangeProof {
}
}

impl TryFrom<Bech32> for ed25519_dalek::PublicKey {
type Error = Error;

fn try_from(bech32: Bech32) -> Result<Self, Self::Error> {
match bech32 {
Bech32::Curve25519Pk(obj) => Ok(obj),
_ => Err(Error::WrongType),
}
}
}

impl TryFrom<Bech32> for ed25519_dalek::Signature {
type Error = Error;

fn try_from(bech32: Bech32) -> Result<Self, Self::Error> {
match bech32 {
Bech32::Ed25519Sign(obj) => Ok(obj),
_ => Err(Error::WrongType),
}
}
}

impl TryFrom<Bech32> for seal::Confidential {
type Error = Error;

Expand Down Expand Up @@ -440,8 +394,6 @@ impl FromStr for Bech32 {
Ok(match hrp {
x if x == Self::HRP_PEDERSEN => Self::PedersenCommitment(strict_deserialize(&data)?),
x if x == Self::HRP_BULLETPROOF => Self::Bulletproof(strict_deserialize(&data)?),
x if x == Self::HRP_CURVE25519OPK => Self::Curve25519Pk(strict_deserialize(&data)?),
x if x == Self::HRP_ED25519OSIGN => Self::Ed25519Sign(strict_deserialize(&data)?),
x if x == Self::HRP_OUTPOINT => Self::BlindedUtxo(strict_deserialize(&data)?),
x if x == Self::HRP_SCHEMA_ID => Self::SchemaId(strict_deserialize(&data)?),
x if x == Self::HRP_CONTRACT_ID => Self::ContractId(strict_deserialize(&data)?),
Expand All @@ -460,8 +412,6 @@ impl Display for Bech32 {
let (hrp, data) = match self {
Self::PedersenCommitment(obj) => (Self::HRP_PEDERSEN, strict_serialize(obj)?),
Self::Bulletproof(obj) => (Self::HRP_BULLETPROOF, strict_serialize(obj)?),
Self::Curve25519Pk(obj) => (Self::HRP_CURVE25519OPK, strict_serialize(obj)?),
Self::Ed25519Sign(obj) => (Self::HRP_ED25519OSIGN, strict_serialize(obj)?),
Self::BlindedUtxo(obj) => (Self::HRP_OUTPOINT, strict_serialize(obj)?),
Self::SchemaId(obj) => (Self::HRP_SCHEMA_ID, strict_serialize(obj)?),
Self::ContractId(obj) => (Self::HRP_CONTRACT_ID, strict_serialize(obj)?),
Expand Down
139 changes: 13 additions & 126 deletions src/contract/assignments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use super::{
data, seal, value, ConcealSeals, ConcealState, EndpointValueMap, NoDataError, SealEndpoint,
SealValueMap, SECP256K1_ZKP,
};
use crate::{schema, ConfidentialDataError, StateRetrievalError};
use crate::{ConfidentialDataError, StateRetrievalError};

lazy_static! {
pub(super) static ref EMPTY_ASSIGNMENT_VEC: AssignmentVec = AssignmentVec::default();
Expand All @@ -45,8 +45,8 @@ pub enum StateType {
Data,
}

#[derive(Clone, PartialEq, Eq, Debug, Display)]
#[display(Debug)]
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(StrictEncode, StrictDecode)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
Expand Down Expand Up @@ -636,8 +636,8 @@ impl State for HashStrategy {
/// State data are assigned to a seal definition, which means that they are
/// owned by a person controlling spending of the seal UTXO, unless the seal
/// is closed, indicating that a transfer of ownership had taken place
#[derive(Clone, Debug, Display)]
#[display(Debug)]
#[derive(Clone, Debug)]
#[derive(StrictEncode, StrictDecode)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
Expand Down Expand Up @@ -976,120 +976,6 @@ where
type Commitment = MerkleNode;
}

mod _strict_encoding {
use std::io;

use data::_strict_encoding::EncodingTag;
use strict_encoding::Error;

use super::*;

impl StrictEncode for AssignmentVec {
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(match self {
AssignmentVec::Declarative(tree) => {
strict_encode_list!(e; schema::StateType::Declarative, tree)
}
AssignmentVec::DiscreteFiniteField(tree) => {
strict_encode_list!(e; schema::StateType::DiscreteFiniteField, EncodingTag::U64, tree)
}
AssignmentVec::CustomData(tree) => {
strict_encode_list!(e; schema::StateType::CustomData, tree)
}
})
}
}

impl StrictDecode for AssignmentVec {
fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
let format = schema::StateType::strict_decode(&mut d)?;
Ok(match format {
schema::StateType::Declarative => {
AssignmentVec::Declarative(StrictDecode::strict_decode(d)?)
}
schema::StateType::DiscreteFiniteField => match EncodingTag::strict_decode(&mut d)?
{
EncodingTag::U64 => {
AssignmentVec::DiscreteFiniteField(StrictDecode::strict_decode(&mut d)?)
}
_ => Err(Error::UnsupportedDataStructure(
"We support only homomorphic commitments to U64 data",
))?,
},
schema::StateType::CustomData => {
AssignmentVec::CustomData(StrictDecode::strict_decode(d)?)
}
})
}
}

impl<StateType> StrictEncode for Assignment<StateType>
where
StateType: State,
StateType::Confidential: PartialEq + Eq,
StateType::Confidential: From<<StateType::Revealed as CommitConceal>::ConcealedCommitment>,
{
fn strict_encode<E: io::Write>(&self, mut e: E) -> Result<usize, Error> {
Ok(match self {
Assignment::Confidential {
seal_definition,
assigned_state,
} => {
strict_encode_list!(e; 0u8, seal_definition, assigned_state)
}
Assignment::Revealed {
seal_definition,
assigned_state,
} => {
strict_encode_list!(e; 1u8, seal_definition, assigned_state)
}
Assignment::ConfidentialSeal {
seal_definition,
assigned_state,
} => {
strict_encode_list!(e; 2u8, seal_definition, assigned_state)
}
Assignment::ConfidentialAmount {
seal_definition,
assigned_state,
} => {
strict_encode_list!(e; 3u8, seal_definition, assigned_state)
}
})
}
}

impl<StateType> StrictDecode for Assignment<StateType>
where
StateType: State,
StateType::Confidential: PartialEq + Eq,
StateType::Confidential: From<<StateType::Revealed as CommitConceal>::ConcealedCommitment>,
{
fn strict_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
let format = u8::strict_decode(&mut d)?;
Ok(match format {
0u8 => Assignment::Confidential {
seal_definition: seal::Confidential::strict_decode(&mut d)?,
assigned_state: StateType::Confidential::strict_decode(&mut d)?,
},
1u8 => Assignment::Revealed {
seal_definition: seal::Revealed::strict_decode(&mut d)?,
assigned_state: StateType::Revealed::strict_decode(&mut d)?,
},
2u8 => Assignment::ConfidentialSeal {
seal_definition: seal::Confidential::strict_decode(&mut d)?,
assigned_state: StateType::Revealed::strict_decode(&mut d)?,
},
3u8 => Assignment::ConfidentialAmount {
seal_definition: seal::Revealed::strict_decode(&mut d)?,
assigned_state: StateType::Confidential::strict_decode(&mut d)?,
},
invalid => Err(Error::EnumValueNotKnown("Assignment", invalid as usize))?,
})
}
}
}

#[cfg(test)]
mod test {
use std::collections::BTreeMap;
Expand All @@ -1107,6 +993,7 @@ mod test {
use super::super::{NodeId, OwnedRights, ParentOwnedRights};
use super::*;
use crate::contract::seal::Revealed;
use crate::schema;

// Hard coded test vectors of Assignment Variants
// Each Variant contains 4 types of Assignments
Expand Down Expand Up @@ -1713,8 +1600,8 @@ mod test {
let data_set = hash_type.filter_revealed_state_data();

// Create state data from precomputed values
let data_1 = data::Revealed::Sha256(sha256::Hash::from_hex(STATE_DATA[2]).unwrap());
let data_2 = data::Revealed::Sha256(sha256::Hash::from_hex(STATE_DATA[0]).unwrap());
let data_1 = data::Revealed::Bytes(sha256::Hash::from_hex(STATE_DATA[2]).unwrap().to_vec());
let data_2 = data::Revealed::Bytes(sha256::Hash::from_hex(STATE_DATA[0]).unwrap().to_vec());

// Check extracted data matches with precomputed values
assert_eq!(data_set[0].to_owned(), data_1);
Expand Down Expand Up @@ -2059,22 +1946,22 @@ mod test {

let assignment_1 = Assignment::<DeclarativeStrategy>::Revealed {
seal_definition: Revealed::from(OutPoint::new(txid_vec[0], 1)),
assigned_state: data::Void,
assigned_state: data::Void(),
};

let assignment_2 = Assignment::<DeclarativeStrategy>::ConfidentialAmount {
seal_definition: Revealed::from(OutPoint::new(txid_vec[1], 2)),
assigned_state: data::Void,
assigned_state: data::Void(),
};

let assignment_3 = Assignment::<DeclarativeStrategy>::ConfidentialSeal {
seal_definition: Revealed::from(OutPoint::new(txid_vec[2], 3)).commit_conceal(),
assigned_state: data::Void,
assigned_state: data::Void(),
};

let assignment_4 = Assignment::<DeclarativeStrategy>::Confidential {
seal_definition: Revealed::from(OutPoint::new(txid_vec[3], 4)).commit_conceal(),
assigned_state: data::Void,
assigned_state: data::Void(),
};

let mut set = Vec::new();
Expand Down Expand Up @@ -2130,7 +2017,7 @@ mod test {

let state_data_vec: Vec<data::Revealed> = STATE_DATA
.iter()
.map(|data| data::Revealed::Sha256(sha256::Hash::from_hex(data).unwrap()))
.map(|data| data::Revealed::Bytes(sha256::Hash::from_hex(data).unwrap().to_vec()))
.collect();

let assignment_1 = Assignment::<HashStrategy>::Revealed {
Expand Down
Loading

0 comments on commit cb747a3

Please sign in to comment.