Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring data types and their strict encoding #98

Merged
merged 16 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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