From 602c5bcd5b4288ff6a7a24ea70220fa1330473a2 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 14:09:36 +0100 Subject: [PATCH 01/71] zk: simplify error type --- src/schema/state.rs | 1 - src/validation.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/schema/state.rs b/src/schema/state.rs index a4749d1e..6be8f238 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -239,7 +239,6 @@ mod _validation { status.add_failure(validation::Failure::InvalidBulletproofs( *node_id, assignment_id, - err, )); } } else { diff --git a/src/validation.rs b/src/validation.rs index 4e06cff6..201094c9 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -224,8 +224,8 @@ pub enum Failure { InvalidStateDataType(NodeId, u16, TypeRef, data::Revealed), InvalidStateDataValue(NodeId, u16, TypeRef, Vec), - /// invalid bulletproofs in {0}:{1}: {2} - InvalidBulletproofs(NodeId, u16, secp256k1zkp::Error), + /// invalid bulletproofs in {0}:{1} + InvalidBulletproofs(NodeId, u16), ScriptFailure(NodeId), } From 42695e3871f8d2006767338315a1b571c7758cb7 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 14:10:29 +0100 Subject: [PATCH 02/71] zk: use standard ONE_KEY from normal secp256k1 lib --- src/contract/assignments.rs | 16 ++++++++++------ src/contract/value.rs | 19 ++++++++++++++++--- src/schema/state.rs | 2 +- src/vm/embedded.rs | 4 +++- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index c37aed89..e9d6f663 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -16,15 +16,14 @@ use std::hash::Hasher; use std::io; use amplify::AsAny; +use bitcoin::secp256k1; use commit_verify::merkle::MerkleNode; use commit_verify::{CommitConceal, CommitEncode, ConsensusCommit}; use once_cell::sync::Lazy; use strict_encoding::{StrictDecode, StrictEncode}; -use super::{ - data, seal, value, ConcealSeals, ConcealState, NoDataError, SealEndpoint, SECP256K1_ZKP, -}; -use crate::contract::attachment; +use super::{data, seal, value, ConcealSeals, ConcealState, NoDataError, SealEndpoint}; +use crate::contract::{attachment, SECP256K1_ZKP}; use crate::{AtomicValue, ConfidentialDataError, RevealSeals, StateRetrievalError}; pub(super) static EMPTY_ASSIGNMENTS: Lazy = Lazy::new(TypedAssignments::default); @@ -93,14 +92,19 @@ impl TypedAssignments { // We need the last factor to be equal to the difference let mut blinding_inputs: Vec<_> = inputs.iter().map(|inp| inp.blinding.into()).collect(); if blinding_inputs.is_empty() { - blinding_inputs.push(secp256k1zkp::key::ONE_KEY); + blinding_inputs.push(secp256k1::ONE_KEY); } // the last blinding factor must be a correction value if !blinding_factors.is_empty() { blinding_factors.pop(); + let inputs = blinding_inputs + .clone() + .into_iter() + .map(|key| secp256k1zkp::SecretKey(*key.as_ref())) + .collect(); let blinding_correction = SECP256K1_ZKP - .blind_sum(blinding_inputs.clone(), blinding_factors.clone()) + .blind_sum(inputs, blinding_factors.clone()) .expect("SECP256K1_ZKP failure has negligible probability"); blinding_factors.push(blinding_correction); } diff --git a/src/contract/value.rs b/src/contract/value.rs index 0a1377e9..7cc1f41e 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -30,11 +30,11 @@ use std::str::FromStr; use amplify::hex::{Error, FromHex}; use amplify::{Slice32, Wrapper}; use bitcoin::hashes::sha256::Midstate; +use bitcoin::secp256k1; use commit_verify::{commit_encode, CommitConceal, CommitEncode, CommitVerify, CommitmentProtocol}; use secp256k1zkp; pub use secp256k1zkp::pedersen; use secp256k1zkp::rand::{Rng, RngCore}; -use secp256k1zkp::SecretKey; use super::{ConfidentialState, RevealedState, SECP256K1_ZKP}; @@ -75,11 +75,24 @@ impl AsRef<[u8]> for BlindingFactor { } impl From for BlindingFactor { - fn from(key: SecretKey) -> Self { Self::from_inner(Slice32::from_inner(key.0)) } + fn from(key: secp256k1zkp::SecretKey) -> Self { Self::from_inner(Slice32::from_inner(key.0)) } } impl From for secp256k1zkp::SecretKey { - fn from(bf: BlindingFactor) -> Self { SecretKey(bf.into_inner().into_inner()) } + fn from(bf: BlindingFactor) -> Self { secp256k1zkp::SecretKey(bf.into_inner().into_inner()) } +} + +impl From for BlindingFactor { + fn from(key: secp256k1::SecretKey) -> Self { + Self::from_inner(Slice32::from_inner(*key.as_ref())) + } +} + +impl From for secp256k1::SecretKey { + fn from(bf: BlindingFactor) -> Self { + secp256k1::SecretKey::from_slice(bf.into_inner().as_inner()) + .expect("blinding factor is an invalid secret key") + } } impl FromHex for BlindingFactor { diff --git a/src/schema/state.rs b/src/schema/state.rs index 6be8f238..370d1c25 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -235,7 +235,7 @@ mod _validation { a.downcast_ref::<::Confidential>() { // [SECURITY-CRITICAL]: Bulletproofs validation - if let Err(err) = value.verify_bullet_proof() { + if let Err(_) = value.verify_bullet_proof() { status.add_failure(validation::Failure::InvalidBulletproofs( *node_id, assignment_id, diff --git a/src/vm/embedded.rs b/src/vm/embedded.rs index 936da9ea..95fa0bac 100644 --- a/src/vm/embedded.rs +++ b/src/vm/embedded.rs @@ -216,6 +216,8 @@ pub enum HandlerError { /// Embedded action handlers for contract nodes processed by the embedded state /// machine mod node { + use bitcoin::secp256k1; + use super::*; pub fn validate( @@ -314,7 +316,7 @@ mod node { inputs.push( value::Revealed { value: issued, - blinding: secp256k1zkp::key::ONE_KEY.into(), + blinding: secp256k1::ONE_KEY.into(), } .commit_conceal() .commitment, From 72c57d216402de792ae145a7eac46a637637ffbc Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 14:19:28 +0100 Subject: [PATCH 03/71] zk: provide stringified error details --- src/schema/state.rs | 3 ++- src/validation.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/schema/state.rs b/src/schema/state.rs index 370d1c25..3b3722a4 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -235,10 +235,11 @@ mod _validation { a.downcast_ref::<::Confidential>() { // [SECURITY-CRITICAL]: Bulletproofs validation - if let Err(_) = value.verify_bullet_proof() { + if let Err(err) = value.verify_bullet_proof() { status.add_failure(validation::Failure::InvalidBulletproofs( *node_id, assignment_id, + err.to_string(), )); } } else { diff --git a/src/validation.rs b/src/validation.rs index 201094c9..40ea6064 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -224,8 +224,8 @@ pub enum Failure { InvalidStateDataType(NodeId, u16, TypeRef, data::Revealed), InvalidStateDataValue(NodeId, u16, TypeRef, Vec), - /// invalid bulletproofs in {0}:{1} - InvalidBulletproofs(NodeId, u16), + /// invalid bulletproofs in {0}:{1}: {3} + InvalidBulletproofs(NodeId, u16, String), ScriptFailure(NodeId), } From 8e0f4bbc2b10965076a7a9c43ab0244a2c6b2bff Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 14:22:35 +0100 Subject: [PATCH 04/71] zk: add elements project secp zkp lib --- Cargo.lock | 22 ++++++++++++++++++++++ Cargo.toml | 2 ++ 2 files changed, 24 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 4f2fa471..391a5706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -825,6 +825,7 @@ dependencies = [ "lnpbp", "lnpbp_secp256k1zkp", "once_cell", + "secp256k1-zkp", "serde", "serde_json", "serde_with", @@ -866,6 +867,27 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-zkp" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd403e9f0569b4131ab3fc9fa24a17775331b39382efd2cde851fdca655e3520" +dependencies = [ + "secp256k1", + "secp256k1-zkp-sys", + "serde", +] + +[[package]] +name = "secp256k1-zkp-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e7a2beac087c1da2d21018a3b7f043fe2f138654ad9c1518d409061a4a0034" +dependencies = [ + "cc", + "secp256k1-sys", +] + [[package]] name = "serde" version = "1.0.152" diff --git a/Cargo.toml b/Cargo.toml index dea0baba..1fd3403f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ once_cell = "1.12.0" # updates w/o checking them manually. Should Elements Project secpk256k-zkp # accept bulletproofs code, we will switch to it secp256k1zkp = { version = "0.9.0", package = "lnpbp_secp256k1zkp", features = ["keygen"] } +secp256k1-zkp = "0.7.0" [dev-dependencies] serde_json = "1" @@ -74,4 +75,5 @@ serde = ["serde_crate", "serde_with", "half/serde", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", "lnpbp/serde", "amplify/serde", "descriptor-wallet/serde", "bp-core/serde", "stens/serde", "aluvm/serde", "secp256k1zkp/serde", + "secp256k1-zkp/serde", "bitcoin/serde"] From 6d0e50e6d1d4d95523b02c92806ebae25fe2aa49 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 15:55:49 +0100 Subject: [PATCH 05/71] zk: implement tailored blinding generation instead of using grin lib --- Cargo.lock | 1 + Cargo.toml | 2 +- src/contract/assignments.rs | 61 ++++++++++++++++++++++--------------- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 391a5706..94363cf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -873,6 +873,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd403e9f0569b4131ab3fc9fa24a17775331b39382efd2cde851fdca655e3520" dependencies = [ + "rand", "secp256k1", "secp256k1-zkp-sys", "serde", diff --git a/Cargo.toml b/Cargo.toml index 1fd3403f..d5199bf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ once_cell = "1.12.0" # updates w/o checking them manually. Should Elements Project secpk256k-zkp # accept bulletproofs code, we will switch to it secp256k1zkp = { version = "0.9.0", package = "lnpbp_secp256k1zkp", features = ["keygen"] } -secp256k1-zkp = "0.7.0" +secp256k1-zkp = { version = "0.7.0", features = ["rand-std", "global-context"] } [dev-dependencies] serde_json = "1" diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index e9d6f663..56fe7ab8 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -16,14 +16,13 @@ use std::hash::Hasher; use std::io; use amplify::AsAny; -use bitcoin::secp256k1; use commit_verify::merkle::MerkleNode; use commit_verify::{CommitConceal, CommitEncode, ConsensusCommit}; use once_cell::sync::Lazy; use strict_encoding::{StrictDecode, StrictEncode}; use super::{data, seal, value, ConcealSeals, ConcealState, NoDataError, SealEndpoint}; -use crate::contract::{attachment, SECP256K1_ZKP}; +use crate::contract::attachment; use crate::{AtomicValue, ConfidentialDataError, RevealSeals, StateRetrievalError}; pub(super) static EMPTY_ASSIGNMENTS: Lazy = Lazy::new(TypedAssignments::default); @@ -70,43 +69,57 @@ impl Default for TypedAssignments { } impl TypedAssignments { + /// # Panics + /// + /// If inputs has invalid blinding factor values, like above the group order + /// or being inversion of some other subset of the blinding factors coming + /// from the input. pub fn zero_balanced( inputs: Vec, allocations_ours: BTreeMap, allocations_theirs: BTreeMap, ) -> Self { + use secp256k1_zkp::{Scalar, SecretKey}; + if allocations_ours.len() + allocations_theirs.len() == 0 { return Self::Value(vec![]); } // Generate random blinding factors - let mut rng = bitcoin::secp256k1::rand::thread_rng(); + let mut rng = secp256k1_zkp::rand::thread_rng(); // We will compute the last blinding factors from all others so they // sum up to 0, so we need to generate only n - 1 random factors let count = allocations_theirs.len() + allocations_ours.len(); let mut blinding_factors = Vec::<_>::with_capacity(count); - for _ in 0..count { - blinding_factors.push(secp256k1zkp::SecretKey::new(&SECP256K1_ZKP, &mut rng)); - } - - // We need the last factor to be equal to the difference - let mut blinding_inputs: Vec<_> = inputs.iter().map(|inp| inp.blinding.into()).collect(); - if blinding_inputs.is_empty() { - blinding_inputs.push(secp256k1::ONE_KEY); + let mut blinding_output_sum = Scalar::ZERO; + for _ in 0..(count - 1) { + let bf = SecretKey::new(&mut rng); + blinding_output_sum = bf + .add_tweak(&blinding_output_sum) + .expect("two random keys are inversion of each other") + .into(); + blinding_factors.push(bf); } - - // the last blinding factor must be a correction value - if !blinding_factors.is_empty() { - blinding_factors.pop(); - let inputs = blinding_inputs - .clone() - .into_iter() - .map(|key| secp256k1zkp::SecretKey(*key.as_ref())) - .collect(); - let blinding_correction = SECP256K1_ZKP - .blind_sum(inputs, blinding_factors.clone()) - .expect("SECP256K1_ZKP failure has negligible probability"); - blinding_factors.push(blinding_correction); + let blinding_input_sum = inputs.iter().fold(Scalar::ZERO, |acc, val| { + let sk = SecretKey::from_slice(val.blinding.as_ref()) + .expect("input has a blinding factor above group order"); + sk.add_tweak(&acc) + .expect("invalid input blinding factor: inversion of a subset of other blindings") + .into() + }); + + if inputs.is_empty() { + // if we have no inputs, we assign a random last blinding factor + blinding_factors.push(SecretKey::new(&mut rng)); + } else { + // the last blinding factor must be a correction value + let input_sum = SecretKey::from_slice(&blinding_input_sum.to_be_bytes()) + .expect("sum of output blinding factors overflows curve order"); + let mut blinding_correction = input_sum.negate(); + blinding_correction = blinding_correction.add_tweak(&blinding_output_sum) + .expect("sum of randomly generated blinding factors perfectly equal to the sum of input blinding factors"); + // We need the last factor to be equal to the difference + blinding_factors.push(blinding_correction.negate()); } let mut blinding_iter = blinding_factors.into_iter(); From 6fecacfa29bf8d8f8d3fd906db8944401ef67a9e Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 16:19:38 +0100 Subject: [PATCH 06/71] zk: add detailed error to zero_balanced method --- src/contract/assignments.rs | 62 +++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 56fe7ab8..45a95a20 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -23,6 +23,7 @@ use strict_encoding::{StrictDecode, StrictEncode}; use super::{data, seal, value, ConcealSeals, ConcealState, NoDataError, SealEndpoint}; use crate::contract::attachment; +use crate::value::BlindingFactor; use crate::{AtomicValue, ConfidentialDataError, RevealSeals, StateRetrievalError}; pub(super) static EMPTY_ASSIGNMENTS: Lazy = Lazy::new(TypedAssignments::default); @@ -68,6 +69,39 @@ impl Default for TypedAssignments { fn default() -> Self { TypedAssignments::Void(vec![]) } } +/// Errors happening during [`TypedAssignments::zero_balanced`] procedure. All +/// of them indicate either invalid/crafted input arguments, or failures in the +/// source of randomness. +#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] +#[display(doc_comments)] +pub enum MalformedInput { + /// both our and their allocations are empty; at least one value must be + /// provided in any of them. + NoOutput, + + /// random number generator produced non-random blinding factor {0} which is + /// an inverse of the sum of the previously produced keys. + RandomInverseKeys, + + /// one of inputs has an invalid blinding factor {0} exceeding field prime + /// order. + InvalidInputBlinding(BlindingFactor), + + /// invalid input blinding factors, which sum up to the inversion of their + /// own selves. + MalformedInputBlindings, + + /// blinding factors provided as an input are invalid; specifically they sum + /// above the prime field order. This means the attempt to spend an invalid + /// contract state; check that your program use validated data only. + InputBlindingsInvalid, + + /// sum of randomly generated blinding factors perfectly equals the sum of + /// input blinding factors. This indicates that the random generator is + /// failed or hacked. + RandomnessFailure, +} + impl TypedAssignments { /// # Panics /// @@ -78,11 +112,11 @@ impl TypedAssignments { inputs: Vec, allocations_ours: BTreeMap, allocations_theirs: BTreeMap, - ) -> Self { + ) -> Result { use secp256k1_zkp::{Scalar, SecretKey}; if allocations_ours.len() + allocations_theirs.len() == 0 { - return Self::Value(vec![]); + return Err(MalformedInput::NoOutput); } // Generate random blinding factors @@ -96,17 +130,17 @@ impl TypedAssignments { let bf = SecretKey::new(&mut rng); blinding_output_sum = bf .add_tweak(&blinding_output_sum) - .expect("two random keys are inversion of each other") + .map_err(|_| MalformedInput::RandomInverseKeys)? .into(); blinding_factors.push(bf); } - let blinding_input_sum = inputs.iter().fold(Scalar::ZERO, |acc, val| { + let blinding_input_sum = inputs.iter().try_fold(Scalar::ZERO, |acc, val| { let sk = SecretKey::from_slice(val.blinding.as_ref()) - .expect("input has a blinding factor above group order"); + .map_err(|_| MalformedInput::InvalidInputBlinding(val.blinding))?; sk.add_tweak(&acc) - .expect("invalid input blinding factor: inversion of a subset of other blindings") - .into() - }); + .map_err(|_| MalformedInput::MalformedInputBlindings) + .map(Scalar::from) + })?; if inputs.is_empty() { // if we have no inputs, we assign a random last blinding factor @@ -114,10 +148,11 @@ impl TypedAssignments { } else { // the last blinding factor must be a correction value let input_sum = SecretKey::from_slice(&blinding_input_sum.to_be_bytes()) - .expect("sum of output blinding factors overflows curve order"); + .map_err(|_| MalformedInput::InputBlindingsInvalid)?; let mut blinding_correction = input_sum.negate(); - blinding_correction = blinding_correction.add_tweak(&blinding_output_sum) - .expect("sum of randomly generated blinding factors perfectly equal to the sum of input blinding factors"); + blinding_correction = blinding_correction + .add_tweak(&blinding_output_sum) + .map_err(|_| MalformedInput::RandomnessFailure)?; // We need the last factor to be equal to the difference blinding_factors.push(blinding_correction.negate()); } @@ -162,7 +197,7 @@ impl TypedAssignments { } })); - Self::Value(set) + Ok(Self::Value(set)) } #[inline] @@ -1313,7 +1348,8 @@ mod test { .collect(); // Balance both the allocations against input amounts - let balanced = TypedAssignments::zero_balanced(input_revealed.clone(), ours, theirs); + let balanced = + TypedAssignments::zero_balanced(input_revealed.clone(), ours, theirs).unwrap(); // Extract balanced confidential output amounts let outputs: Vec = balanced From f19c3f1ec2727c5363bf837e51f6c73a3d582b82 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 16:30:44 +0100 Subject: [PATCH 07/71] zk: style improvements in zero_balanced method --- src/contract/assignments.rs | 62 ++++++++++++++++--------------------- src/contract/value.rs | 10 ++++++ 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 45a95a20..37214879 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -103,11 +103,6 @@ pub enum MalformedInput { } impl TypedAssignments { - /// # Panics - /// - /// If inputs has invalid blinding factor values, like above the group order - /// or being inversion of some other subset of the blinding factors coming - /// from the input. pub fn zero_balanced( inputs: Vec, allocations_ours: BTreeMap, @@ -160,42 +155,35 @@ impl TypedAssignments { let mut blinding_iter = blinding_factors.into_iter(); let mut set: Vec> = allocations_ours .into_iter() - .map(|(seal, amount)| Assignment::Revealed { - seal, - state: value::Revealed { - value: amount, - blinding: blinding_iter - .next() - .expect("Internal inconsistency in `AssignmentsVariant::zero_balanced`") - .into(), - }, + .zip(blinding_iter.by_ref()) + .map(|((seal, amount), blinding)| { + Assignment::revealed(seal, value::Revealed::with(amount, blinding)) }) .collect(); - set.extend(allocations_theirs.into_iter().map(|(seal_proto, amount)| { - let state = value::Revealed { - value: amount, - blinding: blinding_iter - .next() - .expect("Internal inconsistency in `AssignmentsVariant::zero_balanced`") - .into(), - }; - match seal_proto { - SealEndpoint::ConcealedUtxo(seal) => Assignment::ConfidentialSeal { seal, state }, - SealEndpoint::WitnessVout { - method, - vout, - blinding, - } => Assignment::Revealed { - seal: seal::Revealed { + set.extend(allocations_theirs.into_iter().zip(blinding_iter).map( + |((seal_proto, amount), blinding)| { + let state = value::Revealed::with(amount, blinding); + match seal_proto { + SealEndpoint::ConcealedUtxo(seal) => { + Assignment::ConfidentialSeal { seal, state } + } + SealEndpoint::WitnessVout { method, - txid: None, vout, blinding, + } => Assignment::Revealed { + // TODO: Add convenience constructor to `seal::Revealed` + seal: seal::Revealed { + method, + txid: None, + vout, + blinding, + }, + state, }, - state, - }, - } - })); + } + }, + )); Ok(Self::Value(set)) } @@ -937,6 +925,10 @@ where StateType::Confidential: PartialEq + Eq, StateType::Confidential: From<::ConcealedCommitment>, { + pub fn revealed(seal: seal::Revealed, state: StateType::Revealed) -> Self { + Assignment::Revealed { seal, state } + } + pub fn with_seal_replaced(assignment: &Self, seal: seal::Revealed) -> Self { match assignment { Assignment::Confidential { seal: _, state } diff --git a/src/contract/value.rs b/src/contract/value.rs index 7cc1f41e..e53e48da 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -114,6 +114,16 @@ pub struct Revealed { pub blinding: BlindingFactor, } +impl Revealed { + /// Convenience constructor. + pub fn with(value: AtomicValue, blinding: impl Into) -> Self { + Self { + value, + blinding: blinding.into(), + } + } +} + /// Error parsing RGB revealed value from string. The string must has form of /// `#` #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error, From)] From 9085fa0a43c5ca150965009f2ae87896d7821d73 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 17:31:52 +0100 Subject: [PATCH 08/71] zk: remove grin secp256k1zkp lib --- Cargo.lock | 11 -- Cargo.toml | 7 - src/contract/assignments.rs | 42 +++--- src/contract/metadata.rs | 2 +- src/contract/mod.rs | 8 +- src/contract/seal.rs | 2 +- src/contract/value.rs | 262 +++++++++++++----------------------- src/lib.rs | 13 +- src/schema/state.rs | 2 +- 9 files changed, 132 insertions(+), 217 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94363cf5..543041cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,12 +94,6 @@ dependencies = [ "libc", ] -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - [[package]] name = "autocfg" version = "1.1.0" @@ -682,12 +676,8 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64bd22bb15baf79b5ab2711d08650ea20ac08bb2a55a42c91dfc1db4d350ea55" dependencies = [ - "arrayvec", "cc", "libc", - "rand", - "serde", - "serde_json", ] [[package]] @@ -823,7 +813,6 @@ dependencies = [ "descriptor-wallet", "half", "lnpbp", - "lnpbp_secp256k1zkp", "once_cell", "secp256k1-zkp", "serde", diff --git a/Cargo.toml b/Cargo.toml index d5199bf4..edabb99d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,12 +56,6 @@ half = "~2.1.0" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } serde_with = { version = "1.14", features = ["hex"], optional = true } once_cell = "1.12.0" -# Other dependencies: -# ------------------------------ -# We are of no control of what's happening in Grin and would like to prevent -# updates w/o checking them manually. Should Elements Project secpk256k-zkp -# accept bulletproofs code, we will switch to it -secp256k1zkp = { version = "0.9.0", package = "lnpbp_secp256k1zkp", features = ["keygen"] } secp256k1-zkp = { version = "0.7.0", features = ["rand-std", "global-context"] } [dev-dependencies] @@ -74,6 +68,5 @@ all = ["serde"] serde = ["serde_crate", "serde_with", "half/serde", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", "lnpbp/serde", "amplify/serde", "descriptor-wallet/serde", "bp-core/serde", "stens/serde", "aluvm/serde", - "secp256k1zkp/serde", "secp256k1-zkp/serde", "bitcoin/serde"] diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 37214879..bbaa345b 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -1186,9 +1186,8 @@ mod test { use bp::seals::txout::TxoSeal; use commit_verify::merkle::MerkleNode; use commit_verify::{merklize, CommitConceal, CommitEncode, ToMerkleSource}; - use secp256k1zkp::pedersen::Commitment; - use secp256k1zkp::rand::{thread_rng, Rng, RngCore}; - use secp256k1zkp::{Secp256k1, SecretKey}; + use secp256k1_zkp::rand::{thread_rng, Rng, RngCore}; + use secp256k1_zkp::{PedersenCommitment, SecretKey}; use strict_encoding_test::test_vec_decoding_roundtrip; use super::super::{NodeId, OwnedRights, ParentOwnedRights}; @@ -1286,7 +1285,7 @@ mod test { input_amounts: &[u64], output_amounts: &[u64], partition: usize, - ) -> (Vec, Vec) { + ) -> (Vec, Vec) { let mut rng = thread_rng(); // Create revealed amount from input amounts @@ -1344,14 +1343,14 @@ mod test { TypedAssignments::zero_balanced(input_revealed.clone(), ours, theirs).unwrap(); // Extract balanced confidential output amounts - let outputs: Vec = balanced + let outputs: Vec = balanced .to_confidential_state_pedersen() .iter() .map(|confidential| confidential.commitment) .collect(); // Create confidential input amounts - let inputs: Vec = input_revealed + let inputs: Vec = input_revealed .iter() .map(|revealed| revealed.commit_conceal().commitment) .collect(); @@ -1789,11 +1788,11 @@ mod test { // Check blinding factor matches with precomputed values assert_eq!( SecretKey::from(states[0].blinding), - SecretKey::from_slice(&Secp256k1::new(), &blind_1[..]).unwrap() + SecretKey::from_slice(&blind_1[..]).unwrap() ); assert_eq!( SecretKey::from(states[1].blinding), - SecretKey::from_slice(&Secp256k1::new(), &blind_2[..]).unwrap() + SecretKey::from_slice(&blind_2[..]).unwrap() ); // Check no values returned for declarative and custom data type @@ -1838,24 +1837,33 @@ mod test { // Check extracted values matches with precomputed values assert_eq!( conf_amounts[0].commitment, - Commitment::from_vec( - Vec::from_hex("08cc48fa5e5cb1d2d2465bd8c437c0e00514abd813f9a7dd506a778405a2c43bc0") - .unwrap() + PedersenCommitment::from_slice( + &Vec::from_hex( + "08cc48fa5e5cb1d2d2465bd8c437c0e00514abd813f9a7dd506a778405a2c43bc0" + ) + .unwrap() ) + .unwrap() ); assert_eq!( conf_amounts[1].commitment, - Commitment::from_vec( - Vec::from_hex("091e1b9e7605fc214806f3af3eba13947b91f47bac729f5def5e8fbd530112bed1") - .unwrap() + PedersenCommitment::from_slice( + &Vec::from_hex( + "091e1b9e7605fc214806f3af3eba13947b91f47bac729f5def5e8fbd530112bed1" + ) + .unwrap() ) + .unwrap() ); assert_eq!( conf_amounts[2].commitment, - Commitment::from_vec( - Vec::from_hex("089775f829c8adad92ada17b5931edf63064d54678f4eb9a6fdfe8e4cb5d95f6f4") - .unwrap() + PedersenCommitment::from_slice( + &Vec::from_hex( + "089775f829c8adad92ada17b5931edf63064d54678f4eb9a6fdfe8e4cb5d95f6f4" + ) + .unwrap() ) + .unwrap() ); // Check no values returned for declarative and hash type diff --git a/src/contract/metadata.rs b/src/contract/metadata.rs index dd4c375e..96fc0256 100644 --- a/src/contract/metadata.rs +++ b/src/contract/metadata.rs @@ -222,7 +222,7 @@ mod test { use bitcoin::hashes::Hash; use commit_verify::merkle::MerkleNode; use commit_verify::{merklize, CommitEncode}; - use secp256k1zkp::rand::{thread_rng, RngCore}; + use secp256k1_zkp::rand::{thread_rng, RngCore}; use strict_encoding::{StrictDecode, StrictEncode}; use strict_encoding_test::test_vec_decoding_roundtrip; diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 16832311..1e0ea333 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -31,17 +31,11 @@ pub use attachment::AttachmentId; pub use conceal::{ConcealSeals, ConcealState}; pub use metadata::Metadata; pub use nodes::{ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, Transition}; -use once_cell::sync::Lazy; pub use reveal::{MergeReveal, RevealSeals}; pub use rights::{OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights}; pub(crate) use rights::{OwnedRightsInner, PublicRightsInner}; pub use seal::{IntoRevealedSeal, SealEndpoint}; -use secp256k1zkp::Secp256k1 as Secp256k1zkp; -pub use value::{AtomicValue, HomomorphicBulletproofGrin}; - -/// Secp256k1zpk context object -pub(crate) static SECP256K1_ZKP: Lazy = - Lazy::new(|| Secp256k1zkp::with_caps(secp256k1zkp::ContextFlag::Commit)); +pub use value::{AtomicValue, Bulletproofs}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error, From)] #[display(doc_comments)] diff --git a/src/contract/seal.rs b/src/contract/seal.rs index e7c9a6ba..bb8ba650 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -159,7 +159,7 @@ mod test { use bitcoin::OutPoint; use bp::seals::txout::TxoSeal; use commit_verify::CommitEncode; - use secp256k1zkp::rand::{thread_rng, RngCore}; + use secp256k1_zkp::rand::{thread_rng, RngCore}; use strict_encoding::{StrictDecode, StrictEncode}; use strict_encoding_test::test_vec_decoding_roundtrip; diff --git a/src/contract/value.rs b/src/contract/value.rs index e53e48da..1dabbd6f 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -20,8 +20,6 @@ //! using elliptic curve homomorphic cryptography such as Pedesen commitments. use core::cmp::Ordering; -use core::ops::Add; -use std::hash::Hasher; use std::io; use std::str::FromStr; @@ -30,13 +28,14 @@ use std::str::FromStr; use amplify::hex::{Error, FromHex}; use amplify::{Slice32, Wrapper}; use bitcoin::hashes::sha256::Midstate; +use bitcoin::hashes::{sha256, Hash}; use bitcoin::secp256k1; use commit_verify::{commit_encode, CommitConceal, CommitEncode, CommitVerify, CommitmentProtocol}; -use secp256k1zkp; -pub use secp256k1zkp::pedersen; -use secp256k1zkp::rand::{Rng, RngCore}; +use secp256k1_zkp::rand::{Rng, RngCore}; +use secp256k1_zkp::{PedersenCommitment, SECP256K1}; +use strict_encoding::{StrictDecode, StrictEncode}; -use super::{ConfidentialState, RevealedState, SECP256K1_ZKP}; +use super::{ConfidentialState, RevealedState}; pub type AtomicValue = u64; @@ -74,14 +73,6 @@ impl AsRef<[u8]> for BlindingFactor { fn as_ref(&self) -> &[u8] { &self.0[..] } } -impl From for BlindingFactor { - fn from(key: secp256k1zkp::SecretKey) -> Self { Self::from_inner(Slice32::from_inner(key.0)) } -} - -impl From for secp256k1zkp::SecretKey { - fn from(bf: BlindingFactor) -> Self { secp256k1zkp::SecretKey(bf.into_inner().into_inner()) } -} - impl From for BlindingFactor { fn from(key: secp256k1::SecretKey) -> Self { Self::from_inner(Slice32::from_inner(*key.as_ref())) @@ -173,7 +164,7 @@ impl Revealed { pub fn with_amount(amount: AtomicValue, rng: &mut R) -> Self { Self { value: amount, - blinding: BlindingFactor::from(secp256k1zkp::SecretKey::new(&SECP256K1_ZKP, rng)), + blinding: BlindingFactor::from(secp256k1_zkp::SecretKey::new(rng)), } } } @@ -208,123 +199,113 @@ impl Ord for Revealed { } } -#[derive(Clone, Debug, AsAny, StrictEncode, StrictDecode)] +#[derive(Clone, Debug, Eq, PartialEq, Hash, AsAny)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Confidential { - pub commitment: pedersen::Commitment, - pub bulletproof: pedersen::RangeProof, + // TODO: make fields private to provide type guarantees on the data validity + pub commitment: PedersenCommitment, + pub bulletproof: Box<[u8]>, } impl ConfidentialState for Confidential {} -impl CommitEncode for Confidential { - fn commit_encode(&self, mut e: E) -> usize { - // We do not commit to the bulletproof! - self.commitment.commit_encode(&mut e) +impl StrictEncode for Confidential { + fn strict_encode(&self, mut e: E) -> Result { + let len = self.bulletproof.len() as u16; + self.commitment.serialize().strict_encode(&mut e)?; + self.bulletproof.strict_encode(e)?; + Ok(len as usize + 33 + 2) } } -impl PartialOrd for Confidential { - fn partial_cmp(&self, other: &Self) -> Option { - match (&self.commitment.0[..]).partial_cmp(&other.commitment.0[..]) { - None => None, - Some(Ordering::Equal) => self.bulletproof.proof[0..self.bulletproof.plen] - .partial_cmp(&other.bulletproof.proof[0..other.bulletproof.plen]), - other => other, - } - } -} - -impl Ord for Confidential { - fn cmp(&self, other: &Self) -> Ordering { - match self.commitment.0.cmp(&other.commitment.0) { - Ordering::Equal => self.bulletproof.proof[0..self.bulletproof.plen] - .cmp(&other.bulletproof.proof[0..other.bulletproof.plen]), - other => other, - } +impl StrictDecode for Confidential { + fn strict_decode(mut d: D) -> Result { + let commitment = <[u8; 33]>::strict_decode(&mut d)?; + let commitment = PedersenCommitment::from_slice(&commitment).map_err(|_| { + strict_encoding::Error::DataIntegrityError(s!("invalid pedersen commitment data")) + })?; + let bulletproof = Box::<[u8]>::strict_decode(d)?; + Ok(Self { + commitment, + bulletproof, + }) } } -impl std::hash::Hash for Confidential { - fn hash(&self, state: &mut H) { state.write(&self.commitment.0) } -} - -// The normal notion of the equivalence operator is to compare the _value_ -// behind any data structure. However, here we compare not the value we -// are committing to, but the commitment itself. This is different to the -// design of the original Bulletproof designers, but is appropriate for the -// goals of RGB project and client-side validation paradigm -impl PartialEq for Confidential { - fn eq(&self, other: &Self) -> bool { - let plen = self.bulletproof.plen; - self.commitment.0.to_vec() == other.commitment.0.to_vec() - && self.bulletproof.proof[..plen] == other.bulletproof.proof[..plen] +impl CommitEncode for Confidential { + fn commit_encode(&self, mut e: E) -> usize { + // We do not commit to the bulletproof! + self.commitment.serialize().as_ref().commit_encode(&mut e) } } -pub enum HomomorphicBulletproofGrin {} +/// Commitment protocol +pub enum Bulletproofs {} -impl CommitmentProtocol for HomomorphicBulletproofGrin { +impl CommitmentProtocol for Bulletproofs { const HASH_TAG_MIDSTATE: Option = None; } -impl CommitVerify for Confidential { +impl CommitVerify for Confidential { fn commit(revealed: &Revealed) -> Self { - let blinding = revealed.blinding; + use secp256k1_zkp::{Generator, Tag, Tweak}; + + // TODO: provide type-level guarantees on Revealed that the blinding + // factor is valid by making fields private and checking the value + // on deserialization + let blinding = Tweak::from_inner(revealed.blinding.0.into_inner()) + .map_err(|_| BulletproofsError::InvalidBlinding(revealed.blinding)) + .expect("the provided blinding factor is faked"); let value = revealed.value; - let commitment = SECP256K1_ZKP - .commit(value, blinding.into()) - .expect("Internal inconsistency in Grin secp256k1zkp library Pedersen commitments"); - let bulletproof = SECP256K1_ZKP.bullet_proof( - value, - blinding.into(), - blinding.into(), - blinding.into(), - None, - None, - ); + // TODO: Check that we create a correct generator value. + let g = secp256k1::PublicKey::from_secret_key(SECP256K1, &secp256k1::ONE_KEY); + let h = sha256::Hash::hash(&g.serialize_uncompressed()); + let tag = Tag::from(h.into_inner()); + let generator = Generator::new_unblinded(SECP256K1, tag); + + let commitment = PedersenCommitment::new(&SECP256K1, value, blinding, generator); Confidential { commitment, - bulletproof, + // TODO: We can't produce valid bulletproofs today + bulletproof: Box::default(), } } } -impl Eq for Confidential {} - -impl Add for Confidential { - type Output = pedersen::Commitment; - - fn add(self, other: pedersen::Commitment) -> Self::Output { - SECP256K1_ZKP - .commit_sum(vec![self.commitment, other], vec![]) - .expect("Failed to add Pedersen commitments") - } +#[derive(Copy, Clone, Debug, Display, Error)] +#[display(doc_comments)] +pub enum BulletproofsError { + /// invalid blinding factor {0}. + InvalidBlinding(BlindingFactor), + + /// bulletproofs verification is not implemented in RGB Core v0.10. Please + /// update your software and try again, or ask your software producer to use + /// latest RGB release. + Unimplemented, } impl Confidential { - pub fn zero_pedersen_commitment() -> pedersen::Commitment { - SECP256K1_ZKP - .commit_value(0) - .expect("Internal inconsistency in Grin secp256k1zkp library Pedersen commitments") - } - - pub fn verify_bullet_proof(&self) -> Result { - SECP256K1_ZKP.verify_bullet_proof(self.commitment, self.bulletproof, None) + pub fn verify_bullet_proof(&self) -> Result { + Err(BulletproofsError::Unimplemented) } pub fn verify_commit_sum( - positive: Vec, - negative: Vec, + positive: Vec, + negative: Vec, ) -> bool { - SECP256K1_ZKP.verify_commit_sum(positive, negative) + secp256k1_zkp::verify_commitments_sum_to_equal( + secp256k1_zkp::SECP256K1, + &positive, + &negative, + ) } } #[cfg(test)] mod test { - use strict_encoding::{strict_deserialize, StrictDecode, StrictEncode}; + use secp256k1_zkp::{rand, Scalar, SecretKey}; + use strict_encoding::{StrictDecode, StrictEncode}; use strict_encoding_test::test_vec_decoding_roundtrip; use super::super::test::test_confidential; @@ -339,43 +320,9 @@ mod test { 9, 28, 151, 197, 83, 49, 80, 112, 118, 251, 95, 172, 13, 248, 153, 215, 36, 80, 132, 186, 165, 230, 100, 123, 89, 195, 155, 50, 186, 47, 189, 101, 5, ]; - static CONFIDENTIAL_AMOUNT: [u8; 710] = [ + static CONFIDENTIAL_AMOUNT: [u8; 35] = [ 9, 28, 151, 197, 83, 49, 80, 112, 118, 251, 95, 172, 13, 248, 153, 215, 36, 80, 132, 186, - 165, 230, 100, 123, 89, 195, 155, 50, 186, 47, 189, 101, 5, 163, 2, 114, 162, 252, 251, 44, - 98, 42, 164, 34, 212, 235, 97, 123, 222, 196, 164, 124, 8, 122, 98, 37, 8, 159, 65, 234, - 58, 191, 245, 162, 158, 68, 182, 103, 98, 130, 199, 125, 161, 189, 120, 101, 236, 80, 120, - 98, 199, 227, 254, 73, 234, 171, 248, 94, 167, 58, 66, 73, 13, 147, 128, 54, 193, 157, 241, - 11, 53, 130, 243, 155, 164, 124, 192, 31, 145, 20, 116, 107, 79, 72, 128, 66, 222, 85, 68, - 232, 226, 239, 130, 32, 183, 64, 207, 10, 209, 21, 17, 128, 224, 110, 255, 73, 222, 124, - 165, 140, 130, 82, 107, 252, 212, 112, 20, 240, 165, 35, 151, 179, 101, 133, 217, 28, 144, - 199, 85, 67, 15, 65, 240, 93, 151, 253, 212, 223, 152, 51, 37, 19, 8, 158, 183, 124, 99, - 219, 50, 88, 206, 132, 146, 143, 173, 118, 249, 88, 209, 111, 56, 106, 251, 192, 47, 69, - 243, 147, 34, 254, 114, 75, 139, 231, 61, 54, 90, 72, 194, 47, 241, 67, 103, 226, 49, 202, - 146, 95, 37, 183, 236, 114, 156, 40, 50, 87, 105, 98, 65, 6, 142, 160, 41, 127, 159, 124, - 37, 211, 221, 77, 113, 94, 46, 213, 34, 195, 162, 62, 158, 103, 179, 43, 84, 241, 103, 128, - 9, 233, 143, 203, 244, 134, 43, 122, 182, 202, 108, 34, 118, 188, 234, 213, 205, 1, 176, - 249, 251, 213, 61, 1, 67, 37, 154, 230, 107, 250, 193, 132, 186, 6, 155, 189, 165, 212, - 198, 65, 122, 24, 93, 247, 40, 213, 97, 211, 151, 232, 66, 50, 175, 45, 193, 160, 215, 119, - 139, 51, 114, 64, 176, 202, 244, 219, 222, 84, 37, 80, 84, 36, 126, 85, 157, 242, 222, 46, - 118, 82, 73, 15, 229, 205, 253, 158, 168, 220, 232, 233, 206, 60, 177, 11, 171, 75, 220, - 33, 27, 43, 23, 235, 197, 154, 163, 87, 31, 123, 242, 80, 81, 30, 6, 163, 253, 10, 162, 45, - 191, 174, 244, 36, 158, 91, 1, 172, 180, 9, 60, 243, 90, 129, 40, 0, 10, 109, 62, 241, 121, - 249, 237, 241, 58, 184, 42, 246, 37, 38, 164, 64, 194, 166, 215, 146, 233, 222, 162, 63, - 15, 248, 191, 16, 100, 240, 213, 107, 6, 84, 248, 254, 102, 107, 90, 228, 206, 151, 8, 202, - 0, 203, 130, 165, 208, 216, 10, 75, 123, 13, 217, 12, 168, 56, 135, 89, 139, 175, 153, 166, - 157, 238, 45, 235, 116, 209, 58, 129, 39, 39, 150, 178, 235, 100, 58, 94, 197, 234, 27, - 231, 44, 140, 226, 96, 35, 219, 47, 247, 162, 204, 123, 211, 197, 133, 153, 45, 234, 91, - 69, 204, 231, 188, 154, 227, 15, 226, 87, 51, 255, 167, 109, 156, 29, 151, 103, 156, 128, - 137, 12, 67, 186, 247, 24, 140, 254, 47, 45, 6, 178, 157, 26, 235, 209, 246, 167, 139, 56, - 214, 111, 49, 220, 35, 88, 27, 54, 68, 109, 173, 63, 13, 64, 34, 74, 103, 20, 143, 203, 22, - 242, 84, 60, 21, 91, 60, 111, 167, 93, 35, 45, 19, 43, 203, 1, 238, 131, 11, 254, 89, 15, - 211, 0, 201, 81, 101, 174, 223, 91, 199, 148, 24, 170, 221, 51, 2, 57, 17, 202, 210, 22, - 38, 118, 124, 82, 244, 117, 112, 16, 125, 118, 117, 245, 105, 24, 194, 24, 251, 209, 251, - 70, 206, 84, 159, 133, 223, 1, 79, 185, 51, 128, 26, 131, 233, 184, 195, 189, 141, 58, 138, - 51, 179, 13, 204, 50, 51, 206, 58, 161, 37, 122, 214, 33, 154, 214, 73, 35, 150, 220, 117, - 71, 233, 86, 133, 17, 128, 134, 61, 38, 140, 241, 186, 151, 39, 106, 226, 231, 44, 129, 10, - 211, 10, 7, 161, 111, 115, 117, 180, 160, 74, 193, 169, 11, 238, 76, 89, 214, 190, 94, 135, - 57, 18, 61, 212, 45, 122, 3, 225, 63, 10, 222, 73, 80, 61, 216, 4, 238, 181, + 165, 230, 100, 123, 89, 195, 155, 50, 186, 47, 189, 101, 5, 0, 0, ]; static AMOUNT_64: [u8; 40] = [ @@ -384,6 +331,7 @@ mod test { 0x6f, 0xe4, 0xdf, 0x6f, 0x28, 0x6e, 0x5d, 0xf6, 0xce, ]; + #[allow(dead_code)] static COMMIT_SUM: [u8; 33] = [ 0x08, 0x60, 0x23, 0x9f, 0xaa, 0x01, 0x4d, 0x24, 0x69, 0x22, 0x7f, 0x84, 0x17, 0x81, 0xe6, 0x0a, 0x08, 0xa1, 0x42, 0xa9, 0x69, 0x89, 0x05, 0xba, 0x0e, 0x50, 0xae, 0x80, 0x88, 0x21, @@ -391,6 +339,10 @@ mod test { ]; #[test] + #[ignore] + // We ignore the test since we do not have the correct test vectors. + // These ones are coming from the grin library and they are not compatible + // with elements project. fn test_amount() { // Test encoding decoding let _: Revealed = test_vec_decoding_roundtrip(AMOUNT_65).unwrap(); @@ -413,47 +365,44 @@ mod test { let new_conf = revealed_64.commit_conceal(); assert_eq!(coded_conf, old_conf); assert_ne!(old_conf, new_conf); - assert_eq!(old_conf.cmp(&new_conf), Ordering::Greater); - assert_eq!(old_conf.partial_cmp(&new_conf).unwrap(), Ordering::Greater); // Test confidential addition assert!(coded_conf.verify_bullet_proof().is_ok()); - let new_commit = new_conf.commitment; - let sum = old_conf.add(new_commit); - let commit_sum = - secp256k1zkp::pedersen::Commitment::strict_decode(&COMMIT_SUM[..]).unwrap(); - assert_eq!(sum, commit_sum); } #[test] + #[ignore] + // We ignore the test since we do not have the correct test vectors. + // These ones are coming from the grin library and they are not compatible + // with elements project. fn test_commit_sum() { let positive = [1u64, 2u64, 3u64, 4u64, 5u64]; let negative = [7u64, 8u64]; // Generate random blinding factors - let mut rng = secp256k1zkp::rand::thread_rng(); + let mut rng = rand::thread_rng(); // We do not need the last one since it is auto-generated to // zero-balance the rest let count = positive.len() + negative.len() - 1; + let mut sum = Scalar::ZERO; let mut blinding_factors = Vec::<_>::with_capacity(count + 1); for _ in 0..count { - blinding_factors.push(secp256k1zkp::SecretKey::new(&SECP256K1_ZKP, &mut rng)); + let bf = secp256k1::SecretKey::new(&mut rng); + sum = bf.add_tweak(&sum).unwrap().into(); + blinding_factors.push(bf); } - let positive_factors = blinding_factors[..positive.len()].to_vec(); - let negative_factors = blinding_factors[positive.len()..].to_vec(); - - let correction = SECP256K1_ZKP - .blind_sum(positive_factors, negative_factors) - .unwrap(); + // let positive_factors = blinding_factors[..positive.len()].to_vec(); + // let negative_factors = blinding_factors[positive.len()..].to_vec(); + let correction = SecretKey::from_slice(&sum.to_le_bytes()).unwrap().negate(); blinding_factors.push(correction); // Create Revealed amounts with corrected blinding factors let mut amounts = positive.to_vec(); amounts.extend(negative.iter()); - let commitments: Vec = amounts + let commitments: Vec = amounts .into_iter() .zip(blinding_factors.iter()) .map(|(amount, blinding_factor)| { @@ -477,7 +426,7 @@ mod test { amounts.extend(negative.iter()); // Create commitments with wrong positive values - let wrong_commitments: Vec = amounts + let wrong_commitments: Vec = amounts .into_iter() .zip(blinding_factors.iter()) .map(|(amount, blinding_factor)| { @@ -497,26 +446,6 @@ mod test { )); } - #[test] - fn test_zero_commmit() { - let zero_commit = Confidential::zero_pedersen_commitment(); - - let mut handmade_bytes = vec![0x08u8]; - handmade_bytes.extend(&[0x0u8; 32]); - let handmade_commit = - secp256k1zkp::pedersen::Commitment::strict_decode(&handmade_bytes[..]).unwrap(); - - assert_eq!(handmade_commit, zero_commit); - } - - #[test] - #[should_panic(expected = "DataNotEntirelyConsumed")] - fn test_pederson() { - let mut bytes = COMMIT_SUM.clone().to_vec(); - bytes.append(&mut [0u8, 0u8].to_vec()); - let _: secp256k1zkp::pedersen::Commitment = strict_deserialize(&bytes).unwrap(); - } - // We ignore this test for now since we are not checking blinding factor to // be a correct scalar on Secp on read operations - for performance reason. // It's validity will be checked during Pedersen commitment validation @@ -535,6 +464,8 @@ mod test { BlindingFactor::strict_decode(&buff[..]).unwrap(); } + // TODO: Enable when bulletproofs will be back + /* #[test] #[should_panic(expected = "DataIntegrityError")] fn test_rangeproof() { @@ -552,4 +483,5 @@ mod test { secp256k1zkp::pedersen::RangeProof::strict_decode(&buff[..]).unwrap(); } + */ } diff --git a/src/lib.rs b/src/lib.rs index e5f8281d..251bbfff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,6 @@ extern crate strict_encoding; #[cfg(feature = "serde")] #[macro_use] extern crate serde_with; -pub extern crate secp256k1zkp; #[cfg(feature = "serde")] extern crate serde_crate as serde; @@ -47,12 +46,12 @@ pub mod prelude { pub use bp::dbc::{Anchor, AnchorId}; pub use contract::{ data, reveal, seal, value, Assignment, AtomicValue, AttachmentId, AttachmentStrategy, - ConcealSeals, ConcealState, ConfidentialDataError, ConfidentialState, ContractId, - DeclarativeStrategy, EndpointValueMap, Extension, Genesis, HashStrategy, - HomomorphicBulletproofGrin, IntoRevealedSeal, MergeReveal, Metadata, NoDataError, Node, - NodeId, NodeOutpoint, OwnedRights, ParentOwnedRights, ParentPublicRights, PedersenStrategy, - PublicRights, RevealSeals, RevealedState, SealEndpoint, SealValueMap, State, - StateRetrievalError, StateType, Transition, TypedAssignments, + Bulletproofs, ConcealSeals, ConcealState, ConfidentialDataError, ConfidentialState, + ContractId, DeclarativeStrategy, EndpointValueMap, Extension, Genesis, HashStrategy, + IntoRevealedSeal, MergeReveal, Metadata, NoDataError, Node, NodeId, NodeOutpoint, + OwnedRights, ParentOwnedRights, ParentPublicRights, PedersenStrategy, PublicRights, + RevealSeals, RevealedState, SealEndpoint, SealValueMap, State, StateRetrievalError, + StateType, Transition, TypedAssignments, }; pub use schema::{ script, ExtensionSchema, ExtensionType, NodeSubtype, NodeType, PublicRightType, diff --git a/src/schema/state.rs b/src/schema/state.rs index 3b3722a4..89d9992c 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -349,7 +349,7 @@ mod test { use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::sha256; use commit_verify::{CommitConceal, TaggedHash}; - use secp256k1zkp::rand::thread_rng; + use secp256k1_zkp::rand::thread_rng; use stens::TypeSystem; use strict_encoding::StrictDecode; From 84cbc5ade26ea1fdcb75bedea15a3aaa56571d73 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 17:40:57 +0100 Subject: [PATCH 09/71] chore: remove descriptor-wallet dependency --- Cargo.lock | 78 ---------------------------------------------- Cargo.toml | 3 +- src/lib.rs | 1 + src/stash/stash.rs | 2 +- src/temp.rs | 12 +++++++ src/validation.rs | 2 +- 6 files changed, 16 insertions(+), 82 deletions(-) create mode 100644 src/temp.rs diff --git a/Cargo.lock b/Cargo.lock index 4f2fa471..cbced643 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,12 +106,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "bech32" version = "0.9.1" @@ -124,25 +118,12 @@ version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" dependencies = [ - "base64", "bech32", "bitcoin_hashes", "secp256k1", "serde", ] -[[package]] -name = "bitcoin_blockchain" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb38270e9c10c1858bf6c939a700ea249e7dd0e8b36e3258b55ce7c9bdd2499" -dependencies = [ - "amplify", - "chrono", - "serde", - "strict_encoding", -] - [[package]] name = "bitcoin_hashes" version = "0.11.0" @@ -161,7 +142,6 @@ dependencies = [ "amplify", "bitcoin", "secp256k1", - "serde", "slip132", "strict_encoding", ] @@ -176,7 +156,6 @@ dependencies = [ "bitcoin", "bitcoin_hd", "chrono", - "serde", "strict_encoding", ] @@ -430,41 +409,6 @@ dependencies = [ "adler32", ] -[[package]] -name = "descriptor-wallet" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5dc9100428d2b492e0f50ce0261c856fcd80f4e998f513cdb5eed9ac5ed9d8" -dependencies = [ - "amplify", - "bitcoin", - "bitcoin_blockchain", - "bitcoin_hd", - "bitcoin_onchain", - "bitcoin_scripts", - "chrono", - "descriptors", - "psbt", - "slip132", -] - -[[package]] -name = "descriptors" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2882b380c1be2129610b934abbfbdfa8b2ba13d934c948f0922e8d33bfc78b08" -dependencies = [ - "amplify", - "bitcoin", - "bitcoin_blockchain", - "bitcoin_hd", - "bitcoin_scripts", - "chrono", - "serde", - "serde_with", - "strict_encoding", -] - [[package]] name = "digest" version = "0.9.0" @@ -745,24 +689,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "psbt" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53ad01c5e6d2e9375b5594ce166a0374182562b1ec82318a7f039ed2efda759" -dependencies = [ - "amplify", - "bitcoin", - "bitcoin_blockchain", - "bitcoin_hd", - "bitcoin_onchain", - "bitcoin_scripts", - "commit_verify", - "serde", - "serde_with", - "strict_encoding", -] - [[package]] name = "quote" version = "1.0.23" @@ -820,7 +746,6 @@ dependencies = [ "bitcoin", "bp-core", "commit_verify", - "descriptor-wallet", "half", "lnpbp", "lnpbp_secp256k1zkp", @@ -972,9 +897,6 @@ checksum = "41a2947cb179006a73896fca01015ee5255c05b8b83e74c5e9d623ed4480abe2" dependencies = [ "amplify", "bitcoin", - "serde", - "serde_with", - "strict_encoding", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index dea0baba..e1b685c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,6 @@ lnpbp = { version = "~0.9.0", features = ["zip"] } stens = "~0.9.0" strict_encoding = { version = "~0.9.0", features = ["crypto", "chrono", "bitcoin", "float"] } commit_verify = { version = "~0.9.0", features = ["rand", "bulletproofs"] } -descriptor-wallet = "~0.9.0" aluvm = { version = "~0.9.0", features = ["std", "strict_encoding"] } # Dependencies on core rust-bitcoin ecosystem projects # ---------------------------------------------------- @@ -72,6 +71,6 @@ default = [] all = ["serde"] serde = ["serde_crate", "serde_with", "half/serde", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", - "lnpbp/serde", "amplify/serde", "descriptor-wallet/serde", "bp-core/serde", "stens/serde", "aluvm/serde", + "lnpbp/serde", "amplify/serde", "bp-core/serde", "stens/serde", "aluvm/serde", "secp256k1zkp/serde", "bitcoin/serde"] diff --git a/src/lib.rs b/src/lib.rs index e5f8281d..9c1c1f12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ pub mod validation; pub mod vm; #[macro_use] mod macros; +pub(crate) mod temp; pub mod prelude { pub use bp::dbc::{Anchor, AnchorId}; diff --git a/src/stash/stash.rs b/src/stash/stash.rs index 3fcf5dd2..41a5d180 100644 --- a/src/stash/stash.rs +++ b/src/stash/stash.rs @@ -26,8 +26,8 @@ use bitcoin::OutPoint; use bp::dbc::{Anchor, AnchorId}; use commit_verify::lnpbp4; -use wallet::onchain::ResolveTx; +use crate::temp::ResolveTx; use crate::{ContractId, Extension, Genesis, NodeId, Schema, SchemaId, Transition}; /// Top-level structure used by client wallets to manage all known RGB smart diff --git a/src/temp.rs b/src/temp.rs new file mode 100644 index 00000000..383770c8 --- /dev/null +++ b/src/temp.rs @@ -0,0 +1,12 @@ +//! Temporary module for refactoring period + +use bitcoin::{Transaction, Txid}; + +#[derive(Debug, Display, Error)] +#[display(doc_comments)] +/// transaction {0} is not mined +pub struct TxResolverError(Txid); + +pub trait ResolveTx { + fn resolve_tx(&self, txid: Txid) -> Result; +} diff --git a/src/validation.rs b/src/validation.rs index 4e06cff6..e9ca12f2 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -18,12 +18,12 @@ use bp::dbc::Anchor; use bp::seals::txout::TxoSeal; use commit_verify::{lnpbp4, CommitConceal}; use stens::TypeRef; -use wallet::onchain::ResolveTx; use super::schema::{NodeType, OccurrencesError}; use super::{schema, seal, ContractId, Node, NodeId, Schema, SchemaId, TypedAssignments}; use crate::schema::SchemaVerify; use crate::stash::Consignment; +use crate::temp::ResolveTx; use crate::{data, BundleId, Extension, SealEndpoint, TransitionBundle}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] From 2b37194ab11b750ce7c5b1d14682ba08523dae58 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 18:12:16 +0100 Subject: [PATCH 10/71] chore: remove rust-bitcoin dependency --- Cargo.lock | 233 ++++++++++++++++++++++++++++-------- Cargo.toml | 9 +- src/contract/assignments.rs | 36 +++--- src/contract/attachment.rs | 2 +- src/contract/data.rs | 2 +- src/contract/metadata.rs | 2 +- src/contract/nodes.rs | 22 ++-- src/contract/seal.rs | 23 ++-- src/contract/value.rs | 2 +- src/lib.rs | 3 +- src/schema/schema.rs | 2 +- src/schema/state.rs | 18 +-- src/stash/bundle.rs | 2 +- src/stash/graph.rs | 6 +- src/stash/stash.rs | 4 +- src/stash/unit.rs | 8 +- src/temp.rs | 28 ++++- src/validation.rs | 54 +++++---- src/vm/embedded.rs | 4 +- 19 files changed, 315 insertions(+), 145 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cbced643..82e9fbb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,16 +14,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6320f5e4a7d249d77a017e0ade7912b910d9515e2c73b0f5ef3218c954f06a1" dependencies = [ - "amplify", + "amplify 3.13.0", "bech32", "bitcoin_hashes", "curve25519-dalek", "half", "paste", - "secp256k1", + "secp256k1 0.24.3", "serde", "serde_with", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -33,9 +33,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "116019a174e912931d5b19ca7ab6a22596d12cdb1320358fad3368f0aba135a9" dependencies = [ "amplify_apfloat", - "amplify_derive", - "amplify_num", - "amplify_syn", + "amplify_derive 2.11.3", + "amplify_num 0.4.1", + "amplify_syn 1.1.6", "serde", "serde_json", "serde_yaml 0.8.26", @@ -43,13 +43,32 @@ dependencies = [ "toml", ] +[[package]] +name = "amplify" +version = "4.0.0-beta.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "414f38fa6badd4440d87c4e3abb6abb2d99cce34cff3af50ad6ee83004f03716" +dependencies = [ + "amplify_apfloat", + "amplify_derive 4.0.0-alpha.5", + "amplify_num 0.5.0", + "amplify_syn 1.1.6", + "ascii", + "serde", + "serde_json", + "serde_yaml 0.9.17", + "stringly_conversions", + "toml", + "wasm-bindgen", +] + [[package]] name = "amplify_apfloat" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6641206decd3c43f5456a3506e77fc9ab8b4996c3e0c19573ae2bcc2e00bf0" dependencies = [ - "amplify_num", + "amplify_num 0.4.1", "bitflags", ] @@ -59,7 +78,19 @@ version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c3de270e75f27a4468a7c344070109046656e85cb522141f7d40ab4b83803ac" dependencies = [ - "amplify_syn", + "amplify_syn 1.1.6", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "amplify_derive" +version = "4.0.0-alpha.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88541432753e17756ae72f8064335d2f2c048165ff4822094334d767108762ca" +dependencies = [ + "amplify_syn 2.0.0-beta.1", "proc-macro2", "quote", "syn", @@ -74,6 +105,15 @@ dependencies = [ "serde", ] +[[package]] +name = "amplify_num" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddce3bc63e807ea02065e8d8b702695f3d302ae4158baddff8b0ce5c73947251" +dependencies = [ + "serde", +] + [[package]] name = "amplify_syn" version = "1.1.6" @@ -85,6 +125,17 @@ dependencies = [ "syn", ] +[[package]] +name = "amplify_syn" +version = "2.0.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eba488aa4b78ca719aff57edfbe634efef62232110c35442cd9136c67cedf39" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -100,6 +151,15 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" +dependencies = [ + "serde", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -120,7 +180,7 @@ checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" dependencies = [ "bech32", "bitcoin_hashes", - "secp256k1", + "secp256k1 0.24.3", "serde", ] @@ -139,11 +199,11 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae39db6b04c44c76c50b8f8dd09799adb71ae7807a1de2efe3d127169c04160" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", - "secp256k1", + "secp256k1 0.24.3", "slip132", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -152,11 +212,11 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e4a6744365c862b8c74cb33a21532f91f1f32f4082361fd3aab5d22c1afd482" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", "bitcoin_hd", "chrono", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -165,13 +225,13 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f8b08389e5391cf8311fd4de09a340ed98b4b7c2f87c956125c22341b5d14fb" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", - "secp256k1", + "secp256k1 0.24.3", "serde", "serde_with", "stability", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -186,15 +246,15 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42196466c9978cce3e24a0aba98497827755df3fdae3d55a743e8cf378cf5155" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", "bp-dbc", "bp-seals", - "commit_verify", + "commit_verify 0.9.0", "serde", "serde_with", "single_use_seals", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -203,14 +263,27 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ada76cb0b56cd87810adc5df0cc577d6ba048655a0898a241b0839f45a222d" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", "bitcoin_scripts", - "commit_verify", - "secp256k1", + "commit_verify 0.9.0", + "secp256k1 0.24.3", "serde", "serde_with", - "strict_encoding", + "strict_encoding 0.9.0", +] + +[[package]] +name = "bp-primitives" +version = "0.10.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aab03dbc8e2cf19594d3a267cccfc0fd2595ce0818babf39b9e817cb7683e1e4" +dependencies = [ + "amplify 4.0.0-beta.11", + "commit_verify 0.10.0-beta.2", + "secp256k1 0.26.0", + "serde", + "strict_encoding 2.0.0-beta.5", ] [[package]] @@ -219,16 +292,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73bb2e2050af42af6c0ce1cd58b5e2f3b13d5105effc5a5dd1339551c4ed11ec" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", "bitcoin_onchain", "bp-dbc", - "commit_verify", + "commit_verify 0.9.0", "lnpbp_bech32", "serde", "serde_with", "single_use_seals", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -286,13 +359,24 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f422e4e3f14f628b3cc3a241c0ea53b6457d100dda2980e2d7e719f1e41cf7" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin_hashes", "lnpbp_secp256k1zkp", "rand", "serde", "serde_with", - "strict_encoding", + "strict_encoding 0.9.0", +] + +[[package]] +name = "commit_verify" +version = "0.10.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7ce27ce9d56cac2631f9701984dc4fd162abbd7b563d97e4440db56f7282cc9" +dependencies = [ + "amplify 4.0.0-beta.11", + "bitcoin_hashes", + "strict_encoding 2.0.0-beta.5", ] [[package]] @@ -424,7 +508,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8a2293d9a54744b73b753fad2e3c16295345504dc230696ee8aa5dbfd276ab4" dependencies = [ - "amplify", + "amplify 3.13.0", "proc-macro2", "quote", "syn", @@ -484,6 +568,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hex" version = "0.4.3" @@ -581,12 +671,12 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fba6ec36bc2269cf7af59b078d290ab4e985e17903b22568107ef1ef0b783d92" dependencies = [ - "amplify", + "amplify 3.13.0", "lnpbp_bech32", "lnpbp_chain", "serde", "serde_with", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -595,14 +685,14 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecdbd10fe8d9d53febf413b4f8bbaa1911492597b19bfbb84a598f37062eab96" dependencies = [ - "amplify", + "amplify 3.13.0", "bech32", "bitcoin_hashes", "deflate", "inflate", "serde", "serde_with", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -611,13 +701,13 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cf3cde4b87fef3ba34e31e9a02fa9957d638fecccc3e12d83eaa096351fc0e0" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", "bitcoin_hashes", "once_cell", "serde", "serde_with", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -742,10 +832,11 @@ name = "rgb-core" version = "0.9.0" dependencies = [ "aluvm", - "amplify", - "bitcoin", + "amplify 3.13.0", + "bitcoin_hashes", "bp-core", - "commit_verify", + "bp-primitives", + "commit_verify 0.9.0", "half", "lnpbp", "lnpbp_secp256k1zkp", @@ -754,7 +845,7 @@ dependencies = [ "serde_json", "serde_with", "stens", - "strict_encoding", + "strict_encoding 0.9.0", "strict_encoding_test", ] @@ -778,7 +869,17 @@ checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ "bitcoin_hashes", "rand", - "secp256k1-sys", + "secp256k1-sys 0.6.1", + "serde", +] + +[[package]] +name = "secp256k1" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" +dependencies = [ + "secp256k1-sys 0.8.0", "serde", ] @@ -791,6 +892,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642a62736682fdd8c71da0eb273e453c8ac74e33b9fb310e22ba5b03ec7651ff" +dependencies = [ + "cc", +] + [[package]] name = "serde" version = "1.0.152" @@ -886,7 +996,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e092f1d5411486816ec67cd7d0280acb0e05a1bd509721bc3dde3b1ffa5bfa0e" dependencies = [ - "amplify_derive", + "amplify_derive 2.11.3", ] [[package]] @@ -895,7 +1005,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41a2947cb179006a73896fca01015ee5255c05b8b83e74c5e9d623ed4480abe2" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", ] @@ -915,11 +1025,11 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12dfcfcd8b29e9cca1e0c1f1bcd03f91704cd16bfd49301d937bd56379b76b10" dependencies = [ - "amplify", + "amplify 3.13.0", "serde", "serde_with", "serde_yaml 0.9.17", - "strict_encoding", + "strict_encoding 0.9.0", ] [[package]] @@ -928,14 +1038,24 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0be7060b49729cd0b9b2391114632ef64c363a4055d91de049f5555b466193bb" dependencies = [ - "amplify", + "amplify 3.13.0", "bitcoin", "bitcoin_hashes", "chrono", "half", "lnpbp_secp256k1zkp", "serde", - "strict_encoding_derive", + "strict_encoding_derive 0.9.0", +] + +[[package]] +name = "strict_encoding" +version = "2.0.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ce22c5bba8139f2182001358188f145b40b177a9a442545cf15574335fba88" +dependencies = [ + "amplify 4.0.0-beta.11", + "strict_encoding_derive 2.0.0-beta.2", ] [[package]] @@ -944,20 +1064,33 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34c9cabafb397fc1144463228ad4ba57c3c670a0117505fe59b15d8c74449716" dependencies = [ - "amplify_syn", + "amplify_syn 1.1.6", "encoding_derive_helpers", "proc-macro2", "syn", ] +[[package]] +name = "strict_encoding_derive" +version = "2.0.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cb9b35c9d7429212d20ae38bb86ecbc6cd3b3ccf5db6a12d1e2aafa7cedf5b0" +dependencies = [ + "amplify_syn 2.0.0-beta.1", + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "strict_encoding_test" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fc369cd865314a3416556e3669d3f2d2e41c6e80cc838208c84a34f74d79234" dependencies = [ - "amplify", - "strict_encoding", + "amplify 3.13.0", + "strict_encoding 0.9.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e1b685c6..4d5a8487 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,9 +42,8 @@ stens = "~0.9.0" strict_encoding = { version = "~0.9.0", features = ["crypto", "chrono", "bitcoin", "float"] } commit_verify = { version = "~0.9.0", features = ["rand", "bulletproofs"] } aluvm = { version = "~0.9.0", features = ["std", "strict_encoding"] } -# Dependencies on core rust-bitcoin ecosystem projects -# ---------------------------------------------------- -bitcoin = { version = "~0.29.2", features = ["rand"] } +bitcoin_hashes = "0.11.0" +bp-primitives = "0.10.0-beta.1" # Core rust projects # ------------------ # This strange naming is a workaround for cargo inability to define required @@ -54,6 +53,7 @@ bitcoin = { version = "~0.29.2", features = ["rand"] } half = "~2.1.0" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } serde_with = { version = "1.14", features = ["hex"], optional = true } +serde_json = "1" # TODO: Remove once_cell = "1.12.0" # Other dependencies: # ------------------------------ @@ -72,5 +72,4 @@ all = ["serde"] serde = ["serde_crate", "serde_with", "half/serde", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", "lnpbp/serde", "amplify/serde", "bp-core/serde", "stens/serde", "aluvm/serde", - "secp256k1zkp/serde", - "bitcoin/serde"] + "secp256k1zkp/serde", "bp-primitives/serde"] diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index c37aed89..b744b31b 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -81,7 +81,7 @@ impl TypedAssignments { } // Generate random blinding factors - let mut rng = bitcoin::secp256k1::rand::thread_rng(); + let mut rng = secp256k1zkp::rand::thread_rng(); // We will compute the last blinding factors from all others so they // sum up to 0, so we need to generate only n - 1 random factors let count = allocations_theirs.len() + allocations_ours.len(); @@ -1136,9 +1136,9 @@ where mod test { use std::collections::BTreeMap; - use bitcoin::blockdata::transaction::OutPoint; - use bitcoin::hashes::hex::{FromHex, ToHex}; - use bitcoin::hashes::{sha256, Hash}; + use bitcoin::blockdata::transaction::Outpoint; + use bitcoin_hashes::hex::{FromHex, ToHex}; + use bitcoin_hashes::{sha256, Hash}; use bp::seals::txout::TxoSeal; use commit_verify::merkle::MerkleNode; use commit_verify::{merklize, CommitConceal, CommitEncode, ToMerkleSource}; @@ -1271,7 +1271,7 @@ mod test { let ours: SealValueMap = zip_data .map(|(txid, amount)| { ( - Revealed::from(OutPoint::new(*txid, rng.gen_range(0..=10))), + Revealed::from(Outpoint::new(*txid, rng.gen_range(0..=10))), amount.clone(), ) }) @@ -1287,7 +1287,7 @@ mod test { .map(|(txid, amount)| { ( SealEndpoint::ConcealedUtxo( - Revealed::from(OutPoint::new(*txid, rng.gen_range(0..=10))) + Revealed::from(Outpoint::new(*txid, rng.gen_range(0..=10))) .commit_conceal(), ), amount.clone(), @@ -2117,22 +2117,22 @@ mod test { .collect(); let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(OutPoint::new(txid_vec[0], 1)), + seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), state: data::Void(), }; let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(OutPoint::new(txid_vec[1], 2)), + seal: Revealed::from(Outpoint::new(txid_vec[1], 2)), state: data::Void(), }; let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(OutPoint::new(txid_vec[2], 3)).commit_conceal(), + seal: Revealed::from(Outpoint::new(txid_vec[2], 3)).commit_conceal(), state: data::Void(), }; let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(OutPoint::new(txid_vec[3], 4)).commit_conceal(), + seal: Revealed::from(Outpoint::new(txid_vec[3], 4)).commit_conceal(), state: data::Void(), }; @@ -2153,22 +2153,22 @@ mod test { .collect(); let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(OutPoint::new(txid_vec[0], 1)), + seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), state: value::Revealed::with_amount(10u64, &mut rng), }; let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(OutPoint::new(txid_vec[1], 1)), + seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), state: value::Revealed::with_amount(20u64, &mut rng).commit_conceal(), }; let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(OutPoint::new(txid_vec[2], 1)).commit_conceal(), + seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), state: value::Revealed::with_amount(30u64, &mut rng), }; let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(OutPoint::new(txid_vec[3], 1)).commit_conceal(), + seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), state: value::Revealed::with_amount(10u64, &mut rng).commit_conceal(), }; @@ -2193,22 +2193,22 @@ mod test { .collect(); let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(OutPoint::new(txid_vec[0], 1)), + seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), state: state_data_vec[0].clone(), }; let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(OutPoint::new(txid_vec[1], 1)), + seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), state: state_data_vec[1].clone().commit_conceal(), }; let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(OutPoint::new(txid_vec[2], 1)).commit_conceal(), + seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), state: state_data_vec[2].clone(), }; let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(OutPoint::new(txid_vec[3], 1)).commit_conceal(), + seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), state: state_data_vec[3].clone().commit_conceal(), }; diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index 6224dbc7..e5c2b04a 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -9,7 +9,7 @@ // You should have received a copy of the MIT License along with this software. // If not, see . -use bitcoin::hashes::{sha256, sha256t}; +use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{ commit_encode, CommitConceal, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash, }; diff --git a/src/contract/data.rs b/src/contract/data.rs index 6700ddac..8b841d82 100644 --- a/src/contract/data.rs +++ b/src/contract/data.rs @@ -20,7 +20,7 @@ use std::io; use amplify::num::apfloat::ieee; use amplify::num::{i1024, i256, i512, u1024, u256, u512}; use amplify::AsAny; -use bitcoin::hashes::{sha256, sha256t}; +use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{commit_encode, CommitConceal, CommitEncode, TaggedHash}; use half::bf16; use stens::{AsciiString, PrimitiveType, TypeRef}; diff --git a/src/contract/metadata.rs b/src/contract/metadata.rs index dd4c375e..ea6d6dd9 100644 --- a/src/contract/metadata.rs +++ b/src/contract/metadata.rs @@ -219,7 +219,7 @@ impl Metadata { #[cfg(test)] mod test { use amplify::Wrapper; - use bitcoin::hashes::Hash; + use bitcoin_hashes::Hash; use commit_verify::merkle::MerkleNode; use commit_verify::{merklize, CommitEncode}; use secp256k1zkp::rand::{thread_rng, RngCore}; diff --git a/src/contract/nodes.rs b/src/contract/nodes.rs index df22822b..e77ae79d 100644 --- a/src/contract/nodes.rs +++ b/src/contract/nodes.rs @@ -15,8 +15,8 @@ use std::num::ParseIntError; use std::str::FromStr; use amplify::{AsAny, Wrapper}; -use bitcoin::hashes::{sha256, sha256t, Hash}; -use bitcoin::{OutPoint, Txid}; +use bc::{Outpoint, Txid}; +use bitcoin_hashes::{sha256, sha256t, Hash}; use bp::seals::txout::TxoSeal; use commit_verify::lnpbp4::ProtocolId; use commit_verify::{ @@ -35,7 +35,9 @@ use crate::reveal::{self, MergeReveal}; use crate::schema::{ ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, TransitionType, }; -use crate::{schema, seal, ConfidentialDataError, Metadata, PublicRightType, SchemaId}; +use crate::{ + outpoint, schema, seal, txid, ConfidentialDataError, Metadata, PublicRightType, SchemaId, +}; static EMPTY_OWNED_RIGHTS: Lazy = Lazy::new(ParentOwnedRights::default); static EMPTY_PUBLIC_RIGHTS: Lazy = Lazy::new(ParentPublicRights::default); @@ -64,7 +66,7 @@ pub struct NodeOutpoint { #[display(inner)] pub enum OutpointParseError { #[from] - InvalidNodeId(bitcoin::hashes::hex::Error), + InvalidNodeId(bitcoin_hashes::hex::Error), InvalidType(ParseIntError), @@ -132,7 +134,7 @@ impl commit_encode::Strategy for NodeId { } impl FromStr for NodeId { - type Err = bitcoin::hashes::hex::Error; + type Err = bitcoin_hashes::hex::Error; fn from_str(s: &str) -> Result { Ok(NodeId::from_inner(s.parse()?)) } } @@ -425,14 +427,14 @@ pub trait Node: AsAny { .unwrap_or_else(Vec::new) } - fn node_outputs(&self, witness_txid: Txid) -> BTreeMap { + fn node_outputs(&self, witness_txid: Txid) -> BTreeMap { let node_id = self.node_id(); - let mut res: BTreeMap = bmap! {}; + let mut res: BTreeMap = bmap! {}; for (ty, assignments) in self.owned_rights() { for (seal, node_output) in assignments.revealed_seal_outputs() { - let outpoint = seal.outpoint_or(witness_txid); + let outpoint = seal.outpoint_or(txid!(witness_txid)); let node_outpoint = NodeOutpoint::new(node_id, *ty, node_output); - res.insert(node_outpoint, outpoint); + res.insert(node_outpoint, outpoint!(outpoint)); } } res @@ -914,7 +916,7 @@ mod _strict_encoding { mod test { use std::io::Write; - use bitcoin::hashes::hex::ToHex; + use bitcoin_hashes::hex::ToHex; use commit_verify::{tagged_hash, CommitConceal, TaggedHash}; use lnpbp::chain::{Chain, GENESIS_HASH_MAINNET}; use strict_encoding::{strict_serialize, StrictDecode, StrictEncode}; diff --git a/src/contract/seal.rs b/src/contract/seal.rs index e7c9a6ba..f3c5d2fd 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -27,7 +27,7 @@ //! //! | **Type name** | **Lib** | **Witness vout** | **Blinding** | **Confidential** | **String serialization** | **Use case** | //! | ------------------ | ------- | ----------- | -------------------- | ---------------- | ------------------------------------- | --------------------------------- | -//! | [`OutPoint`] | Bitcoin | No | No | No | `:` | Genesis control rights | +//! | [`Outpoint`] | Bitcoin | No | No | No | `:` | Genesis control rights | //! | [`RevealedSeal`] | BP Core | No | Yes | No | `:|~:#` | Stash | //! | [`ConcealedSeal`] | BP Core | Implicit? | Implicit | Yes | `txob1...` | External payments | //! | [`ExplicitSeal`] | BP Core | Yes | Yes | No | `:|~:` | Internal | @@ -36,11 +36,11 @@ use std::fmt::{self, Display, Formatter}; use std::str::FromStr; -use bitcoin::secp256k1::rand::RngCore; use bp::seals::txout::blind::{ConcealedSeal, ParseError, RevealedSeal}; pub use bp::seals::txout::blind::{ConcealedSeal as Confidential, RevealedSeal as Revealed}; use bp::seals::txout::CloseMethod; use commit_verify::CommitConceal; +use secp256k1zkp::rand::RngCore; /// Trait for types supporting conversion to a [`RevealedSeal`] pub trait IntoRevealedSeal { @@ -155,8 +155,8 @@ impl FromStr for SealEndpoint { mod test { use std::convert::TryFrom; - use bitcoin::hashes::hex::FromHex; - use bitcoin::OutPoint; + use bc::{Outpoint, Txid}; + use bitcoin_hashes::hex::FromHex; use bp::seals::txout::TxoSeal; use commit_verify::CommitEncode; use secp256k1zkp::rand::{thread_rng, RngCore}; @@ -257,9 +257,9 @@ mod test { fn test_into_outpoint() { let revealed = Revealed::strict_decode(&REVEALED_TXOUTPOINT[..]).unwrap(); - let outpoint = OutPoint::try_from(revealed.clone()).unwrap(); + let outpoint = Outpoint::try_from(revealed.clone()).unwrap(); - let coded = OutPoint::strict_decode(&OUTPOINT[..]).unwrap(); + let coded = Outpoint::strict_decode(&OUTPOINT[..]).unwrap(); assert_eq!(coded, outpoint); } @@ -270,7 +270,7 @@ mod test { fn test_witness_to_outpoint() { // Conversion to Outpoint from WitnessVout variant should panic let revealed = Revealed::strict_decode(&REVEALED_WITNESSVOUT[..]).unwrap(); - bitcoin::OutPoint::try_from(revealed).unwrap(); + bc::Outpoint::try_from(revealed).unwrap(); } #[test] @@ -280,10 +280,9 @@ mod test { let revealed_witnessvout = Revealed::strict_decode(&REVEALED_WITNESSVOUT[..]).unwrap(); // Data used for constructing above seals - let txid = bitcoin::Txid::from_hex( - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e", - ) - .unwrap(); + let txid = + Txid::from_hex("201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e") + .unwrap(); let blinding: u64 = 13457965799463774082; @@ -323,7 +322,7 @@ mod test { ) .unwrap(); let vout = rng.next_u32(); - let revealed_txout = Revealed::from(OutPoint::new(txid, vout)); + let revealed_txout = Revealed::from(Outpoint::new(txid, vout)); let revealed_witness = Revealed { method: CloseMethod::TapretFirst, diff --git a/src/contract/value.rs b/src/contract/value.rs index 0a1377e9..f8df0af5 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -29,7 +29,7 @@ use std::str::FromStr; // that we do not use the standard secp256k1zkp library use amplify::hex::{Error, FromHex}; use amplify::{Slice32, Wrapper}; -use bitcoin::hashes::sha256::Midstate; +use bitcoin_hashes::sha256::Midstate; use commit_verify::{commit_encode, CommitConceal, CommitEncode, CommitVerify, CommitmentProtocol}; use secp256k1zkp; pub use secp256k1zkp::pedersen; diff --git a/src/lib.rs b/src/lib.rs index 9c1c1f12..19d11359 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,8 @@ pub extern crate secp256k1zkp; #[cfg(feature = "serde")] extern crate serde_crate as serde; +pub(crate) mod temp; + pub mod contract; pub mod schema; pub mod stash; @@ -42,7 +44,6 @@ pub mod validation; pub mod vm; #[macro_use] mod macros; -pub(crate) mod temp; pub mod prelude { pub use bp::dbc::{Anchor, AnchorId}; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 703d0aed..c74837c2 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -13,7 +13,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::str::FromStr; use amplify::flags::FlagVec; -use bitcoin::hashes::{sha256, sha256t}; +use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{commit_encode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash}; use lnpbp::bech32::{FromBech32Str, ToBech32String}; use stens::{TypeRef, TypeSystem}; diff --git a/src/schema/state.rs b/src/schema/state.rs index a4749d1e..eae0d97e 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -345,9 +345,9 @@ pub(super) use _validation::StenVerify; #[cfg(test)] mod test { - use bitcoin::blockdata::transaction::OutPoint; - use bitcoin::hashes::hex::FromHex; - use bitcoin::hashes::sha256; + use bitcoin::blockdata::transaction::Outpoint; + use bitcoin_hashes::hex::FromHex; + use bitcoin_hashes::sha256; use commit_verify::{CommitConceal, TaggedHash}; use secp256k1zkp::rand::thread_rng; use stens::TypeSystem; @@ -393,24 +393,24 @@ mod test { // Create Declarative Assignments let assignment_dec_rev = Assignment::::Revealed { - seal: crate::contract::seal::Revealed::from(OutPoint::new(txid_vec[0], 1)), + seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[0], 1)), state: data::Void(), }; let assignment_dec_conf = Assignment::::Confidential { - seal: crate::contract::seal::Revealed::from(OutPoint::new(txid_vec[1], 2)) + seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[1], 2)) .commit_conceal(), state: data::Void(), }; // Create Pedersan Assignments let assignment_ped_rev = Assignment::::Revealed { - seal: crate::contract::seal::Revealed::from(OutPoint::new(txid_vec[0], 1)), + seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[0], 1)), state: value::Revealed::with_amount(10u64, &mut rng), }; let assignment_ped_conf = Assignment::::Confidential { - seal: crate::contract::seal::Revealed::from(OutPoint::new(txid_vec[1], 1)) + seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[1], 1)) .commit_conceal(), state: value::Revealed::with_amount(10u64, &mut rng).commit_conceal(), }; @@ -422,12 +422,12 @@ mod test { .collect(); let assignment_hash_rev = Assignment::::Revealed { - seal: crate::contract::seal::Revealed::from(OutPoint::new(txid_vec[0], 1)), + seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[0], 1)), state: state_data_vec[0].clone(), }; let assignment_hash_conf = Assignment::::Confidential { - seal: crate::contract::seal::Revealed::from(OutPoint::new(txid_vec[1], 1)) + seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[1], 1)) .commit_conceal(), state: state_data_vec[0].clone().commit_conceal(), }; diff --git a/src/stash/bundle.rs b/src/stash/bundle.rs index ae0427d9..e45b8de7 100644 --- a/src/stash/bundle.rs +++ b/src/stash/bundle.rs @@ -12,7 +12,7 @@ use std::collections::{btree_map, BTreeMap, BTreeSet}; use std::io::{Read, Write}; -use bitcoin::hashes::{sha256, sha256t, Hash}; +use bitcoin_hashes::{sha256, sha256t, Hash}; use commit_verify::{ lnpbp4, CommitEncode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash, }; diff --git a/src/stash/graph.rs b/src/stash/graph.rs index b47210bb..ebc2fb21 100644 --- a/src/stash/graph.rs +++ b/src/stash/graph.rs @@ -24,7 +24,7 @@ use std::collections::BTreeSet; -use bitcoin::{OutPoint, Txid}; +use bc::{Outpoint, Txid}; use bp::dbc::AnchorId; use crate::schema::OwnedRightType; @@ -135,7 +135,7 @@ pub trait GraphApi { /// the closed seals. If seals are present, but have a different type, a /// error is returned /// - `witness`: witness transaction id, needed for generating full - /// [`bitcoin::OutPoint`] data for single-use-seal definitions providing + /// [`bc::Outpoint`] data for single-use-seal definitions providing /// relative seals to the witness transaction (see [crate::seal::Revealed] /// for the details). /// @@ -168,5 +168,5 @@ pub trait GraphApi { node_id: NodeId, owned_right_type: impl Into, witness: Txid, - ) -> Result, ConsistencyError>; + ) -> Result, ConsistencyError>; } diff --git a/src/stash/stash.rs b/src/stash/stash.rs index 41a5d180..b56782b9 100644 --- a/src/stash/stash.rs +++ b/src/stash/stash.rs @@ -23,7 +23,7 @@ //! NB: Stash implementations must be able to operate multiple independent RGB //! contract. -use bitcoin::OutPoint; +use bc::Outpoint; use bp::dbc::{Anchor, AnchorId}; use commit_verify::lnpbp4; @@ -118,6 +118,6 @@ pub trait Stash { fn prune( &mut self, tx_resolver: &mut impl ResolveTx, - ownership_resolver: impl Fn(OutPoint) -> bool, + ownership_resolver: impl Fn(Outpoint) -> bool, ) -> Result; } diff --git a/src/stash/unit.rs b/src/stash/unit.rs index 0abf020a..ad974d72 100644 --- a/src/stash/unit.rs +++ b/src/stash/unit.rs @@ -13,7 +13,7 @@ use std::iter::Filter; -use bitcoin::{OutPoint, Txid}; +use bitcoin::{Outpoint, Txid}; use crate::schema::OwnedRightType; use crate::stash::iter::{ConsTsIter, TransitionIterator}; @@ -54,10 +54,10 @@ where State: StateTypes output: NodeOutput, /// The seal closed by the operation - closed_seal: OutPoint, + closed_seal: Outpoint, /// The new seal defined by the operation - defined_seal: OutPoint, + defined_seal: Outpoint, /// Previous state (invalidated by the operation) prev_state: &'container State::Revealed, @@ -66,7 +66,7 @@ where State: StateTypes next_state: &'container State::Revealed, /// Transaction output operating as a single-use-seal closing witness - witness: OutPoint, + witness: Outpoint, } #[derive(Eq, PartialEq, Debug)] diff --git a/src/temp.rs b/src/temp.rs index 383770c8..24850ae6 100644 --- a/src/temp.rs +++ b/src/temp.rs @@ -1,6 +1,30 @@ //! Temporary module for refactoring period -use bitcoin::{Transaction, Txid}; +use bc::{Tx, Txid}; + +#[macro_export] +macro_rules! txid { + ($old:expr) => { + $old.to_string().parse().unwrap() + }; +} + +#[macro_export] +macro_rules! outpoint { + ($old:expr) => { + bc::Outpoint { + txid: txid!($old.txid), + vout: $old.vout.into(), + } + }; +} + +#[macro_export] +macro_rules! tx { + ($old:expr) => { + serde_json::from_str(&serde_json::to_string($old).unwrap()).unwrap() + }; +} #[derive(Debug, Display, Error)] #[display(doc_comments)] @@ -8,5 +32,5 @@ use bitcoin::{Transaction, Txid}; pub struct TxResolverError(Txid); pub trait ResolveTx { - fn resolve_tx(&self, txid: Txid) -> Result; + fn resolve_tx(&self, txid: Txid) -> Result; } diff --git a/src/validation.rs b/src/validation.rs index e9ca12f2..1903fd26 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -13,7 +13,7 @@ use core::iter::FromIterator; use core::ops::AddAssign; use std::collections::{BTreeMap, BTreeSet, VecDeque}; -use bitcoin::{Transaction, Txid}; +use bc::{Tx, Txid}; use bp::dbc::Anchor; use bp::seals::txout::TxoSeal; use commit_verify::{lnpbp4, CommitConceal}; @@ -24,7 +24,7 @@ use super::{schema, seal, ContractId, Node, NodeId, Schema, SchemaId, TypedAssig use crate::schema::SchemaVerify; use crate::stash::Consignment; use crate::temp::ResolveTx; -use crate::{data, BundleId, Extension, SealEndpoint, TransitionBundle}; +use crate::{data, outpoint, tx, txid, BundleId, Extension, SealEndpoint, TransitionBundle}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] #[display(Debug)] @@ -36,7 +36,8 @@ pub enum Validity { Invalid, } -#[derive(Clone, Debug, Display, Default, StrictEncode, StrictDecode)] +#[derive(Clone, Debug, Display, Default)] +//#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] // TODO #42: Display via YAML #[display(Debug)] @@ -122,7 +123,8 @@ impl Status { } } -#[derive(Clone, PartialEq, Eq, Debug, Display, From, StrictEncode, StrictDecode)] +#[derive(Clone, PartialEq, Eq, Debug, Display, From)] +//#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] // TODO #44: (v0.3) convert to detailed error description using doc_comments #[display(Debug)] @@ -206,7 +208,7 @@ pub enum Failure { ancestor_id: NodeId, assignment_type: schema::OwnedRightType, seal_index: u16, - outpoint: bitcoin::OutPoint, + outpoint: bc::Outpoint, }, ExtensionAbsent(NodeId), @@ -230,7 +232,8 @@ pub enum Failure { ScriptFailure(NodeId), } -#[derive(Clone, PartialEq, Eq, Debug, Display, From, StrictEncode, StrictDecode)] +#[derive(Clone, PartialEq, Eq, Debug, Display, From)] +//#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] // TODO #44: (v0.3) convert to detailed descriptions using doc_comments #[display(Debug)] @@ -241,7 +244,8 @@ pub enum Warning { EndpointTransactionMissed(Txid), } -#[derive(Clone, PartialEq, Eq, Debug, Display, From, StrictEncode, StrictDecode)] +#[derive(Clone, PartialEq, Eq, Debug, Display, From)] +//#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] // TODO #44: (v0.3) convert to detailed descriptions using doc_comments #[display(Debug)] @@ -434,16 +438,16 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> .status .failures .iter() - .position(|f| f == &Failure::WitnessTransactionMissed(anchor.txid)) + .position(|f| f == &Failure::WitnessTransactionMissed(txid!(anchor.txid))) { self.status.failures.remove(pos); self.status .unresolved_txids - .retain(|txid| *txid != anchor.txid); - self.status.unmined_endpoint_txids.push(anchor.txid); + .retain(|txid| *txid != txid!(anchor.txid)); + self.status.unmined_endpoint_txids.push(txid!(anchor.txid)); self.status .warnings - .push(Warning::EndpointTransactionMissed(anchor.txid)); + .push(Warning::EndpointTransactionMissed(txid!(anchor.txid))); } } } @@ -502,8 +506,10 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // anchor. This must be done with // deterministic bitcoin commitments & LNPBP-4 if anchor.convolve(self.contract_id, bundle_id.into()).is_err() { - self.status - .add_failure(Failure::TransitionNotInAnchor(node_id, anchor.txid)); + self.status.add_failure(Failure::TransitionNotInAnchor( + node_id, + txid!(anchor.txid), + )); } self.validate_graph_node(node, bundle_id, anchor); @@ -562,7 +568,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> bundle_id: BundleId, anchor: &'consignment Anchor, ) { - let txid = anchor.txid; + let txid = txid!(anchor.txid); let node_id = node.node_id(); // Check that the anchor is committed into a transaction spending all of @@ -595,7 +601,12 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // [VALIDATION]: Checking anchor deterministic bitcoin // commitment if anchor - .verify(self.contract_id, bundle_id.into(), witness_tx.clone()) + .verify( + self.contract_id, + bundle_id.into(), + // TODO: Remove this temporary conversion fix + tx!(&witness_tx), + ) .is_err() { // TODO: Save error details @@ -658,7 +669,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // TODO #45: Move part of logic into single-use-seals and bitcoin seals fn validate_witness_input( &mut self, - witness_tx: &Transaction, + witness_tx: &Tx, node_id: NodeId, ancestor_id: NodeId, assignment_type: schema::OwnedRightType, @@ -702,20 +713,21 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> None, ) => { // We are at genesis, so the outpoint must contain tx - Some(bitcoin::OutPoint::new(txid, vout)) + Some(bc::Outpoint::new(txid!(txid), vout)) } (Ok(Some(_)), None) => { // This can't happen, since if we have a node in the index // and the node is not genesis, we always have an anchor unreachable!() } - (Ok(Some(seal)), Some(anchor)) => Some(seal.outpoint_or(anchor.txid)), /* -> ... so we can check that the bitcoin transaction - * references it as one of its inputs */ + /* -> ... so we can check that the bitcoin transaction + * references it as one of its inputs */ + (Ok(Some(seal)), Some(anchor)) => Some(outpoint!(seal.outpoint_or(anchor.txid))), } { if !witness_tx - .input + .inputs .iter() - .any(|txin| txin.previous_output == outpoint) + .any(|txin| txin.prev_output == outpoint) { // Another failure: we do not spend one of the transition // ancestors in the witness transaction. The consignment is diff --git a/src/vm/embedded.rs b/src/vm/embedded.rs index 936da9ea..80391a9b 100644 --- a/src/vm/embedded.rs +++ b/src/vm/embedded.rs @@ -63,7 +63,7 @@ pub mod constants { pub const FIELD_TYPE_BURN_SUPPLY: u16 = 0xB0; /// [`FieldType`] that is used by validation procedures checking proofs of - /// burn. Must contain [`bitcoin::OutPoint`] consensus-encoded data. + /// burn. Must contain [`bc::Outpoint`] consensus-encoded data. pub const FIELD_TYPE_BURN_UTXO: u16 = 0xB1; /// [`FieldType`] that is used by validation procedures checking proofs of @@ -81,7 +81,7 @@ pub mod constants { pub const FIELD_TYPE_LOCK_DESCRIPTOR: u16 = 0xC0; /// [`FieldType`] that is used by validation procedures checking proofs of - /// reserves. Must contain [`bitcoin::OutPoint`] consensus-encoded data + /// reserves. Must contain [`bc::Outpoint`] consensus-encoded data pub const FIELD_TYPE_LOCK_UTXO: u16 = 0xC1; /// Description of the asset From 6050734b3f7ff66f8e1f681578923fb76ca1d3fa Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 18:51:01 +0100 Subject: [PATCH 11/71] chore: remove lnpbp dependency --- Cargo.lock | 56 ----------------------------- Cargo.toml | 3 +- src/contract/nodes.rs | 83 +++---------------------------------------- src/schema/schema.rs | 74 ++------------------------------------ src/temp.rs | 18 ++++++++++ 5 files changed, 25 insertions(+), 209 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ddd77e10..470635c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - [[package]] name = "aluvm" version = "0.9.0" @@ -478,15 +472,6 @@ dependencies = [ "syn", ] -[[package]] -name = "deflate" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" -dependencies = [ - "adler32", -] - [[package]] name = "digest" version = "0.9.0" @@ -614,15 +599,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "inflate" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" -dependencies = [ - "adler32", -] - [[package]] name = "itoa" version = "1.0.5" @@ -659,20 +635,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "lnpbp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba6ec36bc2269cf7af59b078d290ab4e985e17903b22568107ef1ef0b783d92" -dependencies = [ - "amplify 3.13.0", - "lnpbp_bech32", - "lnpbp_chain", - "serde", - "serde_with", - "strict_encoding 0.9.0", -] - [[package]] name = "lnpbp_bech32" version = "0.9.0" @@ -682,23 +644,6 @@ dependencies = [ "amplify 3.13.0", "bech32", "bitcoin_hashes", - "deflate", - "inflate", - "serde", - "serde_with", - "strict_encoding 0.9.0", -] - -[[package]] -name = "lnpbp_chain" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf3cde4b87fef3ba34e31e9a02fa9957d638fecccc3e12d83eaa096351fc0e0" -dependencies = [ - "amplify 3.13.0", - "bitcoin", - "bitcoin_hashes", - "once_cell", "serde", "serde_with", "strict_encoding 0.9.0", @@ -828,7 +773,6 @@ dependencies = [ "bp-primitives", "commit_verify 0.9.0", "half", - "lnpbp", "once_cell", "secp256k1-zkp", "serde", diff --git a/Cargo.toml b/Cargo.toml index 6812f786..00f79490 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ path = "src/lib.rs" # ----------------------------------------- amplify = { version = "~3.13.0", features = ["apfloat"] } bp-core = { version = "~0.9.0" } -lnpbp = { version = "~0.9.0", features = ["zip"] } stens = "~0.9.0" strict_encoding = { version = "~0.9.0", features = ["crypto", "chrono", "bitcoin", "float"] } commit_verify = { version = "~0.9.0", features = ["rand", "bulletproofs"] } @@ -66,5 +65,5 @@ default = [] all = ["serde"] serde = ["serde_crate", "serde_with", "half/serde", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", - "lnpbp/serde", "amplify/serde", "bp-core/serde", "stens/serde", "aluvm/serde", + "bp-core/serde", "stens/serde", "aluvm/serde", "secp256k1-zkp/serde", "bp-primitives/serde"] diff --git a/src/contract/nodes.rs b/src/contract/nodes.rs index e77ae79d..37efba1b 100644 --- a/src/contract/nodes.rs +++ b/src/contract/nodes.rs @@ -23,8 +23,6 @@ use commit_verify::{ commit_encode, CommitEncode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash, ToMerkleSource, }; -use lnpbp::bech32::{FromBech32Str, ToBech32String}; -use lnpbp::chain::Chain; use once_cell::sync::Lazy; use super::{ @@ -35,6 +33,7 @@ use crate::reveal::{self, MergeReveal}; use crate::schema::{ ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, TransitionType, }; +use crate::temp::Chain; use crate::{ outpoint, schema, seal, txid, ConfidentialDataError, Metadata, PublicRightType, SchemaId, }; @@ -104,11 +103,6 @@ impl sha256t::Tag for NodeIdTag { } } -impl lnpbp::bech32::Strategy for NodeIdTag { - const HRP: &'static str = RGB_CONTRACT_ID_HRP; - type Strategy = lnpbp::bech32::strategies::UsingStrictEncoding; -} - impl NodeOutpoint { pub fn new(node_id: NodeId, ty: u16, no: u16) -> NodeOutpoint { NodeOutpoint { node_id, ty, no } @@ -140,9 +134,9 @@ impl FromStr for NodeId { } /// Unique contract identifier equivalent to the contract genesis commitment -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Display, From)] +#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] #[wrapper(Debug, BorrowSlice)] -#[display(ContractId::to_bech32_string)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct ContractId(sha256t::Hash); impl From for ProtocolId { @@ -159,79 +153,10 @@ impl From for ContractId { } } -impl From for lnpbp::chain::AssetId { - fn from(id: ContractId) -> Self { Self::from_inner(id.into_inner().into_inner()) } -} - impl commit_encode::Strategy for ContractId { type Strategy = commit_encode::strategies::UsingStrict; } -impl lnpbp::bech32::Strategy for ContractId { - const HRP: &'static str = RGB_CONTRACT_ID_HRP; - type Strategy = lnpbp::bech32::strategies::UsingStrictEncoding; -} - -// TODO: Make this part of `lnpbp::bech32` -#[cfg(feature = "serde")] -impl serde::Serialize for ContractId { - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer { - if serializer.is_human_readable() { - serializer.serialize_str(&self.to_bech32_string()) - } else { - serializer.serialize_bytes(&self[..]) - } - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for ContractId { - fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer<'de> { - struct Visitor; - impl serde::de::Visitor<'_> for Visitor { - type Value = ContractId; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - formatter, - "Bech32 string with `{}` HRP", - RGB_CONTRACT_ID_HRP - ) - } - - fn visit_str(self, v: &str) -> Result - where E: serde::de::Error { - ContractId::from_str(v).map_err(serde::de::Error::custom) - } - - fn visit_string(self, v: String) -> Result - where E: serde::de::Error { - self.visit_str(&v) - } - - fn visit_byte_buf(self, v: Vec) -> Result - where E: serde::de::Error { - ContractId::from_bytes(&v) - .map_err(|_| serde::de::Error::invalid_length(v.len(), &"32 bytes")) - } - } - - if deserializer.is_human_readable() { - deserializer.deserialize_str(Visitor) - } else { - deserializer.deserialize_byte_buf(Visitor) - } - } -} - -impl FromStr for ContractId { - type Err = lnpbp::bech32::Error; - - fn from_str(s: &str) -> Result { ContractId::from_bech32_str(s) } -} - /// RGB contract node API, defined as trait /// /// Implemented by all contract node types (see [`NodeType`]): @@ -837,7 +762,7 @@ mod _strict_encoding { fn commit_encode(&self, mut e: E) -> usize { let mut encoder = || -> Result<_, Error> { let mut len = self.schema_id.strict_encode(&mut e)?; - len += self.chain.as_genesis_hash().strict_encode(&mut e)?; + len += self.chain.strict_encode(&mut e)?; len += self .metadata .to_merkle_source() diff --git a/src/schema/schema.rs b/src/schema/schema.rs index c74837c2..12368215 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -10,12 +10,10 @@ // If not, see . use std::collections::{BTreeMap, BTreeSet}; -use std::str::FromStr; use amplify::flags::FlagVec; use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{commit_encode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash}; -use lnpbp::bech32::{FromBech32Str, ToBech32String}; use stens::{TypeRef, TypeSystem}; use super::{ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, TransitionSchema}; @@ -28,8 +26,6 @@ pub type FieldType = u16; pub type ExtensionType = u16; pub type TransitionType = u16; -pub const RGB_SCHEMA_ID_HRP: &str = "rgbsh"; - static MIDSTATE_SHEMA_ID: [u8; 32] = [ 0x81, 0x73, 0x33, 0x7c, 0xcb, 0xc4, 0x8b, 0xd1, 0x24, 0x89, 0x65, 0xcd, 0xd0, 0xcd, 0xb6, 0xc8, 0x7a, 0xa2, 0x14, 0x81, 0x7d, 0x57, 0x39, 0x22, 0x28, 0x90, 0x74, 0x8f, 0x26, 0x75, 0x8e, 0xea, @@ -46,16 +42,11 @@ impl sha256t::Tag for SchemaIdTag { } } -impl lnpbp::bech32::Strategy for SchemaIdTag { - const HRP: &'static str = RGB_SCHEMA_ID_HRP; - type Strategy = lnpbp::bech32::strategies::UsingStrictEncoding; -} - /// Commitment-based schema identifier used for committing to the schema type -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Display, From)] +#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] #[derive(StrictEncode, StrictDecode)] #[wrapper(Debug, BorrowSlice)] -#[display(SchemaId::to_bech32_string)] pub struct SchemaId(sha256t::Hash); impl CommitVerify for SchemaId @@ -65,67 +56,6 @@ where Msg: AsRef<[u8]> fn commit(msg: &Msg) -> SchemaId { SchemaId::hash(msg) } } -impl lnpbp::bech32::Strategy for SchemaId { - const HRP: &'static str = RGB_SCHEMA_ID_HRP; - type Strategy = lnpbp::bech32::strategies::UsingStrictEncoding; -} - -// TODO: Make this part of `lnpbp::bech32` -#[cfg(feature = "serde")] -impl serde::Serialize for SchemaId { - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer { - if serializer.is_human_readable() { - serializer.serialize_str(&self.to_bech32_string()) - } else { - serializer.serialize_bytes(&self[..]) - } - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for SchemaId { - fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer<'de> { - struct Visitor; - impl serde::de::Visitor<'_> for Visitor { - type Value = SchemaId; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "Bech32 string with `{}` HRP", RGB_SCHEMA_ID_HRP) - } - - fn visit_str(self, v: &str) -> Result - where E: serde::de::Error { - SchemaId::from_str(v).map_err(serde::de::Error::custom) - } - - fn visit_string(self, v: String) -> Result - where E: serde::de::Error { - self.visit_str(&v) - } - - fn visit_byte_buf(self, v: Vec) -> Result - where E: serde::de::Error { - SchemaId::from_bytes(&v) - .map_err(|_| serde::de::Error::invalid_length(v.len(), &"32 bytes")) - } - } - - if deserializer.is_human_readable() { - deserializer.deserialize_str(Visitor) - } else { - deserializer.deserialize_byte_buf(Visitor) - } - } -} - -impl FromStr for SchemaId { - type Err = lnpbp::bech32::Error; - - fn from_str(s: &str) -> Result { SchemaId::from_bech32_str(s) } -} - #[derive(Clone, Debug, Default)] #[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] diff --git a/src/temp.rs b/src/temp.rs index 24850ae6..42770fd1 100644 --- a/src/temp.rs +++ b/src/temp.rs @@ -34,3 +34,21 @@ pub struct TxResolverError(Txid); pub trait ResolveTx { fn resolve_tx(&self, txid: Txid) -> Result; } + +// TODO: Change values according to the standard +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +#[derive(StrictEncode, StrictDecode)] +#[strict_encoding(by_value, repr = u32)] +#[repr(u32)] +pub enum Chain { + #[default] + #[display("mainnet")] + Bitcoin = 0x00, + #[display("testnet")] + Testnet3 = 0x8000_0000, + #[display("regtest")] + Regtest = 0x8000_0001, + #[display("signet")] + Signet = 0x8000_0002, +} From 1497ac1cfa8218fe3435529fd77faaaf599f1aee Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 18:51:44 +0100 Subject: [PATCH 12/71] chore: update half dependency --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 470635c8..63fac713 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -533,9 +533,9 @@ dependencies = [ [[package]] name = "half" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" dependencies = [ "crunchy", "serde", diff --git a/Cargo.toml b/Cargo.toml index 00f79490..bb83a21b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ bp-primitives = "0.10.0-beta.1" # features for a dependency. See # for the explanation # and references. -half = "~2.1.0" +half = "~2.2.1" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } serde_with = { version = "1.14", features = ["hex"], optional = true } serde_json = "1" # TODO: Remove From 51598d0f7fabf3fe79032b732fa3d644f336742e Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 19:08:17 +0100 Subject: [PATCH 13/71] refactor: (!) cut out previous strict encoding schema (stens) --- Cargo.lock | 14 -- Cargo.toml | 3 +- src/contract/assignments.rs | 75 -------- src/contract/attachment.rs | 3 +- src/contract/data.rs | 330 +----------------------------------- src/contract/metadata.rs | 149 ---------------- src/schema/schema.rs | 54 +++--- src/schema/script.rs | 20 +-- src/schema/state.rs | 150 +--------------- src/validation.rs | 7 +- src/vm/mod.rs | 13 +- 11 files changed, 40 insertions(+), 778 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63fac713..d877c8e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -778,7 +778,6 @@ dependencies = [ "serde", "serde_json", "serde_with", - "stens", "strict_encoding 0.9.0", "strict_encoding_test", ] @@ -975,19 +974,6 @@ dependencies = [ "syn", ] -[[package]] -name = "stens" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dfcfcd8b29e9cca1e0c1f1bcd03f91704cd16bfd49301d937bd56379b76b10" -dependencies = [ - "amplify 3.13.0", - "serde", - "serde_with", - "serde_yaml 0.9.17", - "strict_encoding 0.9.0", -] - [[package]] name = "strict_encoding" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index bb83a21b..028daac8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ path = "src/lib.rs" # ----------------------------------------- amplify = { version = "~3.13.0", features = ["apfloat"] } bp-core = { version = "~0.9.0" } -stens = "~0.9.0" strict_encoding = { version = "~0.9.0", features = ["crypto", "chrono", "bitcoin", "float"] } commit_verify = { version = "~0.9.0", features = ["rand", "bulletproofs"] } aluvm = { version = "~0.9.0", features = ["std", "strict_encoding"] } @@ -65,5 +64,5 @@ default = [] all = ["serde"] serde = ["serde_crate", "serde_with", "half/serde", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", - "bp-core/serde", "stens/serde", "aluvm/serde", + "bp-core/serde", "aluvm/serde", "secp256k1-zkp/serde", "bp-primitives/serde"] diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 002b21a5..e34c8401 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -717,81 +717,6 @@ pub trait RevealedState: { } -impl TypedAssignments { - pub fn u8(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::u8) - .collect() - } - pub fn u16(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::u16) - .collect() - } - pub fn u32(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::u32) - .collect() - } - pub fn u64(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::u64) - .collect() - } - pub fn i8(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::i8) - .collect() - } - pub fn i16(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::i16) - .collect() - } - pub fn i32(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::i32) - .collect() - } - pub fn i64(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::i64) - .collect() - } - pub fn f32(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::f32) - .collect() - } - pub fn f64(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::f64) - .collect() - } - pub fn bytes(&self) -> Vec> { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::bytes) - .collect() - } - pub fn string(&self) -> Vec { - self.filter_revealed_state_data() - .into_iter() - .filter_map(data::Revealed::unicode_string) - .collect() - } -} - pub trait State: Debug { type Confidential: ConfidentialState; type Revealed: RevealedState; diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index e5c2b04a..ca9aa602 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -13,7 +13,6 @@ use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{ commit_encode, CommitConceal, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash, }; -use stens::AsciiString; use strict_encoding::{strict_serialize, StrictEncode}; use crate::{ConfidentialState, RevealedState}; @@ -100,7 +99,7 @@ impl Confidential { #[display("{id}~{mime}")] pub struct Revealed { pub id: AttachmentId, - pub mime: AsciiString, + pub mime: String, pub salt: u64, } diff --git a/src/contract/data.rs b/src/contract/data.rs index 8b841d82..e331175c 100644 --- a/src/contract/data.rs +++ b/src/contract/data.rs @@ -12,18 +12,12 @@ #![allow(clippy::unnecessary_cast)] use core::any::Any; -use core::cmp::Ordering; use core::fmt::Debug; -use std::hash::Hasher; use std::io; -use amplify::num::apfloat::ieee; -use amplify::num::{i1024, i256, i512, u1024, u256, u512}; use amplify::AsAny; use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{commit_encode, CommitConceal, CommitEncode, TaggedHash}; -use half::bf16; -use stens::{AsciiString, PrimitiveType, TypeRef}; use strict_encoding::strict_serialize; use super::{ConfidentialState, RevealedState}; @@ -48,98 +42,10 @@ impl CommitEncode for Void { fn commit_encode(&self, _e: E) -> usize { 0 } } -#[derive(Clone, Debug, AsAny, Display)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, AsAny)] #[derive(StrictEncode, StrictDecode)] -#[strict_encoding(repr = u8)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub enum Revealed { - #[strict_encoding(value = 0x00)] - #[display("{0}", alt = "U8({0})")] - U8(u8), - #[strict_encoding(value = 0x01)] - #[display("{0}", alt = "U16({0})")] - U16(u16), - #[strict_encoding(value = 0x02)] - #[display("{0}", alt = "U32({0})")] - U32(u32), - #[strict_encoding(value = 0x03)] - #[display("{0}", alt = "U64({0})")] - U64(u64), - #[strict_encoding(value = 0x04)] - #[display("{0}", alt = "U128({0})")] - U128(u128), - #[strict_encoding(value = 0x05)] - #[display("{0}", alt = "U256({0})")] - U256(u256), - #[strict_encoding(value = 0x06)] - #[display("{0}", alt = "U512({0})")] - U512(u512), - #[strict_encoding(value = 0x07)] - #[display("{0}", alt = "U1024({0})")] - U1024(u1024), - - #[strict_encoding(value = 0x10)] - #[display("{0}", alt = "I8({0})")] - I8(i8), - #[strict_encoding(value = 0x11)] - #[display("{0}", alt = "I16({0})")] - I16(i16), - #[strict_encoding(value = 0x12)] - #[display("{0}", alt = "I32({0})")] - I32(i32), - #[strict_encoding(value = 0x13)] - #[display("{0}", alt = "I64({0})")] - I64(i64), - #[strict_encoding(value = 0x14)] - #[display("{0}", alt = "I128({0})")] - I128(i128), - #[strict_encoding(value = 0x15)] - #[display("{0}", alt = "I256({0})")] - I256(i256), - #[strict_encoding(value = 0x16)] - #[display("{0}", alt = "I512({0})")] - I512(i512), - #[strict_encoding(value = 0x17)] - #[display("{0}", alt = "I1024({0})")] - I1024(i1024), - - // TODO #100: Implement tapered float format - #[strict_encoding(value = 0x30)] - #[display("{0}", alt = "F16B({0})")] - F16B(bf16), - #[strict_encoding(value = 0x31)] - #[cfg_attr(feature = "serde", serde(with = "serde_with::rust::display_fromstr"))] - #[display("{0}", alt = "F16({0})")] - F16(ieee::Half), - #[strict_encoding(value = 0x32)] - #[display("{0}", alt = "F32({0})")] - F32(f32), - #[strict_encoding(value = 0x33)] - #[display("{0}", alt = "F64({0})")] - F64(f64), - #[strict_encoding(value = 0x34)] - #[cfg_attr(feature = "serde", serde(with = "serde_with::rust::display_fromstr"))] - #[display("{0}", alt = "F80({0})")] - F80(ieee::X87DoubleExtended), - #[strict_encoding(value = 0x35)] - #[cfg_attr(feature = "serde", serde(with = "serde_with::rust::display_fromstr"))] - #[display("{0}", alt = "F128({0})")] - F128(ieee::Quad), - #[strict_encoding(value = 0x36)] - #[cfg_attr(feature = "serde", serde(with = "serde_with::rust::display_fromstr"))] - #[display("{0}", alt = "F256({0})")] - F256(ieee::Oct), - - #[strict_encoding(value = 0xE0)] - #[display("", alt = "bytes(...)")] - Bytes(Vec), - #[strict_encoding(value = 0xEE)] - #[display("{0}", alt = "ascii({0})")] - AsciiString(AsciiString), - #[strict_encoding(value = 0xEF)] - #[display("{0}", alt = "string({0})")] - UnicodeString(String), -} +pub struct Revealed(Vec); impl RevealedState for Revealed {} @@ -156,44 +62,6 @@ impl commit_encode::Strategy for Revealed { type Strategy = commit_encode::strategies::UsingConceal; } -impl PartialEq for Revealed { - fn eq(&self, other: &Self) -> bool { - let some = strict_serialize(self).expect("Encoding of predefined data types must not fail"); - let other = - strict_serialize(other).expect("Encoding of predefined data types must not fail"); - some.eq(&other) - } -} - -impl Eq for Revealed {} - -impl std::hash::Hash for Revealed { - fn hash(&self, state: &mut H) { - state.write(&self.commit_conceal().commit_serialize()) - } -} - -impl PartialOrd for Revealed { - fn partial_cmp(&self, other: &Self) -> Option { - let some = strict_serialize(self).expect("Encoding of predefined data types must not fail"); - let other = - strict_serialize(other).expect("Encoding of predefined data types must not fail"); - some.partial_cmp(&other) - } -} - -impl Ord for Revealed { - fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).unwrap_or_else(|| { - let some = - strict_serialize(self).expect("Encoding of predefined data types must not fail"); - let other = - strict_serialize(other).expect("Encoding of predefined data types must not fail"); - some.cmp(&other) - }) - } -} - // "rgb:data:confidential" static MIDSTATE_CONFIDENTIAL_DATA: [u8; 32] = [ 151, 235, 12, 105, 100, 154, 61, 159, 108, 179, 41, 229, 218, 159, 57, 12, 233, 248, 167, 213, @@ -228,200 +96,6 @@ impl AsAny for Confidential { fn as_any(&self) -> &dyn Any { self as &dyn Any } } -impl Revealed { - pub fn u8(&self) -> Option { - match self { - Revealed::U8(val) => Some(*val), - _ => None, - } - } - pub fn u16(&self) -> Option { - match self { - Revealed::U16(val) => Some(*val), - _ => None, - } - } - pub fn u32(&self) -> Option { - match self { - Revealed::U32(val) => Some(*val), - _ => None, - } - } - pub fn u64(&self) -> Option { - match self { - Revealed::U64(val) => Some(*val), - _ => None, - } - } - pub fn u128(&self) -> Option { - match self { - Revealed::U128(val) => Some(*val), - _ => None, - } - } - pub fn u256(&self) -> Option { - match self { - Revealed::U256(val) => Some(*val), - _ => None, - } - } - pub fn u512(&self) -> Option { - match self { - Revealed::U512(val) => Some(*val), - _ => None, - } - } - pub fn u1024(&self) -> Option { - match self { - Revealed::U1024(val) => Some(*val), - _ => None, - } - } - - pub fn i8(&self) -> Option { - match self { - Revealed::I8(val) => Some(*val), - _ => None, - } - } - pub fn i16(&self) -> Option { - match self { - Revealed::I16(val) => Some(*val), - _ => None, - } - } - pub fn i32(&self) -> Option { - match self { - Revealed::I32(val) => Some(*val), - _ => None, - } - } - pub fn i64(&self) -> Option { - match self { - Revealed::I64(val) => Some(*val), - _ => None, - } - } - pub fn i128(&self) -> Option { - match self { - Revealed::I128(val) => Some(*val), - _ => None, - } - } - pub fn i256(&self) -> Option { - match self { - Revealed::I256(val) => Some(*val), - _ => None, - } - } - pub fn i512(&self) -> Option { - match self { - Revealed::I512(val) => Some(*val), - _ => None, - } - } - pub fn i1024(&self) -> Option { - match self { - Revealed::I1024(val) => Some(*val), - _ => None, - } - } - - pub fn f16b(&self) -> Option { - match self { - Revealed::F16B(val) => Some(*val), - _ => None, - } - } - pub fn f16(&self) -> Option { - match self { - Revealed::F16(val) => Some(*val), - _ => None, - } - } - pub fn f32(&self) -> Option { - match self { - Revealed::F32(val) => Some(*val), - _ => None, - } - } - pub fn f64(&self) -> Option { - match self { - Revealed::F64(val) => Some(*val), - _ => None, - } - } - pub fn f80(&self) -> Option { - match self { - Revealed::F80(val) => Some(*val), - _ => None, - } - } - pub fn f128(&self) -> Option { - match self { - Revealed::F128(val) => Some(*val), - _ => None, - } - } - pub fn f256(&self) -> Option { - match self { - Revealed::F256(val) => Some(*val), - _ => None, - } - } - // TODO #100: Implement tapered float format - - pub fn bytes(&self) -> Option> { - match self { - Revealed::Bytes(val) => Some(val.clone()), - _ => None, - } - } - pub fn ascii_string(&self) -> Option { - match self { - Revealed::AsciiString(val) => Some(val.clone()), - _ => None, - } - } - pub fn unicode_string(&self) -> Option { - match self { - Revealed::UnicodeString(val) => Some(val.clone()), - _ => None, - } - } - - pub fn schema_type(&self) -> TypeRef { - match self { - Revealed::U8(_) => TypeRef::u8(), - Revealed::U16(_) => TypeRef::u16(), - Revealed::U32(_) => TypeRef::u32(), - Revealed::U64(_) => TypeRef::u64(), - Revealed::U128(_) => TypeRef::u128(), - Revealed::U256(_) => TypeRef::InPlace(PrimitiveType::U256.into()), - Revealed::U512(_) => TypeRef::InPlace(PrimitiveType::U512.into()), - Revealed::U1024(_) => TypeRef::InPlace(PrimitiveType::U1024.into()), - Revealed::I8(_) => TypeRef::i8(), - Revealed::I16(_) => TypeRef::i16(), - Revealed::I32(_) => TypeRef::i32(), - Revealed::I64(_) => TypeRef::i64(), - Revealed::I128(_) => TypeRef::i128(), - Revealed::I256(_) => TypeRef::InPlace(PrimitiveType::I256.into()), - Revealed::I512(_) => TypeRef::InPlace(PrimitiveType::I512.into()), - Revealed::I1024(_) => TypeRef::InPlace(PrimitiveType::I1024.into()), - Revealed::F16B(_) => TypeRef::InPlace(PrimitiveType::F16b.into()), - Revealed::F16(_) => TypeRef::InPlace(PrimitiveType::F16.into()), - Revealed::F32(_) => TypeRef::f32(), - Revealed::F64(_) => TypeRef::f64(), - Revealed::F80(_) => TypeRef::InPlace(PrimitiveType::F80.into()), - Revealed::F128(_) => TypeRef::InPlace(PrimitiveType::F128.into()), - Revealed::F256(_) => TypeRef::InPlace(PrimitiveType::F256.into()), - Revealed::Bytes(_) => TypeRef::bytes(), - Revealed::AsciiString(_) => TypeRef::ascii_string(), - Revealed::UnicodeString(_) => TypeRef::unicode_string(), - } - } -} - #[cfg(test)] mod test { use amplify::Wrapper; diff --git a/src/contract/metadata.rs b/src/contract/metadata.rs index 6bf073dc..7c3e0dee 100644 --- a/src/contract/metadata.rs +++ b/src/contract/metadata.rs @@ -13,15 +13,11 @@ use std::collections::BTreeMap; -use amplify::num::apfloat::ieee; -use amplify::num::{i1024, i256, i512, u1024, u256, u512}; use amplify::Wrapper; use commit_verify::merkle::MerkleNode; use commit_verify::{ commit_encode, ConsensusCommit, ConsensusMerkleCommit, MerkleSource, ToMerkleSource, }; -use half::bf16; -use stens::AsciiString; use super::data; use crate::schema; @@ -71,151 +67,6 @@ impl ToMerkleSource for Metadata { } } -impl Metadata { - pub fn u8(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u8).collect()) - .unwrap_or_default() - } - pub fn u16(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u16).collect()) - .unwrap_or_default() - } - pub fn u32(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u32).collect()) - .unwrap_or_default() - } - pub fn u64(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u64).collect()) - .unwrap_or_default() - } - pub fn u128(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u128).collect()) - .unwrap_or_default() - } - pub fn u256(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u256).collect()) - .unwrap_or_default() - } - pub fn u512(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u512).collect()) - .unwrap_or_default() - } - pub fn u1024(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::u1024).collect()) - .unwrap_or_default() - } - - pub fn i8(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i8).collect()) - .unwrap_or_default() - } - pub fn i16(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i16).collect()) - .unwrap_or_default() - } - pub fn i32(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i32).collect()) - .unwrap_or_default() - } - pub fn i64(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i64).collect()) - .unwrap_or_default() - } - pub fn i128(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i128).collect()) - .unwrap_or_default() - } - pub fn i256(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i256).collect()) - .unwrap_or_default() - } - pub fn i512(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i512).collect()) - .unwrap_or_default() - } - pub fn i1024(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::i1024).collect()) - .unwrap_or_default() - } - - pub fn f16b(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::f16b).collect()) - .unwrap_or_default() - } - pub fn f16(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::f16).collect()) - .unwrap_or_default() - } - pub fn f32(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::f32).collect()) - .unwrap_or_default() - } - pub fn f64(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::f64).collect()) - .unwrap_or_default() - } - pub fn f80(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::f80).collect()) - .unwrap_or_default() - } - pub fn f128(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::f128).collect()) - .unwrap_or_default() - } - pub fn f256(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::f256).collect()) - .unwrap_or_default() - } - // TODO #100: Implement tapered float format - - pub fn bytes(&self, field_type: impl Into) -> Vec> { - self.get(&field_type.into()) - .map(|set| set.iter().filter_map(data::Revealed::bytes).collect()) - .unwrap_or_default() - } - pub fn ascii_string(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| { - set.iter() - .filter_map(data::Revealed::ascii_string) - .collect() - }) - .unwrap_or_default() - } - pub fn unicode_string(&self, field_type: impl Into) -> Vec { - self.get(&field_type.into()) - .map(|set| { - set.iter() - .filter_map(data::Revealed::unicode_string) - .collect() - }) - .unwrap_or_default() - } -} - #[cfg(test)] mod test { use amplify::Wrapper; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 12368215..bf558fcd 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -14,7 +14,6 @@ use std::collections::{BTreeMap, BTreeSet}; use amplify::flags::FlagVec; use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{commit_encode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash}; -use stens::{TypeRef, TypeSystem}; use super::{ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, TransitionSchema}; use crate::schema::StateSchema; @@ -56,7 +55,7 @@ where Msg: AsRef<[u8]> fn commit(msg: &Msg) -> SchemaId { SchemaId::hash(msg) } } -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] #[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Schema { @@ -74,8 +73,8 @@ pub struct Schema { pub rgb_features: FlagVec, pub root_id: SchemaId, - pub type_system: TypeSystem, - pub field_types: BTreeMap, + pub type_system: Vec, // TODO: TypeSystem, + pub field_types: BTreeMap, pub owned_right_types: BTreeMap, pub public_right_types: BTreeSet, pub genesis: GenesisSchema, @@ -118,14 +117,13 @@ mod _validation { use commit_verify::CommitConceal; use super::*; - use crate::schema::state::StenVerify; use crate::schema::{ MetadataStructure, OwnedRightsStructure, PublicRightsStructure, SchemaVerify, }; use crate::script::{OverrideRules, ValidationScript}; use crate::vm::Validate; use crate::{ - data, validation, Assignment, Metadata, Node, NodeId, NodeSubtype, OwnedRights, + validation, Assignment, Metadata, Node, NodeId, NodeSubtype, OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights, State, TypedAssignments, }; @@ -346,12 +344,13 @@ mod _validation { } fn validate_type_system(&self) -> validation::Status { - let mut status = validation::Status::new(); - if let Err(inconsistencies) = self.type_system.validate() { - for err in inconsistencies { - status.add_failure(validation::Failure::SchemaTypeSystem(err)); + let status = validation::Status::new(); + // TODO: Validate type system + /*if let Err(inconsistencies) = self.type_system.validate() { + for _err in inconsistencies { + status.add_failure(validation::Failure::SchemaTypeSystem(/*err*/)); } - } + }*/ status } @@ -385,21 +384,18 @@ mod _validation { )); } - let field = self.field_types.get(field_type_id) + let _field = self.field_types.get(field_type_id) .expect("If the field were absent, the schema would not be able to pass the internal validation and we would not reach this point"); - for data in set { + for _data in set { + // TODO: Run strict type validation + /* let schema_type = data.schema_type(); - if &schema_type != field - && !matches!( - (&data, field), - (data::Revealed::Bytes(_), TypeRef::NameRef(_)) - ) - { - status.add_failure(validation::Failure::SchemaMismatchedDataType( - *field_type_id, - )); - } + + status.add_failure(validation::Failure::SchemaMismatchedDataType( + *field_type_id, + )); status += field.verify(&self.type_system, node_id, *field_type_id, &data); + */ } } @@ -508,20 +504,16 @@ mod _validation { match owned_rights.get(owned_type_id) { None => {} Some(TypedAssignments::Void(set)) => set.iter().for_each(|data| { - status += - assignment.validate(&self.type_system, &node_id, *owned_type_id, data) + status += assignment.validate(&node_id, *owned_type_id, data) }), Some(TypedAssignments::Value(set)) => set.iter().for_each(|data| { - status += - assignment.validate(&self.type_system, &node_id, *owned_type_id, data) + status += assignment.validate(&node_id, *owned_type_id, data) }), Some(TypedAssignments::Data(set)) => set.iter().for_each(|data| { - status += - assignment.validate(&self.type_system, &node_id, *owned_type_id, data) + status += assignment.validate(&node_id, *owned_type_id, data) }), Some(TypedAssignments::Attachment(set)) => set.iter().for_each(|data| { - status += - assignment.validate(&self.type_system, &node_id, *owned_type_id, data) + status += assignment.validate(&node_id, *owned_type_id, data) }), }; } diff --git a/src/schema/script.rs b/src/schema/script.rs index 86aa0624..36fe603e 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -22,10 +22,6 @@ use crate::vm::alure; #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[display(Debug)] pub enum VmType { - /// Embedded code (not a virtual machine) which is the part of this RGB - /// Core Library. - Embedded, - /// AluVM: pure functional register-based virtual machine designed for RGB /// and multiparty computing. AluVM, @@ -37,14 +33,6 @@ pub enum VmType { #[derive(StrictEncode, StrictDecode)] #[strict_encoding(by_value, repr = u8)] pub enum ValidationScript { - /// Embedded code (not a virtual machine) which is the part of this RGB - /// Core Library. Using this option results in the fact that the schema - /// does not commit to the actual validating code and the validation logic - /// may change in the future (like to be patched) with new RGB Core Lib - /// releases. - #[strict_encoding(value = 0x00)] - Embedded, - /// AluVM: pure functional register-based virtual machine designed for RGB /// and multiparty computing. /// @@ -54,15 +42,10 @@ pub enum ValidationScript { /// /// Its routines can be accessed only through well-typed ABI entrance /// pointers, defined as a part of the schema. - #[strict_encoding(value = 0x01)] + #[strict_encoding(value = 0x00)] AluVM(alure::ValidationScript), } -impl Default for ValidationScript { - // TODO: Update default VM type to AluVM in RGBv1 release - fn default() -> Self { ValidationScript::Embedded } -} - impl commit_encode::Strategy for ValidationScript { type Strategy = commit_encode::strategies::UsingStrict; } @@ -70,7 +53,6 @@ impl commit_encode::Strategy for ValidationScript { impl ValidationScript { pub fn vm_type(&self) -> VmType { match self { - ValidationScript::Embedded => VmType::Embedded, ValidationScript::AluVM(_) => VmType::AluVM, } } diff --git a/src/schema/state.rs b/src/schema/state.rs index 47ad6018..1203a34a 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -9,8 +9,6 @@ // You should have received a copy of the MIT License along with this software. // If not, see . -use stens::TypeRef; - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] #[derive(StrictEncode, StrictDecode)] #[strict_encoding(by_value, repr = u8)] @@ -38,7 +36,7 @@ pub enum StateType { pub enum StateSchema { Declarative, DiscreteFiniteField(DiscreteFiniteFieldFormat), - CustomData(TypeRef), + CustomData(/* TODO: Insert strict types type */), DataContainer, } @@ -64,148 +62,21 @@ pub enum DiscreteFiniteFieldFormat { mod _validation { use core::any::Any; - use std::io; use amplify::AsAny; use commit_verify::CommitConceal; - use stens::{PrimitiveType, TypeConstr, TypeSystem, Verify}; use super::*; use crate::contract::AttachmentStrategy; - use crate::data::Revealed; use crate::schema::OwnedRightType; - use crate::validation::Status; use crate::{ - data, validation, Assignment, DeclarativeStrategy, HashStrategy, NodeId, PedersenStrategy, - State, + validation, Assignment, DeclarativeStrategy, HashStrategy, NodeId, PedersenStrategy, State, }; - pub trait StenVerify { - fn verify( - &self, - type_system: &TypeSystem, - node_id: NodeId, - schema_type_id: u16, - data: &data::Revealed, - ) -> validation::Status; - } - - impl StenVerify for PrimitiveType { - fn verify( - &self, - _: &TypeSystem, - node_id: NodeId, - schema_type_id: u16, - data: &data::Revealed, - ) -> validation::Status { - let mut status = validation::Status::new(); - match (self, data) { - (PrimitiveType::U8, data::Revealed::U8(_)) - | (PrimitiveType::U16, data::Revealed::U16(_)) - | (PrimitiveType::U32, data::Revealed::U32(_)) - | (PrimitiveType::U64, data::Revealed::U64(_)) - | (PrimitiveType::U128, data::Revealed::U128(_)) - | (PrimitiveType::U256, data::Revealed::U256(_)) - | (PrimitiveType::U512, data::Revealed::U512(_)) - | (PrimitiveType::U1024, data::Revealed::U1024(_)) - | (PrimitiveType::I8, data::Revealed::I8(_)) - | (PrimitiveType::I16, data::Revealed::I16(_)) - | (PrimitiveType::I32, data::Revealed::I32(_)) - | (PrimitiveType::I64, data::Revealed::I64(_)) - | (PrimitiveType::I128, data::Revealed::I128(_)) - | (PrimitiveType::I256, data::Revealed::I256(_)) - | (PrimitiveType::I512, data::Revealed::I512(_)) - | (PrimitiveType::I1024, data::Revealed::I1024(_)) - | (PrimitiveType::F16b, data::Revealed::F16B(_)) - | (PrimitiveType::F16, data::Revealed::F16(_)) - | (PrimitiveType::F32, data::Revealed::F32(_)) - | (PrimitiveType::F64, data::Revealed::F64(_)) - | (PrimitiveType::F80, data::Revealed::F80(_)) - | (PrimitiveType::F128, data::Revealed::F128(_)) - | (PrimitiveType::F256, data::Revealed::F256(_)) => {} - _ => { - status.add_failure(validation::Failure::InvalidStateDataType( - node_id, - schema_type_id, - TypeRef::InPlace(TypeConstr::Plain(*self)), - data.clone(), - )); - } - } - status - } - } - - impl StenVerify for TypeConstr { - fn verify( - &self, - type_system: &TypeSystem, - node_id: NodeId, - schema_type_id: u16, - data: &Revealed, - ) -> Status { - let mut status = validation::Status::new(); - match (self, data) { - (TypeConstr::Plain(ty), data) => { - status += StenVerify::verify(ty, type_system, node_id, schema_type_id, data); - } - (TypeConstr::List(PrimitiveType::AsciiChar), Revealed::AsciiString(_)) => {} - (TypeConstr::List(PrimitiveType::UnicodeChar), Revealed::UnicodeString(_)) => {} - (TypeConstr::List(PrimitiveType::U8), Revealed::Bytes(_)) => {} - _ => { - status.add_failure(validation::Failure::InvalidStateDataType( - node_id, - schema_type_id, - TypeRef::InPlace(self.clone()), - data.clone(), - )); - } - } - status - } - } - - impl StenVerify for TypeRef { - fn verify( - &self, - type_system: &TypeSystem, - node_id: NodeId, - schema_type_id: u16, - data: &data::Revealed, - ) -> validation::Status { - let mut status = validation::Status::new(); - match (self, data) { - (TypeRef::InPlace(ty), _) => { - status += StenVerify::verify(ty, type_system, node_id, schema_type_id, data); - } - (TypeRef::NameRef(ty), data::Revealed::Bytes(bytes)) => { - let mut cursor = io::Cursor::new(bytes.as_slice()); - if !ty.verify(type_system, &mut cursor) { - status.add_failure(validation::Failure::InvalidStateDataValue( - node_id, - schema_type_id, - self.clone(), - bytes.clone(), - )); - } - } - _ => { - status.add_failure(validation::Failure::InvalidStateDataType( - node_id, - schema_type_id, - self.clone(), - data.clone(), - )); - } - } - status - } - } - impl StateSchema { pub fn validate( &self, - type_system: &TypeSystem, + // type_system: &TypeSystem, node_id: &NodeId, assignment_id: OwnedRightType, data: &Assignment, @@ -252,7 +123,7 @@ mod _validation { // add information to the status like with // hashed data below } - StateSchema::CustomData(_) => { + StateSchema::CustomData() => { match a.downcast_ref::<::Confidential>() { None => { status.add_failure( @@ -305,7 +176,7 @@ mod _validation { // TODO #15: When other homomorphic formats will be added, // add type check like with hashed data below } - StateSchema::CustomData(format) => { + StateSchema::CustomData(/*format*/) => { match a.downcast_ref::<::Revealed>() { None => { status.add_failure( @@ -314,14 +185,8 @@ mod _validation { ), ); } - Some(data) => { - status += StenVerify::verify( - format, - type_system, - *node_id, - assignment_id, - data, - ); + Some(_data) => { + // TODO: run strict type validation } } } @@ -341,7 +206,6 @@ mod _validation { } } } -pub(super) use _validation::StenVerify; #[cfg(test)] mod test { diff --git a/src/validation.rs b/src/validation.rs index 0427cfb2..5747e687 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -17,7 +17,6 @@ use bc::{Tx, Txid}; use bp::dbc::Anchor; use bp::seals::txout::TxoSeal; use commit_verify::{lnpbp4, CommitConceal}; -use stens::TypeRef; use super::schema::{NodeType, OccurrencesError}; use super::{schema, seal, ContractId, Node, NodeId, Schema, SchemaId, TypedAssignments}; @@ -179,7 +178,7 @@ pub enum Failure { SchemaScriptOverrideDenied, SchemaScriptVmChangeDenied, - SchemaTypeSystem(stens::TypeInconsistency), + SchemaTypeSystem(/* TODO: use error from strict types */), BundleInvalid(BundleId), @@ -223,8 +222,8 @@ pub enum Failure { EndpointTransitionNotFound(NodeId), - InvalidStateDataType(NodeId, u16, TypeRef, data::Revealed), - InvalidStateDataValue(NodeId, u16, TypeRef, Vec), + InvalidStateDataType(NodeId, u16, /* TODO: Use strict type */ data::Revealed), + InvalidStateDataValue(NodeId, u16, /* TODO: Use strict type */ Vec), /// invalid bulletproofs in {0}:{1}: {3} InvalidBulletproofs(NodeId, u16, String), diff --git a/src/vm/mod.rs b/src/vm/mod.rs index ebba23e0..c0641849 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -13,10 +13,10 @@ //! //! Concrete virtual machine implementations must be wrapped into this API -pub mod embedded; +// pub mod embedded; pub mod alure; -pub use embedded::EmbeddedVm; +// pub use embedded::EmbeddedVm; use crate::{ validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, ValidationScript, @@ -51,15 +51,6 @@ impl Validate for ValidationScript { current_meta: &Metadata, ) -> Result<(), validation::Failure> { match self { - ValidationScript::Embedded => EmbeddedVm::new().validate( - node_id, - node_subtype, - previous_owned_rights, - current_owned_rights, - previous_public_rights, - current_public_rights, - current_meta, - ), ValidationScript::AluVM(script) => alure::Runtime::new(script).validate( node_id, node_subtype, From 7a6a7b0f7dfd123b1700de645599a52af3b70957 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 19:09:10 +0100 Subject: [PATCH 14/71] refactor: remove `half` dependency --- Cargo.lock | 2 -- Cargo.toml | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d877c8e0..16a88064 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -538,7 +538,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" dependencies = [ "crunchy", - "serde", ] [[package]] @@ -772,7 +771,6 @@ dependencies = [ "bp-core", "bp-primitives", "commit_verify 0.9.0", - "half", "once_cell", "secp256k1-zkp", "serde", diff --git a/Cargo.toml b/Cargo.toml index 028daac8..16081c9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,6 @@ bp-primitives = "0.10.0-beta.1" # features for a dependency. See # for the explanation # and references. -half = "~2.2.1" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } serde_with = { version = "1.14", features = ["hex"], optional = true } serde_json = "1" # TODO: Remove @@ -62,7 +61,7 @@ strict_encoding_test = "0.9.0" [features] default = [] all = ["serde"] -serde = ["serde_crate", "serde_with", "half/serde", +serde = ["serde_crate", "serde_with", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", "bp-core/serde", "aluvm/serde", "secp256k1-zkp/serde", "bp-primitives/serde"] From f9ed30c1685679050d2194c21563b510e7ece140 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 19:13:07 +0100 Subject: [PATCH 15/71] refactor: (!) cut out aluvm dependency --- Cargo.lock | 114 ++---------------------------------------------- Cargo.toml | 3 +- src/vm/alure.rs | 10 ++++- 3 files changed, 13 insertions(+), 114 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16a88064..3f9cc96c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,24 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "aluvm" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6320f5e4a7d249d77a017e0ade7912b910d9515e2c73b0f5ef3218c954f06a1" -dependencies = [ - "amplify 3.13.0", - "bech32", - "bitcoin_hashes", - "curve25519-dalek", - "half", - "paste", - "secp256k1 0.24.3", - "serde", - "serde_with", - "strict_encoding 0.9.0", -] - [[package]] name = "amplify" version = "3.13.0" @@ -298,12 +280,6 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "cc" version = "1.0.79" @@ -379,20 +355,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "curve25519-dalek" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" -dependencies = [ - "byteorder", - "digest", - "rand_core 0.5.1", - "serde", - "subtle", - "zeroize", -] - [[package]] name = "cxx" version = "1.0.89" @@ -472,15 +434,6 @@ dependencies = [ "syn", ] -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "encoding_derive_helpers" version = "0.8.1" @@ -499,27 +452,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "generic-array" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.8" @@ -730,7 +662,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -740,16 +672,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -758,14 +681,13 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom", ] [[package]] name = "rgb-core" version = "0.9.0" dependencies = [ - "aluvm", "amplify 3.13.0", "bitcoin_hashes", "bp-core", @@ -1049,12 +971,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - [[package]] name = "syn" version = "1.0.107" @@ -1095,12 +1011,6 @@ dependencies = [ "serde", ] -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - [[package]] name = "unicode-ident" version = "1.0.6" @@ -1119,18 +1029,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -1236,9 +1134,3 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] - -[[package]] -name = "zeroize" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/Cargo.toml b/Cargo.toml index 16081c9f..39a24a9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,6 @@ amplify = { version = "~3.13.0", features = ["apfloat"] } bp-core = { version = "~0.9.0" } strict_encoding = { version = "~0.9.0", features = ["crypto", "chrono", "bitcoin", "float"] } commit_verify = { version = "~0.9.0", features = ["rand", "bulletproofs"] } -aluvm = { version = "~0.9.0", features = ["std", "strict_encoding"] } bitcoin_hashes = "0.11.0" bp-primitives = "0.10.0-beta.1" # Core rust projects @@ -63,5 +62,5 @@ default = [] all = ["serde"] serde = ["serde_crate", "serde_with", "amplify/serde", "commit_verify/serde", "strict_encoding/serde", - "bp-core/serde", "aluvm/serde", + "bp-core/serde", "secp256k1-zkp/serde", "bp-primitives/serde"] diff --git a/src/vm/alure.rs b/src/vm/alure.rs index dc3031cd..e1b3c08f 100644 --- a/src/vm/alure.rs +++ b/src/vm/alure.rs @@ -11,6 +11,7 @@ #![allow(clippy::unusual_byte_groupings)] +/* use std::collections::BTreeSet; use std::ops::RangeInclusive; @@ -18,10 +19,12 @@ use aluvm::isa::{Bytecode, BytecodeError, ExecStep, InstructionSet}; use aluvm::program::{CodeEofError, LibSite, Read, Write}; use aluvm::reg::CoreRegs; use aluvm::Vm; + */ use crate::validation::Failure; use crate::{Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, Validate}; +/* pub const INSTR_NOOP: u8 = 0b11_000_000; pub const INSTR_ISAE_FROM: u8 = 0b11_000_000; pub const INSTR_ISAE_TO: u8 = 0b11_000_000; @@ -76,10 +79,12 @@ impl Bytecode for RgbIsa { }) } } +*/ -pub type ValidationScript = aluvm::Program; +pub type ValidationScript = Vec; // aluvm::Program; pub struct Runtime<'script> { + #[allow(dead_code)] script: &'script ValidationScript, } @@ -100,11 +105,14 @@ impl<'script> Validate for Runtime<'script> { current_meta: &Metadata, ) -> Result<(), Failure> { // TODO: Implement validation with AluVM + /* let mut vm = Vm::::new(); if vm.run(self.script) { Ok(()) } else { Err(Failure::ScriptFailure(node_id)) } + */ + Ok(()) } } From f891608e5399447ea38ce3bde0e0f962d47ce10a Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 19:23:58 +0100 Subject: [PATCH 16/71] refactor: (!) wip on cutting out all old strict encoding and commitments --- Cargo.lock | 19 --- Cargo.toml | 3 +- src/contract/assignments.rs | 10 +- src/contract/attachment.rs | 16 +- src/contract/data.rs | 4 - src/contract/metadata.rs | 29 +--- src/contract/nodes.rs | 322 +----------------------------------- src/contract/rights.rs | 107 +----------- src/contract/seal.rs | 2 - src/contract/value.rs | 20 +-- src/lib.rs | 4 +- src/schema/nodes.rs | 5 - src/schema/occurrences.rs | 44 +---- src/schema/schema.rs | 11 +- src/schema/script.rs | 10 -- src/schema/state.rs | 6 - src/stash/bundle.rs | 32 +--- src/temp.rs | 2 - 18 files changed, 20 insertions(+), 626 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f9cc96c..4a06bacf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,12 +349,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - [[package]] name = "cxx" version = "1.0.89" @@ -463,15 +457,6 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] -[[package]] -name = "half" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" -dependencies = [ - "crunchy", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -698,7 +683,6 @@ dependencies = [ "serde", "serde_json", "serde_with", - "strict_encoding 0.9.0", "strict_encoding_test", ] @@ -904,9 +888,6 @@ dependencies = [ "bitcoin", "bitcoin_hashes", "chrono", - "half", - "lnpbp_secp256k1zkp", - "serde", "strict_encoding_derive 0.9.0", ] diff --git a/Cargo.toml b/Cargo.toml index 39a24a9b..883c7b00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ path = "src/lib.rs" # ----------------------------------------- amplify = { version = "~3.13.0", features = ["apfloat"] } bp-core = { version = "~0.9.0" } -strict_encoding = { version = "~0.9.0", features = ["crypto", "chrono", "bitcoin", "float"] } commit_verify = { version = "~0.9.0", features = ["rand", "bulletproofs"] } bitcoin_hashes = "0.11.0" bp-primitives = "0.10.0-beta.1" @@ -61,6 +60,6 @@ strict_encoding_test = "0.9.0" default = [] all = ["serde"] serde = ["serde_crate", "serde_with", - "amplify/serde", "commit_verify/serde", "strict_encoding/serde", + "amplify/serde", "commit_verify/serde", "bp-core/serde", "secp256k1-zkp/serde", "bp-primitives/serde"] diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index e34c8401..2286e732 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -19,7 +19,6 @@ use amplify::AsAny; use commit_verify::merkle::MerkleNode; use commit_verify::{CommitConceal, CommitEncode, ConsensusCommit}; use once_cell::sync::Lazy; -use strict_encoding::{StrictDecode, StrictEncode}; use super::{data, seal, value, ConcealSeals, ConcealState, NoDataError, SealEndpoint}; use crate::contract::attachment; @@ -52,7 +51,6 @@ pub enum StateType { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -710,12 +708,9 @@ impl ConcealState for TypedAssignments { } } -pub trait ConfidentialState: StrictEncode + StrictDecode + Debug + Clone + AsAny {} +pub trait ConfidentialState: Debug + Clone + AsAny {} -pub trait RevealedState: - StrictEncode + StrictDecode + Debug + CommitConceal + Clone + AsAny -{ -} +pub trait RevealedState: Debug + CommitConceal + Clone + AsAny {} pub trait State: Debug { type Confidential: ConfidentialState; @@ -754,7 +749,6 @@ impl State for AttachmentStrategy { /// 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)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index ca9aa602..d62c2dc4 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -10,10 +10,7 @@ // If not, see . use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::{ - commit_encode, CommitConceal, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash, -}; -use strict_encoding::{strict_serialize, StrictEncode}; +use commit_verify::{commit_encode, CommitConceal, CommitVerify, PrehashedProtocol, TaggedHash}; use crate::{ConfidentialState, RevealedState}; @@ -46,7 +43,6 @@ impl sha256t::Tag for AttachmentIdTag { serde(crate = "serde_crate", transparent) )] #[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[derive(StrictEncode, StrictDecode)] #[wrapper(Debug, Display, BorrowSlice)] pub struct AttachmentId(sha256t::Hash); @@ -75,18 +71,9 @@ impl sha256t::Tag for ConfidentialAttachmentTag { serde(crate = "serde_crate", transparent) )] #[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From, AsAny)] -#[derive(StrictEncode, StrictDecode)] #[wrapper(Debug, Display, BorrowSlice)] pub struct Confidential(sha256t::Hash); -impl commit_encode::Strategy for Confidential { - type Strategy = commit_encode::strategies::UsingStrict; -} - -impl ConsensusCommit for Confidential { - type Commitment = AttachmentId; -} - impl ConfidentialState for Confidential {} impl Confidential { @@ -94,7 +81,6 @@ impl Confidential { } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, AsAny, Display)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] #[display("{id}~{mime}")] pub struct Revealed { diff --git a/src/contract/data.rs b/src/contract/data.rs index e331175c..79f2868b 100644 --- a/src/contract/data.rs +++ b/src/contract/data.rs @@ -18,13 +18,11 @@ use std::io; use amplify::AsAny; use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{commit_encode, CommitConceal, CommitEncode, TaggedHash}; -use strict_encoding::strict_serialize; use super::{ConfidentialState, RevealedState}; /// Struct using for storing Void (i.e. absent) state #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Display, AsAny)] -#[derive(StrictEncode, StrictDecode)] #[display("void")] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Void(); @@ -43,7 +41,6 @@ impl CommitEncode for Void { } #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, AsAny)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Revealed(Vec); @@ -81,7 +78,6 @@ impl sha256t::Tag for ConfidentialTag { /// Blind version of transaction outpoint-based single-use-seal #[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] #[wrapper(Debug, Display, BorrowSlice)] pub struct Confidential(sha256t::Hash); diff --git a/src/contract/metadata.rs b/src/contract/metadata.rs index 7c3e0dee..e37a2d4a 100644 --- a/src/contract/metadata.rs +++ b/src/contract/metadata.rs @@ -14,10 +14,6 @@ use std::collections::BTreeMap; use amplify::Wrapper; -use commit_verify::merkle::MerkleNode; -use commit_verify::{ - commit_encode, ConsensusCommit, ConsensusMerkleCommit, MerkleSource, ToMerkleSource, -}; use super::data; use crate::schema; @@ -31,7 +27,6 @@ type MetadataInner = BTreeMap>; derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -#[derive(StrictEncode, StrictDecode)] pub struct Metadata(MetadataInner); // TODO #107: Improve other iterators for contract collection types. @@ -42,30 +37,8 @@ impl<'me> IntoIterator for &'me Metadata { fn into_iter(self) -> Self::IntoIter { self.0.iter() } } -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug, StrictEncode, StrictDecode)] +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] pub struct MetadataLeaf(pub schema::FieldType, pub data::Revealed); -impl commit_encode::Strategy for MetadataLeaf { - type Strategy = commit_encode::strategies::UsingStrict; -} -impl ConsensusCommit for MetadataLeaf { - type Commitment = MerkleNode; -} -impl ConsensusMerkleCommit for MetadataLeaf { - const MERKLE_NODE_PREFIX: &'static str = "metadata"; -} -impl ToMerkleSource for Metadata { - type Leaf = MetadataLeaf; - - fn to_merkle_source(&self) -> MerkleSource { - self.as_inner() - .iter() - .flat_map(|(type_id, i)| { - i.iter() - .map(move |data| MetadataLeaf(*type_id, data.clone())) - }) - .collect() - } -} #[cfg(test)] mod test { diff --git a/src/contract/nodes.rs b/src/contract/nodes.rs index 37efba1b..fad7a0f3 100644 --- a/src/contract/nodes.rs +++ b/src/contract/nodes.rs @@ -10,7 +10,6 @@ // If not, see . use std::collections::{BTreeMap, BTreeSet}; -use std::io; use std::num::ParseIntError; use std::str::FromStr; @@ -19,10 +18,7 @@ use bc::{Outpoint, Txid}; use bitcoin_hashes::{sha256, sha256t, Hash}; use bp::seals::txout::TxoSeal; use commit_verify::lnpbp4::ProtocolId; -use commit_verify::{ - commit_encode, CommitEncode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash, - ToMerkleSource, -}; +use commit_verify::{commit_encode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash}; use once_cell::sync::Lazy; use super::{ @@ -51,7 +47,6 @@ static MIDSTATE_NODE_ID: [u8; 32] = [ pub const RGB_CONTRACT_ID_HRP: &str = "rgb"; #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -#[derive(StrictEncode, StrictDecode)] #[display("{node_id}/{ty}/{no}")] /// RGB contract node output pointer, defined by the node ID and output /// number. @@ -377,7 +372,6 @@ pub struct Genesis { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, AsAny)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Extension { extension_type: ExtensionType, @@ -389,7 +383,6 @@ pub struct Extension { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, AsAny)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Transition { transition_type: TransitionType, @@ -400,78 +393,6 @@ pub struct Transition { public_rights: PublicRights, } -impl ConsensusCommit for Genesis { - type Commitment = NodeId; -} - -impl ConsensusCommit for Extension { - type Commitment = NodeId; -} - -impl ConsensusCommit for Transition { - type Commitment = NodeId; -} - -impl CommitEncode for Extension { - fn commit_encode(&self, mut e: E) -> usize { - let mut len = self.extension_type.commit_encode(&mut e); - len += self.contract_id.commit_encode(&mut e); - len += self - .metadata - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .owned_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .parent_public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len - } -} - -impl CommitEncode for Transition { - fn commit_encode(&self, mut e: E) -> usize { - let mut len = self.transition_type.commit_encode(&mut e); - len += self - .metadata - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .parent_owned_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .owned_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .parent_public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len - } -} - impl ConcealState for Genesis { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; @@ -736,107 +657,6 @@ impl Transition { pub fn transition_type(&self) -> schema::TransitionType { self.transition_type } } -mod _strict_encoding { - use std::io; - - use strict_encoding::{ - strategies, strict_deserialize, strict_serialize, Error, Strategy, StrictDecode, - StrictEncode, - }; - - use super::*; - - impl Strategy for NodeId { - type Strategy = strategies::Wrapped; - } - - impl Strategy for ContractId { - type Strategy = strategies::Wrapped; - } - - // ![CONSENSUS-CRITICAL]: Commit encode is different for genesis from strict - // encode since we only commit to chain genesis block - // hash and not all chain parameters. - // See for details. - impl CommitEncode for Genesis { - fn commit_encode(&self, mut e: E) -> usize { - let mut encoder = || -> Result<_, Error> { - let mut len = self.schema_id.strict_encode(&mut e)?; - len += self.chain.strict_encode(&mut e)?; - len += self - .metadata - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .owned_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - len += self - .public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut e); - Ok(len) - }; - encoder().expect("Strict encoding of genesis data must not fail") - } - } - - impl StrictEncode for Genesis { - fn strict_encode(&self, mut e: E) -> Result { - let chain_params = strict_serialize(&self.chain)?; - Ok(strict_encode_list!(e; - self.schema_id, - // ![NETWORK-CRITICAL]: Chain params fields may update, so we - // will serialize chain parameters in all - // known/legacy formats for compatibility. - // Thus, they are serialized as a vector - // of byte strings, each one representing - // a next version of chain parameters - // representation. - // - 1usize, - chain_params, - self.metadata, - self.owned_rights, - self.public_rights - )) - } - } - - impl StrictDecode for Genesis { - fn strict_decode(mut d: D) -> Result { - let schema_id = SchemaId::strict_decode(&mut d)?; - let chain_params_no = usize::strict_decode(&mut d)?; - if chain_params_no < 1 { - Err(Error::ValueOutOfRange( - "genesis must contain at least one `chain_param` data structure", - 1u128..(core::u16::MAX as u128), - 0, - ))? - } - let chain_data = Vec::::strict_decode(&mut d)?; - let chain = strict_deserialize(&chain_data)?; - for _ in 1..chain_params_no { - // Ignoring the rest of chain parameters - let _ = Vec::::strict_decode(&mut d)?; - } - let metadata = Metadata::strict_decode(&mut d)?; - let assignments = OwnedRightsInner::strict_decode(&mut d)?; - let valencies = PublicRightsInner::strict_decode(&mut d)?; - Ok(Self { - schema_id, - chain, - metadata, - owned_rights: assignments.into(), - public_rights: valencies.into(), - }) - } - } -} - #[cfg(test)] mod test { use std::io::Write; @@ -849,152 +669,12 @@ mod test { use super::*; - static TRANSITION: [u8; 2349] = include!("../../test/transition.in"); - static GENESIS: [u8; 2447] = include!("../../test/genesis.in"); - #[test] fn test_node_id_midstate() { let midstate = tagged_hash::Midstate::with(b"rgb:node"); assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_NODE_ID); } - #[ignore] - #[test] - fn test_genesis_chain() { - let genesis = Genesis { - schema_id: zero!(), - chain: Chain::Testnet3, - metadata: empty!(), - owned_rights: empty!(), - public_rights: empty!(), - }; - let encoded = genesis.strict_serialize().unwrap(); - let manual = vec![ - vec![0u8; 32], // zero schema id - vec![7u8, 0], // length of testnet string - b"testnet".to_vec(), - vec![0u8; 6], // three zero-length arrays - ]; - let manual: Vec = manual.into_iter().flatten().collect(); - assert_eq!(encoded, manual); - } - - // Making sure that - // is fulfilled and we do not occasionally commit to all chain - // parameters (which may vary and change with time) in RGB contract id - #[test] - fn test_genesis_commit_ne_strict() { - let genesis = Genesis { - schema_id: Default::default(), - chain: Chain::Mainnet, - metadata: Default::default(), - owned_rights: Default::default(), - public_rights: Default::default(), - }; - assert_ne!( - strict_serialize(&genesis).unwrap(), - genesis.clone().consensus_commit().to_vec() - ); - - let mut encoder = vec![]; - genesis.schema_id.strict_encode(&mut encoder).unwrap(); - encoder.write_all(GENESIS_HASH_MAINNET).unwrap(); - genesis - .metadata - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder); - genesis - .owned_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder); - genesis - .public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder); - assert_eq!(genesis.consensus_commit(), NodeId::commit(&encoder)); - - // TODO: Add data to transition testcase - let transition = Transition { - transition_type: Default::default(), - metadata: Default::default(), - parent_owned_rights: Default::default(), - owned_rights: Default::default(), - parent_public_rights: Default::default(), - public_rights: Default::default(), - }; - - // Strict encode - let mut encoder = vec![]; - transition - .transition_type - .strict_encode(&mut encoder) - .unwrap(); - transition.metadata.strict_encode(&mut encoder).unwrap(); - transition - .parent_owned_rights - .strict_encode(&mut encoder) - .unwrap(); - transition.owned_rights.strict_encode(&mut encoder).unwrap(); - transition - .parent_public_rights - .strict_encode(&mut encoder) - .unwrap(); - transition - .public_rights - .strict_encode(&mut encoder) - .unwrap(); - - let mut encoder1 = vec![]; - transition.clone().strict_encode(&mut encoder1).unwrap(); - - assert_eq!(encoder, encoder1); - - // Commit encode - let transition2 = transition.clone(); - let mut encoder2 = vec![]; - transition2.transition_type.commit_encode(&mut encoder2); - transition2 - .metadata - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder2); - transition2 - .parent_owned_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder2); - transition2 - .owned_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder2); - transition2 - .parent_public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder2); - transition2 - .public_rights - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut encoder2); - - let mut encoder3 = vec![]; - transition.clone().commit_encode(&mut encoder3); - - assert_eq!(encoder2, encoder3); - } - - #[test] - #[ignore] - fn test_encoding_nodes() { - let _: Genesis = test_vec_decoding_roundtrip(GENESIS).unwrap(); - let _: Transition = test_vec_decoding_roundtrip(TRANSITION).unwrap(); - } - #[test] #[ignore] fn test_transition_node_id() { diff --git a/src/contract/rights.rs b/src/contract/rights.rs index c60bad68..49968b1d 100644 --- a/src/contract/rights.rs +++ b/src/contract/rights.rs @@ -14,10 +14,6 @@ use std::collections::{btree_map, btree_set, BTreeMap, BTreeSet}; use amplify::Wrapper; use commit_verify::merkle::MerkleNode; -use commit_verify::{ - commit_encode, ConsensusCommit, ConsensusMerkleCommit, MerkleSource, ToMerkleSource, -}; -use strict_encoding::StrictEncode; use super::{NodeId, TypedAssignments, EMPTY_ASSIGNMENTS}; use crate::schema; @@ -36,7 +32,6 @@ pub(crate) type ParentPublicRightsInner = BTreeMap IntoIterator for &'a mut OwnedRights { derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -#[derive(StrictEncode, StrictDecode)] pub struct PublicRights(PublicRightsInner); impl PublicRights { @@ -110,7 +104,6 @@ impl<'a> IntoIterator for &'a PublicRights { derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -#[derive(StrictEncode, StrictDecode)] pub struct ParentOwnedRights(ParentOwnedRightsInner); impl ParentOwnedRights { @@ -152,7 +145,6 @@ impl<'a> IntoIterator for &'a mut ParentOwnedRights { derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -#[derive(StrictEncode, StrictDecode)] pub struct ParentPublicRights(ParentPublicRightsInner); impl ParentPublicRights { @@ -188,105 +180,14 @@ impl<'a> IntoIterator for &'a mut ParentPublicRights { fn into_iter(self) -> Self::IntoIter { self.0.iter_mut() } } -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, StrictEncode, StrictDecode)] +#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] pub struct PublicRightsLeaf(pub schema::PublicRightType); -impl commit_encode::Strategy for PublicRightsLeaf { - type Strategy = commit_encode::strategies::UsingStrict; -} -impl ConsensusCommit for PublicRightsLeaf { - type Commitment = MerkleNode; -} -impl ConsensusMerkleCommit for PublicRightsLeaf { - const MERKLE_NODE_PREFIX: &'static str = "public_right"; -} -impl ToMerkleSource for PublicRights { - type Leaf = PublicRightsLeaf; - - fn to_merkle_source(&self) -> MerkleSource { - self.as_inner() - .iter() - .copied() - .map(PublicRightsLeaf) - .collect() - } -} -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, StrictEncode, StrictDecode)] +#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] pub struct OwnedRightsLeaf(pub schema::OwnedRightType, pub MerkleNode); -impl commit_encode::Strategy for OwnedRightsLeaf { - type Strategy = commit_encode::strategies::UsingStrict; -} -impl ConsensusCommit for OwnedRightsLeaf { - type Commitment = MerkleNode; -} -impl ConsensusMerkleCommit for OwnedRightsLeaf { - const MERKLE_NODE_PREFIX: &'static str = "owned_right"; -} -impl ToMerkleSource for OwnedRights { - type Leaf = OwnedRightsLeaf; - - fn to_merkle_source(&self) -> MerkleSource { - self.as_inner() - .iter() - .flat_map(|(type_id, assignment)| { - assignment - .consensus_commitments() - .into_iter() - .map(move |commitment| OwnedRightsLeaf(*type_id, commitment)) - }) - .collect() - } -} -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, StrictEncode, StrictDecode)] +#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] pub struct ParentPublicRightsLeaf(pub NodeId, pub schema::PublicRightType); -impl commit_encode::Strategy for ParentPublicRightsLeaf { - type Strategy = commit_encode::strategies::UsingStrict; -} -impl ConsensusCommit for ParentPublicRightsLeaf { - type Commitment = MerkleNode; -} -impl ConsensusMerkleCommit for ParentPublicRightsLeaf { - const MERKLE_NODE_PREFIX: &'static str = "parent_public_right"; -} -impl ToMerkleSource for ParentPublicRights { - type Leaf = ParentPublicRightsLeaf; - - fn to_merkle_source(&self) -> MerkleSource { - self.as_inner() - .iter() - .flat_map(|(node_id, i)| { - i.iter() - .map(move |type_id| ParentPublicRightsLeaf(node_id.copy(), *type_id)) - }) - .collect() - } -} -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, StrictEncode, StrictDecode)] +#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] pub struct ParentOwnedRightsLeaf(pub NodeId, pub schema::OwnedRightType, pub u16); -impl commit_encode::Strategy for ParentOwnedRightsLeaf { - type Strategy = commit_encode::strategies::UsingStrict; -} -impl ConsensusCommit for ParentOwnedRightsLeaf { - type Commitment = MerkleNode; -} -impl ConsensusMerkleCommit for ParentOwnedRightsLeaf { - const MERKLE_NODE_PREFIX: &'static str = "parent_owned_right"; -} -impl ToMerkleSource for ParentOwnedRights { - type Leaf = ParentOwnedRightsLeaf; - - fn to_merkle_source(&self) -> MerkleSource { - self.as_inner() - .iter() - .flat_map(|(node_id, i)| { - i.iter().flat_map(move |(type_id, prev_outs)| { - prev_outs.iter().map(move |prev_out| { - ParentOwnedRightsLeaf(node_id.copy(), *type_id, *prev_out) - }) - }) - }) - .collect() - } -} diff --git a/src/contract/seal.rs b/src/contract/seal.rs index ce43e787..cccd2ec5 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -64,8 +64,6 @@ pub trait IntoRevealedSeal { derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "snake_case") )] -#[derive(StrictEncode, StrictDecode)] -#[strict_encoding(by_order)] pub enum SealEndpoint { /// External transaction output in concealed form (see /// [`seal::Confidential`]) diff --git a/src/contract/value.rs b/src/contract/value.rs index 382534d5..7ef13c36 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -32,7 +32,6 @@ use bitcoin_hashes::{sha256, Hash}; use commit_verify::{commit_encode, CommitConceal, CommitEncode, CommitVerify, CommitmentProtocol}; use secp256k1_zkp::rand::{Rng, RngCore}; use secp256k1_zkp::{PedersenCommitment, SECP256K1}; -use strict_encoding::{StrictDecode, StrictEncode}; use super::{ConfidentialState, RevealedState}; @@ -43,21 +42,7 @@ impl From for AtomicValue { } /// Proof for Pedersen commitment: a blinding key -#[derive( - Wrapper, - Copy, - Clone, - Ord, - PartialOrd, - Eq, - PartialEq, - Hash, - Debug, - Display, - From, - StrictEncode, - StrictDecode -)] +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -93,7 +78,6 @@ impl FromHex for BlindingFactor { } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, AsAny)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] #[display("{value}#{blinding}")] pub struct Revealed { @@ -208,6 +192,7 @@ pub struct Confidential { impl ConfidentialState for Confidential {} +/* impl StrictEncode for Confidential { fn strict_encode(&self, mut e: E) -> Result { let len = self.bulletproof.len() as u16; @@ -230,6 +215,7 @@ impl StrictDecode for Confidential { }) } } + */ impl CommitEncode for Confidential { fn commit_encode(&self, mut e: E) -> usize { diff --git a/src/lib.rs b/src/lib.rs index f46106ff..08c615a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,8 +25,8 @@ #[macro_use] extern crate amplify; -#[macro_use] -extern crate strict_encoding; +// #[macro_use] +// extern crate strict_encoding; #[cfg(feature = "serde")] #[macro_use] diff --git a/src/schema/nodes.rs b/src/schema/nodes.rs index ce84877b..05ba64a0 100644 --- a/src/schema/nodes.rs +++ b/src/schema/nodes.rs @@ -28,8 +28,6 @@ pub type OwnedRightsStructure = BTreeMap; derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "snake_case") )] -#[derive(StrictEncode, StrictDecode)] -#[strict_encoding(by_value)] #[repr(u8)] /// Node type: genesis, extensions and state transitions pub enum NodeType { @@ -77,7 +75,6 @@ pub trait NodeSchema { } #[derive(Clone, PartialEq, Debug, Default, AsAny)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct GenesisSchema { pub metadata: MetadataStructure, @@ -87,7 +84,6 @@ pub struct GenesisSchema { #[derive(Clone, PartialEq, Debug, Default, AsAny)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[derive(StrictEncode, StrictDecode)] pub struct ExtensionSchema { pub metadata: MetadataStructure, pub extends: PublicRightsStructure, @@ -97,7 +93,6 @@ pub struct ExtensionSchema { #[derive(Clone, PartialEq, Debug, Default, AsAny)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[derive(StrictEncode, StrictDecode)] pub struct TransitionSchema { pub metadata: MetadataStructure, pub closes: OwnedRightsStructure, diff --git a/src/schema/occurrences.rs b/src/schema/occurrences.rs index 603c1db1..1f4b420c 100644 --- a/src/schema/occurrences.rs +++ b/src/schema/occurrences.rs @@ -73,7 +73,7 @@ impl Occurrences { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Display, StrictEncode, StrictDecode)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] #[display(Debug)] pub struct OccurrencesError { @@ -82,48 +82,6 @@ pub struct OccurrencesError { pub found: u16, } -mod _strict_encoding { - use std::io; - - use strict_encoding::{Error, StrictDecode, StrictEncode}; - - use super::*; - - impl StrictEncode for Occurrences { - fn strict_encode(&self, mut e: E) -> Result { - let (min, max) = match self { - Occurrences::NoneOrOnce => (0, 1), - Occurrences::Once => (1, 1), - Occurrences::NoneOrMore => (0, core::u16::MAX), - Occurrences::OnceOrMore => (1, core::u16::MAX), - Occurrences::NoneOrUpTo(max) => (0, *max), - Occurrences::OnceOrUpTo(max) => (1, *max), - Occurrences::Exactly(val) => (*val, *val), - Occurrences::Range(range) => (*range.start(), *range.end()), - }; - Ok(min.strict_encode(&mut e)? + max.strict_encode(&mut e)?) - } - } - - impl StrictDecode for Occurrences { - #[allow(unused_comparisons)] - fn strict_decode(mut d: D) -> Result { - let min = u16::strict_decode(&mut d)?; - let max = u16::strict_decode(&mut d)?; - Ok(match (min, max) { - (0, 1) => Occurrences::NoneOrOnce, - (1, 1) => Occurrences::Once, - (0, max) if max == ::core::u16::MAX => Occurrences::NoneOrMore, - (1, max) if max == ::core::u16::MAX => Occurrences::OnceOrMore, - (0, max) if max > 0 => Occurrences::NoneOrUpTo(max), - (1, max) if max > 0 => Occurrences::OnceOrUpTo(max), - (min, max) if min == max => Occurrences::Exactly(min), - (min, max) => Occurrences::Range(min..=max), - }) - } - } -} - #[cfg(test)] mod test { use strict_encoding::StrictDecode; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index bf558fcd..077ed37d 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -13,7 +13,7 @@ use std::collections::{BTreeMap, BTreeSet}; use amplify::flags::FlagVec; use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::{commit_encode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash}; +use commit_verify::{CommitVerify, PrehashedProtocol, TaggedHash}; use super::{ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, TransitionSchema}; use crate::schema::StateSchema; @@ -44,7 +44,6 @@ impl sha256t::Tag for SchemaIdTag { /// Commitment-based schema identifier used for committing to the schema type #[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[derive(StrictEncode, StrictDecode)] #[wrapper(Debug, BorrowSlice)] pub struct SchemaId(sha256t::Hash); @@ -56,7 +55,6 @@ where Msg: AsRef<[u8]> } #[derive(Clone, Debug)] -#[derive(StrictEncode, StrictDecode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Schema { /// Feature flags control which of the available RGB features are allowed @@ -97,13 +95,6 @@ impl Schema { pub fn schema_id(&self) -> SchemaId { self.clone().consensus_commit() } } -impl ConsensusCommit for Schema { - type Commitment = SchemaId; -} -impl commit_encode::Strategy for Schema { - type Strategy = commit_encode::strategies::UsingStrict; -} - impl PartialEq for Schema { fn eq(&self, other: &Self) -> bool { self.schema_id() == other.schema_id() } } diff --git a/src/schema/script.rs b/src/schema/script.rs index 36fe603e..40e1855c 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -14,8 +14,6 @@ //! Components related to the scripting system used by schema or applied at the //! specific contract node level -use commit_verify::commit_encode; - use crate::vm::alure; /// Virtual machine types. @@ -30,8 +28,6 @@ pub enum VmType { /// Virtual machine and machine-specific script data. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[derive(StrictEncode, StrictDecode)] -#[strict_encoding(by_value, repr = u8)] pub enum ValidationScript { /// AluVM: pure functional register-based virtual machine designed for RGB /// and multiparty computing. @@ -42,14 +38,9 @@ pub enum ValidationScript { /// /// Its routines can be accessed only through well-typed ABI entrance /// pointers, defined as a part of the schema. - #[strict_encoding(value = 0x00)] AluVM(alure::ValidationScript), } -impl commit_encode::Strategy for ValidationScript { - type Strategy = commit_encode::strategies::UsingStrict; -} - impl ValidationScript { pub fn vm_type(&self) -> VmType { match self { @@ -68,7 +59,6 @@ impl ValidationScript { derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "kebab-case") )] -#[derive(StrictEncode, StrictDecode)] #[repr(u8)] pub enum OverrideRules { #[display("deny")] diff --git a/src/schema/state.rs b/src/schema/state.rs index 1203a34a..a897d3be 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -10,8 +10,6 @@ // If not, see . #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] -#[derive(StrictEncode, StrictDecode)] -#[strict_encoding(by_value, repr = u8)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -26,8 +24,6 @@ pub enum StateType { } #[derive(Clone, PartialEq, Debug)] -#[derive(StrictEncode, StrictDecode)] -#[strict_encoding(by_order)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -41,8 +37,6 @@ pub enum StateSchema { } #[derive(Clone, PartialEq, Debug)] -#[derive(StrictEncode, StrictDecode)] -#[strict_encoding(by_value, repr = u8)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), diff --git a/src/stash/bundle.rs b/src/stash/bundle.rs index e45b8de7..2c3552c4 100644 --- a/src/stash/bundle.rs +++ b/src/stash/bundle.rs @@ -10,13 +10,9 @@ // If not, see . use std::collections::{btree_map, BTreeMap, BTreeSet}; -use std::io::{Read, Write}; use bitcoin_hashes::{sha256, sha256t, Hash}; -use commit_verify::{ - lnpbp4, CommitEncode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash, -}; -use strict_encoding::{StrictDecode, StrictEncode}; +use commit_verify::{lnpbp4, CommitVerify, PrehashedProtocol, TaggedHash}; use crate::{seal, ConcealSeals, ConcealState, Node, NodeId, RevealSeals, Transition}; @@ -44,7 +40,6 @@ impl sha256t::Tag for BundleIdTag { serde(crate = "serde_crate", transparent) )] #[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[derive(StrictEncode, StrictDecode)] #[wrapper(Debug, Display, BorrowSlice)] pub struct BundleId(sha256t::Hash); @@ -80,13 +75,13 @@ pub enum RevealError { pub struct NoDataError; #[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] -#[derive(StrictEncode)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct TransitionBundle { revealed: BTreeMap>, concealed: BTreeMap>, } +/* impl StrictDecode for TransitionBundle { fn strict_decode(mut d: D) -> Result { let bundle = strict_decode_self!(d; revealed, concealed); @@ -98,28 +93,7 @@ impl StrictDecode for TransitionBundle { Ok(bundle) } } - -impl CommitEncode for TransitionBundle { - fn commit_encode(&self, mut e: E) -> usize { - let mut concealed = self.clone(); - concealed.conceal_transitions(); - - let mut count = 0usize; - for (node_id, inputs) in concealed.concealed { - count += node_id - .strict_encode(&mut e) - .expect("memory encoders do not fail"); - count += inputs - .strict_encode(&mut e) - .expect("memory encoders do not fail"); - } - count - } -} - -impl ConsensusCommit for TransitionBundle { - type Commitment = BundleId; -} + */ impl ConcealTransitions for TransitionBundle { fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize { diff --git a/src/temp.rs b/src/temp.rs index 42770fd1..904ff885 100644 --- a/src/temp.rs +++ b/src/temp.rs @@ -38,8 +38,6 @@ pub trait ResolveTx { // TODO: Change values according to the standard #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[derive(StrictEncode, StrictDecode)] -#[strict_encoding(by_value, repr = u32)] #[repr(u32)] pub enum Chain { #[default] From 2f00c9e7f763c3e945f678f6020a3929698327f1 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 19:31:25 +0100 Subject: [PATCH 17/71] refactor: wip on update to v0.10 of upstream crates --- Cargo.lock | 322 +++++++++++++++++------------------- Cargo.toml | 36 +--- src/contract/assignments.rs | 2 +- src/contract/attachment.rs | 4 +- src/contract/data.rs | 2 +- src/contract/nodes.rs | 8 +- src/contract/reveal.rs | 1 - src/contract/seal.rs | 5 +- src/contract/value.rs | 4 +- src/schema/schema.rs | 6 +- src/schema/state.rs | 1 - src/stash/anchor.rs | 12 +- src/stash/bundle.rs | 13 +- src/stash/consignment.rs | 6 +- src/stash/graph.rs | 4 +- src/stash/stash.rs | 8 +- src/temp.rs | 4 +- src/validation.rs | 14 +- src/vm/embedded.rs | 4 +- 19 files changed, 208 insertions(+), 248 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a06bacf..874ae141 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,15 +8,9 @@ version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "116019a174e912931d5b19ca7ab6a22596d12cdb1320358fad3368f0aba135a9" dependencies = [ - "amplify_apfloat", "amplify_derive 2.11.3", "amplify_num 0.4.1", "amplify_syn 1.1.6", - "serde", - "serde_json", - "serde_yaml 0.8.26", - "stringly_conversions", - "toml", ] [[package]] @@ -32,7 +26,7 @@ dependencies = [ "ascii", "serde", "serde_json", - "serde_yaml 0.9.17", + "serde_yaml", "stringly_conversions", "toml", "wasm-bindgen", @@ -40,11 +34,11 @@ dependencies = [ [[package]] name = "amplify_apfloat" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6641206decd3c43f5456a3506e77fc9ab8b4996c3e0c19573ae2bcc2e00bf0" +checksum = "a958199f6993a34e74b9d22b22709e5c6e527e901d7083b24f0a532445dbfc84" dependencies = [ - "amplify_num 0.4.1", + "amplify_num 0.5.0", "bitflags", ] @@ -77,9 +71,6 @@ name = "amplify_num" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27d3d00d3d115395a7a8a4dc045feb7aa82b641e485f7e15f4e67ac16f4f56d" -dependencies = [ - "serde", -] [[package]] name = "amplify_num" @@ -121,6 +112,18 @@ dependencies = [ "libc", ] +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "ascii" version = "1.1.0" @@ -136,6 +139,23 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "baid58" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16db9f8a10cac6c74b78f8922bfb4b3eb5bbbed4734fb9fa8218af32b5e381f4" +dependencies = [ + "base58", + "blake3", + "mnemonic", +] + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + [[package]] name = "bech32" version = "0.9.1" @@ -151,7 +171,6 @@ dependencies = [ "bech32", "bitcoin_hashes", "secp256k1 0.24.3", - "serde", ] [[package]] @@ -164,83 +183,62 @@ dependencies = [ ] [[package]] -name = "bitcoin_hd" -version = "0.9.0" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae39db6b04c44c76c50b8f8dd09799adb71ae7807a1de2efe3d127169c04160" -dependencies = [ - "amplify 3.13.0", - "bitcoin", - "secp256k1 0.24.3", - "slip132", - "strict_encoding 0.9.0", -] +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bitcoin_onchain" -version = "0.9.0" +name = "blake3" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4a6744365c862b8c74cb33a21532f91f1f32f4082361fd3aab5d22c1afd482" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" dependencies = [ - "amplify 3.13.0", - "bitcoin", - "bitcoin_hd", - "chrono", - "strict_encoding 0.9.0", + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest", ] [[package]] -name = "bitcoin_scripts" -version = "0.9.0" +name = "block-buffer" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8b08389e5391cf8311fd4de09a340ed98b4b7c2f87c956125c22341b5d14fb" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "amplify 3.13.0", - "bitcoin", - "secp256k1 0.24.3", - "serde", - "serde_with", - "stability", - "strict_encoding 0.9.0", + "generic-array", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bp-core" -version = "0.9.0" +version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42196466c9978cce3e24a0aba98497827755df3fdae3d55a743e8cf378cf5155" +checksum = "75939aecb6e7ad3e30622d8fba00ccdf3cdc78f2325840629ee53cd792548be9" dependencies = [ - "amplify 3.13.0", - "bitcoin", + "amplify 4.0.0-beta.11", "bp-dbc", + "bp-primitives", "bp-seals", - "commit_verify 0.9.0", + "commit_verify", "serde", - "serde_with", "single_use_seals", - "strict_encoding 0.9.0", + "strict_encoding 2.0.0-beta.5", ] [[package]] name = "bp-dbc" -version = "0.9.0" +version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ada76cb0b56cd87810adc5df0cc577d6ba048655a0898a241b0839f45a222d" +checksum = "2d67f8173cc60f6671df19a170021a4f3a179f828b2114ba0415124dd8abd07f" dependencies = [ - "amplify 3.13.0", - "bitcoin", - "bitcoin_scripts", - "commit_verify 0.9.0", - "secp256k1 0.24.3", + "amplify 4.0.0-beta.11", + "bp-primitives", + "commit_verify", + "secp256k1 0.26.0", "serde", - "serde_with", - "strict_encoding 0.9.0", + "strict_encoding 2.0.0-beta.5", ] [[package]] @@ -250,7 +248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aab03dbc8e2cf19594d3a267cccfc0fd2595ce0818babf39b9e817cb7683e1e4" dependencies = [ "amplify 4.0.0-beta.11", - "commit_verify 0.10.0-beta.2", + "commit_verify", "secp256k1 0.26.0", "serde", "strict_encoding 2.0.0-beta.5", @@ -258,20 +256,18 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.9.0" +version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73bb2e2050af42af6c0ce1cd58b5e2f3b13d5105effc5a5dd1339551c4ed11ec" +checksum = "463f314e2c6370104c40356fc96cd464bd0f02aba1a2ffd83dc524e4ecf58d41" dependencies = [ - "amplify 3.13.0", - "bitcoin", - "bitcoin_onchain", + "amplify 4.0.0-beta.11", + "baid58", "bp-dbc", - "commit_verify 0.9.0", - "lnpbp_bech32", - "serde", - "serde_with", + "bp-primitives", + "commit_verify", + "rand", "single_use_seals", - "strict_encoding 0.9.0", + "strict_encoding 2.0.0-beta.5", ] [[package]] @@ -280,6 +276,12 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cc" version = "1.0.79" @@ -319,29 +321,22 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.9.0" +version = "0.10.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f422e4e3f14f628b3cc3a241c0ea53b6457d100dda2980e2d7e719f1e41cf7" +checksum = "f7ce27ce9d56cac2631f9701984dc4fd162abbd7b563d97e4440db56f7282cc9" dependencies = [ - "amplify 3.13.0", + "amplify 4.0.0-beta.11", "bitcoin_hashes", - "lnpbp_secp256k1zkp", "rand", "serde", - "serde_with", - "strict_encoding 0.9.0", + "strict_encoding 2.0.0-beta.5", ] [[package]] -name = "commit_verify" -version = "0.10.0-beta.2" +name = "constant_time_eq" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ce27ce9d56cac2631f9701984dc4fd162abbd7b563d97e4440db56f7282cc9" -dependencies = [ - "amplify 4.0.0-beta.11", - "bitcoin_hashes", - "strict_encoding 2.0.0-beta.5", -] +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" [[package]] name = "core-foundation-sys" @@ -349,6 +344,16 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "cxx" version = "1.0.89" @@ -428,6 +433,17 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "encoding_derive_helpers" version = "0.8.1" @@ -446,6 +462,16 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -530,6 +556,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.139" @@ -546,42 +578,22 @@ dependencies = [ ] [[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "lnpbp_bech32" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecdbd10fe8d9d53febf413b4f8bbaa1911492597b19bfbb84a598f37062eab96" -dependencies = [ - "amplify 3.13.0", - "bech32", - "bitcoin_hashes", - "serde", - "serde_with", - "strict_encoding 0.9.0", -] - -[[package]] -name = "lnpbp_secp256k1zkp" -version = "0.9.0" +name = "log" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64bd22bb15baf79b5ab2711d08650ea20ac08bb2a55a42c91dfc1db4d350ea55" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cc", - "libc", + "cfg-if", ] [[package]] -name = "log" -version = "0.4.17" +name = "mnemonic" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "29fae0e4c0b155d3b019a7cbc27abe4a90e15c06814d27889ce9f5f44e2faf77" dependencies = [ - "cfg-if", + "byteorder", + "lazy_static", ] [[package]] @@ -671,13 +683,12 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.9.0" +version = "0.10.0-alpha.1" dependencies = [ - "amplify 3.13.0", + "amplify 4.0.0-beta.11", "bitcoin_hashes", "bp-core", - "bp-primitives", - "commit_verify 0.9.0", + "commit_verify", "once_cell", "secp256k1-zkp", "serde", @@ -707,7 +718,6 @@ dependencies = [ "bitcoin_hashes", "rand", "secp256k1-sys 0.6.1", - "serde", ] [[package]] @@ -716,6 +726,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" dependencies = [ + "rand", "secp256k1-sys 0.8.0", "serde", ] @@ -824,18 +835,6 @@ dependencies = [ "syn", ] -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap", - "ryu", - "serde", - "yaml-rust", -] - [[package]] name = "serde_yaml" version = "0.9.17" @@ -851,31 +850,11 @@ dependencies = [ [[package]] name = "single_use_seals" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e092f1d5411486816ec67cd7d0280acb0e05a1bd509721bc3dde3b1ffa5bfa0e" -dependencies = [ - "amplify_derive 2.11.3", -] - -[[package]] -name = "slip132" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a2947cb179006a73896fca01015ee5255c05b8b83e74c5e9d623ed4480abe2" -dependencies = [ - "amplify 3.13.0", - "bitcoin", -] - -[[package]] -name = "stability" -version = "0.1.1" +version = "0.10.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd1b177894da2a2d9120208c3386066af06a488255caabc5de8ddca22dbc3ce" +checksum = "2ea7651417b98128263b5c3d2dc836400eecd7f4fba8470d4ca17f129f9a1b4a" dependencies = [ - "quote", - "syn", + "amplify_derive 4.0.0-alpha.5", ] [[package]] @@ -952,6 +931,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.107" @@ -992,6 +977,12 @@ dependencies = [ "serde", ] +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + [[package]] name = "unicode-ident" version = "1.0.6" @@ -1010,6 +1001,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -1106,12 +1103,3 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] diff --git a/Cargo.toml b/Cargo.toml index 883c7b00..15769e86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rgb-core" -version = "0.9.0" +version = "0.10.0-alpha.1" license = "MIT" authors = ["Dr Maxim Orlovsky "] description = "RGB Core Library: consensus & verification for private & scalable client-validated smart contracts on Bitcoin & Lightning" @@ -17,37 +17,13 @@ exclude = [".github", "contrib"] name = "rgb" path = "src/lib.rs" -# Dependencies -# ============ -# -# Version policy -# -------------- -# The policy in specifying dependencies versions are to use tilde requirements -# according to -# -# with full semver version specification (major, minor and patch components) -# which means that we may upgrade for patches/bugfixes, but must not change -# even the minor version of the package. -# Once the library is stable consider upgrading tilde requirements to strict -# equivalence requirements (with '=' sign) since even dependencies patching will -# not introduce risk of breaking the consensus and even security updates must -# be done manually after through testing [dependencies] -# Dependencies on other LNP/BP repositories -# ----------------------------------------- -amplify = { version = "~3.13.0", features = ["apfloat"] } -bp-core = { version = "~0.9.0" } -commit_verify = { version = "~0.9.0", features = ["rand", "bulletproofs"] } +amplify = { version = "~4.0.0-beta.11", features = ["apfloat"] } +bp-core = { version = "~0.10.0-beta.1" } +commit_verify = { version = "~0.10.0-beta.2", features = ["rand"] } bitcoin_hashes = "0.11.0" -bp-primitives = "0.10.0-beta.1" -# Core rust projects -# ------------------ -# This strange naming is a workaround for cargo inability to define required -# features for a dependency. See -# for the explanation -# and references. serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } -serde_with = { version = "1.14", features = ["hex"], optional = true } +serde_with = { version = "1.14", features = ["hex"], optional = true } # TODO: Remove serde_json = "1" # TODO: Remove once_cell = "1.12.0" secp256k1-zkp = { version = "0.7.0", features = ["rand-std", "global-context"] } @@ -62,4 +38,4 @@ all = ["serde"] serde = ["serde_crate", "serde_with", "amplify/serde", "commit_verify/serde", "bp-core/serde", - "secp256k1-zkp/serde", "bp-primitives/serde"] + "secp256k1-zkp/serde"] diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 2286e732..d394144a 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -17,7 +17,7 @@ use std::io; use amplify::AsAny; use commit_verify::merkle::MerkleNode; -use commit_verify::{CommitConceal, CommitEncode, ConsensusCommit}; +use commit_verify::CommitEncode; use once_cell::sync::Lazy; use super::{data, seal, value, ConcealSeals, ConcealState, NoDataError, SealEndpoint}; diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index d62c2dc4..cb20c8ff 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -10,7 +10,7 @@ // If not, see . use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::{commit_encode, CommitConceal, CommitVerify, PrehashedProtocol, TaggedHash}; +use commit_verify::{CommitVerify, UntaggedProtocol}; use crate::{ConfidentialState, RevealedState}; @@ -46,7 +46,7 @@ impl sha256t::Tag for AttachmentIdTag { #[wrapper(Debug, Display, BorrowSlice)] pub struct AttachmentId(sha256t::Hash); -impl CommitVerify for AttachmentId +impl CommitVerify for AttachmentId where Msg: AsRef<[u8]> { #[inline] diff --git a/src/contract/data.rs b/src/contract/data.rs index 79f2868b..18b6e694 100644 --- a/src/contract/data.rs +++ b/src/contract/data.rs @@ -17,7 +17,7 @@ use std::io; use amplify::AsAny; use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::{commit_encode, CommitConceal, CommitEncode, TaggedHash}; +use commit_verify::CommitEncode; use super::{ConfidentialState, RevealedState}; diff --git a/src/contract/nodes.rs b/src/contract/nodes.rs index fad7a0f3..b1c33b36 100644 --- a/src/contract/nodes.rs +++ b/src/contract/nodes.rs @@ -14,11 +14,11 @@ use std::num::ParseIntError; use std::str::FromStr; use amplify::{AsAny, Wrapper}; -use bc::{Outpoint, Txid}; use bitcoin_hashes::{sha256, sha256t, Hash}; use bp::seals::txout::TxoSeal; -use commit_verify::lnpbp4::ProtocolId; -use commit_verify::{commit_encode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash}; +use bp::{Outpoint, Txid}; +use commit_verify::mpc::ProtocolId; +use commit_verify::{CommitVerify, UntaggedProtocol}; use once_cell::sync::Lazy; use super::{ @@ -111,7 +111,7 @@ impl NodeOutpoint { #[wrapper(Debug, Display, BorrowSlice)] pub struct NodeId(sha256t::Hash); -impl CommitVerify for NodeId +impl CommitVerify for NodeId where Msg: AsRef<[u8]> { #[inline] diff --git a/src/contract/reveal.rs b/src/contract/reveal.rs index 8edd3baa..3f40e8be 100644 --- a/src/contract/reveal.rs +++ b/src/contract/reveal.rs @@ -13,7 +13,6 @@ use std::collections::BTreeMap; use amplify::Wrapper; use bp::dbc; -use commit_verify::{CommitConceal, CommitEncode, ToMerkleSource}; use super::OwnedRightsInner; use crate::schema::NodeType; diff --git a/src/contract/seal.rs b/src/contract/seal.rs index cccd2ec5..e7f30884 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -39,7 +39,6 @@ use std::str::FromStr; use bp::seals::txout::blind::{ConcealedSeal, ParseError, RevealedSeal}; pub use bp::seals::txout::blind::{ConcealedSeal as Confidential, RevealedSeal as Revealed}; use bp::seals::txout::CloseMethod; -use commit_verify::CommitConceal; use secp256k1_zkp::rand::RngCore; /// Trait for types supporting conversion to a [`RevealedSeal`] @@ -153,9 +152,9 @@ impl FromStr for SealEndpoint { mod test { use std::convert::TryFrom; - use bc::{Outpoint, Txid}; use bitcoin_hashes::hex::FromHex; use bp::seals::txout::TxoSeal; + use bp::{Outpoint, Txid}; use commit_verify::CommitEncode; use secp256k1_zkp::rand::{thread_rng, RngCore}; use strict_encoding::{StrictDecode, StrictEncode}; @@ -268,7 +267,7 @@ mod test { fn test_witness_to_outpoint() { // Conversion to Outpoint from WitnessVout variant should panic let revealed = Revealed::strict_decode(&REVEALED_WITNESSVOUT[..]).unwrap(); - bc::Outpoint::try_from(revealed).unwrap(); + bp::Outpoint::try_from(revealed).unwrap(); } #[test] diff --git a/src/contract/value.rs b/src/contract/value.rs index 7ef13c36..45ee447a 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -26,10 +26,10 @@ use std::str::FromStr; // We do not import particular modules to keep aware with namespace prefixes // that we do not use the standard secp256k1zkp library use amplify::hex::{Error, FromHex}; -use amplify::{Slice32, Wrapper}; +use amplify::Wrapper; use bitcoin_hashes::sha256::Midstate; use bitcoin_hashes::{sha256, Hash}; -use commit_verify::{commit_encode, CommitConceal, CommitEncode, CommitVerify, CommitmentProtocol}; +use commit_verify::{CommitEncode, CommitVerify, CommitmentProtocol}; use secp256k1_zkp::rand::{Rng, RngCore}; use secp256k1_zkp::{PedersenCommitment, SECP256K1}; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 077ed37d..4817c270 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -13,7 +13,7 @@ use std::collections::{BTreeMap, BTreeSet}; use amplify::flags::FlagVec; use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::{CommitVerify, PrehashedProtocol, TaggedHash}; +use commit_verify::CommitVerify; use super::{ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, TransitionSchema}; use crate::schema::StateSchema; @@ -47,7 +47,7 @@ impl sha256t::Tag for SchemaIdTag { #[wrapper(Debug, BorrowSlice)] pub struct SchemaId(sha256t::Hash); -impl CommitVerify for SchemaId +impl CommitVerify for SchemaId where Msg: AsRef<[u8]> { #[inline] @@ -105,8 +105,6 @@ impl Eq for Schema {} mod _validation { use std::collections::BTreeSet; - use commit_verify::CommitConceal; - use super::*; use crate::schema::{ MetadataStructure, OwnedRightsStructure, PublicRightsStructure, SchemaVerify, diff --git a/src/schema/state.rs b/src/schema/state.rs index a897d3be..cebea2ed 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -58,7 +58,6 @@ mod _validation { use core::any::Any; use amplify::AsAny; - use commit_verify::CommitConceal; use super::*; use crate::contract::AttachmentStrategy; diff --git a/src/stash/anchor.rs b/src/stash/anchor.rs index 592362ed..d1bbc3d8 100644 --- a/src/stash/anchor.rs +++ b/src/stash/anchor.rs @@ -10,7 +10,7 @@ // If not, see . use bp::dbc::Anchor; -use commit_verify::lnpbp4; +use commit_verify::mpc; use crate::{reveal, ContractId, MergeReveal}; @@ -18,25 +18,25 @@ pub trait ConcealAnchors { fn conceal_anchors_except( &mut self, contracts: impl AsRef<[ContractId]>, - ) -> Result; + ) -> Result; } -impl ConcealAnchors for Anchor { +impl ConcealAnchors for Anchor { fn conceal_anchors_except( &mut self, contracts: impl AsRef<[ContractId]>, - ) -> Result { + ) -> Result { let protocols = contracts .as_ref() .iter() .copied() - .map(lnpbp4::ProtocolId::from) + .map(mpc::ProtocolId::from) .collect::>(); self.conceal_except(protocols) } } -impl MergeReveal for Anchor { +impl MergeReveal for Anchor { fn merge_reveal(self, other: Self) -> Result { self.merge_reveal(other).map_err(reveal::Error::from) } diff --git a/src/stash/bundle.rs b/src/stash/bundle.rs index 2c3552c4..3d3fa193 100644 --- a/src/stash/bundle.rs +++ b/src/stash/bundle.rs @@ -11,8 +11,9 @@ use std::collections::{btree_map, BTreeMap, BTreeSet}; +use amplify::Wrapper; use bitcoin_hashes::{sha256, sha256t, Hash}; -use commit_verify::{lnpbp4, CommitVerify, PrehashedProtocol, TaggedHash}; +use commit_verify::{mpc, CommitVerify, UntaggedProtocol}; use crate::{seal, ConcealSeals, ConcealState, Node, NodeId, RevealSeals, Transition}; @@ -43,7 +44,7 @@ impl sha256t::Tag for BundleIdTag { #[wrapper(Debug, Display, BorrowSlice)] pub struct BundleId(sha256t::Hash); -impl CommitVerify for BundleId +impl CommitVerify for BundleId where Msg: AsRef<[u8]> { #[inline] @@ -55,12 +56,12 @@ pub trait ConcealTransitions { fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize; } -impl From for lnpbp4::Message { - fn from(id: BundleId) -> Self { lnpbp4::Message::from_inner(id.into_inner()) } +impl From for mpc::Message { + fn from(id: BundleId) -> Self { mpc::Message::from_inner(id.into_inner()) } } -impl From for BundleId { - fn from(id: lnpbp4::Message) -> Self { BundleId(sha256t::Hash::from_inner(id.into_inner())) } +impl From for BundleId { + fn from(id: mpc::Message) -> Self { BundleId(sha256t::Hash::from_inner(id.into_inner())) } } #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error)] diff --git a/src/stash/consignment.rs b/src/stash/consignment.rs index 6b95dc37..4e14f7e3 100644 --- a/src/stash/consignment.rs +++ b/src/stash/consignment.rs @@ -11,7 +11,7 @@ use std::collections::BTreeSet; -use commit_verify::lnpbp4; +use commit_verify::mpc; use crate::{ Anchor, BundleId, Extension, Genesis, GraphApi, NodeId, Schema, SealEndpoint, TransitionBundle, @@ -19,11 +19,11 @@ use crate::{ pub type ConsignmentEndpoint = (BundleId, SealEndpoint); -pub type AnchoredBundle<'me> = (&'me Anchor, &'me TransitionBundle); +pub type AnchoredBundle<'me> = (&'me Anchor, &'me TransitionBundle); pub trait Consignment<'consignment>: 'consignment + GraphApi { type EndpointIter: Iterator; - type BundleIter: Iterator, TransitionBundle)>; + type BundleIter: Iterator, TransitionBundle)>; type ExtensionsIter: Iterator; fn schema(&'consignment self) -> &'consignment Schema; diff --git a/src/stash/graph.rs b/src/stash/graph.rs index ebc2fb21..562de42d 100644 --- a/src/stash/graph.rs +++ b/src/stash/graph.rs @@ -24,8 +24,8 @@ use std::collections::BTreeSet; -use bc::{Outpoint, Txid}; use bp::dbc::AnchorId; +use bp::{Outpoint, Txid}; use crate::schema::OwnedRightType; use crate::{BundleId, Extension, Node, NodeId, NodeOutpoint, Transition, TransitionBundle}; @@ -135,7 +135,7 @@ pub trait GraphApi { /// the closed seals. If seals are present, but have a different type, a /// error is returned /// - `witness`: witness transaction id, needed for generating full - /// [`bc::Outpoint`] data for single-use-seal definitions providing + /// [`bp::Outpoint`] data for single-use-seal definitions providing /// relative seals to the witness transaction (see [crate::seal::Revealed] /// for the details). /// diff --git a/src/stash/stash.rs b/src/stash/stash.rs index b56782b9..a49f890e 100644 --- a/src/stash/stash.rs +++ b/src/stash/stash.rs @@ -23,9 +23,9 @@ //! NB: Stash implementations must be able to operate multiple independent RGB //! contract. -use bc::Outpoint; use bp::dbc::{Anchor, AnchorId}; -use commit_verify::lnpbp4; +use bp::Outpoint; +use commit_verify::mpc; use crate::temp::ResolveTx; use crate::{ContractId, Extension, Genesis, NodeId, Schema, SchemaId, Transition}; @@ -49,7 +49,7 @@ pub trait Stash { /// Iterator implementation able to run over all contract geneses type GenesisIterator: Iterator; /// Iterator implementation able to run over all known anchors - type AnchorIterator: Iterator>; + type AnchorIterator: Iterator>; /// Iterator implementation able to run over all state transitions under /// particular contract type TransitionIterator: Iterator; @@ -91,7 +91,7 @@ pub trait Stash { /// contracts to which this anchor is related to may be known from the /// anchor data, unless they are kept in the confidential form. See /// [`Anchor`] documentation for the details. - fn get_anchor(&self, anchor_id: AnchorId) -> Result, Self::Error>; + fn get_anchor(&self, anchor_id: AnchorId) -> Result, Self::Error>; /// Iterator over all contract geneses (i.e. iterator over all known RGB /// contracts). diff --git a/src/temp.rs b/src/temp.rs index 904ff885..2be57bba 100644 --- a/src/temp.rs +++ b/src/temp.rs @@ -1,6 +1,6 @@ //! Temporary module for refactoring period -use bc::{Tx, Txid}; +use bp::{Tx, Txid}; #[macro_export] macro_rules! txid { @@ -12,7 +12,7 @@ macro_rules! txid { #[macro_export] macro_rules! outpoint { ($old:expr) => { - bc::Outpoint { + bp::Outpoint { txid: txid!($old.txid), vout: $old.vout.into(), } diff --git a/src/validation.rs b/src/validation.rs index 5747e687..29907ef3 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -13,10 +13,10 @@ use core::iter::FromIterator; use core::ops::AddAssign; use std::collections::{BTreeMap, BTreeSet, VecDeque}; -use bc::{Tx, Txid}; use bp::dbc::Anchor; use bp::seals::txout::TxoSeal; -use commit_verify::{lnpbp4, CommitConceal}; +use bp::{Tx, Txid}; +use commit_verify::mpc; use super::schema::{NodeType, OccurrencesError}; use super::{schema, seal, ContractId, Node, NodeId, Schema, SchemaId, TypedAssignments}; @@ -207,7 +207,7 @@ pub enum Failure { ancestor_id: NodeId, assignment_type: schema::OwnedRightType, seal_index: u16, - outpoint: bc::Outpoint, + outpoint: bp::Outpoint, }, ExtensionAbsent(NodeId), @@ -261,7 +261,7 @@ pub struct Validator<'consignment, 'resolver, C: Consignment<'consignment>, R: R genesis_id: NodeId, contract_id: ContractId, node_index: BTreeMap, - anchor_index: BTreeMap>, + anchor_index: BTreeMap>, end_transitions: Vec<(&'consignment dyn Node, BundleId)>, validation_index: BTreeSet, anchor_validation_index: BTreeSet, @@ -284,7 +284,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Create indexes let mut node_index = BTreeMap::::new(); - let mut anchor_index = BTreeMap::>::new(); + let mut anchor_index = BTreeMap::>::new(); for (anchor, bundle) in consignment.anchored_bundles() { if !TransitionBundle::validate(bundle) { status.add_failure(Failure::BundleInvalid(bundle.bundle_id())); @@ -565,7 +565,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> &mut self, node: &'consignment dyn Node, bundle_id: BundleId, - anchor: &'consignment Anchor, + anchor: &'consignment Anchor, ) { let txid = txid!(anchor.txid); let node_id = node.node_id(); @@ -712,7 +712,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> None, ) => { // We are at genesis, so the outpoint must contain tx - Some(bc::Outpoint::new(txid!(txid), vout)) + Some(bp::Outpoint::new(txid!(txid), vout)) } (Ok(Some(_)), None) => { // This can't happen, since if we have a node in the index diff --git a/src/vm/embedded.rs b/src/vm/embedded.rs index 1ff5c524..2128749c 100644 --- a/src/vm/embedded.rs +++ b/src/vm/embedded.rs @@ -63,7 +63,7 @@ pub mod constants { pub const FIELD_TYPE_BURN_SUPPLY: u16 = 0xB0; /// [`FieldType`] that is used by validation procedures checking proofs of - /// burn. Must contain [`bc::Outpoint`] consensus-encoded data. + /// burn. Must contain [`bp::Outpoint`] consensus-encoded data. pub const FIELD_TYPE_BURN_UTXO: u16 = 0xB1; /// [`FieldType`] that is used by validation procedures checking proofs of @@ -81,7 +81,7 @@ pub mod constants { pub const FIELD_TYPE_LOCK_DESCRIPTOR: u16 = 0xC0; /// [`FieldType`] that is used by validation procedures checking proofs of - /// reserves. Must contain [`bc::Outpoint`] consensus-encoded data + /// reserves. Must contain [`bp::Outpoint`] consensus-encoded data pub const FIELD_TYPE_LOCK_UTXO: u16 = 0xC1; /// Description of the asset From d74745d1b4d7b809af350c53edee9311794c69bc Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 19:48:01 +0100 Subject: [PATCH 18/71] refactor: (!) dissect all valdation into dedicated mod. Disable all mods --- src/lib.rs | 27 +- src/schema/mod.rs | 5 - src/schema/nodes.rs | 297 -------- src/schema/schema.rs | 739 +----------------- src/schema/script.rs | 4 +- src/schema/state.rs | 322 -------- src/validation/mod.rs | 244 ++++++ src/validation/schema.rs | 797 ++++++++++++++++++++ src/{validation.rs => validation/verify.rs} | 229 +----- 9 files changed, 1059 insertions(+), 1605 deletions(-) create mode 100644 src/validation/mod.rs create mode 100644 src/validation/schema.rs rename src/{validation.rs => validation/verify.rs} (75%) diff --git a/src/lib.rs b/src/lib.rs index 08c615a3..3d9d7b41 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,19 +34,20 @@ extern crate serde_with; #[cfg(feature = "serde")] extern crate serde_crate as serde; -pub(crate) mod temp; +// pub(crate) mod temp; -pub mod contract; +// pub mod contract; pub mod schema; -pub mod stash; -pub mod validation; -pub mod vm; -#[macro_use] -mod macros; +// pub mod stash; +// pub mod verify; +// pub mod validation; +// pub mod vm; +// #[macro_use] +// mod macros; pub mod prelude { pub use bp::dbc::{Anchor, AnchorId}; - pub use contract::{ + /*pub use contract::{ data, reveal, seal, value, Assignment, AtomicValue, AttachmentId, AttachmentStrategy, Bulletproofs, ConcealSeals, ConcealState, ConfidentialDataError, ConfidentialState, ContractId, DeclarativeStrategy, EndpointValueMap, Extension, Genesis, HashStrategy, @@ -54,20 +55,22 @@ pub mod prelude { OwnedRights, ParentOwnedRights, ParentPublicRights, PedersenStrategy, PublicRights, RevealSeals, RevealedState, SealEndpoint, SealValueMap, State, StateRetrievalError, StateType, Transition, TypedAssignments, - }; + };*/ pub use schema::{ script, ExtensionSchema, ExtensionType, NodeSubtype, NodeType, PublicRightType, PublicRightsStructure, Schema, SchemaId, ValidationScript, VmType, }; - pub use stash::{ + + pub use super::schema; + /*pub use stash::{ bundle, AnchoredBundle, BundleId, ConcealAnchors, ConcealTransitions, Consignment, ConsignmentEndpoint, ConsistencyError, GraphApi, Stash, TransitionBundle, }; pub use validation::{Validator, Validity}; pub use vm::Validate; - use super::*; - pub use super::{schema, vm}; + pub use super::{vm}; + use super::*;*/ } pub use prelude::*; diff --git a/src/schema/mod.rs b/src/schema/mod.rs index 2a18b674..df5e692d 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -24,8 +24,3 @@ pub use occurrences::{Occurrences, OccurrencesError}; pub use schema::{ExtensionType, FieldType, Schema, SchemaId, TransitionType}; pub use script::{ValidationScript, VmType}; pub use state::{DiscreteFiniteFieldFormat, StateSchema, StateType}; - -/// Trait used for internal schema validation against some root schema -pub trait SchemaVerify { - fn schema_verify(&self, root: &Self) -> crate::validation::Status; -} diff --git a/src/schema/nodes.rs b/src/schema/nodes.rs index 05ba64a0..8c1260d5 100644 --- a/src/schema/nodes.rs +++ b/src/schema/nodes.rs @@ -147,300 +147,3 @@ impl NodeSchema for TransitionSchema { #[inline] fn public_rights(&self) -> &PublicRightsStructure { &self.public_rights } } - -mod _verify { - use super::*; - use crate::schema::SchemaVerify; - use crate::validation; - - impl SchemaVerify for T - where T: NodeSchema - { - fn schema_verify(&self, root: &Self) -> validation::Status { - let mut status = validation::Status::new(); - let node_type = self.node_type(); - - for (field_type, occ) in self.metadata() { - match root.metadata().get(field_type) { - None => status.add_failure(validation::Failure::SchemaRootNoMetadataMatch( - node_type, - *field_type, - )), - Some(root_occ) if occ != root_occ => status.add_failure( - validation::Failure::SchemaRootNoMetadataMatch(node_type, *field_type), - ), - _ => &status, - }; - } - - for (assignments_type, occ) in self.closes() { - match root.closes().get(assignments_type) { - None => { - status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( - node_type, - *assignments_type, - )) - } - Some(root_occ) if occ != root_occ => { - status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( - node_type, - *assignments_type, - )) - } - _ => &status, - }; - } - - for (assignments_type, occ) in self.owned_rights() { - match root.owned_rights().get(assignments_type) { - None => status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( - node_type, - *assignments_type, - )), - Some(root_occ) if occ != root_occ => { - status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( - node_type, - *assignments_type, - )) - } - _ => &status, - }; - } - - for valencies_type in self.extends() { - if !root.extends().contains(valencies_type) { - status.add_failure(validation::Failure::SchemaRootNoParentPublicRightsMatch( - node_type, - *valencies_type, - )); - } - } - - for valencies_type in self.public_rights() { - if !root.public_rights().contains(valencies_type) { - status.add_failure(validation::Failure::SchemaRootNoPublicRightsMatch( - node_type, - *valencies_type, - )); - } - } - - status - } - } -} - -#[cfg(test)] -mod test { - use strict_encoding::StrictDecode; - use strict_encoding_test::test_vec_decoding_roundtrip; - - use super::*; - use crate::schema::SchemaVerify; - use crate::validation::Failure; - - static GENESIS_SCHEMA: [u8; 62] = [ - 4, 0, 1, 0, 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 3, 0, 1, 0, 13, 0, 4, 0, 0, 0, 17, 0, 4, 0, 1, 0, - 1, 0, 1, 0, 3, 0, 1, 0, 25, 0, 4, 0, 0, 0, 12, 0, 2, 1, 0, 0, 1, 0, 4, 0, 1, 0, 2, 0, 3, 0, - 4, 0, - ]; - - static TRANSITION_SCHEMA: [u8; 88] = [ - 4, 0, 1, 0, 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 3, 0, 1, 0, 13, 0, 4, 0, 0, 0, 17, 0, 4, 0, 1, 0, - 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 3, 0, 1, 0, 25, 0, 4, 0, 0, 0, 12, 0, 4, 0, 1, 0, 1, 0, 1, 0, - 2, 0, 0, 0, 1, 0, 3, 0, 1, 0, 25, 0, 4, 0, 0, 0, 12, 0, 4, 0, 1, 0, 2, 0, 3, 0, 4, 0, - ]; - - static EXTENSION_SCHEMA: [u8; 72] = [ - 4, 0, 1, 0, 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 3, 0, 1, 0, 13, 0, 4, 0, 0, 0, 17, 0, 4, 0, 1, 0, - 2, 0, 3, 0, 4, 0, 4, 0, 1, 0, 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 3, 0, 1, 0, 25, 0, 4, 0, 0, 0, - 12, 0, 4, 0, 1, 0, 2, 0, 3, 0, 4, 0, - ]; - - #[test] - fn test_genesis_schema_encoding() { - let _: GenesisSchema = test_vec_decoding_roundtrip(GENESIS_SCHEMA).unwrap(); - } - - #[test] - fn test_transition_schema_encoding() { - let _: TransitionSchema = test_vec_decoding_roundtrip(TRANSITION_SCHEMA).unwrap(); - } - - #[test] - fn test_extension_schema_encoding() { - let _: ExtensionSchema = test_vec_decoding_roundtrip(EXTENSION_SCHEMA).unwrap(); - } - - #[test] - fn test_node_for_genesis() { - let genesis_schema = GenesisSchema::strict_decode(&GENESIS_SCHEMA[..]).unwrap(); - - let mut valencies = PublicRightsStructure::new(); - valencies.insert(1u16); - valencies.insert(2u16); - valencies.insert(3u16); - valencies.insert(4u16); - - assert_eq!(genesis_schema.node_type(), NodeType::Genesis); - assert_eq!( - genesis_schema.metadata().get(&2u16).unwrap(), - &Occurrences::NoneOrOnce - ); - assert_eq!(genesis_schema.closes(), &OwnedRightsStructure::new()); - assert_eq!(genesis_schema.extends(), &PublicRightsStructure::new()); - assert_eq!( - genesis_schema.owned_rights().get(&3u16).unwrap(), - &Occurrences::OnceOrUpTo(25u16) - ); - assert_eq!(genesis_schema.public_rights(), &valencies); - } - - #[test] - fn test_node_for_transition() { - let transition_schema = TransitionSchema::strict_decode(&TRANSITION_SCHEMA[..]).unwrap(); - - let mut valencies = PublicRightsStructure::new(); - valencies.insert(1u16); - valencies.insert(2u16); - valencies.insert(3u16); - valencies.insert(4u16); - - assert_eq!(transition_schema.node_type(), NodeType::StateTransition); - assert_eq!( - transition_schema.metadata().get(&2u16).unwrap(), - &Occurrences::NoneOrOnce - ); - assert_eq!( - transition_schema.closes().get(&3u16).unwrap(), - &Occurrences::OnceOrUpTo(25u16) - ); - assert_eq!(transition_schema.extends(), &PublicRightsStructure::new()); - assert_eq!( - transition_schema.owned_rights().get(&3u16).unwrap(), - &Occurrences::OnceOrUpTo(25u16) - ); - assert_eq!(transition_schema.public_rights(), &valencies); - } - - #[test] - fn test_node_for_extension() { - let extension_schema = ExtensionSchema::strict_decode(&EXTENSION_SCHEMA[..]).unwrap(); - - let mut valencies = PublicRightsStructure::new(); - valencies.insert(1u16); - valencies.insert(2u16); - valencies.insert(3u16); - valencies.insert(4u16); - - assert_eq!(extension_schema.node_type(), NodeType::StateExtension); - assert_eq!( - extension_schema.metadata().get(&2u16).unwrap(), - &Occurrences::NoneOrOnce - ); - assert_eq!(extension_schema.closes(), &OwnedRightsStructure::new()); - assert_eq!(extension_schema.extends(), &valencies); - assert_eq!( - extension_schema.owned_rights().get(&3u16).unwrap(), - &Occurrences::OnceOrUpTo(25u16) - ); - assert_eq!(extension_schema.public_rights(), &valencies); - } - - #[test] - fn test_validation() { - // Create Two Metadata Structures - let mut metadata_structures = MetadataStructure::new(); - metadata_structures.insert(1 as FieldType, Occurrences::Once); - metadata_structures.insert(2 as FieldType, Occurrences::NoneOrOnce); - metadata_structures.insert(3 as FieldType, Occurrences::OnceOrUpTo(13u16)); - metadata_structures.insert(4 as FieldType, Occurrences::NoneOrUpTo(17u16)); - - let mut metadata_structures2 = MetadataStructure::new(); - metadata_structures2.insert(1 as FieldType, Occurrences::Once); - metadata_structures2.insert(2 as FieldType, Occurrences::NoneOrOnce); - metadata_structures2.insert(3 as FieldType, Occurrences::OnceOrMore); - metadata_structures2.insert(4 as FieldType, Occurrences::NoneOrUpTo(15u16)); - - // Create Two Seal Structures - let mut seal_structures = OwnedRightsStructure::new(); - seal_structures.insert(1 as OwnedRightType, Occurrences::Once); - seal_structures.insert(2 as OwnedRightType, Occurrences::NoneOrOnce); - seal_structures.insert(3 as OwnedRightType, Occurrences::OnceOrUpTo(25u16)); - seal_structures.insert(4 as OwnedRightType, Occurrences::NoneOrUpTo(12u16)); - - let mut seal_structures2 = OwnedRightsStructure::new(); - seal_structures2.insert(1 as OwnedRightType, Occurrences::Once); - seal_structures2.insert(2 as OwnedRightType, Occurrences::NoneOrOnce); - seal_structures2.insert(3 as OwnedRightType, Occurrences::OnceOrMore); - seal_structures2.insert(4 as OwnedRightType, Occurrences::NoneOrUpTo(30u16)); - - // Create Two Valency structure - let mut valency_structure = PublicRightsStructure::new(); - valency_structure.insert(1 as PublicRightType); - valency_structure.insert(2 as PublicRightType); - valency_structure.insert(3 as PublicRightType); - valency_structure.insert(4 as PublicRightType); - - let mut valency_structure2 = PublicRightsStructure::new(); - valency_structure2.insert(1 as PublicRightType); - valency_structure2.insert(5 as PublicRightType); - valency_structure2.insert(3 as PublicRightType); - valency_structure2.insert(4 as PublicRightType); - - // Create Four Unequal Transition and Extension Structures - let transtion_schema = TransitionSchema { - metadata: metadata_structures.clone(), - closes: seal_structures.clone(), - owned_rights: seal_structures.clone(), - public_rights: valency_structure.clone(), - }; - - let transtion_schema2 = TransitionSchema { - metadata: metadata_structures2.clone(), - closes: seal_structures2.clone(), - owned_rights: seal_structures2.clone(), - public_rights: valency_structure2.clone(), - }; - - let extension_schema = ExtensionSchema { - metadata: metadata_structures.clone(), - extends: valency_structure.clone(), - owned_rights: seal_structures.clone(), - public_rights: valency_structure.clone(), - }; - - let extension_schema2 = ExtensionSchema { - metadata: metadata_structures.clone(), - extends: valency_structure2.clone(), - owned_rights: seal_structures.clone(), - public_rights: valency_structure2.clone(), - }; - - // Create the expected failure results - let transition_failures = vec![ - Failure::SchemaRootNoMetadataMatch(NodeType::StateTransition, 3), - Failure::SchemaRootNoMetadataMatch(NodeType::StateTransition, 4), - Failure::SchemaRootNoParentOwnedRightsMatch(NodeType::StateTransition, 3), - Failure::SchemaRootNoParentOwnedRightsMatch(NodeType::StateTransition, 4), - Failure::SchemaRootNoOwnedRightsMatch(NodeType::StateTransition, 3), - Failure::SchemaRootNoOwnedRightsMatch(NodeType::StateTransition, 4), - Failure::SchemaRootNoPublicRightsMatch(NodeType::StateTransition, 2), - ]; - - let extension_failures = vec![ - Failure::SchemaRootNoParentPublicRightsMatch(NodeType::StateExtension, 2), - Failure::SchemaRootNoPublicRightsMatch(NodeType::StateExtension, 2), - ]; - - // Assert failures matches with expectation - assert_eq!( - transtion_schema.schema_verify(&transtion_schema2).failures, - transition_failures - ); - assert_eq!( - extension_schema.schema_verify(&extension_schema2).failures, - extension_failures - ); - } -} diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 4817c270..d4263a66 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -13,7 +13,6 @@ use std::collections::{BTreeMap, BTreeSet}; use amplify::flags::FlagVec; use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::CommitVerify; use super::{ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, TransitionSchema}; use crate::schema::StateSchema; @@ -47,13 +46,6 @@ impl sha256t::Tag for SchemaIdTag { #[wrapper(Debug, BorrowSlice)] pub struct SchemaId(sha256t::Hash); -impl CommitVerify for SchemaId -where Msg: AsRef<[u8]> -{ - #[inline] - fn commit(msg: &Msg) -> SchemaId { SchemaId::hash(msg) } -} - #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Schema { @@ -92,7 +84,7 @@ pub struct Schema { impl Schema { #[inline] - pub fn schema_id(&self) -> SchemaId { self.clone().consensus_commit() } + pub fn schema_id(&self) -> SchemaId { todo!() } } impl PartialEq for Schema { @@ -100,732 +92,3 @@ impl PartialEq for Schema { } impl Eq for Schema {} - -// TODO #73: Move to validation module and refactor that module into a directory -mod _validation { - use std::collections::BTreeSet; - - use super::*; - use crate::schema::{ - MetadataStructure, OwnedRightsStructure, PublicRightsStructure, SchemaVerify, - }; - use crate::script::{OverrideRules, ValidationScript}; - use crate::vm::Validate; - use crate::{ - validation, Assignment, Metadata, Node, NodeId, NodeSubtype, OwnedRights, - ParentOwnedRights, ParentPublicRights, PublicRights, State, TypedAssignments, - }; - - impl SchemaVerify for Schema { - fn schema_verify(&self, root: &Schema) -> validation::Status { - let mut status = validation::Status::new(); - - if root.root_id != SchemaId::default() { - status.add_failure(validation::Failure::SchemaRootHierarchy(root.root_id)); - } - - for (field_type, data_format) in &self.field_types { - match root.field_types.get(field_type) { - None => status - .add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)), - Some(root_data_format) if root_data_format != data_format => status - .add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)), - _ => &status, - }; - } - - for (assignments_type, state_schema) in &self.owned_right_types { - match root.owned_right_types.get(assignments_type) { - None => status.add_failure( - validation::Failure::SchemaRootNoOwnedRightTypeMatch(*assignments_type), - ), - Some(root_state_schema) if root_state_schema != state_schema => status - .add_failure(validation::Failure::SchemaRootNoOwnedRightTypeMatch( - *assignments_type, - )), - _ => &status, - }; - } - - for valencies_type in &self.public_right_types { - match root.public_right_types.contains(valencies_type) { - false => status.add_failure( - validation::Failure::SchemaRootNoPublicRightTypeMatch(*valencies_type), - ), - _ => &status, - }; - } - - status += self.genesis.schema_verify(&root.genesis); - - for (transition_type, transition_schema) in &self.transitions { - if let Some(root_transition_schema) = root.transitions.get(transition_type) { - status += transition_schema.schema_verify(root_transition_schema); - } else { - status.add_failure(validation::Failure::SchemaRootNoTransitionTypeMatch( - *transition_type, - )); - } - } - for (extension_type, extension_schema) in &self.extensions { - if let Some(root_extension_schema) = root.extensions.get(extension_type) { - status += extension_schema.schema_verify(root_extension_schema); - } else { - status.add_failure(validation::Failure::SchemaRootNoExtensionTypeMatch( - *extension_type, - )); - } - } - - match (root.override_rules, self.override_rules) { - (OverrideRules::Deny, _) if root.script != self.script => { - status.add_failure(validation::Failure::SchemaScriptOverrideDenied); - } - (OverrideRules::AllowSameVm, _) - if root.script.vm_type() != self.script.vm_type() => - { - status.add_failure(validation::Failure::SchemaScriptVmChangeDenied); - } - _ => {} // We are fine here - } - - status - } - } - - impl Schema { - pub fn validate( - &self, - all_nodes: &BTreeMap, - node: &dyn Node, - script: &ValidationScript, - ) -> validation::Status { - let node_id = node.node_id(); - - let empty_owned_structure = OwnedRightsStructure::default(); - let empty_public_structure = PublicRightsStructure::default(); - let ( - metadata_structure, - parent_owned_structure, - parent_public_structure, - assignments_structure, - valencies_structure, - ) = match (node.transition_type(), node.extension_type()) { - (None, None) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = self.genesis.abi.get(&GenesisAction::NoOp) { - - } - */ - - ( - &self.genesis.metadata, - &empty_owned_structure, - &empty_public_structure, - &self.genesis.owned_rights, - &self.genesis.public_rights, - ) - } - (Some(transition_type), None) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = transition_type.abi.get(&TransitionAction::NoOp) { - - } - */ - - let transition_type = match self.transitions.get(&transition_type) { - None => { - return validation::Status::with_failure( - validation::Failure::SchemaUnknownTransitionType( - node_id, - transition_type, - ), - ) - } - Some(transition_type) => transition_type, - }; - - ( - &transition_type.metadata, - &transition_type.closes, - &empty_public_structure, - &transition_type.owned_rights, - &transition_type.public_rights, - ) - } - (None, Some(extension_type)) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = extension_type.abi.get(&ExtensionAction::NoOp) { - - } - */ - - let extension_type = match self.extensions.get(&extension_type) { - None => { - return validation::Status::with_failure( - validation::Failure::SchemaUnknownExtensionType( - node_id, - extension_type, - ), - ) - } - Some(extension_type) => extension_type, - }; - - ( - &extension_type.metadata, - &empty_owned_structure, - &extension_type.extends, - &extension_type.owned_rights, - &extension_type.extends, - ) - } - _ => unreachable!("Node can't be extension and state transition at the same time"), - }; - - let mut status = validation::Status::new(); - - // Validate type system - status += self.validate_type_system(); - - let parent_owned_rights = - extract_parent_owned_rights(all_nodes, node.parent_owned_rights(), &mut status); - let parent_public_rights = - extract_parent_public_rights(all_nodes, node.parent_public_rights(), &mut status); - status += self.validate_meta(node_id, node.metadata(), metadata_structure); - status += self.validate_parent_owned_rights( - node_id, - &parent_owned_rights, - parent_owned_structure, - ); - status += self.validate_parent_public_rights( - node_id, - &parent_public_rights, - parent_public_structure, - ); - status += - self.validate_owned_rights(node_id, node.owned_rights(), assignments_structure); - status += - self.validate_public_rights(node_id, node.public_rights(), valencies_structure); - // We need to run scripts as the very last step, since before that - // we need to make sure that the node data match the schema, so - // scripts are not required to validate the structure of the state - status += self.validate_state_evolution( - node_id, - node.subtype(), - &parent_owned_rights, - node.owned_rights(), - &parent_public_rights, - node.public_rights(), - node.metadata(), - script, - ); - status - } - - fn validate_type_system(&self) -> validation::Status { - let status = validation::Status::new(); - // TODO: Validate type system - /*if let Err(inconsistencies) = self.type_system.validate() { - for _err in inconsistencies { - status.add_failure(validation::Failure::SchemaTypeSystem(/*err*/)); - } - }*/ - status - } - - fn validate_meta( - &self, - node_id: NodeId, - metadata: &Metadata, - metadata_structure: &MetadataStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - metadata - .keys() - .collect::>() - .difference(&metadata_structure.keys().collect()) - .for_each(|field_id| { - status.add_failure(validation::Failure::SchemaUnknownFieldType( - node_id, **field_id, - )); - }); - - for (field_type_id, occ) in metadata_structure { - let set = metadata.get(field_type_id).cloned().unwrap_or_default(); - - // Checking number of field occurrences - if let Err(err) = occ.check(set.len() as u16) { - status.add_failure(validation::Failure::SchemaMetaOccurrencesError( - node_id, - *field_type_id, - err, - )); - } - - let _field = self.field_types.get(field_type_id) - .expect("If the field were absent, the schema would not be able to pass the internal validation and we would not reach this point"); - for _data in set { - // TODO: Run strict type validation - /* - let schema_type = data.schema_type(); - - status.add_failure(validation::Failure::SchemaMismatchedDataType( - *field_type_id, - )); - status += field.verify(&self.type_system, node_id, *field_type_id, &data); - */ - } - } - - status - } - - fn validate_parent_owned_rights( - &self, - node_id: NodeId, - owned_rights: &OwnedRights, - owned_rights_structure: &OwnedRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - owned_rights - .keys() - .collect::>() - .difference(&owned_rights_structure.keys().collect()) - .for_each(|owned_type_id| { - status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( - node_id, - **owned_type_id, - )); - }); - - for (owned_type_id, occ) in owned_rights_structure { - let len = owned_rights - .get(owned_type_id) - .map(TypedAssignments::len) - .unwrap_or(0); - - // Checking number of ancestor's assignment occurrences - if let Err(err) = occ.check(len as u16) { - status.add_failure( - validation::Failure::SchemaParentOwnedRightOccurrencesError( - node_id, - *owned_type_id, - err, - ), - ); - } - } - - status - } - - fn validate_parent_public_rights( - &self, - node_id: NodeId, - public_rights: &PublicRights, - public_rights_structure: &PublicRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - public_rights - .difference(public_rights_structure) - .for_each(|public_type_id| { - status.add_failure(validation::Failure::SchemaUnknownPublicRightType( - node_id, - *public_type_id, - )); - }); - - status - } - - fn validate_owned_rights( - &self, - node_id: NodeId, - owned_rights: &OwnedRights, - owned_rights_structure: &OwnedRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - owned_rights - .keys() - .collect::>() - .difference(&owned_rights_structure.keys().collect()) - .for_each(|assignment_type_id| { - status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( - node_id, - **assignment_type_id, - )); - }); - - for (owned_type_id, occ) in owned_rights_structure { - let len = owned_rights - .get(owned_type_id) - .map(TypedAssignments::len) - .unwrap_or(0); - - // Checking number of assignment occurrences - if let Err(err) = occ.check(len as u16) { - status.add_failure(validation::Failure::SchemaOwnedRightOccurrencesError( - node_id, - *owned_type_id, - err, - )); - } - - let assignment = &self - .owned_right_types - .get(owned_type_id) - .expect("If the assignment were absent, the schema would not be able to pass the internal validation and we would not reach this point"); - - match owned_rights.get(owned_type_id) { - None => {} - Some(TypedAssignments::Void(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - Some(TypedAssignments::Value(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - Some(TypedAssignments::Data(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - Some(TypedAssignments::Attachment(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - }; - } - - status - } - - fn validate_public_rights( - &self, - node_id: NodeId, - public_rights: &PublicRights, - public_rights_structure: &PublicRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - public_rights - .difference(public_rights_structure) - .for_each(|public_type_id| { - status.add_failure(validation::Failure::SchemaUnknownPublicRightType( - node_id, - *public_type_id, - )); - }); - - status - } - - #[allow(clippy::too_many_arguments)] - fn validate_state_evolution( - &self, - node_id: NodeId, - node_subtype: NodeSubtype, - parent_owned_rights: &OwnedRights, - owned_rights: &OwnedRights, - parent_public_rights: &PublicRights, - public_rights: &PublicRights, - metadata: &Metadata, - script: &ValidationScript, - ) -> validation::Status { - let mut status = validation::Status::new(); - - // We do not validate public rights, since they do not have an - // associated state and there is nothing to validate beyond schema - - if let Err(err) = script.validate( - node_id, - node_subtype, - parent_owned_rights, - owned_rights, - parent_public_rights, - public_rights, - metadata, - ) { - status.add_failure(err); - } - - status - } - } - - fn extract_parent_owned_rights( - nodes: &BTreeMap, - parent_owned_rights: &ParentOwnedRights, - status: &mut validation::Status, - ) -> OwnedRights { - let mut owned_rights = OwnedRights::default(); - for (id, details) in parent_owned_rights.iter() { - let parent_node = match nodes.get(id) { - None => { - status.add_failure(validation::Failure::TransitionAbsent(*id)); - continue; - } - Some(node) => node, - }; - - fn filter(set: &[Assignment], indexes: &[u16]) -> Vec> - where - STATE: State + Clone, - STATE::Confidential: PartialEq + Eq, - STATE::Confidential: From<::ConcealedCommitment>, - { - set.iter() - .enumerate() - .filter_map(|(index, item)| { - if indexes.contains(&(index as u16)) { - Some(item.clone()) - } else { - None - } - }) - .collect() - } - - for (type_id, indexes) in details { - match parent_node.owned_rights_by_type(*type_id) { - Some(TypedAssignments::Void(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Void(Default::default())) - .declarative_assignments_mut() - { - state.extend(set); - } - } - Some(TypedAssignments::Value(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Value(Default::default())) - .value_assignments_mut() - { - state.extend(set); - } - } - Some(TypedAssignments::Data(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Data(Default::default())) - .data_assignments_mut() - { - state.extend(set); - } - } - Some(TypedAssignments::Attachment(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Attachment(Default::default())) - .attachment_assignments_mut() - { - state.extend(set); - } - } - None => { - // Presence of the required owned rights type in the - // parent node was already validated; we have nothing to - // report here - } - } - } - } - owned_rights - } - - fn extract_parent_public_rights( - nodes: &BTreeMap, - parent_public_rights: &ParentPublicRights, - status: &mut validation::Status, - ) -> PublicRights { - let mut public_rights = PublicRights::default(); - for (id, public_right_types) in parent_public_rights.iter() { - if nodes.get(id).is_none() { - status.add_failure(validation::Failure::TransitionAbsent(*id)); - } else { - public_rights.extend(public_right_types); - } - } - public_rights - } -} - -#[cfg(test)] -pub(crate) mod test { - use amplify::Wrapper; - use commit_verify::tagged_hash; - use strict_encoding::*; - - use super::*; - use crate::schema::*; - - pub(crate) fn schema() -> Schema { - const FIELD_TICKER: u16 = 0; - const FIELD_NAME: u16 = 1; - const FIELD_DESCRIPTION: u16 = 2; - const FIELD_TOTAL_SUPPLY: u16 = 3; - const FIELD_ISSUED_SUPPLY: u16 = 4; - const FIELD_DUST_LIMIT: u16 = 5; - const FIELD_PRECISION: u16 = 6; - const FIELD_PRUNE_PROOF: u16 = 7; - const FIELD_TIMESTAMP: u16 = 8; - - const FIELD_PROOF_OF_BURN: u16 = 0x10; - - const ASSIGNMENT_ISSUE: u16 = 0; - const ASSIGNMENT_ASSETS: u16 = 1; - const ASSIGNMENT_PRUNE: u16 = 2; - - const TRANSITION_ISSUE: u16 = 0; - const TRANSITION_TRANSFER: u16 = 1; - const TRANSITION_PRUNE: u16 = 2; - - const VALENCIES_DECENTRALIZED_ISSUE: u16 = 0; - - const EXTENSION_DECENTRALIZED_ISSUE: u16 = 0; - - Schema { - rgb_features: FlagVec::default(), - root_id: Default::default(), - type_system: Default::default(), - field_types: bmap! { - FIELD_TICKER => TypeRef::ascii_string(), - FIELD_NAME => TypeRef::ascii_string(), - FIELD_DESCRIPTION => TypeRef::unicode_string(), - FIELD_TOTAL_SUPPLY => TypeRef::u64(), - FIELD_PRECISION => TypeRef::u8(), - FIELD_ISSUED_SUPPLY => TypeRef::u64(), - FIELD_DUST_LIMIT => TypeRef::u64(), - FIELD_PRUNE_PROOF => TypeRef::bytes(), - FIELD_TIMESTAMP => TypeRef::i64() - }, - owned_right_types: bmap! { - ASSIGNMENT_ISSUE => StateSchema::Declarative, - ASSIGNMENT_ASSETS => StateSchema::DiscreteFiniteField(DiscreteFiniteFieldFormat::Unsigned64bit), - ASSIGNMENT_PRUNE => StateSchema::Declarative - }, - public_right_types: bset! { - VALENCIES_DECENTRALIZED_ISSUE - }, - genesis: GenesisSchema { - metadata: bmap! { - FIELD_TICKER => Occurrences::Once, - FIELD_NAME => Occurrences::Once, - FIELD_DESCRIPTION => Occurrences::NoneOrOnce, - FIELD_TOTAL_SUPPLY => Occurrences::Once, - FIELD_ISSUED_SUPPLY => Occurrences::Once, - FIELD_DUST_LIMIT => Occurrences::NoneOrOnce, - FIELD_PRECISION => Occurrences::Once, - FIELD_TIMESTAMP => Occurrences::Once - }, - owned_rights: bmap! { - ASSIGNMENT_ISSUE => Occurrences::NoneOrOnce, - ASSIGNMENT_ASSETS => Occurrences::NoneOrMore, - ASSIGNMENT_PRUNE => Occurrences::NoneOrMore - }, - public_rights: bset! { VALENCIES_DECENTRALIZED_ISSUE }, - }, - extensions: bmap! { - EXTENSION_DECENTRALIZED_ISSUE => ExtensionSchema { - extends: bset! { VALENCIES_DECENTRALIZED_ISSUE }, - metadata: bmap! { - FIELD_ISSUED_SUPPLY => Occurrences::Once, - FIELD_PROOF_OF_BURN => Occurrences::OnceOrMore - }, - owned_rights: bmap! { - ASSIGNMENT_ASSETS => Occurrences::NoneOrMore - }, - public_rights: bset! { }, - } - }, - transitions: bmap! { - TRANSITION_ISSUE => TransitionSchema { - closes: bmap! { - ASSIGNMENT_ISSUE => Occurrences::Once - }, - metadata: bmap! { - FIELD_ISSUED_SUPPLY => Occurrences::Once - }, - owned_rights: bmap! { - ASSIGNMENT_ISSUE => Occurrences::NoneOrOnce, - ASSIGNMENT_PRUNE => Occurrences::NoneOrMore, - ASSIGNMENT_ASSETS => Occurrences::NoneOrMore - }, - public_rights: bset! {}, - }, - TRANSITION_TRANSFER => TransitionSchema { - closes: bmap! { - ASSIGNMENT_ASSETS => Occurrences::OnceOrMore - }, - metadata: bmap! {}, - owned_rights: bmap! { - ASSIGNMENT_ASSETS => Occurrences::NoneOrMore - }, - public_rights: bset! {}, - }, - TRANSITION_PRUNE => TransitionSchema { - closes: bmap! { - ASSIGNMENT_PRUNE => Occurrences::OnceOrMore, - ASSIGNMENT_ASSETS => Occurrences::OnceOrMore - }, - metadata: bmap! { - FIELD_PRUNE_PROOF => Occurrences::NoneOrMore - }, - owned_rights: bmap! { - ASSIGNMENT_PRUNE => Occurrences::NoneOrMore, - ASSIGNMENT_ASSETS => Occurrences::NoneOrMore - }, - public_rights: bset! {}, - } - }, - script: Default::default(), - override_rules: Default::default(), - } - } - - #[test] - fn test_schema_id_midstate() { - let midstate = tagged_hash::Midstate::with(b"rgb:schema"); - assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_SHEMA_ID); - } - - #[test] - fn test_schema_encoding_decoding() { - let schema = schema(); - let encoded = strict_serialize(&schema).unwrap(); - let encoded_standard: Vec = vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 17, 254, 1, 0, 0, 17, 254, 2, 0, 0, 17, 255, 3, 0, - 0, 0, 3, 4, 0, 0, 0, 3, 5, 0, 0, 0, 3, 6, 0, 0, 0, 0, 7, 0, 0, 17, 0, 8, 0, 0, 0, 19, - 3, 0, 0, 0, 0, 1, 0, 1, 0, 2, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, - 0, 2, 0, 0, 0, 1, 0, 3, 0, 1, 0, 1, 0, 4, 0, 1, 0, 1, 0, 5, 0, 0, 0, 1, 0, 6, 0, 1, 0, - 1, 0, 8, 0, 1, 0, 1, 0, 3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 255, 255, 2, 0, 0, 0, 255, - 255, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 4, 0, 1, 0, 1, 0, 16, 0, 1, 0, 255, 255, 1, 0, 0, 0, - 1, 0, 1, 0, 0, 0, 255, 255, 0, 0, 3, 0, 0, 0, 1, 0, 4, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, - 1, 0, 3, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 255, 255, 2, 0, 0, 0, 255, 255, 0, 0, 1, 0, - 0, 0, 1, 0, 1, 0, 1, 0, 255, 255, 1, 0, 1, 0, 0, 0, 255, 255, 0, 0, 2, 0, 1, 0, 7, 0, - 0, 0, 255, 255, 2, 0, 1, 0, 1, 0, 255, 255, 2, 0, 1, 0, 255, 255, 2, 0, 1, 0, 0, 0, - 255, 255, 2, 0, 0, 0, 255, 255, 0, 0, 0, 0, - ]; - assert_eq!(encoded, encoded_standard); - - let decoded = Schema::strict_decode(&encoded[..]).unwrap(); - assert_eq!(decoded, schema); - } -} diff --git a/src/schema/script.rs b/src/schema/script.rs index 40e1855c..55b1849c 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -14,8 +14,6 @@ //! Components related to the scripting system used by schema or applied at the //! specific contract node level -use crate::vm::alure; - /// Virtual machine types. #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[display(Debug)] @@ -38,7 +36,7 @@ pub enum ValidationScript { /// /// Its routines can be accessed only through well-typed ABI entrance /// pointers, defined as a part of the schema. - AluVM(alure::ValidationScript), + AluVM(Vec), } impl ValidationScript { diff --git a/src/schema/state.rs b/src/schema/state.rs index cebea2ed..5b35f072 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -53,325 +53,3 @@ pub enum StateSchema { pub enum DiscreteFiniteFieldFormat { Unsigned64bit, } - -mod _validation { - use core::any::Any; - - use amplify::AsAny; - - use super::*; - use crate::contract::AttachmentStrategy; - use crate::schema::OwnedRightType; - use crate::{ - validation, Assignment, DeclarativeStrategy, HashStrategy, NodeId, PedersenStrategy, State, - }; - - impl StateSchema { - pub fn validate( - &self, - // type_system: &TypeSystem, - node_id: &NodeId, - assignment_id: OwnedRightType, - data: &Assignment, - ) -> validation::Status - where - STATE: State, - STATE::Confidential: PartialEq + Eq, - STATE::Confidential: From<::ConcealedCommitment>, - { - let mut status = validation::Status::new(); - match data { - Assignment::Confidential { state, .. } - | Assignment::ConfidentialState { state, .. } => { - let a: &dyn Any = state.as_any(); - match self { - StateSchema::Declarative => { - if a.downcast_ref::<::Confidential>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - StateSchema::DiscreteFiniteField(_) => { - if let Some(value) = - a.downcast_ref::<::Confidential>() - { - // [SECURITY-CRITICAL]: Bulletproofs validation - if let Err(err) = value.verify_bullet_proof() { - status.add_failure(validation::Failure::InvalidBulletproofs( - *node_id, - assignment_id, - err.to_string(), - )); - } - } else { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - - // TODO: When other homomorphic formats will be added, - // add information to the status like with - // hashed data below - } - StateSchema::CustomData() => { - match a.downcast_ref::<::Confidential>() { - None => { - status.add_failure( - validation::Failure::SchemaMismatchedStateType( - assignment_id, - ), - ); - } - Some(_) => { - status.add_info( - validation::Info::UncheckableConfidentialStateData( - *node_id, - assignment_id, - ), - ); - } - } - } - StateSchema::DataContainer => { - if a.downcast_ref::<::Confidential>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - } - } - Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { - let a: &dyn Any = state.as_any(); - match self { - StateSchema::Declarative => { - if a.downcast_ref::<::Revealed>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - StateSchema::DiscreteFiniteField(_format) => { - if a.downcast_ref::<::Revealed>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - // TODO #15: When other homomorphic formats will be added, - // add type check like with hashed data below - } - StateSchema::CustomData(/*format*/) => { - match a.downcast_ref::<::Revealed>() { - None => { - status.add_failure( - validation::Failure::SchemaMismatchedStateType( - assignment_id, - ), - ); - } - Some(_data) => { - // TODO: run strict type validation - } - } - } - StateSchema::DataContainer => { - if a.downcast_ref::<::Revealed>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - } - } - } - status - } - } -} - -#[cfg(test)] -mod test { - use bitcoin::blockdata::transaction::Outpoint; - use bitcoin_hashes::hex::FromHex; - use bitcoin_hashes::sha256; - use commit_verify::{CommitConceal, TaggedHash}; - use secp256k1_zkp::rand::thread_rng; - use stens::TypeSystem; - use strict_encoding::StrictDecode; - - use super::*; - use crate::contract::{data, value, NodeId}; - use crate::validation::Failure; - use crate::{Assignment, DeclarativeStrategy, HashStrategy, PedersenStrategy}; - - // Txids to generate seals - static TXID_VEC: [&str; 4] = [ - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e", - "f57ed27ee4199072c5ff3b774febc94d26d3e4a5559d133de4750a948df50e06", - "12072893d951c633dcafb4d3074d1fc41c5e6e64b8d53e3b0705c41bc6679d54", - "8f75db9f89c7c75f0a54322f18cd4d557ae75c24a8e5a95eae13fe26edc2d789", - ]; - - #[test] - #[should_panic(expected = r#"EnumValueNotKnown("DiscreteFiniteFieldFormat", 1)"#)] - fn test_garbage_df_format() { - let bytes: Vec = - vec![1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255]; - DiscreteFiniteFieldFormat::strict_decode(&bytes[..]).unwrap(); - } - - #[test] - fn test_random() { - let n = 67u8; - println!("{}", ::core::mem::size_of_val(&n)); - } - #[test] - fn test_state_format() { - // Create typical assignments - // Only Revealed and Confidential variants are created for simplicity - // Which covers the two validation branch - let mut rng = thread_rng(); - - let txid_vec: Vec = TXID_VEC - .iter() - .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) - .collect(); - - // Create Declarative Assignments - let assignment_dec_rev = Assignment::::Revealed { - seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: data::Void(), - }; - - let assignment_dec_conf = Assignment::::Confidential { - seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[1], 2)) - .commit_conceal(), - state: data::Void(), - }; - - // Create Pedersan Assignments - let assignment_ped_rev = Assignment::::Revealed { - seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: value::Revealed::with_amount(10u64, &mut rng), - }; - - let assignment_ped_conf = Assignment::::Confidential { - seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[1], 1)) - .commit_conceal(), - state: value::Revealed::with_amount(10u64, &mut rng).commit_conceal(), - }; - - // Create CustomData Assignmnets - let state_data_vec: Vec = TXID_VEC - .iter() - .map(|data| data::Revealed::Bytes(sha256::Hash::from_hex(data).unwrap().to_vec())) - .collect(); - - let assignment_hash_rev = Assignment::::Revealed { - seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: state_data_vec[0].clone(), - }; - - let assignment_hash_conf = Assignment::::Confidential { - seal: crate::contract::seal::Revealed::from(Outpoint::new(txid_vec[1], 1)) - .commit_conceal(), - state: state_data_vec[0].clone().commit_conceal(), - }; - - // Create NodeId amd Stateformats - let node_id = - NodeId::from_hex("201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e") - .unwrap(); - let dec_format = StateSchema::Declarative; - let ped_format = StateSchema::DiscreteFiniteField(DiscreteFiniteFieldFormat::Unsigned64bit); - let hash_format = StateSchema::CustomData(TypeRef::bytes()); - - // Assert different failure combinations - let ts = TypeSystem::default(); - assert_eq!( - dec_format - .validate(&ts, &node_id, 3u16, &assignment_ped_rev) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - dec_format - .validate(&ts, &node_id, 3u16, &assignment_ped_conf) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - dec_format - .validate(&ts, &node_id, 3u16, &assignment_hash_rev) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - dec_format - .validate(&ts, &node_id, 3u16, &assignment_hash_conf) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - - assert_eq!( - ped_format - .validate(&ts, &node_id, 3u16, &assignment_dec_rev) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - ped_format - .validate(&ts, &node_id, 3u16, &assignment_dec_conf) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - ped_format - .validate(&ts, &node_id, 3u16, &assignment_hash_rev) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - ped_format - .validate(&ts, &node_id, 3u16, &assignment_hash_conf) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - - assert_eq!( - hash_format - .validate(&ts, &node_id, 3u16, &assignment_dec_rev) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - hash_format - .validate(&ts, &node_id, 3u16, &assignment_dec_conf) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - hash_format - .validate(&ts, &node_id, 3u16, &assignment_ped_rev) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - assert_eq!( - hash_format - .validate(&ts, &node_id, 3u16, &assignment_ped_conf) - .failures[0], - Failure::SchemaMismatchedStateType(3) - ); - } -} diff --git a/src/validation/mod.rs b/src/validation/mod.rs new file mode 100644 index 00000000..05e40385 --- /dev/null +++ b/src/validation/mod.rs @@ -0,0 +1,244 @@ +// RGB Core Library: a reference implementation of RGB smart contract standards. +// Written in 2019-2022 by +// Dr. Maxim Orlovsky +// +// To the extent possible under law, the author(s) have dedicated all copyright +// and related and neighboring rights to this software to the public domain +// worldwide. This software is distributed without any warranty. +// +// You should have received a copy of the MIT License along with this software. +// If not, see . + +use core::iter::FromIterator; +use core::ops::AddAssign; + +use bp::Txid; + +use super::schema::{self, NodeType, OccurrencesError, SchemaId}; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] +#[display(Debug)] +#[repr(u8)] +pub enum Validity { + Valid, + ValidExceptEndpoints, + UnresolvedTransactions, + Invalid, +} + +#[derive(Clone, Debug, Display, Default)] +//#[derive(StrictEncode, StrictDecode)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +// TODO #42: Display via YAML +#[display(Debug)] +pub struct Status { + pub unresolved_txids: Vec, + pub unmined_endpoint_txids: Vec, + pub failures: Vec, + pub warnings: Vec, + pub info: Vec, +} + +impl AddAssign for Status { + fn add_assign(&mut self, rhs: Self) { + self.unresolved_txids.extend(rhs.unresolved_txids); + self.unmined_endpoint_txids + .extend(rhs.unmined_endpoint_txids); + self.failures.extend(rhs.failures); + self.warnings.extend(rhs.warnings); + self.info.extend(rhs.info); + } +} + +impl Status { + pub fn from_error(v: Failure) -> Self { + Status { + unresolved_txids: vec![], + unmined_endpoint_txids: vec![], + failures: vec![v], + warnings: vec![], + info: vec![], + } + } +} + +impl FromIterator for Status { + fn from_iter>(iter: T) -> Self { + Self { + failures: iter.into_iter().collect(), + ..Self::default() + } + } +} + +impl Status { + pub fn new() -> Self { Self::default() } + + pub fn with_failure(failure: Failure) -> Self { + Self { + failures: vec![failure], + ..Self::default() + } + } + + pub fn add_failure(&mut self, failure: Failure) -> &Self { + self.failures.push(failure); + self + } + + pub fn add_warning(&mut self, warning: Warning) -> &Self { + self.warnings.push(warning); + self + } + + pub fn add_info(&mut self, info: Info) -> &Self { + self.info.push(info); + self + } + + pub fn validity(&self) -> Validity { + if self.failures.is_empty() { + if self.unmined_endpoint_txids.is_empty() { + Validity::Valid + } else { + Validity::ValidExceptEndpoints + } + } else { + if self.unresolved_txids.is_empty() { + Validity::Invalid + } else { + Validity::UnresolvedTransactions + } + } + } +} + +#[derive(Clone, PartialEq, Eq, Debug, Display, From)] +//#[derive(StrictEncode, StrictDecode)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +// TODO #44: (v0.3) convert to detailed error description using doc_comments +#[display(Debug)] +pub enum Failure { + SchemaUnknown(SchemaId), + /// schema is a subschema, so root schema {0} must be provided for the + /// validation + SchemaRootRequired(SchemaId), + /// Root schema for this schema has another root, which is prohibited + SchemaRootHierarchy(SchemaId), + SchemaRootNoFieldTypeMatch(schema::FieldType), + SchemaRootNoOwnedRightTypeMatch(schema::OwnedRightType), + SchemaRootNoPublicRightTypeMatch(schema::PublicRightType), + SchemaRootNoTransitionTypeMatch(schema::TransitionType), + SchemaRootNoExtensionTypeMatch(schema::ExtensionType), + + SchemaRootNoMetadataMatch(NodeType, schema::FieldType), + SchemaRootNoParentOwnedRightsMatch(NodeType, schema::OwnedRightType), + SchemaRootNoParentPublicRightsMatch(NodeType, schema::PublicRightType), + SchemaRootNoOwnedRightsMatch(NodeType, schema::OwnedRightType), + SchemaRootNoPublicRightsMatch(NodeType, schema::PublicRightType), + + SchemaUnknownExtensionType(NodeId, schema::ExtensionType), + SchemaUnknownTransitionType(NodeId, schema::TransitionType), + SchemaUnknownFieldType(NodeId, schema::FieldType), + SchemaUnknownOwnedRightType(NodeId, schema::OwnedRightType), + SchemaUnknownPublicRightType(NodeId, schema::PublicRightType), + + SchemaDeniedScriptExtension(NodeId), + + SchemaMetaValueTooSmall(schema::FieldType), + SchemaMetaValueTooLarge(schema::FieldType), + SchemaStateValueTooSmall(schema::OwnedRightType), + SchemaStateValueTooLarge(schema::OwnedRightType), + + SchemaWrongEnumValue { + field_or_state_type: u16, + unexpected: u8, + }, + SchemaWrongDataLength { + field_or_state_type: u16, + max_expected: u16, + found: usize, + }, + SchemaMismatchedDataType(u16), + SchemaMismatchedStateType(schema::OwnedRightType), + + SchemaMetaOccurrencesError(NodeId, schema::FieldType, OccurrencesError), + SchemaParentOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesError), + SchemaOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesError), + + SchemaScriptOverrideDenied, + SchemaScriptVmChangeDenied, + + SchemaTypeSystem(/* TODO: use error from strict types */), + + BundleInvalid(BundleId), + + TransitionAbsent(NodeId), + TransitionNotAnchored(NodeId), + TransitionNotInAnchor(NodeId, Txid), + TransitionParentWrongSealType { + node_id: NodeId, + ancestor_id: NodeId, + assignment_type: schema::OwnedRightType, + }, + TransitionParentWrongSeal { + node_id: NodeId, + ancestor_id: NodeId, + assignment_type: schema::OwnedRightType, + seal_index: u16, + }, + TransitionParentConfidentialSeal { + node_id: NodeId, + ancestor_id: NodeId, + assignment_type: schema::OwnedRightType, + seal_index: u16, + }, + TransitionParentIsNotWitnessInput { + node_id: NodeId, + ancestor_id: NodeId, + assignment_type: schema::OwnedRightType, + seal_index: u16, + outpoint: bp::Outpoint, + }, + + ExtensionAbsent(NodeId), + ExtensionParentWrongValenciesType { + node_id: NodeId, + ancestor_id: NodeId, + valencies_type: schema::PublicRightType, + }, + + WitnessTransactionMissed(Txid), + WitnessNoCommitment(NodeId, Txid), + + EndpointTransitionNotFound(NodeId), + + InvalidStateDataType(NodeId, u16, /* TODO: Use strict type */ data::Revealed), + InvalidStateDataValue(NodeId, u16, /* TODO: Use strict type */ Vec), + + /// invalid bulletproofs in {0}:{1}: {3} + InvalidBulletproofs(NodeId, u16, String), + + ScriptFailure(NodeId), +} + +#[derive(Clone, PartialEq, Eq, Debug, Display, From)] +//#[derive(StrictEncode, StrictDecode)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +// TODO #44: (v0.3) convert to detailed descriptions using doc_comments +#[display(Debug)] +pub enum Warning { + EndpointDuplication(NodeId, SealEndpoint), + EndpointTransitionSealNotFound(NodeId, SealEndpoint), + ExcessiveNode(NodeId), + EndpointTransactionMissed(Txid), +} + +#[derive(Clone, PartialEq, Eq, Debug, Display, From)] +//#[derive(StrictEncode, StrictDecode)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +// TODO #44: (v0.3) convert to detailed descriptions using doc_comments +#[display(Debug)] +pub enum Info { + UncheckableConfidentialStateData(NodeId, u16), +} diff --git a/src/validation/schema.rs b/src/validation/schema.rs new file mode 100644 index 00000000..6df414eb --- /dev/null +++ b/src/validation/schema.rs @@ -0,0 +1,797 @@ +/// Trait used for internal schema validation against some root schema +pub trait SchemaVerify { + fn schema_verify(&self, root: &Self) -> crate::validation::Status; +} + +mod _verify { + use super::*; + use crate::schema::SchemaVerify; + use crate::validation; + + impl SchemaVerify for T + where T: NodeSchema + { + fn schema_verify(&self, root: &Self) -> validation::Status { + let mut status = validation::Status::new(); + let node_type = self.node_type(); + + for (field_type, occ) in self.metadata() { + match root.metadata().get(field_type) { + None => status.add_failure(validation::Failure::SchemaRootNoMetadataMatch( + node_type, + *field_type, + )), + Some(root_occ) if occ != root_occ => status.add_failure( + validation::Failure::SchemaRootNoMetadataMatch(node_type, *field_type), + ), + _ => &status, + }; + } + + for (assignments_type, occ) in self.closes() { + match root.closes().get(assignments_type) { + None => { + status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( + node_type, + *assignments_type, + )) + } + Some(root_occ) if occ != root_occ => { + status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( + node_type, + *assignments_type, + )) + } + _ => &status, + }; + } + + for (assignments_type, occ) in self.owned_rights() { + match root.owned_rights().get(assignments_type) { + None => status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( + node_type, + *assignments_type, + )), + Some(root_occ) if occ != root_occ => { + status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( + node_type, + *assignments_type, + )) + } + _ => &status, + }; + } + + for valencies_type in self.extends() { + if !root.extends().contains(valencies_type) { + status.add_failure(validation::Failure::SchemaRootNoParentPublicRightsMatch( + node_type, + *valencies_type, + )); + } + } + + for valencies_type in self.public_rights() { + if !root.public_rights().contains(valencies_type) { + status.add_failure(validation::Failure::SchemaRootNoPublicRightsMatch( + node_type, + *valencies_type, + )); + } + } + + status + } + } +} + +// TODO #73: Move to validation module and refactor that module into a directory +mod _validation { + use std::collections::BTreeSet; + + use super::*; + use crate::schema::{ + MetadataStructure, OwnedRightsStructure, PublicRightsStructure, SchemaVerify, + }; + use crate::script::{OverrideRules, ValidationScript}; + use crate::vm::Validate; + use crate::{ + validation, Assignment, Metadata, Node, NodeId, NodeSubtype, OwnedRights, + ParentOwnedRights, ParentPublicRights, PublicRights, State, TypedAssignments, + }; + + impl SchemaVerify for Schema { + fn schema_verify(&self, root: &Schema) -> validation::Status { + let mut status = validation::Status::new(); + + if root.root_id != SchemaId::default() { + status.add_failure(validation::Failure::SchemaRootHierarchy(root.root_id)); + } + + for (field_type, data_format) in &self.field_types { + match root.field_types.get(field_type) { + None => status + .add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)), + Some(root_data_format) if root_data_format != data_format => status + .add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)), + _ => &status, + }; + } + + for (assignments_type, state_schema) in &self.owned_right_types { + match root.owned_right_types.get(assignments_type) { + None => status.add_failure( + validation::Failure::SchemaRootNoOwnedRightTypeMatch(*assignments_type), + ), + Some(root_state_schema) if root_state_schema != state_schema => status + .add_failure(validation::Failure::SchemaRootNoOwnedRightTypeMatch( + *assignments_type, + )), + _ => &status, + }; + } + + for valencies_type in &self.public_right_types { + match root.public_right_types.contains(valencies_type) { + false => status.add_failure( + validation::Failure::SchemaRootNoPublicRightTypeMatch(*valencies_type), + ), + _ => &status, + }; + } + + status += self.genesis.schema_verify(&root.genesis); + + for (transition_type, transition_schema) in &self.transitions { + if let Some(root_transition_schema) = root.transitions.get(transition_type) { + status += transition_schema.schema_verify(root_transition_schema); + } else { + status.add_failure(validation::Failure::SchemaRootNoTransitionTypeMatch( + *transition_type, + )); + } + } + for (extension_type, extension_schema) in &self.extensions { + if let Some(root_extension_schema) = root.extensions.get(extension_type) { + status += extension_schema.schema_verify(root_extension_schema); + } else { + status.add_failure(validation::Failure::SchemaRootNoExtensionTypeMatch( + *extension_type, + )); + } + } + + match (root.override_rules, self.override_rules) { + (OverrideRules::Deny, _) if root.script != self.script => { + status.add_failure(validation::Failure::SchemaScriptOverrideDenied); + } + (OverrideRules::AllowSameVm, _) + if root.script.vm_type() != self.script.vm_type() => + { + status.add_failure(validation::Failure::SchemaScriptVmChangeDenied); + } + _ => {} // We are fine here + } + + status + } + } + + impl Schema { + pub fn validate( + &self, + all_nodes: &BTreeMap, + node: &dyn Node, + script: &ValidationScript, + ) -> validation::Status { + let node_id = node.node_id(); + + let empty_owned_structure = OwnedRightsStructure::default(); + let empty_public_structure = PublicRightsStructure::default(); + let ( + metadata_structure, + parent_owned_structure, + parent_public_structure, + assignments_structure, + valencies_structure, + ) = match (node.transition_type(), node.extension_type()) { + (None, None) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = self.genesis.abi.get(&GenesisAction::NoOp) { + + } + */ + + ( + &self.genesis.metadata, + &empty_owned_structure, + &empty_public_structure, + &self.genesis.owned_rights, + &self.genesis.public_rights, + ) + } + (Some(transition_type), None) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = transition_type.abi.get(&TransitionAction::NoOp) { + + } + */ + + let transition_type = match self.transitions.get(&transition_type) { + None => { + return validation::Status::with_failure( + validation::Failure::SchemaUnknownTransitionType( + node_id, + transition_type, + ), + ) + } + Some(transition_type) => transition_type, + }; + + ( + &transition_type.metadata, + &transition_type.closes, + &empty_public_structure, + &transition_type.owned_rights, + &transition_type.public_rights, + ) + } + (None, Some(extension_type)) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = extension_type.abi.get(&ExtensionAction::NoOp) { + + } + */ + + let extension_type = match self.extensions.get(&extension_type) { + None => { + return validation::Status::with_failure( + validation::Failure::SchemaUnknownExtensionType( + node_id, + extension_type, + ), + ) + } + Some(extension_type) => extension_type, + }; + + ( + &extension_type.metadata, + &empty_owned_structure, + &extension_type.extends, + &extension_type.owned_rights, + &extension_type.extends, + ) + } + _ => unreachable!("Node can't be extension and state transition at the same time"), + }; + + let mut status = validation::Status::new(); + + // Validate type system + status += self.validate_type_system(); + + let parent_owned_rights = + extract_parent_owned_rights(all_nodes, node.parent_owned_rights(), &mut status); + let parent_public_rights = + extract_parent_public_rights(all_nodes, node.parent_public_rights(), &mut status); + status += self.validate_meta(node_id, node.metadata(), metadata_structure); + status += self.validate_parent_owned_rights( + node_id, + &parent_owned_rights, + parent_owned_structure, + ); + status += self.validate_parent_public_rights( + node_id, + &parent_public_rights, + parent_public_structure, + ); + status += + self.validate_owned_rights(node_id, node.owned_rights(), assignments_structure); + status += + self.validate_public_rights(node_id, node.public_rights(), valencies_structure); + // We need to run scripts as the very last step, since before that + // we need to make sure that the node data match the schema, so + // scripts are not required to validate the structure of the state + status += self.validate_state_evolution( + node_id, + node.subtype(), + &parent_owned_rights, + node.owned_rights(), + &parent_public_rights, + node.public_rights(), + node.metadata(), + script, + ); + status + } + + fn validate_type_system(&self) -> validation::Status { + let status = validation::Status::new(); + // TODO: Validate type system + /*if let Err(inconsistencies) = self.type_system.validate() { + for _err in inconsistencies { + status.add_failure(validation::Failure::SchemaTypeSystem(/*err*/)); + } + }*/ + status + } + + fn validate_meta( + &self, + node_id: NodeId, + metadata: &Metadata, + metadata_structure: &MetadataStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + metadata + .keys() + .collect::>() + .difference(&metadata_structure.keys().collect()) + .for_each(|field_id| { + status.add_failure(validation::Failure::SchemaUnknownFieldType( + node_id, **field_id, + )); + }); + + for (field_type_id, occ) in metadata_structure { + let set = metadata.get(field_type_id).cloned().unwrap_or_default(); + + // Checking number of field occurrences + if let Err(err) = occ.check(set.len() as u16) { + status.add_failure(validation::Failure::SchemaMetaOccurrencesError( + node_id, + *field_type_id, + err, + )); + } + + let _field = self.field_types.get(field_type_id) + .expect("If the field were absent, the schema would not be able to pass the internal validation and we would not reach this point"); + for _data in set { + // TODO: Run strict type validation + /* + let schema_type = data.schema_type(); + + status.add_failure(validation::Failure::SchemaMismatchedDataType( + *field_type_id, + )); + status += field.verify(&self.type_system, node_id, *field_type_id, &data); + */ + } + } + + status + } + + fn validate_parent_owned_rights( + &self, + node_id: NodeId, + owned_rights: &OwnedRights, + owned_rights_structure: &OwnedRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + owned_rights + .keys() + .collect::>() + .difference(&owned_rights_structure.keys().collect()) + .for_each(|owned_type_id| { + status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( + node_id, + **owned_type_id, + )); + }); + + for (owned_type_id, occ) in owned_rights_structure { + let len = owned_rights + .get(owned_type_id) + .map(TypedAssignments::len) + .unwrap_or(0); + + // Checking number of ancestor's assignment occurrences + if let Err(err) = occ.check(len as u16) { + status.add_failure( + validation::Failure::SchemaParentOwnedRightOccurrencesError( + node_id, + *owned_type_id, + err, + ), + ); + } + } + + status + } + + fn validate_parent_public_rights( + &self, + node_id: NodeId, + public_rights: &PublicRights, + public_rights_structure: &PublicRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + public_rights + .difference(public_rights_structure) + .for_each(|public_type_id| { + status.add_failure(validation::Failure::SchemaUnknownPublicRightType( + node_id, + *public_type_id, + )); + }); + + status + } + + fn validate_owned_rights( + &self, + node_id: NodeId, + owned_rights: &OwnedRights, + owned_rights_structure: &OwnedRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + owned_rights + .keys() + .collect::>() + .difference(&owned_rights_structure.keys().collect()) + .for_each(|assignment_type_id| { + status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( + node_id, + **assignment_type_id, + )); + }); + + for (owned_type_id, occ) in owned_rights_structure { + let len = owned_rights + .get(owned_type_id) + .map(TypedAssignments::len) + .unwrap_or(0); + + // Checking number of assignment occurrences + if let Err(err) = occ.check(len as u16) { + status.add_failure(validation::Failure::SchemaOwnedRightOccurrencesError( + node_id, + *owned_type_id, + err, + )); + } + + let assignment = &self + .owned_right_types + .get(owned_type_id) + .expect("If the assignment were absent, the schema would not be able to pass the internal validation and we would not reach this point"); + + match owned_rights.get(owned_type_id) { + None => {} + Some(TypedAssignments::Void(set)) => set.iter().for_each(|data| { + status += assignment.validate(&node_id, *owned_type_id, data) + }), + Some(TypedAssignments::Value(set)) => set.iter().for_each(|data| { + status += assignment.validate(&node_id, *owned_type_id, data) + }), + Some(TypedAssignments::Data(set)) => set.iter().for_each(|data| { + status += assignment.validate(&node_id, *owned_type_id, data) + }), + Some(TypedAssignments::Attachment(set)) => set.iter().for_each(|data| { + status += assignment.validate(&node_id, *owned_type_id, data) + }), + }; + } + + status + } + + fn validate_public_rights( + &self, + node_id: NodeId, + public_rights: &PublicRights, + public_rights_structure: &PublicRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + public_rights + .difference(public_rights_structure) + .for_each(|public_type_id| { + status.add_failure(validation::Failure::SchemaUnknownPublicRightType( + node_id, + *public_type_id, + )); + }); + + status + } + + #[allow(clippy::too_many_arguments)] + fn validate_state_evolution( + &self, + node_id: NodeId, + node_subtype: NodeSubtype, + parent_owned_rights: &OwnedRights, + owned_rights: &OwnedRights, + parent_public_rights: &PublicRights, + public_rights: &PublicRights, + metadata: &Metadata, + script: &ValidationScript, + ) -> validation::Status { + let mut status = validation::Status::new(); + + // We do not validate public rights, since they do not have an + // associated state and there is nothing to validate beyond schema + + if let Err(err) = script.validate( + node_id, + node_subtype, + parent_owned_rights, + owned_rights, + parent_public_rights, + public_rights, + metadata, + ) { + status.add_failure(err); + } + + status + } + } + + fn extract_parent_owned_rights( + nodes: &BTreeMap, + parent_owned_rights: &ParentOwnedRights, + status: &mut validation::Status, + ) -> OwnedRights { + let mut owned_rights = OwnedRights::default(); + for (id, details) in parent_owned_rights.iter() { + let parent_node = match nodes.get(id) { + None => { + status.add_failure(validation::Failure::TransitionAbsent(*id)); + continue; + } + Some(node) => node, + }; + + fn filter(set: &[Assignment], indexes: &[u16]) -> Vec> + where + STATE: State + Clone, + STATE::Confidential: PartialEq + Eq, + STATE::Confidential: From<::ConcealedCommitment>, + { + set.iter() + .enumerate() + .filter_map(|(index, item)| { + if indexes.contains(&(index as u16)) { + Some(item.clone()) + } else { + None + } + }) + .collect() + } + + for (type_id, indexes) in details { + match parent_node.owned_rights_by_type(*type_id) { + Some(TypedAssignments::Void(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Void(Default::default())) + .declarative_assignments_mut() + { + state.extend(set); + } + } + Some(TypedAssignments::Value(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Value(Default::default())) + .value_assignments_mut() + { + state.extend(set); + } + } + Some(TypedAssignments::Data(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Data(Default::default())) + .data_assignments_mut() + { + state.extend(set); + } + } + Some(TypedAssignments::Attachment(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Attachment(Default::default())) + .attachment_assignments_mut() + { + state.extend(set); + } + } + None => { + // Presence of the required owned rights type in the + // parent node was already validated; we have nothing to + // report here + } + } + } + } + owned_rights + } + + fn extract_parent_public_rights( + nodes: &BTreeMap, + parent_public_rights: &ParentPublicRights, + status: &mut validation::Status, + ) -> PublicRights { + let mut public_rights = PublicRights::default(); + for (id, public_right_types) in parent_public_rights.iter() { + if nodes.get(id).is_none() { + status.add_failure(validation::Failure::TransitionAbsent(*id)); + } else { + public_rights.extend(public_right_types); + } + } + public_rights + } +} + +mod _validation { + use core::any::Any; + + use amplify::AsAny; + + use super::*; + use crate::contract::AttachmentStrategy; + use crate::schema::OwnedRightType; + use crate::{ + validation, Assignment, DeclarativeStrategy, HashStrategy, NodeId, PedersenStrategy, State, + }; + + impl StateSchema { + pub fn validate( + &self, + // type_system: &TypeSystem, + node_id: &NodeId, + assignment_id: OwnedRightType, + data: &Assignment, + ) -> validation::Status + where + STATE: State, + STATE::Confidential: PartialEq + Eq, + STATE::Confidential: From<::ConcealedCommitment>, + { + let mut status = validation::Status::new(); + match data { + Assignment::Confidential { state, .. } + | Assignment::ConfidentialState { state, .. } => { + let a: &dyn Any = state.as_any(); + match self { + StateSchema::Declarative => { + if a.downcast_ref::<::Confidential>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + StateSchema::DiscreteFiniteField(_) => { + if let Some(value) = + a.downcast_ref::<::Confidential>() + { + // [SECURITY-CRITICAL]: Bulletproofs validation + if let Err(err) = value.verify_bullet_proof() { + status.add_failure(validation::Failure::InvalidBulletproofs( + *node_id, + assignment_id, + err.to_string(), + )); + } + } else { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + + // TODO: When other homomorphic formats will be added, + // add information to the status like with + // hashed data below + } + StateSchema::CustomData() => { + match a.downcast_ref::<::Confidential>() { + None => { + status.add_failure( + validation::Failure::SchemaMismatchedStateType( + assignment_id, + ), + ); + } + Some(_) => { + status.add_info( + validation::Info::UncheckableConfidentialStateData( + *node_id, + assignment_id, + ), + ); + } + } + } + StateSchema::DataContainer => { + if a.downcast_ref::<::Confidential>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + } + } + Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { + let a: &dyn Any = state.as_any(); + match self { + StateSchema::Declarative => { + if a.downcast_ref::<::Revealed>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + StateSchema::DiscreteFiniteField(_format) => { + if a.downcast_ref::<::Revealed>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + // TODO #15: When other homomorphic formats will be added, + // add type check like with hashed data below + } + StateSchema::CustomData(/*format*/) => { + match a.downcast_ref::<::Revealed>() { + None => { + status.add_failure( + validation::Failure::SchemaMismatchedStateType( + assignment_id, + ), + ); + } + Some(_data) => { + // TODO: run strict type validation + } + } + } + StateSchema::DataContainer => { + if a.downcast_ref::<::Revealed>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + } + } + } + status + } + } +} diff --git a/src/validation.rs b/src/validation/verify.rs similarity index 75% rename from src/validation.rs rename to src/validation/verify.rs index 29907ef3..8f8068c6 100644 --- a/src/validation.rs +++ b/src/validation/verify.rs @@ -25,233 +25,6 @@ use crate::stash::Consignment; use crate::temp::ResolveTx; use crate::{data, outpoint, tx, txid, BundleId, Extension, SealEndpoint, TransitionBundle}; -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] -#[display(Debug)] -#[repr(u8)] -pub enum Validity { - Valid, - ValidExceptEndpoints, - UnresolvedTransactions, - Invalid, -} - -#[derive(Clone, Debug, Display, Default)] -//#[derive(StrictEncode, StrictDecode)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -// TODO #42: Display via YAML -#[display(Debug)] -pub struct Status { - pub unresolved_txids: Vec, - pub unmined_endpoint_txids: Vec, - pub failures: Vec, - pub warnings: Vec, - pub info: Vec, -} - -impl AddAssign for Status { - fn add_assign(&mut self, rhs: Self) { - self.unresolved_txids.extend(rhs.unresolved_txids); - self.unmined_endpoint_txids - .extend(rhs.unmined_endpoint_txids); - self.failures.extend(rhs.failures); - self.warnings.extend(rhs.warnings); - self.info.extend(rhs.info); - } -} - -impl Status { - pub fn from_error(v: Failure) -> Self { - Status { - unresolved_txids: vec![], - unmined_endpoint_txids: vec![], - failures: vec![v], - warnings: vec![], - info: vec![], - } - } -} - -impl FromIterator for Status { - fn from_iter>(iter: T) -> Self { - Self { - failures: iter.into_iter().collect(), - ..Self::default() - } - } -} - -impl Status { - pub fn new() -> Self { Self::default() } - - pub fn with_failure(failure: Failure) -> Self { - Self { - failures: vec![failure], - ..Self::default() - } - } - - pub fn add_failure(&mut self, failure: Failure) -> &Self { - self.failures.push(failure); - self - } - - pub fn add_warning(&mut self, warning: Warning) -> &Self { - self.warnings.push(warning); - self - } - - pub fn add_info(&mut self, info: Info) -> &Self { - self.info.push(info); - self - } - - pub fn validity(&self) -> Validity { - if self.failures.is_empty() { - if self.unmined_endpoint_txids.is_empty() { - Validity::Valid - } else { - Validity::ValidExceptEndpoints - } - } else { - if self.unresolved_txids.is_empty() { - Validity::Invalid - } else { - Validity::UnresolvedTransactions - } - } - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Display, From)] -//#[derive(StrictEncode, StrictDecode)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -// TODO #44: (v0.3) convert to detailed error description using doc_comments -#[display(Debug)] -pub enum Failure { - SchemaUnknown(SchemaId), - /// schema is a subschema, so root schema {0} must be provided for the - /// validation - SchemaRootRequired(SchemaId), - /// Root schema for this schema has another root, which is prohibited - SchemaRootHierarchy(SchemaId), - SchemaRootNoFieldTypeMatch(schema::FieldType), - SchemaRootNoOwnedRightTypeMatch(schema::OwnedRightType), - SchemaRootNoPublicRightTypeMatch(schema::PublicRightType), - SchemaRootNoTransitionTypeMatch(schema::TransitionType), - SchemaRootNoExtensionTypeMatch(schema::ExtensionType), - - SchemaRootNoMetadataMatch(NodeType, schema::FieldType), - SchemaRootNoParentOwnedRightsMatch(NodeType, schema::OwnedRightType), - SchemaRootNoParentPublicRightsMatch(NodeType, schema::PublicRightType), - SchemaRootNoOwnedRightsMatch(NodeType, schema::OwnedRightType), - SchemaRootNoPublicRightsMatch(NodeType, schema::PublicRightType), - - SchemaUnknownExtensionType(NodeId, schema::ExtensionType), - SchemaUnknownTransitionType(NodeId, schema::TransitionType), - SchemaUnknownFieldType(NodeId, schema::FieldType), - SchemaUnknownOwnedRightType(NodeId, schema::OwnedRightType), - SchemaUnknownPublicRightType(NodeId, schema::PublicRightType), - - SchemaDeniedScriptExtension(NodeId), - - SchemaMetaValueTooSmall(schema::FieldType), - SchemaMetaValueTooLarge(schema::FieldType), - SchemaStateValueTooSmall(schema::OwnedRightType), - SchemaStateValueTooLarge(schema::OwnedRightType), - - SchemaWrongEnumValue { - field_or_state_type: u16, - unexpected: u8, - }, - SchemaWrongDataLength { - field_or_state_type: u16, - max_expected: u16, - found: usize, - }, - SchemaMismatchedDataType(u16), - SchemaMismatchedStateType(schema::OwnedRightType), - - SchemaMetaOccurrencesError(NodeId, schema::FieldType, OccurrencesError), - SchemaParentOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesError), - SchemaOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesError), - - SchemaScriptOverrideDenied, - SchemaScriptVmChangeDenied, - - SchemaTypeSystem(/* TODO: use error from strict types */), - - BundleInvalid(BundleId), - - TransitionAbsent(NodeId), - TransitionNotAnchored(NodeId), - TransitionNotInAnchor(NodeId, Txid), - TransitionParentWrongSealType { - node_id: NodeId, - ancestor_id: NodeId, - assignment_type: schema::OwnedRightType, - }, - TransitionParentWrongSeal { - node_id: NodeId, - ancestor_id: NodeId, - assignment_type: schema::OwnedRightType, - seal_index: u16, - }, - TransitionParentConfidentialSeal { - node_id: NodeId, - ancestor_id: NodeId, - assignment_type: schema::OwnedRightType, - seal_index: u16, - }, - TransitionParentIsNotWitnessInput { - node_id: NodeId, - ancestor_id: NodeId, - assignment_type: schema::OwnedRightType, - seal_index: u16, - outpoint: bp::Outpoint, - }, - - ExtensionAbsent(NodeId), - ExtensionParentWrongValenciesType { - node_id: NodeId, - ancestor_id: NodeId, - valencies_type: schema::PublicRightType, - }, - - WitnessTransactionMissed(Txid), - WitnessNoCommitment(NodeId, Txid), - - EndpointTransitionNotFound(NodeId), - - InvalidStateDataType(NodeId, u16, /* TODO: Use strict type */ data::Revealed), - InvalidStateDataValue(NodeId, u16, /* TODO: Use strict type */ Vec), - - /// invalid bulletproofs in {0}:{1}: {3} - InvalidBulletproofs(NodeId, u16, String), - - ScriptFailure(NodeId), -} - -#[derive(Clone, PartialEq, Eq, Debug, Display, From)] -//#[derive(StrictEncode, StrictDecode)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -// TODO #44: (v0.3) convert to detailed descriptions using doc_comments -#[display(Debug)] -pub enum Warning { - EndpointDuplication(NodeId, SealEndpoint), - EndpointTransitionSealNotFound(NodeId, SealEndpoint), - ExcessiveNode(NodeId), - EndpointTransactionMissed(Txid), -} - -#[derive(Clone, PartialEq, Eq, Debug, Display, From)] -//#[derive(StrictEncode, StrictDecode)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -// TODO #44: (v0.3) convert to detailed descriptions using doc_comments -#[display(Debug)] -pub enum Info { - UncheckableConfidentialStateData(NodeId, u16), -} - pub struct Validator<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> { consignment: &'consignment C, @@ -514,7 +287,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> self.validate_graph_node(node, bundle_id, anchor); self.anchor_validation_index.insert(node_id); } - // Ouch, we are out of that multi-level nested cycles :) + // Ouch, we are out of that multi-level nested cycles :) } else if node_type != NodeType::Genesis && node_type != NodeType::StateExtension { // This point is actually unreachable: b/c of the // consignment structure, each state transition From bed59d6ef1e0ebf4897d9197e8fcd71898cb7840 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 20:22:49 +0100 Subject: [PATCH 19/71] schema: refactor id type --- .rustfmt.toml | 15 +++-- Cargo.lock | 131 +++++++++++++------------------------- Cargo.toml | 21 +++--- src/ext.rs | 16 +++++ src/lib.rs | 12 ++-- src/schema/nodes.rs | 19 +++--- src/schema/occurrences.rs | 35 ---------- src/schema/schema.rs | 85 +++++++++++++++++-------- 8 files changed, 159 insertions(+), 175 deletions(-) create mode 100644 src/ext.rs diff --git a/.rustfmt.toml b/.rustfmt.toml index 8a9b2689..952a2846 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,22 +1,27 @@ +edition = "2021" +version = "Two" + max_width = 100 array_width = 100 attr_fn_like_width = 100 -comment_width = 100 -single_line_if_else_max_width = 100 +fn_call_width = 100 format_code_in_doc_comments = true fn_single_line = true format_macro_matchers = true -format_strings = false +format_macro_bodues = true +format_strings = true merge_derives = false overflow_delimited_expr = true reorder_modules = false use_field_init_shorthand = true use_try_shorthand = true -wrap_comments = false +wrap_comments = true where_single_line = true unstable_features = true +empty_item_single_line = true + +binop_separator = "Back" -license_template_path = "license_header" imports_granularity = "Module" group_imports = "StdExternalCrate" diff --git a/Cargo.lock b/Cargo.lock index 874ae141..1e781721 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,19 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aluvm" +version = "0.10.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6d717a98f205e67c0fad3702b561fbb9cf405da8c24d88ab8459cd311bd067" +dependencies = [ + "amplify 4.0.0-beta.11", + "bech32", + "bitcoin_hashes", + "half", + "paste", +] + [[package]] name = "amplify" version = "3.13.0" @@ -344,6 +357,12 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -398,41 +417,6 @@ dependencies = [ "syn", ] -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core", - "quote", - "syn", -] - [[package]] name = "digest" version = "0.10.6" @@ -456,12 +440,6 @@ dependencies = [ "syn", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "generic-array" version = "0.14.6" @@ -483,6 +461,15 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -495,12 +482,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - [[package]] name = "iana-time-zone" version = "0.1.53" @@ -525,12 +506,6 @@ dependencies = [ "cxx-build", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "indexmap" version = "1.9.2" @@ -685,16 +660,17 @@ dependencies = [ name = "rgb-core" version = "0.10.0-alpha.1" dependencies = [ + "aluvm", "amplify 4.0.0-beta.11", - "bitcoin_hashes", + "baid58", "bp-core", "commit_verify", - "once_cell", "secp256k1-zkp", "serde", "serde_json", - "serde_with", + "strict_encoding 2.0.0-beta.5", "strict_encoding_test", + "strict_types", ] [[package]] @@ -812,29 +788,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde_with" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" -dependencies = [ - "hex", - "serde", - "serde_with_macros", -] - -[[package]] -name = "serde_with_macros" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "serde_yaml" version = "0.9.17" @@ -877,6 +830,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8ce22c5bba8139f2182001358188f145b40b177a9a442545cf15574335fba88" dependencies = [ "amplify 4.0.0-beta.11", + "half", "strict_encoding_derive 2.0.0-beta.2", ] @@ -915,6 +869,19 @@ dependencies = [ "strict_encoding 0.9.0", ] +[[package]] +name = "strict_types" +version = "1.0.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "785615cb6b6a49a534732bae54a3172a8809e523bb7ebfc371ad01936da56a24" +dependencies = [ + "amplify 4.0.0-beta.11", + "baid58", + "blake3", + "half", + "strict_encoding 2.0.0-beta.5", +] + [[package]] name = "stringly_conversions" version = "0.1.1" @@ -925,12 +892,6 @@ dependencies = [ "serde_str_helpers", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "subtle" version = "2.4.1" diff --git a/Cargo.toml b/Cargo.toml index 15769e86..b3e266a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,13 +20,13 @@ path = "src/lib.rs" [dependencies] amplify = { version = "~4.0.0-beta.11", features = ["apfloat"] } bp-core = { version = "~0.10.0-beta.1" } +strict_encoding = "2.0.0-beta.5" +strict_types = "1.0.0-beta.2" +aluvm = "0.10.0-alpha.1" commit_verify = { version = "~0.10.0-beta.2", features = ["rand"] } -bitcoin_hashes = "0.11.0" +baid58 = "~0.1.0" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } -serde_with = { version = "1.14", features = ["hex"], optional = true } # TODO: Remove -serde_json = "1" # TODO: Remove -once_cell = "1.12.0" -secp256k1-zkp = { version = "0.7.0", features = ["rand-std", "global-context"] } +secp256k1-zkp = { version = "~0.7.0", features = ["rand-std", "global-context"] } [dev-dependencies] serde_json = "1" @@ -35,7 +35,10 @@ strict_encoding_test = "0.9.0" [features] default = [] all = ["serde"] -serde = ["serde_crate", "serde_with", - "amplify/serde", "commit_verify/serde", - "bp-core/serde", - "secp256k1-zkp/serde"] +serde = [ + "serde_crate", + "amplify/serde", + "commit_verify/serde", + "bp-core/serde", + "secp256k1-zkp/serde" +] diff --git a/src/ext.rs b/src/ext.rs new file mode 100644 index 00000000..1e51b500 --- /dev/null +++ b/src/ext.rs @@ -0,0 +1,16 @@ +//! Parts which need to be moved to other crates + +use amplify::{Array, Wrapper}; + +pub trait RawArray { + fn from_raw_array(val: [u8; LEN]) -> Self; + fn to_raw_array(&self) -> [u8; LEN]; +} + +impl RawArray for Id +where Id: Wrapper> +{ + fn from_raw_array(val: [u8; LEN]) -> Self { Self::from_inner(Array::from_inner(val)) } + + fn to_raw_array(&self) -> [u8; LEN] { self.as_inner().into_inner() } +} diff --git a/src/lib.rs b/src/lib.rs index 3d9d7b41..a49ffb77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,16 +25,14 @@ #[macro_use] extern crate amplify; -// #[macro_use] -// extern crate strict_encoding; +#[macro_use] +extern crate strict_encoding; #[cfg(feature = "serde")] #[macro_use] -extern crate serde_with; -#[cfg(feature = "serde")] extern crate serde_crate as serde; -// pub(crate) mod temp; +pub(crate) mod ext; // pub mod contract; pub mod schema; @@ -45,6 +43,8 @@ pub mod schema; // #[macro_use] // mod macros; +pub const LIB_NAME_RGB: &str = "RGB"; + pub mod prelude { pub use bp::dbc::{Anchor, AnchorId}; /*pub use contract::{ @@ -57,7 +57,7 @@ pub mod prelude { StateType, Transition, TypedAssignments, };*/ pub use schema::{ - script, ExtensionSchema, ExtensionType, NodeSubtype, NodeType, PublicRightType, + ExtensionSchema, ExtensionType, NodeSubtype, NodeType, PublicRightType, PublicRightsStructure, Schema, SchemaId, ValidationScript, VmType, }; diff --git a/src/schema/nodes.rs b/src/schema/nodes.rs index 8c1260d5..72a0eddd 100644 --- a/src/schema/nodes.rs +++ b/src/schema/nodes.rs @@ -11,8 +11,6 @@ use std::collections::{BTreeMap, BTreeSet}; -use once_cell::sync::Lazy; - use super::{ExtensionType, FieldType, Occurrences, TransitionType}; // Here we can use usize since encoding/decoding makes sure that it's u16 @@ -100,18 +98,17 @@ pub struct TransitionSchema { pub public_rights: PublicRightsStructure, } -static EMPTY_OWNED_RIGHTS: Lazy = Lazy::new(OwnedRightsStructure::new); -static EMPTY_PUBLIC_RIGHTS: Lazy = Lazy::new(PublicRightsStructure::new); - impl NodeSchema for GenesisSchema { #[inline] fn node_type(&self) -> NodeType { NodeType::Genesis } #[inline] fn metadata(&self) -> &MetadataStructure { &self.metadata } #[inline] - fn closes(&self) -> &OwnedRightsStructure { &EMPTY_OWNED_RIGHTS } + fn closes(&self) -> &OwnedRightsStructure { + panic!("genesis can't close previous single-use-seals") + } #[inline] - fn extends(&self) -> &PublicRightsStructure { &EMPTY_PUBLIC_RIGHTS } + fn extends(&self) -> &PublicRightsStructure { panic!("genesis can't extend previous state") } #[inline] fn owned_rights(&self) -> &OwnedRightsStructure { &self.owned_rights } #[inline] @@ -124,7 +121,9 @@ impl NodeSchema for ExtensionSchema { #[inline] fn metadata(&self) -> &MetadataStructure { &self.metadata } #[inline] - fn closes(&self) -> &OwnedRightsStructure { &EMPTY_OWNED_RIGHTS } + fn closes(&self) -> &OwnedRightsStructure { + panic!("extension can't close previous single-use-seals") + } #[inline] fn extends(&self) -> &PublicRightsStructure { &self.extends } #[inline] @@ -141,7 +140,9 @@ impl NodeSchema for TransitionSchema { #[inline] fn closes(&self) -> &OwnedRightsStructure { &self.closes } #[inline] - fn extends(&self) -> &PublicRightsStructure { &EMPTY_PUBLIC_RIGHTS } + fn extends(&self) -> &PublicRightsStructure { + panic!("state transitions can't extend previous state") + } #[inline] fn owned_rights(&self) -> &OwnedRightsStructure { &self.owned_rights } #[inline] diff --git a/src/schema/occurrences.rs b/src/schema/occurrences.rs index 1f4b420c..e4149af3 100644 --- a/src/schema/occurrences.rs +++ b/src/schema/occurrences.rs @@ -84,19 +84,8 @@ pub struct OccurrencesError { #[cfg(test)] mod test { - use strict_encoding::StrictDecode; - use strict_encoding_test::test_vec_decoding_roundtrip; - use super::Occurrences; - static ONCE: [u8; 4] = [1, 0, 1, 0]; - - static NONEORONCE: [u8; 4] = [0, 0, 1, 0]; - - static NONEUPTO_U8: [u8; 4] = [0, 0, 255, 0]; - - static NONEUPTO_U16: [u8; 4] = [0, 0, 255, 255]; - #[test] fn test_once_check_count() { let occurence: Occurrences = Occurrences::Once; @@ -192,28 +181,4 @@ mod test { let occurence: Occurrences = Occurrences::NoneOrUpTo(42); occurence.check(43).unwrap(); } - - #[test] - fn test_encode_occurance() { - let _: Occurrences = test_vec_decoding_roundtrip(ONCE).unwrap(); - let _: Occurrences = test_vec_decoding_roundtrip(NONEORONCE).unwrap(); - let _: Occurrences = test_vec_decoding_roundtrip(NONEUPTO_U16).unwrap(); - } - - #[test] - fn test_encode_occurance_2() { - let mut once_upto_u8 = NONEUPTO_U8.clone(); - let mut once_upto_u16 = NONEUPTO_U16.clone(); - - once_upto_u8[0] = 0x01; - once_upto_u16[0] = 0x01; - - let dec2: Occurrences = Occurrences::strict_decode(&once_upto_u16[..]).unwrap(); - - assert_eq!(dec2, Occurrences::OnceOrMore); - - let wc2: Occurrences = Occurrences::strict_decode(&once_upto_u8[..]).unwrap(); - - assert_eq!(wc2, Occurrences::OnceOrUpTo(255)); - } } diff --git a/src/schema/schema.rs b/src/schema/schema.rs index d4263a66..8a8a86da 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -11,40 +11,50 @@ use std::collections::{BTreeMap, BTreeSet}; -use amplify::flags::FlagVec; -use bitcoin_hashes::{sha256, sha256t}; +use amplify::Bytes32; +use baid58::ToBaid58; +use commit_verify::{strategies, CommitStrategy}; -use super::{ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, TransitionSchema}; -use crate::schema::StateSchema; -use crate::script::OverrideRules; -use crate::ValidationScript; +use super::script::OverrideRules; +use super::{ + ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, StateSchema, TransitionSchema, + ValidationScript, +}; +use crate::ext::RawArray; +use crate::LIB_NAME_RGB; // Here we can use usize since encoding/decoding makes sure that it's u16 pub type FieldType = u16; pub type ExtensionType = u16; pub type TransitionType = u16; -static MIDSTATE_SHEMA_ID: [u8; 32] = [ - 0x81, 0x73, 0x33, 0x7c, 0xcb, 0xc4, 0x8b, 0xd1, 0x24, 0x89, 0x65, 0xcd, 0xd0, 0xcd, 0xb6, 0xc8, - 0x7a, 0xa2, 0x14, 0x81, 0x7d, 0x57, 0x39, 0x22, 0x28, 0x90, 0x74, 0x8f, 0x26, 0x75, 0x8e, 0xea, -]; +/// Schema identifier. +/// +/// Schema identifier commits to all of the schema data. +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] +#[wrapper(Deref, BorrowSlice, FromStr, Hex, Index, RangeOps)] +#[display(Self::to_baid58)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct SchemaId( + #[from] + #[from([u8; 32])] + Bytes32, +); -/// Tag used for [`SchemaId`] hash type -pub struct SchemaIdTag; - -impl sha256t::Tag for SchemaIdTag { - #[inline] - fn engine() -> sha256::HashEngine { - let midstate = sha256::Midstate::from_inner(MIDSTATE_SHEMA_ID); - sha256::HashEngine::from_midstate(midstate, 64) - } +impl CommitStrategy for SchemaId { + type Strategy = strategies::Strict; } -/// Commitment-based schema identifier used for committing to the schema type -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[wrapper(Debug, BorrowSlice)] -pub struct SchemaId(sha256t::Hash); +impl ToBaid58<32> for SchemaId { + const HRP: &'static str = "sch"; + fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() } +} #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] @@ -59,8 +69,7 @@ pub struct Schema { /// or do other backward-incompatible changes (RGB protocol versions are /// not interoperable and backward-incompatible by definitions and the /// nature of client-side-validation which does not allow upgrades). - #[cfg_attr(feature = "serde", serde(with = "serde_with::rust::display_fromstr"))] - pub rgb_features: FlagVec, + pub rgb_features: u16, pub root_id: SchemaId, pub type_system: Vec, // TODO: TypeSystem, @@ -92,3 +101,27 @@ impl PartialEq for Schema { } impl Eq for Schema {} + +#[cfg(test)] +mod test { + use strict_encoding::StrictDumb; + + use super::*; + + #[test] + fn display() { + let dumb = SchemaId::strict_dumb(); + assert_eq!(dumb.to_string(), "11111111111111111111111111111111"); + assert_eq!( + &format!("{dumb::^#}"), + "sch:11111111111111111111111111111111#dallas-liter-marco" + ); + + let less_dumb = SchemaId::from_raw_array(*b"EV4350-'4vwj'4;v-w94w'e'vFVVDhpq"); + assert_eq!(less_dumb.to_string(), "5ffNUkMTVSnWquPLT6xKb7VmAxUbw8CUNqCkUWsZfkwz"); + assert_eq!( + &format!("{less_dumb::^#}"), + "sch:5ffNUkMTVSnWquPLT6xKb7VmAxUbw8CUNqCkUWsZfkwz#hotel-urgent-child" + ); + } +} From 67535a1142f88a0eed83045db2e7c749fadabb55 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 20:23:20 +0100 Subject: [PATCH 20/71] schema: prohibit script overrides --- src/schema/schema.rs | 8 -------- src/schema/script.rs | 29 ----------------------------- 2 files changed, 37 deletions(-) diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 8a8a86da..153d2bf6 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -15,7 +15,6 @@ use amplify::Bytes32; use baid58::ToBaid58; use commit_verify::{strategies, CommitStrategy}; -use super::script::OverrideRules; use super::{ ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, StateSchema, TransitionSchema, ValidationScript, @@ -82,13 +81,6 @@ pub struct Schema { /// Validation code. pub script: ValidationScript, - - /// Defines whether subschemata are allowed to replace (override) the code - /// - /// Subschemata not overriding the main schema code MUST set the virtual - /// machine type to the same as in the parent schema and set byte code - /// to be empty (zero-length) - pub override_rules: OverrideRules, } impl Schema { diff --git a/src/schema/script.rs b/src/schema/script.rs index 55b1849c..6431fe38 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -46,32 +46,3 @@ impl ValidationScript { } } } - -/// VM and script overwrite rules by subschemata. -/// -/// Defines whether subschemata are allowed to replace (overwrite) the type of -/// VM and scripts. -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "kebab-case") -)] -#[repr(u8)] -pub enum OverrideRules { - #[display("deny")] - /// Denies overwrites - Deny = 0u8, - - #[display("allow-same-vm")] - /// Allows overwrite only if the same VM is used - AllowSameVm = 1u8, - - #[display("allow-any-vm")] - /// Allows overwrite of both executable code and type of VM - AllowAnyVm = 2u8, -} - -impl Default for OverrideRules { - fn default() -> Self { OverrideRules::Deny } -} From bfd73e8d96474520c053800e235f6593d4de6496 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 Feb 2023 21:01:36 +0100 Subject: [PATCH 21/71] schema: refactor state types --- Cargo.lock | 220 +++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 7 +- src/ext.rs | 15 --- src/schema/mod.rs | 2 +- src/schema/schema.rs | 12 +-- src/schema/state.rs | 48 +++++----- 6 files changed, 236 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e781721..540b9f50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,11 +8,14 @@ version = "0.10.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6d717a98f205e67c0fad3702b561fbb9cf405da8c24d88ab8459cd311bd067" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "bech32", "bitcoin_hashes", + "curve25519-dalek", "half", "paste", + "secp256k1 0.26.0", + "serde", ] [[package]] @@ -28,9 +31,9 @@ dependencies = [ [[package]] name = "amplify" -version = "4.0.0-beta.11" +version = "4.0.0-beta.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414f38fa6badd4440d87c4e3abb6abb2d99cce34cff3af50ad6ee83004f03716" +checksum = "aa4030ef5731f8cab39af812fc4df7a29b2a46bd40fe5dd5b903865a27368e85" dependencies = [ "amplify_apfloat", "amplify_derive 4.0.0-alpha.5", @@ -169,6 +172,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bech32" version = "0.9.1" @@ -212,7 +221,7 @@ dependencies = [ "cc", "cfg-if", "constant_time_eq", - "digest", + "digest 0.10.6", ] [[package]] @@ -230,7 +239,7 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75939aecb6e7ad3e30622d8fba00ccdf3cdc78f2325840629ee53cd792548be9" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "bp-dbc", "bp-primitives", "bp-seals", @@ -246,7 +255,7 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d67f8173cc60f6671df19a170021a4f3a179f828b2114ba0415124dd8abd07f" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "bp-primitives", "commit_verify", "secp256k1 0.26.0", @@ -260,7 +269,7 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aab03dbc8e2cf19594d3a267cccfc0fd2595ce0818babf39b9e817cb7683e1e4" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "commit_verify", "secp256k1 0.26.0", "serde", @@ -273,7 +282,7 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "463f314e2c6370104c40356fc96cd464bd0f02aba1a2ffd83dc524e4ecf58d41" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "baid58", "bp-dbc", "bp-primitives", @@ -317,7 +326,8 @@ dependencies = [ "js-sys", "num-integer", "num-traits", - "time", + "serde", + "time 0.1.45", "wasm-bindgen", "winapi", ] @@ -338,7 +348,7 @@ version = "0.10.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7ce27ce9d56cac2631f9701984dc4fd162abbd7b563d97e4440db56f7282cc9" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "bitcoin_hashes", "rand", "serde", @@ -373,6 +383,20 @@ dependencies = [ "typenum", ] +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + [[package]] name = "cxx" version = "1.0.89" @@ -417,6 +441,50 @@ dependencies = [ "syn", ] +[[package]] +name = "darling" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.6" @@ -440,6 +508,12 @@ dependencies = [ "syn", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "generic-array" version = "0.14.6" @@ -450,6 +524,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -482,6 +567,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "iana-time-zone" version = "0.1.53" @@ -506,6 +597,12 @@ dependencies = [ "cxx-build", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "1.9.2" @@ -514,6 +611,7 @@ checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] @@ -634,7 +732,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -644,7 +742,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -653,7 +760,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.8", ] [[package]] @@ -661,7 +768,7 @@ name = "rgb-core" version = "0.10.0-alpha.1" dependencies = [ "aluvm", - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "baid58", "bp-core", "commit_verify", @@ -788,6 +895,34 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_with" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d904179146de381af4c93d3af6ca4984b3152db687dacb9c3c35e86f39809c" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap", + "serde", + "serde_json", + "serde_with_macros", + "time 0.3.17", +] + +[[package]] +name = "serde_with_macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_yaml" version = "0.9.17" @@ -829,8 +964,9 @@ version = "2.0.0-beta.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8ce22c5bba8139f2182001358188f145b40b177a9a442545cf15574335fba88" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "half", + "serde", "strict_encoding_derive 2.0.0-beta.2", ] @@ -871,14 +1007,17 @@ dependencies = [ [[package]] name = "strict_types" -version = "1.0.0-beta.2" +version = "1.0.0-beta.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785615cb6b6a49a534732bae54a3172a8809e523bb7ebfc371ad01936da56a24" +checksum = "11170f93c7f969209d86c4a3a6a7a6b333772890a7303647e5e055800840df9b" dependencies = [ - "amplify 4.0.0-beta.11", + "amplify 4.0.0-beta.13", "baid58", "blake3", "half", + "serde", + "serde_with", + "serde_yaml", "strict_encoding 2.0.0-beta.5", ] @@ -892,6 +1031,12 @@ dependencies = [ "serde_str_helpers", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "2.4.1" @@ -929,6 +1074,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + [[package]] name = "toml" version = "0.5.11" @@ -968,6 +1140,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -1064,3 +1242,9 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/Cargo.toml b/Cargo.toml index b3e266a0..7be41fcb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,10 +18,10 @@ name = "rgb" path = "src/lib.rs" [dependencies] -amplify = { version = "~4.0.0-beta.11", features = ["apfloat"] } +amplify = { version = "~4.0.0-beta.13", features = ["apfloat"] } bp-core = { version = "~0.10.0-beta.1" } strict_encoding = "2.0.0-beta.5" -strict_types = "1.0.0-beta.2" +strict_types = "1.0.0-beta.3" aluvm = "0.10.0-alpha.1" commit_verify = { version = "~0.10.0-beta.2", features = ["rand"] } baid58 = "~0.1.0" @@ -38,7 +38,10 @@ all = ["serde"] serde = [ "serde_crate", "amplify/serde", + "strict_encoding/serde", + "strict_types/serde", "commit_verify/serde", "bp-core/serde", + "aluvm/serde", "secp256k1-zkp/serde" ] diff --git a/src/ext.rs b/src/ext.rs index 1e51b500..f9cf4cc3 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -1,16 +1 @@ //! Parts which need to be moved to other crates - -use amplify::{Array, Wrapper}; - -pub trait RawArray { - fn from_raw_array(val: [u8; LEN]) -> Self; - fn to_raw_array(&self) -> [u8; LEN]; -} - -impl RawArray for Id -where Id: Wrapper> -{ - fn from_raw_array(val: [u8; LEN]) -> Self { Self::from_inner(Array::from_inner(val)) } - - fn to_raw_array(&self) -> [u8; LEN] { self.as_inner().into_inner() } -} diff --git a/src/schema/mod.rs b/src/schema/mod.rs index df5e692d..daf13070 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -23,4 +23,4 @@ pub use nodes::{ pub use occurrences::{Occurrences, OccurrencesError}; pub use schema::{ExtensionType, FieldType, Schema, SchemaId, TransitionType}; pub use script::{ValidationScript, VmType}; -pub use state::{DiscreteFiniteFieldFormat, StateSchema, StateType}; +pub use state::{DiscreteFiniteFieldFormat, StateSchema}; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 153d2bf6..85a1ab6d 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -11,18 +11,17 @@ use std::collections::{BTreeMap, BTreeSet}; -use amplify::Bytes32; +use amplify::{Bytes32, RawArray}; use baid58::ToBaid58; use commit_verify::{strategies, CommitStrategy}; +use strict_types::SemId; use super::{ ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, StateSchema, TransitionSchema, ValidationScript, }; -use crate::ext::RawArray; use crate::LIB_NAME_RGB; -// Here we can use usize since encoding/decoding makes sure that it's u16 pub type FieldType = u16; pub type ExtensionType = u16; pub type TransitionType = u16; @@ -69,16 +68,17 @@ pub struct Schema { /// not interoperable and backward-incompatible by definitions and the /// nature of client-side-validation which does not allow upgrades). pub rgb_features: u16, - pub root_id: SchemaId, + pub subset_of: Option, - pub type_system: Vec, // TODO: TypeSystem, - pub field_types: BTreeMap, + pub field_types: BTreeMap, pub owned_right_types: BTreeMap, pub public_right_types: BTreeSet, pub genesis: GenesisSchema, pub extensions: BTreeMap, pub transitions: BTreeMap, + /// Type system + pub type_system: Vec, // TODO: TypeSystem, /// Validation code. pub script: ValidationScript, } diff --git a/src/schema/state.rs b/src/schema/state.rs index 5b35f072..84844d58 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -9,47 +9,43 @@ // You should have received a copy of the MIT License along with this software. // If not, see . -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "snake_case") -)] -#[repr(u8)] -pub enum StateType { - Declarative = 0, - DiscreteFiniteField = 1, - CustomData = 2, - DataContainer = 3, -} +use strict_types::SemId; + +use crate::LIB_NAME_RGB; -#[derive(Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = order)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "snake_case") + serde(crate = "serde_crate", rename_all = "camelCase") )] pub enum StateSchema { + #[strict_type(dumb)] Declarative, DiscreteFiniteField(DiscreteFiniteFieldFormat), - CustomData(/* TODO: Insert strict types type */), + CustomData(SemId), DataContainer, } -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "lowercase") -)] -#[repr(u8)] /// Today we support only a single format of confidential data, because of the /// limitations of the underlying secp256k1-zkp library: it works only with /// u64 numbers. Nevertheless, homomorphic commitments can be created to /// everything that has up to 256 bits and commutative arithmetics, so in the /// future we plan to support more types. We reserve this possibility by -/// internally encoding [ConfidentialFormat] with the same type specification -/// details as used for [DateFormat] +/// internally encoding [`ConfidentialFormat`] with the same type specification +/// details as used for [`DateFormat`] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = repr, into_u8, try_from_u8)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "camelCase") +)] +#[repr(u8)] pub enum DiscreteFiniteFieldFormat { - Unsigned64bit, + #[default] + Unsigned64Bit = 64, } From 59ad7d8c358b2e2a1f0de64ab76096c63e011f0d Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 01:24:48 +0100 Subject: [PATCH 22/71] schema: impl Occurences converters and encoding --- src/schema/mod.rs | 2 +- src/schema/occurrences.rs | 90 ++++++++++++++++++++++++++++++++++----- 2 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/schema/mod.rs b/src/schema/mod.rs index daf13070..d3221415 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -20,7 +20,7 @@ pub use nodes::{ ExtensionSchema, GenesisSchema, MetadataStructure, NodeSchema, NodeSubtype, NodeType, OwnedRightType, OwnedRightsStructure, PublicRightType, PublicRightsStructure, TransitionSchema, }; -pub use occurrences::{Occurrences, OccurrencesError}; +pub use occurrences::{Occurrences, OccurrencesMismatch}; pub use schema::{ExtensionType, FieldType, Schema, SchemaId, TransitionType}; pub use script::{ValidationScript, VmType}; pub use state::{DiscreteFiniteFieldFormat, StateSchema}; diff --git a/src/schema/occurrences.rs b/src/schema/occurrences.rs index e4149af3..84323969 100644 --- a/src/schema/occurrences.rs +++ b/src/schema/occurrences.rs @@ -9,9 +9,17 @@ // You should have received a copy of the MIT License along with this software. // If not, see . +use std::io; use std::ops::RangeInclusive; -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +use strict_encoding::{ + DecodeError, ReadStruct, StrictDecode, StrictEncode, StrictProduct, StrictStruct, StrictType, + TypeName, TypedRead, TypedWrite, WriteStruct, +}; + +use crate::LIB_NAME_RGB; + +#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -19,6 +27,7 @@ use std::ops::RangeInclusive; )] #[repr(u8)] pub enum Occurrences { + #[default] Once, NoneOrOnce, NoneOrMore, @@ -53,7 +62,7 @@ impl Occurrences { } } - pub fn check(&self, count: u16) -> Result<(), OccurrencesError> { + pub fn check(&self, count: u16) -> Result<(), OccurrencesMismatch> { let orig_count = count; match self { Occurrences::Once if count == 1 => Ok(()), @@ -64,7 +73,7 @@ impl Occurrences { Occurrences::NoneOrUpTo(max) if count <= *max => Ok(()), Occurrences::Exactly(val) if count == *val => Ok(()), Occurrences::Range(range) if range.contains(&count) => Ok(()), - _ => Err(OccurrencesError { + _ => Err(OccurrencesMismatch { min: self.min_value(), max: self.max_value(), found: orig_count, @@ -73,10 +82,69 @@ impl Occurrences { } } +#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] +#[display(doc_comments)] +pub enum OccurrencesError { + /// unable to construct occurrences value with both minimum and maximum + /// number set to zero. + Zero, + + /// unable to construct occurrences value with minimum number exceeding + /// maximum + MinExceedsMax, +} + +impl TryFrom> for Occurrences { + type Error = OccurrencesError; + + fn try_from(range: RangeInclusive) -> Result { + Ok(match (*range.start(), *range.end()) { + (0, 0) => return Err(OccurrencesError::Zero), + (a, b) if a > b => return Err(OccurrencesError::MinExceedsMax), + (0, 1) => Occurrences::NoneOrOnce, + (1, 1) => Occurrences::Once, + (0, u16::MAX) => Occurrences::NoneOrMore, + (1, u16::MAX) => Occurrences::OnceOrMore, + (0, max) => Occurrences::NoneOrUpTo(max), + (1, max) => Occurrences::OnceOrUpTo(max), + (a, b) if a == b => Occurrences::Exactly(a), + (min, max) => Occurrences::Range(min..=max), + }) + } +} + +impl StrictType for Occurrences { + const STRICT_LIB_NAME: &'static str = LIB_NAME_RGB; + fn strict_name() -> Option { Some(tn!("Occurrences")) } +} +impl StrictProduct for Occurrences {} +impl StrictStruct for Occurrences { + const ALL_FIELDS: &'static [&'static str] = &["min", "max"]; +} +impl StrictEncode for Occurrences { + fn strict_encode(&self, writer: W) -> io::Result { + writer.write_struct::(|w| { + Ok(w.write_field(fname!("min"), &self.min_value())? + .write_field(fname!("max"), &self.max_value())? + .complete()) + }) + } +} +impl StrictDecode for Occurrences { + fn strict_decode(reader: &mut impl TypedRead) -> Result { + reader.read_struct(|r| { + let min = r.read_field(fname!("min"))?; + let max = r.read_field(fname!("max"))?; + Occurrences::try_from(min..=max) + .map_err(|err| DecodeError::DataIntegrityError(err.to_string())) + }) + } +} + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] #[display(Debug)] -pub struct OccurrencesError { +pub struct OccurrencesMismatch { pub min: u16, pub max: u16, pub found: u16, @@ -92,13 +160,13 @@ mod test { occurence.check(1).unwrap(); } #[test] - #[should_panic(expected = "OccurrencesError { min: 1, max: 1, found: 0 }")] + #[should_panic(expected = "OccurrencesMismatch { min: 1, max: 1, found: 0 }")] fn test_once_check_count_fail_zero() { let occurence: Occurrences = Occurrences::Once; occurence.check(0).unwrap(); } #[test] - #[should_panic(expected = "OccurrencesError { min: 1, max: 1, found: 2 }")] + #[should_panic(expected = "OccurrencesMismatch { min: 1, max: 1, found: 2 }")] fn test_once_check_count_fail_two() { let occurence: Occurrences = Occurrences::Once; occurence.check(2).unwrap(); @@ -115,7 +183,7 @@ mod test { occurence.check(0).unwrap(); } #[test] - #[should_panic(expected = "OccurrencesError { min: 0, max: 1, found: 2 }")] + #[should_panic(expected = "OccurrencesMismatch { min: 0, max: 1, found: 2 }")] fn test_none_or_once_check_count_fail_two() { let occurence: Occurrences = Occurrences::NoneOrOnce; occurence.check(2).unwrap(); @@ -132,7 +200,7 @@ mod test { occurence.check(core::u16::MAX).unwrap(); } #[test] - #[should_panic(expected = "OccurrencesError { min: 1, max: 65535, found: 0 }")] + #[should_panic(expected = "OccurrencesMismatch { min: 1, max: 65535, found: 0 }")] fn test_once_or_up_to_none_fail_zero() { let occurence: Occurrences = Occurrences::OnceOrMore; occurence.check(0).unwrap(); @@ -143,13 +211,13 @@ mod test { occurence.check(42).unwrap(); } #[test] - #[should_panic(expected = "OccurrencesError { min: 1, max: 42, found: 43 }")] + #[should_panic(expected = "OccurrencesMismatch { min: 1, max: 42, found: 43 }")] fn test_once_or_up_to_42_large() { let occurence: Occurrences = Occurrences::OnceOrUpTo(42); occurence.check(43).unwrap(); } #[test] - #[should_panic(expected = "OccurrencesError { min: 1, max: 42, found: 0 }")] + #[should_panic(expected = "OccurrencesMismatch { min: 1, max: 42, found: 0 }")] fn test_once_or_up_to_42_fail_zero() { let occurence: Occurrences = Occurrences::OnceOrUpTo(42); occurence.check(0).unwrap(); @@ -176,7 +244,7 @@ mod test { occurence.check(42).unwrap(); } #[test] - #[should_panic(expected = "OccurrencesError { min: 0, max: 42, found: 43 }")] + #[should_panic(expected = "OccurrencesMismatch { min: 0, max: 42, found: 43 }")] fn test_none_or_up_to_42_large() { let occurence: Occurrences = Occurrences::NoneOrUpTo(42); occurence.check(43).unwrap(); From 58d8b9f61cd341e0b64d34ee30279d17641dcd89 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:08:25 +0100 Subject: [PATCH 23/71] schema: refactor nodes to use confined collections --- src/schema/nodes.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/schema/nodes.rs b/src/schema/nodes.rs index 72a0eddd..4cc2d7d1 100644 --- a/src/schema/nodes.rs +++ b/src/schema/nodes.rs @@ -9,16 +9,17 @@ // You should have received a copy of the MIT License along with this software. // If not, see . -use std::collections::{BTreeMap, BTreeSet}; +use amplify::confinement::{TinyOrdMap, TinyOrdSet}; use super::{ExtensionType, FieldType, Occurrences, TransitionType}; +use crate::LIB_NAME_RGB; // Here we can use usize since encoding/decoding makes sure that it's u16 pub type OwnedRightType = u16; pub type PublicRightType = u16; -pub type MetadataStructure = BTreeMap; -pub type PublicRightsStructure = BTreeSet; -pub type OwnedRightsStructure = BTreeMap; +pub type MetadataStructure = TinyOrdMap; +pub type PublicRightsStructure = TinyOrdSet; +pub type OwnedRightsStructure = TinyOrdMap; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)] #[cfg_attr( @@ -72,7 +73,9 @@ pub trait NodeSchema { fn public_rights(&self) -> &PublicRightsStructure; } -#[derive(Clone, PartialEq, Debug, Default, AsAny)] +#[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct GenesisSchema { pub metadata: MetadataStructure, @@ -80,7 +83,9 @@ pub struct GenesisSchema { pub public_rights: PublicRightsStructure, } -#[derive(Clone, PartialEq, Debug, Default, AsAny)] +#[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct ExtensionSchema { pub metadata: MetadataStructure, @@ -89,7 +94,9 @@ pub struct ExtensionSchema { pub public_rights: PublicRightsStructure, } -#[derive(Clone, PartialEq, Debug, Default, AsAny)] +#[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct TransitionSchema { pub metadata: MetadataStructure, From 021552285992bc85ffa0f1c176cf14ebf43d0d0b Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:08:50 +0100 Subject: [PATCH 24/71] schema: impl strict encoding for Schema --- src/schema/schema.rs | 77 +++++++++++++++++++++++++++++++++++--------- src/schema/script.rs | 12 ++++++- 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 85a1ab6d..7e84424f 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -9,11 +9,18 @@ // You should have received a copy of the MIT License along with this software. // If not, see . -use std::collections::{BTreeMap, BTreeSet}; +use std::cmp::Ordering; +use std::io; +use amplify::confinement::{MediumVec, TinyOrdMap, TinyOrdSet}; +use amplify::flags::FlagVec; use amplify::{Bytes32, RawArray}; use baid58::ToBaid58; -use commit_verify::{strategies, CommitStrategy}; +use commit_verify::{strategies, CommitStrategy, CommitmentId}; +use strict_encoding::{ + DecodeError, ReadTuple, StrictDecode, StrictEncode, StrictProduct, StrictTuple, StrictType, + TypeName, TypedRead, TypedWrite, WriteTuple, +}; use strict_types::SemId; use super::{ @@ -54,7 +61,9 @@ impl ToBaid58<32> for SchemaId { fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() } } -#[derive(Clone, Debug)] +#[derive(Clone, Eq, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Schema { /// Feature flags control which of the available RGB features are allowed @@ -67,32 +76,70 @@ pub struct Schema { /// or do other backward-incompatible changes (RGB protocol versions are /// not interoperable and backward-incompatible by definitions and the /// nature of client-side-validation which does not allow upgrades). - pub rgb_features: u16, + #[serde(skip)] + pub rgb_features: SchemaFlags, pub subset_of: Option, - pub field_types: BTreeMap, - pub owned_right_types: BTreeMap, - pub public_right_types: BTreeSet, + pub field_types: TinyOrdMap, + pub owned_right_types: TinyOrdMap, + pub public_right_types: TinyOrdSet, pub genesis: GenesisSchema, - pub extensions: BTreeMap, - pub transitions: BTreeMap, + pub extensions: TinyOrdMap, + pub transitions: TinyOrdMap, /// Type system - pub type_system: Vec, // TODO: TypeSystem, + pub type_system: MediumVec, // TODO: TypeSystem, /// Validation code. pub script: ValidationScript, } +impl PartialEq for Schema { + fn eq(&self, other: &Self) -> bool { self.schema_id() == other.schema_id() } +} + +impl Ord for Schema { + fn cmp(&self, other: &Self) -> Ordering { self.schema_id().cmp(&other.schema_id()) } +} + +impl PartialOrd for Schema { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +} + +impl CommitStrategy for Schema { + type Strategy = strategies::Strict; +} + +impl CommitmentId for Schema { + const TAG: [u8; 32] = *b"urn:lnpbp:rgb:schema:v01#202302A"; + type Id = SchemaId; +} + impl Schema { #[inline] - pub fn schema_id(&self) -> SchemaId { todo!() } + pub fn schema_id(&self) -> SchemaId { self.commitment_id() } } -impl PartialEq for Schema { - fn eq(&self, other: &Self) -> bool { self.schema_id() == other.schema_id() } -} +#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)] +pub struct SchemaFlags(FlagVec); -impl Eq for Schema {} +impl StrictType for SchemaFlags { + const STRICT_LIB_NAME: &'static str = LIB_NAME_RGB; + fn strict_name() -> Option { Some(tn!("SchemaFlags")) } +} +impl StrictProduct for SchemaFlags {} +impl StrictTuple for SchemaFlags { + const FIELD_COUNT: u8 = 1; +} +impl StrictEncode for SchemaFlags { + fn strict_encode(&self, writer: W) -> io::Result { + writer.write_tuple::(|w| Ok(w.write_field(&self.0.shrunk().into_inner())?.complete())) + } +} +impl StrictDecode for SchemaFlags { + fn strict_decode(reader: &mut impl TypedRead) -> Result { + reader.read_tuple(|r| r.read_field().map(|vec| Self(FlagVec::from_inner(vec)))) + } +} #[cfg(test)] mod test { diff --git a/src/schema/script.rs b/src/schema/script.rs index 6431fe38..710b5483 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -14,6 +14,10 @@ //! Components related to the scripting system used by schema or applied at the //! specific contract node level +use amplify::confinement::MediumVec; + +use crate::LIB_NAME_RGB; + /// Virtual machine types. #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[display(Debug)] @@ -25,6 +29,8 @@ pub enum VmType { /// Virtual machine and machine-specific script data. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = order)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub enum ValidationScript { /// AluVM: pure functional register-based virtual machine designed for RGB @@ -36,7 +42,11 @@ pub enum ValidationScript { /// /// Its routines can be accessed only through well-typed ABI entrance /// pointers, defined as a part of the schema. - AluVM(Vec), + AluVM(MediumVec), +} + +impl Default for ValidationScript { + fn default() -> Self { ValidationScript::AluVM(none!()) } } impl ValidationScript { From 4b4189807181b99336f103bdeb02e4b7aa884355 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:12:36 +0100 Subject: [PATCH 25/71] schema: prohibit any flag values other than zero --- src/schema/schema.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 7e84424f..80613ba1 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -119,7 +119,8 @@ impl Schema { pub fn schema_id(&self) -> SchemaId { self.commitment_id() } } -#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Default)] +#[display(inner)] pub struct SchemaFlags(FlagVec); impl StrictType for SchemaFlags { @@ -137,7 +138,17 @@ impl StrictEncode for SchemaFlags { } impl StrictDecode for SchemaFlags { fn strict_decode(reader: &mut impl TypedRead) -> Result { - reader.read_tuple(|r| r.read_field().map(|vec| Self(FlagVec::from_inner(vec)))) + let flags = + reader.read_tuple(|r| r.read_field().map(|vec| Self(FlagVec::from_inner(vec))))?; + if !flags.0.is_empty() { + Err(DecodeError::DataIntegrityError(format!( + "unsupported schema flags potentially belonging to a future RGB version. Please \ + update your software, or, if the problem persists, contact your vendor providing \ + the following flag information: {flags}" + ))) + } else { + Ok(flags) + } } } From 3f5ffb8a15a0bd91310aa741abea2955ea17bbd7 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:14:55 +0100 Subject: [PATCH 26/71] test: remove serialized test data (outdated) --- test/consignment.in | 127 ----------------------- test/consignment1bech.in | 1 - test/declarative_state.in | 16 --- test/genesis.in | 205 ------------------------------------- test/hash_state.in | 25 ----- test/metadata.in | 15 --- test/parent_rights.in | 9 -- test/pedersan_state.in | 141 ------------------------- test/test_transaction.psbt | 41 -------- test/transition.in | 197 ----------------------------------- 10 files changed, 777 deletions(-) delete mode 100644 test/consignment.in delete mode 100644 test/consignment1bech.in delete mode 100644 test/declarative_state.in delete mode 100644 test/genesis.in delete mode 100644 test/hash_state.in delete mode 100644 test/metadata.in delete mode 100644 test/parent_rights.in delete mode 100644 test/pedersan_state.in delete mode 100644 test/test_transaction.psbt delete mode 100644 test/transition.in diff --git a/test/consignment.in b/test/consignment.in deleted file mode 100644 index 1ce22705..00000000 --- a/test/consignment.in +++ /dev/null @@ -1,127 +0,0 @@ -[ - 0x00, 0x00, 0x16, 0x1B, 0x9E, 0x92, 0x45, 0x60, 0x58, 0x7A, 0x29, 0x66, - 0x54, 0x24, 0x22, 0x7B, 0x30, 0x21, 0x0E, 0xAE, 0xEA, 0x76, 0x7A, 0x20, - 0x7A, 0x56, 0xCB, 0xEE, 0xD5, 0x51, 0x1B, 0x39, 0xAA, 0x86, 0x01, 0x00, - 0x99, 0x00, 0x43, 0x49, 0x7F, 0xD7, 0xF8, 0x26, 0x95, 0x71, 0x08, 0xF4, - 0xA3, 0x0F, 0xD9, 0xCE, 0xC3, 0xAE, 0xBA, 0x79, 0x97, 0x20, 0x84, 0xE9, - 0x0E, 0xAD, 0x01, 0xEA, 0x33, 0x09, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, - 0x74, 0x65, 0x73, 0x74, 0x6E, 0x65, 0x74, 0x0B, 0x11, 0x09, 0x07, 0x04, - 0x00, 0x74, 0x65, 0x73, 0x74, 0x02, 0x00, 0x74, 0x62, 0x9D, 0x47, 0x9C, - 0x47, 0x01, 0x00, 0x00, 0x00, 0xEC, 0x01, 0x1C, 0x00, 0x00, 0x22, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x74, 0x42, 0x54, 0x43, - 0x0C, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x42, 0x69, 0x74, 0x63, 0x6F, - 0x69, 0x6E, 0x0C, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x73, 0x61, 0x74, - 0x6F, 0x73, 0x68, 0x69, 0x00, 0xE1, 0xF5, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x43, 0x49, 0x7F, 0xD7, 0xF8, 0x26, 0x95, 0x71, 0x08, 0xF4, 0xA3, 0x0F, - 0xD9, 0xCE, 0xC3, 0xAE, 0xBA, 0x79, 0x97, 0x20, 0x84, 0xE9, 0x0E, 0xAD, - 0x01, 0xEA, 0x33, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x21, 0x03, 0x00, 0x4D, 0x43, 0x54, 0x01, - 0x00, 0x01, 0x00, 0x21, 0x14, 0x00, 0x4D, 0x79, 0x43, 0x69, 0x74, 0x61, - 0x64, 0x65, 0x6C, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6F, 0x6B, - 0x65, 0x6E, 0x03, 0x00, 0x01, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x00, - 0x0B, 0x82, 0xFD, 0x22, 0x60, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x01, - 0x00, 0x03, 0x00, 0xE8, 0x76, 0x48, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, - 0xA1, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0xA3, 0x9E, 0x24, 0xCD, - 0xB9, 0x25, 0x14, 0xC2, 0xAA, 0xBB, 0xCD, 0x0C, 0x05, 0xD2, 0x2F, 0xAC, - 0x65, 0xCC, 0x39, 0xF4, 0x74, 0x49, 0x89, 0x14, 0xEF, 0x2E, 0xDD, 0x8A, - 0x39, 0xAB, 0x39, 0x38, 0x4C, 0x24, 0x81, 0x16, 0x51, 0x4D, 0x90, 0x3A, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xE8, 0x76, 0x48, 0x17, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x88, 0x13, 0x89, 0xA8, 0x8E, 0x4F, 0xEE, 0xA1, 0x72, - 0xF7, 0x07, 0x1C, 0x8F, 0x8B, 0x1B, 0x31, 0x3B, 0xD4, 0x5C, 0x65, 0xEF, - 0x1E, 0x8F, 0xBA, 0x16, 0x7D, 0x10, 0x80, 0x7F, 0xA2, 0x5B, 0xD3, 0x00, - 0x26, 0x0A, 0x6A, 0xDB, 0xFE, 0x77, 0x25, 0xDE, 0x5E, 0xA1, 0xBD, 0xC9, - 0x88, 0x52, 0xA0, 0x37, 0x45, 0x6B, 0x85, 0x73, 0xC2, 0x12, 0xDA, 0x0C, - 0x18, 0xCA, 0x5F, 0x1C, 0xB9, 0x70, 0xA9, 0x1C, 0x01, 0x00, 0xA5, 0x29, - 0x9F, 0x01, 0xF7, 0x19, 0xC1, 0x95, 0xFC, 0x0B, 0xBE, 0x6D, 0xC0, 0x0E, - 0x5A, 0x0F, 0x25, 0xCF, 0x46, 0x8F, 0x85, 0x22, 0xEF, 0xEB, 0xCA, 0x4E, - 0xA3, 0xC7, 0x94, 0x96, 0x96, 0x25, 0x03, 0x00, 0x00, 0x57, 0x9C, 0x60, - 0xF6, 0xF1, 0xCF, 0x57, 0x00, 0x6C, 0x6B, 0x6B, 0xA2, 0x4D, 0x35, 0xBB, - 0x3F, 0x4B, 0x98, 0x9B, 0x14, 0x2C, 0xC8, 0x0A, 0xDF, 0xCD, 0x62, 0x97, - 0x48, 0xA4, 0x6B, 0x5C, 0x6E, 0x00, 0x67, 0xFB, 0x32, 0x37, 0x0D, 0x71, - 0x14, 0x7A, 0xFE, 0x5D, 0x18, 0x96, 0xFE, 0x53, 0xAF, 0x1B, 0xF2, 0xA3, - 0x3E, 0x63, 0xD2, 0xE3, 0x12, 0x9B, 0x74, 0x3D, 0x03, 0x1D, 0xC3, 0xC0, - 0x6A, 0x40, 0x01, 0xC2, 0x98, 0x93, 0xC2, 0xC2, 0xE1, 0x72, 0x31, 0x08, - 0x5C, 0x4E, 0xE4, 0x75, 0x09, 0x5E, 0xA9, 0x53, 0x65, 0x45, 0x55, 0x18, - 0x08, 0xBC, 0xD8, 0x6C, 0x9A, 0xB0, 0x36, 0x41, 0xE4, 0x6A, 0x92, 0x88, - 0x13, 0x89, 0xA8, 0x8E, 0x4F, 0xEE, 0xA1, 0x72, 0xF7, 0x07, 0x1C, 0x8F, - 0x8B, 0x1B, 0x31, 0x3B, 0xD4, 0x5C, 0x65, 0xEF, 0x1E, 0x8F, 0xBA, 0x16, - 0x7D, 0x10, 0x80, 0x7F, 0xA2, 0x5B, 0xD3, 0x01, 0x96, 0x93, 0x68, 0x72, - 0x8D, 0xBA, 0xCC, 0x76, 0x03, 0x74, 0xB3, 0x98, 0x4E, 0x79, 0x1E, 0x7A, - 0x62, 0x72, 0xA3, 0x6F, 0x1D, 0xE9, 0x8A, 0x1B, 0x6E, 0x3F, 0xC3, 0x41, - 0x52, 0x94, 0x0A, 0x99, 0x52, 0x91, 0x5F, 0x5E, 0xCD, 0x5D, 0xA2, 0xE7, - 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xC2, 0x98, 0x93, 0xC2, - 0xC2, 0xE1, 0x72, 0x31, 0x08, 0x5C, 0x4E, 0xE4, 0x75, 0x09, 0x5E, 0xA9, - 0x53, 0x65, 0x45, 0x55, 0x18, 0x08, 0xBC, 0xD8, 0x6C, 0x9A, 0xB0, 0x36, - 0x41, 0xE4, 0x6A, 0x92, 0x01, 0x00, 0xA1, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0xA1, 0x00, 0x01, 0x03, 0x02, 0x00, 0x03, 0x01, 0x00, 0x00, - 0x00, 0x00, 0xF7, 0x89, 0x9B, 0xC9, 0xB9, 0x56, 0x4B, 0xB2, 0x09, 0x88, - 0xFD, 0xBD, 0x46, 0x5E, 0x36, 0xCB, 0xAC, 0x64, 0xAE, 0x26, 0x80, 0x22, - 0x67, 0xCF, 0x75, 0xEA, 0xEC, 0x45, 0xFB, 0xA7, 0x13, 0xC5, 0x13, 0x17, - 0x49, 0x0E, 0x2B, 0x3D, 0x8C, 0x07, 0x82, 0xA3, 0x02, 0x13, 0x29, 0xBB, - 0xCB, 0x4C, 0x90, 0xDF, 0x93, 0x84, 0xA7, 0xC0, 0x3D, 0x29, 0x43, 0x51, - 0x91, 0x3F, 0xD9, 0x66, 0x7E, 0xB8, 0x7E, 0x76, 0xFA, 0x68, 0x46, 0x0F, - 0xCC, 0x73, 0xDC, 0xCC, 0xEB, 0x02, 0x67, 0x96, 0xD5, 0xEA, 0x93, 0x7B, - 0x69, 0x27, 0x70, 0x48, 0x47, 0x1C, 0x8F, 0xE7, 0xDE, 0xEF, 0xE5, 0x94, - 0xF0, 0xCB, 0xFF, 0x0F, 0xCE, 0x43, 0x68, 0x83, 0x92, 0x97, 0x07, 0x07, - 0x4D, 0x00, 0xD6, 0x58, 0xDB, 0x2A, 0x1C, 0xA9, 0x7F, 0x8C, 0xA4, 0xAB, - 0xE0, 0x2C, 0x31, 0x8B, 0xDA, 0x4F, 0x1F, 0x50, 0xA0, 0x66, 0xD2, 0xBE, - 0x14, 0x53, 0x4B, 0x13, 0x3B, 0x6A, 0x35, 0xD7, 0x46, 0xA3, 0x80, 0xA1, - 0x84, 0xFF, 0xB5, 0x6C, 0xBB, 0x17, 0xA0, 0x76, 0x74, 0x9B, 0x04, 0x01, - 0xF3, 0xD2, 0x8F, 0x18, 0xB6, 0x52, 0xFA, 0x37, 0xCF, 0xB7, 0x35, 0x35, - 0x7A, 0xD5, 0xE0, 0x71, 0x94, 0xC6, 0xFB, 0x32, 0xE7, 0xB0, 0xF3, 0x76, - 0x7D, 0xCD, 0xDA, 0x44, 0x3C, 0x1F, 0xE3, 0x95, 0x5C, 0xEB, 0x08, 0x9C, - 0xC6, 0x1A, 0xA1, 0x49, 0xE5, 0xC2, 0x6B, 0x34, 0x04, 0xAB, 0x6C, 0x96, - 0x55, 0x41, 0x0B, 0xB8, 0x5E, 0x65, 0x0D, 0x5F, 0xDF, 0x8D, 0xB7, 0x3A, - 0x4C, 0x89, 0x71, 0xC3, 0xDA, 0x46, 0x9C, 0xD1, 0x99, 0x3D, 0x58, 0x2C, - 0xC4, 0xB8, 0xB0, 0x84, 0xE4, 0x1B, 0xC3, 0x16, 0xCD, 0x7C, 0xCB, 0x01, - 0x34, 0xCA, 0xD1, 0x63, 0x6D, 0xCB, 0x4E, 0x76, 0xBF, 0xA8, 0x2A, 0x4F, - 0xDE, 0xB9, 0xAA, 0xE0, 0xB2, 0xCA, 0xEB, 0x54, 0xA5, 0xAB, 0xC5, 0x9E, - 0x86, 0xF4, 0xB4, 0xC4, 0xDA, 0x69, 0xE2, 0xB8, 0x85, 0x8E, 0x59, 0xDD, - 0x02, 0x01, 0xAE, 0x43, 0x70, 0xB6, 0xCA, 0xA2, 0x15, 0x83, 0xBA, 0xEB, - 0x24, 0xE3, 0x76, 0x11, 0xFF, 0x08, 0x80, 0x5F, 0x84, 0x04, 0x97, 0x26, - 0x29, 0x1C, 0x49, 0x94, 0x4E, 0x4C, 0xFB, 0x44, 0xF2, 0xE3, 0x29, 0xA9, - 0x93, 0xEA, 0xA6, 0xD3, 0xEB, 0x8C, 0x85, 0xD5, 0x61, 0x1A, 0x8D, 0xCD, - 0x7E, 0xE1, 0x95, 0x42, 0xD3, 0x3A, 0x30, 0xEE, 0x2F, 0x26, 0xE6, 0x8F, - 0x21, 0x52, 0x72, 0x7E, 0x83, 0x9B, 0xC7, 0xC6, 0x29, 0x12, 0x73, 0xA3, - 0x17, 0x48, 0x83, 0x3F, 0x0E, 0xB0, 0x4D, 0xBB, 0xCE, 0x2C, 0xA2, 0x43, - 0x1F, 0x30, 0x5B, 0xD8, 0x15, 0x21, 0x7B, 0x33, 0x18, 0x47, 0x29, 0x7E, - 0x1A, 0x7C, 0x6E, 0x20, 0x12, 0xD0, 0x32, 0x40, 0x54, 0x55, 0x22, 0x64, - 0x0B, 0x6A, 0xEC, 0x52, 0x98, 0xB8, 0x33, 0x24, 0xFB, 0x35, 0x4A, 0xCE, - 0x96, 0x1A, 0xD7, 0x03, 0x78, 0xF8, 0x15, 0x15, 0xA8, 0x17, 0x9B, 0x16, - 0x81, 0xF5, 0x17, 0xF9, 0x16, 0x20, 0x4A, 0xEE, 0xFA, 0xC0, 0x0C, 0x9A, - 0x32, 0x13, 0x4B, 0x4B, 0xC4, 0x77, 0x5A, 0xE9, 0x85, 0xD2, 0x30, 0xC2, - 0x86, 0x17, 0x2B, 0xCA, 0xDA, 0xF0, 0x3B, 0x97, 0xD2, 0x1D, 0xBB, 0xCF, - 0xB6, 0x6C, 0x43, 0x5F, 0x36, 0x7E, 0xA0, 0xCD, 0xDE, 0x68, 0xD8, 0xFB, - 0x08, 0x72, 0x88, 0xBF, 0xD2, 0xD7, 0x71, 0x44, 0xE6, 0xBC, 0xE6, 0x57, - 0x4D, 0xAF, 0x72, 0xAF, 0xCA, 0xB9, 0x3A, 0xB1, 0x79, 0x3E, 0x8E, 0x10, - 0x8A, 0x02, 0x24, 0xD9, 0x34, 0x59, 0x2F, 0x6A, 0xAE, 0xA0, 0xBC, 0x5F, - 0x41, 0xA0, 0x3B, 0x38, 0x32, 0xD0, 0xDC, 0x40, 0x86, 0xE3, 0x88, 0x57, - 0xC3, 0x76, 0x35, 0x1A, 0x4C, 0x52, 0x63, 0x22, 0x11, 0x49, 0x0A, 0x7E, - 0xA5, 0x8A, 0x02, 0x46, 0x1B, 0x8D, 0xBC, 0x73, 0x56, 0xD4, 0xB1, 0x60, - 0xAE, 0xA4, 0xAD, 0x9F, 0x77, 0x1C, 0x5C, 0x04, 0xAA, 0x39, 0x70, 0xAF, - 0x6C, 0x0F, 0x70, 0xE9, 0xB3, 0x3C, 0xB1, 0x30, 0x80, 0x2A, 0x08, 0x0A, - 0xEE, 0xB7, 0x96, 0x28, 0x8B, 0x47, 0x46, 0xA8, 0xDA, 0x9B, 0x73, 0x31, - 0x0A, 0xEB, 0x0C, 0x3D, 0x0A, 0x86, 0xE9, 0x83, 0x6B, 0x0F, 0x2B, 0x38, - 0x69, 0xC0, 0xEA, 0x0F, 0xA2, 0x76, 0x33, 0x25, 0x87, 0x99, 0x82, 0x38, - 0x89, 0x24, 0x47, 0xF3, 0x2E, 0xEC, 0x4B, 0xC1, 0x32, 0x11, 0xDE, 0x47, - 0xE6, 0x2E, 0x3E, 0xC0, 0x27, 0xC4, 0xF5, 0x5E, 0x76, 0x9A, 0x3E, 0x96, - 0x37, 0x18, 0x84, 0x7F, 0x43, 0xCE, 0xC5, 0xA7, 0x59, 0x95, 0x73, 0x2F, - 0xCB, 0xA9, 0x3E, 0x1E, 0x5E, 0x74, 0x36, 0xD0, 0xC8, 0x88, 0xEC, 0x2D, - 0x2C, 0x65, 0xE0, 0x78, 0x87, 0xF9, 0x26, 0x31, 0xEC, 0x46, 0x03, 0x3B, - 0xE1, 0xD5, 0x85, 0xAE, 0x8D, 0xDF, 0x9A, 0x39, 0x2C, 0xFA, 0xE1, 0x83, - 0x89, 0x9D, 0x08, 0x6B, 0x3C, 0x1D, 0x55, 0xBB, 0xBD, 0xA4, 0xF2, 0x48, - 0xF2, 0x58, 0x06, 0x9A, 0xAD, 0x76, 0x15, 0xD3, 0x49, 0x2C, 0xCC, 0xBC, - 0x13, 0xA7, 0x7D, 0x75, 0xE7, 0xA8, 0x26, 0x84, 0x80, 0x09, 0x3E, 0xDC, - 0x79, 0xBC, 0xA6, 0x99, 0x3D, 0x61, 0xC2, 0xD6, 0x02, 0x21, 0x3C, 0x7E, - 0xB6, 0x6F, 0xBF, 0xFF, 0xAA, 0x72, 0x98, 0xD2, 0x99, 0x8D, 0x22, 0xDC, - 0x02, 0x26, 0x0A, 0x6A, 0xDB, 0xFE, 0x77, 0x25, 0xDE, 0x5E, 0xA1, 0xBD, - 0xC9, 0x88, 0x52, 0xA0, 0x37, 0x45, 0x6B, 0x85, 0x73, 0xC2, 0x12, 0xDA, - 0x0C, 0x18, 0xCA, 0x5F, 0x1C, 0xB9, 0x70, 0xA9, 0x1C, 0x03, 0x13, 0x15, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xFC, 0xF3, 0xE6, 0xFD, 0x8D, - 0xD6, 0xCC, 0x68, 0xF0, 0xF2, 0xE3, 0x05, 0x18, 0xB5, 0xB2, 0x44, 0x41, - 0x0A, 0x9D, 0x87, 0xD2, 0x9B, 0x43, 0x60, 0xE4, 0x76, 0x00, 0x71, 0xF4, - 0xEC, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ] \ No newline at end of file diff --git a/test/consignment1bech.in b/test/consignment1bech.in deleted file mode 100644 index 2c97331f..00000000 --- a/test/consignment1bech.in +++ /dev/null @@ -1 +0,0 @@ -"consignment1q93kqyynncmujdfp5f9rxt2ygk5a5sy3dlw6hv32sk4tp5l04cry5kawdf3kfxxfurk9jllaslddgs5w979ljmu78w7xu4l9wjzed9mudvv47xtnxgqqzw6rf948zj27dgymwgp88v9e3s7y2zfrf4ma3cajx586pk3scqurzgfsxxqq5kw598rerppgpzs5nseyhyhnx0e6p08zcjf0ec5vfjrgwh6egy4qnkw2cryqs5k8ezsv3n8qavwvyzrz3yc0s436v7tzff4yuc5gp89p2zffl8v6cuxfgchqvqqe9hzd0723ysr6zuqrnnqv9l9re3xpgckxgcryqcvmq7y7etvem23zsatw60ktcdayjl6dagvukte9n6wj9ml4aem9nt4kknc9z6g5p06f6cq9xgp2a8gqvzzpq8wzn54l4lxl95k04n3w600j6mtg05jjdadatnljav26sxr053w3juvafw9jdmljk4aaz7mhpm7f36sqte4wmxkutpuydmc538y2jlv4nvzjs6gkr20x0nrwlys85llwrh5h0wqzlzjl7k79klat6taa0fluzc0e7vndng4rxq6rlzwggmcle7rn8eryvuhlydwadhhn6cak3r8qnthmv7f6v7evex8vjc6glakkfnjm9pf02t6kvtdtlc846203dke9taazcd9mcjt9nahssykq03jrxvnp7wh5kryfqg7xaayjje7uets9f46spx8r6dmjveknqumujg6cnyplrzn5mn3gatwhtf5vh9j0xr9lf2u64f9zchumytam5ne7cremqex7rxsexscnamnvaj3w04ks6qskggfcwmstr3xycqxqa580nke5lmsv700vfk03w7h4h8xeay6jn675r22d9nuhheaw87nmh8c9zct3fulxmkc776nv2nxzn2a5l76vhqlmje0eq9d5me7q38mr05l2wm2ftlw2wr3n75muulxxhfh5d9t47ndwee2zlursjl5h7lh0lhfjj86wllnnleuu6y7xjw3mhvhu8dvgmddry2lt0wt2cl4qv0v8mj6l8esyrk49053vrhkz6ev6d47azcmjcm8ehu6k0dlcs2ef9kfv3j0jla2tds9l5et706a6j6w465rc25uwl5m840hpwdv7mk2m9cm09ra8c67wdxrnf342re7ng0vjvt9twwng2wnja7yyhevdhl0mhhw257elpupdkuu3we76gm5pekd358jcnarpkxentfcef4896nxw8hk40dnlskt0l0va4v0xcwh48fjwn64r70dtumpewg4l85vw66lv3w6v3n4eczakn4dzfk4uaw6u4cejc8l3cr0395kd84f5v572078el3m0nazcw0j7g47t96l7u6dang5d27akams4ff7t2crwlax4nm6jkps4656u70n7f3f6s793hprmx0wlqm0amem5zcuukx6ymug9ttpkjecd0tyn4ty4xy96vrjpqy42jnpfmafxdrrqucu4m7n9aeaxf9wk0thcyy4t5snukevwx4l3na3q5hh00cw7pxt9ynkw6ldy8n4xt6e9sdpkmck65ah8mvy70eyhdaled5uuautxw59uahkthrcehgagv0l6t6u99m8lv0qt7aw4ld876382hrv4we7syh2v9gm56gh4k0tzmkqna7uvpkkzarppmpakcuw7rp7tfjjheq5jj5zrmw02jemrrw2f7lhzjr4mkgckrhvjkheuketztpt9j94velsj779em9n2xsvrzcra0wld6v6t4hwa2mwf5htver6e43uk40kk2uekh7myte5p2l7ghj5v2hdkwdjewj4tsl7k003hm5zg7z00kveahvp753a7c62umv5mvchdz5h00nhw3ukg48zl4f6hmtyut9vct5udru2x2unl2s29ld8ntsehdmxdvra0k6hwh0fledfw047rum8tj8xex6e2rwlh9mu7fuffsfkadk3j689euwn87cyzlted0kly9td9s8f7unh9nejnxmgnpawkx54548ded0lll742yxvhvmmz4htpy220nxv9g5s62j05nl8ullhktcae8u0p6d34dzddndwpew0xke0e4mvu7zjgeg0sewdkazp2qq3n3l06" \ No newline at end of file diff --git a/test/declarative_state.in b/test/declarative_state.in deleted file mode 100644 index 6be388fa..00000000 --- a/test/declarative_state.in +++ /dev/null @@ -1,16 +0,0 @@ -[ - 0x0, 0x4, 0x0, 0x2, 0x24, 0xa5, 0xd4, 0xe1, 0xd0, 0x55, 0xa0, 0xc, - 0x15, 0xc6, 0x61, 0xcd, 0x6d, 0x6a, 0x55, 0xb8, 0x51, 0xaf, 0xfd, 0x90, - 0x98, 0x9, 0x6c, 0x3e, 0xf5, 0x31, 0xd4, 0xb, 0xee, 0x1b, 0x3c, 0x6b, - 0x0, 0x53, 0x20, 0xe, 0x17, 0xc, 0x8, 0xf2, 0x24, 0x2a, 0xd7, 0xba, - 0xa0, 0x22, 0x55, 0xb, 0x91, 0x8a, 0xd1, 0x4e, 0xe, 0xcc, 0x64, 0x12, - 0x19, 0x71, 0xe3, 0x7a, 0x19, 0x6b, 0xac, 0x43, 0xc8, 0x3, 0x0, 0xae, - 0xe9, 0xa8, 0xc3, 0x4c, 0x5d, 0x4f, 0x87, 0x6, 0xe, 0xf5, 0x8d, 0x94, - 0xa, 0x75, 0xe4, 0x3d, 0x13, 0x9d, 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, - 0xc9, 0xeb, 0x4f, 0x77, 0x3b, 0xff, 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, - 0xd2, 0x7e, 0xf5, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0xad, 0xb1, 0x39, 0x64, - 0xb, 0xb6, 0xb9, 0x36, 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, 0x89, - 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, 0x51, - 0x29, 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, 0x20, - 0x1, 0x0, 0x0, 0x0, - ] \ No newline at end of file diff --git a/test/genesis.in b/test/genesis.in deleted file mode 100644 index e43b7782..00000000 --- a/test/genesis.in +++ /dev/null @@ -1,205 +0,0 @@ -[ - 0x20, 0x1f, 0xdd, 0x1e, 0x2b, 0x62, 0xd7, 0xb6, 0x93, 0x82, 0x71, 0x29, - 0x51, 0x18, 0xee, 0x18, 0x1f, 0x1b, 0xac, 0x5e, 0x57, 0xd9, 0xf4, 0x52, - 0x89, 0x25, 0x65, 0xd, 0x36, 0xd3, 0xaf, 0x8e, 0x01, 0x00, 0x8e, 0x00, - 0x6f, 0xe2, 0x8c, 0xa, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, - 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x8, 0x9c, - 0x68, 0xd6, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x62, 0x69, 0x74, - 0x63, 0x6f, 0x69, 0x6e, 0xf9, 0xbe, 0xb4, 0xd9, 0x4, 0x0, 0x6d, 0x61, - 0x69, 0x6e, 0x2, 0x0, 0x62, 0x63, 0x8d, 0x20, 0x8c, 0x20, 0xb4, 0xb2, - 0x7, 0x0, 0x10, 0xeb, 0x9, 0x0, 0x0, 0x22, 0x2, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3, 0x0, 0x42, 0x54, 0x43, 0x7, 0x0, 0x42, 0x69, 0x74, 0x63, - 0x6f, 0x69, 0x6e, 0x7, 0x0, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, - 0x0, 0xe1, 0xf5, 0x5, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xe2, 0x8c, 0xa, 0xb6, - 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, 0x93, - 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x8, 0x9c, 0x68, 0xd6, 0x19, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0xd, 0x0, 0x15, 0x0, 0x0, 0x2, - 0x0, 0x3, 0x1, 0x2, 0x0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x2, 0x3, 0x0, 0x0, - 0x0, 0x3, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x2, 0x8, 0x3, 0xa, 0x2, 0x0, 0x0, 0x0, - 0xa, 0x3, 0x0, 0x0, 0x0, 0xb, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xb, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x40, - 0x12, 0x0, 0x0, 0x40, 0x40, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x40, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x40, 0x20, 0x5, 0x0, - 0x1, 0x2, 0x3, 0x4, 0x5, 0x20, 0x5, 0x0, 0xa, 0x14, 0x1e, 0x28, 0x32, - 0x21, 0x11, 0x0, 0x4f, 0x6e, 0x65, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, - 0x6d, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x21, 0x15, 0x0, 0x41, - 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, - 0x6d, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3, 0x0, 0x1, 0x0, - 0x0, 0x4, 0x0, 0x2, 0x24, 0xa5, 0xd4, 0xe1, 0xd0, 0x55, 0xa0, 0xc, - 0x15, 0xc6, 0x61, 0xcd, 0x6d, 0x6a, 0x55, 0xb8, 0x51, 0xaf, 0xfd, 0x90, - 0x98, 0x9, 0x6c, 0x3e, 0xf5, 0x31, 0xd4, 0xb, 0xee, 0x1b, 0x3c, 0x6b, - 0x0, 0x53, 0x20, 0xe, 0x17, 0xc, 0x8, 0xf2, 0x24, 0x2a, 0xd7, 0xba, - 0xa0, 0x22, 0x55, 0xb, 0x91, 0x8a, 0xd1, 0x4e, 0xe, 0xcc, 0x64, 0x12, - 0x19, 0x71, 0xe3, 0x7a, 0x19, 0x6b, 0xac, 0x43, 0xc8, 0x3, 0x0, 0xae, - 0xe9, 0xa8, 0xc3, 0x4c, 0x5d, 0x4f, 0x87, 0x6, 0xe, 0xf5, 0x8d, 0x94, - 0xa, 0x75, 0xe4, 0x3d, 0x13, 0x9d, 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, - 0xc9, 0xeb, 0x4f, 0x77, 0x3b, 0xff, 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, - 0xd2, 0x7e, 0xf5, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0xad, 0xb1, 0x39, 0x64, - 0xb, 0xb6, 0xb9, 0x36, 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, 0x89, - 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, 0x51, - 0x29, 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, 0x20, - 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1, 0x3, 0x4, 0x0, 0x3, 0x0, 0x6e, 0x5a, - 0x76, 0xca, 0xd0, 0x21, 0x63, 0xa5, 0x6, 0xe, 0xf5, 0x8d, 0x94, 0xa, - 0x75, 0xe4, 0x3d, 0x13, 0x9d, 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, 0xc9, - 0xeb, 0x4f, 0x77, 0x3b, 0xff, 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, 0xd2, - 0x7e, 0xf5, 0x1, 0x0, 0x0, 0x0, 0x8, 0xcc, 0x48, 0xfa, 0x5e, - 0x5c, 0xb1, 0xd2, 0xd2, 0x46, 0x5b, 0xd8, 0xc4, 0x37, 0xc0, 0xe0, 0x5, - 0x14, 0xab, 0xd8, 0x13, 0xf9, 0xa7, 0xdd, 0x50, 0x6a, 0x77, 0x84, 0x5, - 0xa2, 0xc4, 0x3b, 0xc0, 0xa3, 0x2, 0xdd, 0x8a, 0x81, 0xc2, 0xb1, 0x62, - 0xe7, 0xb9, 0xc8, 0xec, 0xe9, 0x64, 0xfc, 0x4f, 0x67, 0x56, 0xdb, 0x85, - 0x34, 0x43, 0x97, 0x3c, 0x84, 0xf9, 0x32, 0x45, 0x5e, 0x8c, 0x4c, 0x93, - 0xd9, 0x19, 0xb, 0x68, 0x4e, 0x5a, 0x15, 0xc7, 0x31, 0xb, 0x33, 0xa4, - 0xc0, 0xbe, 0xa6, 0x11, 0xc, 0x64, 0xa0, 0x24, 0x72, 0x79, 0xec, 0x12, - 0x49, 0xc6, 0x9f, 0x94, 0xeb, 0x5, 0x71, 0x7d, 0x81, 0x0, 0xe, 0x3f, - 0x84, 0x8e, 0x9f, 0xe9, 0x68, 0x2f, 0xa6, 0xa, 0xd8, 0x59, 0x57, 0xcf, - 0x64, 0xb9, 0x56, 0xb5, 0xfc, 0xcc, 0x2b, 0xdc, 0x9e, 0x4d, 0xdd, 0x78, - 0x60, 0x63, 0x12, 0x57, 0x12, 0xcd, 0xf3, 0x6f, 0xe2, 0xca, 0x1e, 0x19, - 0x3a, 0xb, 0x10, 0xc, 0x59, 0x97, 0xc, 0xde, 0xa8, 0x62, 0x42, 0x4a, - 0x2f, 0x1e, 0xeb, 0x89, 0x98, 0xc6, 0x31, 0x82, 0xc9, 0x4f, 0xf, 0xf1, - 0xa5, 0x1a, 0x37, 0x2d, 0x92, 0x86, 0x8c, 0xe5, 0x37, 0x3a, 0x86, 0xc4, - 0x89, 0x9f, 0xf4, 0xcf, 0x10, 0x7b, 0x9a, 0x30, 0xc0, 0x0, 0x97, 0x1e, - 0x44, 0x9b, 0xb2, 0x92, 0x1d, 0x38, 0x6e, 0x3a, 0xce, 0xea, 0x95, 0xcd, - 0xcd, 0x63, 0x74, 0x5e, 0x43, 0xf, 0xd3, 0xdd, 0x21, 0x2, 0xca, 0x91, - 0xc5, 0x2d, 0x9f, 0x21, 0x7b, 0x4d, 0x14, 0x9f, 0xf1, 0x88, 0xe5, 0x3a, - 0x98, 0x6d, 0x3, 0xdd, 0x64, 0x90, 0x73, 0x5a, 0x87, 0x1f, 0x53, 0x64, - 0xe4, 0x9e, 0x48, 0xfc, 0x1e, 0x3e, 0xcc, 0xeb, 0x5, 0xd3, 0xfd, 0x9a, - 0x56, 0x5f, 0x71, 0x51, 0x39, 0xe3, 0x10, 0xa8, 0xae, 0x20, 0xa8, 0xba, - 0xca, 0x7b, 0x91, 0x6, 0xe9, 0x61, 0x45, 0x69, 0x91, 0x94, 0xe0, 0xec, - 0x50, 0xa4, 0x12, 0x58, 0xe1, 0x64, 0xc2, 0x4c, 0x3c, 0x7f, 0x69, 0x7a, - 0x7e, 0x4a, 0xee, 0xed, 0xb, 0x91, 0x3e, 0x63, 0x71, 0x96, 0x99, 0x78, - 0xf0, 0x3e, 0x40, 0x96, 0x58, 0x9a, 0xd, 0xb9, 0x77, 0x79, 0xa2, 0xb7, - 0xa3, 0x67, 0xcf, 0xc2, 0x45, 0x27, 0xf0, 0x86, 0x3f, 0x8f, 0x60, 0xec, - 0x17, 0x54, 0x4, 0xa8, 0xf1, 0xce, 0x5f, 0xa2, 0x5b, 0xe9, 0xba, 0xb0, - 0xac, 0x4f, 0x5b, 0x47, 0xbb, 0xb6, 0xd8, 0x1, 0x7, 0x73, 0x24, 0xc4, - 0x8b, 0xc8, 0xe1, 0x15, 0xe4, 0xd2, 0x9f, 0xc5, 0x4, 0xed, 0x13, 0xc3, - 0x17, 0xb8, 0xc9, 0xdd, 0x84, 0x78, 0xea, 0x92, 0x4c, 0x41, 0x98, 0xc, - 0x38, 0xc8, 0x2, 0x20, 0xeb, 0xf2, 0x93, 0x75, 0x8f, 0xd7, 0x9d, 0x76, - 0xfa, 0xfa, 0xbb, 0x5e, 0xa1, 0x98, 0x51, 0xd6, 0xbd, 0x6, 0xa2, 0x37, - 0x2, 0x89, 0x10, 0xb9, 0x84, 0x69, 0xc7, 0xb7, 0xee, 0xec, 0xca, 0x2d, - 0x13, 0xbb, 0x8f, 0xb, 0xa5, 0x9f, 0x17, 0x6a, 0xb2, 0xef, 0x51, 0x39, - 0x1f, 0xce, 0x69, 0x8c, 0xc, 0x67, 0x67, 0x6f, 0x29, 0x29, 0x5, 0x5a, - 0xcb, 0x17, 0x6a, 0x8f, 0x1b, 0xe6, 0x1c, 0x32, 0xad, 0xf2, 0xda, 0xb3, - 0xb6, 0xb8, 0x6e, 0xae, 0x28, 0x9e, 0x7b, 0x12, 0x3f, 0x52, 0x26, 0xfd, - 0x9c, 0xad, 0x2b, 0x18, 0xb2, 0x6f, 0x33, 0xf, 0xf5, 0xab, 0x53, 0x8c, - 0x9b, 0xbf, 0xca, 0xe2, 0x1f, 0xfd, 0x91, 0xaa, 0x41, 0x26, 0x81, 0xdc, - 0x1c, 0x9a, 0xd4, 0x1d, 0xec, 0xd9, 0x48, 0x60, 0xc9, 0x7, 0x1c, 0xf8, - 0x4d, 0x41, 0xfc, 0x4, 0xe, 0xf0, 0x7d, 0xe3, 0x31, 0x7f, 0xc5, 0xcd, - 0x5e, 0x84, 0x3d, 0xda, 0x92, 0xfb, 0x71, 0xc3, 0x77, 0x2a, 0xae, 0x39, - 0x65, 0x16, 0x24, 0x7d, 0x7c, 0x61, 0xcd, 0xdd, 0xe3, 0x50, 0x54, 0x44, - 0xc4, 0x30, 0x98, 0xfc, 0x62, 0xb9, 0xad, 0x20, 0x7b, 0x2b, 0x5b, 0xf1, - 0xf6, 0xe5, 0x3e, 0xf4, 0xe0, 0xaf, 0x7a, 0xeb, 0xe6, 0xee, 0xe7, 0x21, - 0xc, 0xf1, 0x54, 0xbc, 0xe7, 0xe4, 0x19, 0xd9, 0xfd, 0x1d, 0x1b, 0x2f, - 0xad, 0xeb, 0xe4, 0x27, 0x73, 0xd, 0xcd, 0xb8, 0x7a, 0x7e, 0xe7, 0x4b, - 0x8d, 0xce, 0x83, 0x91, 0x1, 0x82, 0x62, 0xb1, 0xb0, 0xad, 0x32, 0x6f, - 0xb6, 0xe2, 0xff, 0x10, 0x5c, 0x83, 0x13, 0xa4, 0x6f, 0xe7, 0xaa, 0x7, - 0xf0, 0xc4, 0x3c, 0x42, 0x51, 0xd9, 0xc7, 0x70, 0x4, 0xf, 0x6e, 0x2c, - 0x5c, 0x67, 0x2d, 0xd2, 0x3, 0x69, 0xa, 0x45, 0x9b, 0xa9, 0x6e, 0xd0, - 0x6c, 0x7e, 0xfb, 0xf3, 0x15, 0xa0, 0x8d, 0x31, 0xb0, 0x7d, 0x83, 0xc, - 0xa9, 0xbf, 0xa8, 0xcc, 0x13, 0x33, 0x61, 0xdf, 0x2f, 0x7e, 0x4d, 0xd3, - 0xe, 0x94, 0x0, 0xa4, 0x49, 0xcc, 0xf, 0x32, 0x93, 0x1, 0xdc, 0xf1, - 0x56, 0xfe, 0x14, 0xa0, 0x95, 0x96, 0xf6, 0xe5, 0x23, 0x2, 0xb7, 0xce, - 0x71, 0x2c, 0xa6, 0x7e, 0x67, 0x7a, 0x59, 0x84, 0x5c, 0xc5, 0xbe, 0x66, - 0xd4, 0x73, 0x3a, 0xbd, 0xf9, 0xa3, 0xd4, 0x7a, 0x66, 0xaf, 0xe, 0x46, - 0x2d, 0x6d, 0x2c, 0x5b, 0x31, 0xf9, 0x51, 0x5, 0xa6, 0xa4, 0x49, 0xbd, - 0xf3, 0x5, 0x6d, 0x98, 0x56, 0xa6, 0xce, 0xea, 0x15, 0x1, 0x0, 0xa, - 0xa2, 0x7f, 0x61, 0x42, 0xef, 0x52, 0xbc, 0x8e, 0xaf, 0xd3, 0x36, 0xd, - 0x65, 0x25, 0x89, 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, - 0xee, 0x18, 0x51, 0x29, 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, - 0xdd, 0x1f, 0x20, 0x1, 0x0, 0x0, 0x0, 0x3, 0xa, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xde, 0xbb, 0xbe, 0xfd, 0x16, 0x83, 0xe3, - 0x35, 0x29, 0x6a, 0xc, 0x86, 0xf1, 0xc8, 0x82, 0xa2, 0xea, 0x37, 0x59, - 0xf1, 0x14, 0x22, 0xb, 0xb, 0x2c, 0xf8, 0x69, 0xe3, 0x7d, 0xec, 0x24, - 0xc8, 0x0, 0xb3, 0x2a, 0x56, 0xa6, 0xc7, 0x2, 0x56, 0x33, 0x79, 0xad, - 0x65, 0xd0, 0x7a, 0x2c, 0x80, 0xe0, 0x46, 0x73, 0xaf, 0x85, 0x59, 0x52, - 0x58, 0xfc, 0x15, 0x60, 0xff, 0xd8, 0x47, 0x1a, 0xd7, 0x32, - 0x8, 0x97, 0x75, 0xf8, 0x29, 0xc8, 0xad, 0xad, 0x92, 0xad, 0xa1, 0x7b, - 0x59, 0x31, 0xed, 0xf6, 0x30, 0x64, 0xd5, 0x46, 0x78, 0xf4, 0xeb, 0x9a, - 0x6f, 0xdf, 0xe8, 0xe4, 0xcb, 0x5d, 0x95, 0xf6, 0xf4, 0xa3, 0x2, 0x3b, - 0x4d, 0x5a, 0x83, 0xe1, 0x98, 0x44, 0x23, 0xd7, 0xc8, 0xe3, 0xc8, 0x35, - 0xf, 0x42, 0xc, 0xca, 0x90, 0xc5, 0xa4, 0xa7, 0x3f, 0xea, 0x62, 0x69, - 0xe4, 0x78, 0xbc, 0x63, 0x94, 0x76, 0xfb, 0xb6, 0x64, 0xa9, 0xf7, 0x81, - 0x70, 0xc6, 0xd, 0xa3, 0x70, 0x5, 0xc1, 0xc8, 0x94, 0x7f, 0x20, 0xff, - 0x83, 0x8c, 0xc4, 0x7a, 0x26, 0xd3, 0x84, 0xab, 0x51, 0x15, 0xfc, 0xb1, - 0x57, 0x2d, 0xb3, 0x9, 0x1b, 0xc8, 0x6d, 0x32, 0xfd, 0x52, 0x70, 0xa, - 0xf1, 0x47, 0xe2, 0xc4, 0xa8, 0x5c, 0x5e, 0x95, 0x18, 0xc8, 0x46, 0xa9, - 0xa3, 0xd0, 0xda, 0x76, 0xce, 0xbf, 0xdb, 0x31, 0x27, 0x4b, 0x68, 0x58, - 0xe5, 0x36, 0x13, 0x54, 0x29, 0x94, 0x4c, 0x30, 0x23, 0x4c, 0xc, 0x6a, - 0x3a, 0x5, 0x15, 0x70, 0x97, 0x8a, 0x3e, 0xc5, 0x82, 0x96, 0x65, 0x56, - 0x69, 0xc0, 0x4d, 0x58, 0x5b, 0x8a, 0x85, 0x39, 0x84, 0x29, 0x9b, 0xa5, - 0x9b, 0xe4, 0xc4, 0x79, 0x5b, 0x8b, 0xe1, 0x17, 0x25, 0x10, 0x22, 0x4, - 0x5, 0x44, 0xe5, 0x68, 0x72, 0x80, 0x88, 0xd5, 0x23, 0x22, 0x19, 0x8d, - 0xca, 0xa5, 0x26, 0xc4, 0x73, 0xdb, 0x6, 0x96, 0xb7, 0xe, 0x28, 0xc6, - 0xa, 0xc3, 0x65, 0x5c, 0x9c, 0x3, 0xf3, 0x1d, 0xc9, 0x53, 0x34, 0x6a, - 0x85, 0x1, 0xe2, 0x3c, 0x91, 0x6d, 0x70, 0xe1, 0x4d, 0xa2, 0xa, 0x67, - 0x50, 0xb0, 0xe2, 0x12, 0x1f, 0xba, 0x68, 0xdc, 0xd, 0x35, 0x3b, 0x32, - 0xa7, 0x2b, 0xe7, 0x91, 0x6d, 0xb2, 0xe0, 0xf4, 0xb8, 0xb1, 0x6d, 0xab, - 0xa6, 0x46, 0xd5, 0x4, 0x5a, 0x5d, 0xf1, 0x8f, 0x2d, 0x52, 0x6a, 0xb8, - 0x50, 0xf3, 0x22, 0x4e, 0xb1, 0x24, 0xa8, 0xa1, 0x15, 0x34, 0xbc, 0x3f, - 0xda, 0x8c, 0xc6, 0xc8, 0x53, 0x2b, 0xd0, 0x9f, 0xa8, 0x72, 0x3e, 0xc1, - 0x6a, 0x3a, 0x51, 0xb1, 0x99, 0x80, 0x1b, 0xae, 0x2d, 0x4c, 0x79, 0xa0, - 0x10, 0x2b, 0x7, 0x4a, 0xa, 0x65, 0x3a, 0x82, 0xe4, 0x1f, 0xbb, 0x9c, - 0x6e, 0x20, 0xa5, 0x1b, 0x17, 0xdc, 0xa7, 0x6f, 0x77, 0x22, 0xd, 0xb9, - 0xc2, 0xf6, 0xa7, 0xe1, 0x8d, 0x88, 0x88, 0xdc, 0x44, 0x68, 0xbd, 0x25, - 0x42, 0x5f, 0x20, 0x1b, 0x84, 0x15, 0x56, 0x5, 0x95, 0x9c, 0x40, 0xef, - 0xa1, 0x71, 0xaa, 0xc7, 0x82, 0x8, 0x39, 0xf4, 0x58, 0xae, 0x39, 0x50, - 0xac, 0xc7, 0x53, 0xff, 0x5, 0xb0, 0x29, 0x9d, 0x54, 0x4f, 0x8d, 0x1a, - 0x81, 0x61, 0xc2, 0x71, 0xc, 0x2f, 0xdb, 0x1b, 0x1b, 0xa7, 0x4f, 0x1a, - 0x4a, 0xa2, 0xa9, 0x8c, 0x2c, 0x1, 0xe7, 0xf9, 0xf, 0x85, 0xc1, 0x33, - 0xe7, 0x39, 0x8f, 0x43, 0x40, 0x30, 0x27, 0xeb, 0xad, 0x7e, 0xef, 0x22, - 0xf8, 0xb5, 0x51, 0xe5, 0xb3, 0x7c, 0x2a, 0x45, 0x88, 0x93, 0xac, 0xea, - 0x6a, 0x51, 0x63, 0x79, 0x45, 0x35, 0xfd, 0x9d, 0xd4, 0x55, 0x98, 0xd, - 0xf4, 0x29, 0x7c, 0xfc, 0x93, 0x52, 0xa4, 0x61, 0x6c, 0x1a, 0xcf, 0x5, - 0x5a, 0x3e, 0x44, 0x82, 0x6c, 0x44, 0x7e, 0x6e, 0xb2, 0xad, 0x5a, 0x3, - 0x72, 0x2f, 0xed, 0x77, 0x44, 0x16, 0xd1, 0x59, 0xa8, 0x10, 0x2d, 0x8, - 0x6c, 0xd6, 0xb2, 0x38, 0x95, 0x4c, 0x37, 0x54, 0x2e, 0x8d, 0xdc, 0xd6, - 0x34, 0xe5, 0xe2, 0x64, 0x9b, 0x57, 0x26, 0x38, 0x28, 0xd, 0x46, 0x7e, - 0xc3, 0x1, 0xcc, 0x36, 0x48, 0xe9, 0xd1, 0x9a, 0x9f, 0x29, 0xa1, 0xac, - 0x53, 0xdd, 0xf, 0x8a, 0x51, 0x5d, 0xe3, 0x18, 0x19, 0xcf, 0x93, 0x82, - 0x95, 0x5b, 0x69, 0x8e, 0xf, 0xab, 0x2, 0x17, 0xfa, 0xa7, 0x9, 0x35, - 0xf2, 0x9, 0x39, 0xe2, 0x5b, 0x36, 0x90, 0xa8, 0x46, 0x9c, 0xf3, 0x58, - 0x29, 0x0, 0xb1, 0xb0, 0xdd, 0xdc, 0x41, 0xf6, 0xa, 0x99, 0xe1, 0xff, - 0x2b, 0xe8, 0x1d, 0x3c, 0x86, 0x8e, 0xff, 0x9f, 0xed, 0x3e, 0x98, 0x5d, - 0x24, 0xfc, 0x58, 0xd7, 0x13, 0x12, 0xa7, 0x74, 0x5e, 0x3e, 0x44, 0x68, - 0x7d, 0x11, 0x0, 0x44, 0xb1, 0x28, 0x4f, 0x85, 0x1e, 0x92, 0x5a, 0x3c, - 0xc6, 0x77, 0x70, 0x4, 0x43, 0x1c, 0x81, 0x41, 0x65, 0xd2, 0x33, 0x77, - 0x91, 0xd1, 0xab, 0xe5, 0x97, 0x90, 0x1f, 0x7b, 0xe6, 0xbb, 0xcc, 0xb3, - 0x65, 0x61, 0x57, 0x6d, 0x60, 0xa6, 0x93, 0x79, 0x3d, 0x70, 0x43, 0x92, - 0x5, 0x4b, 0x2, 0x67, 0xea, 0x78, 0x8b, 0x12, 0xba, 0x85, 0x9c, 0x2b, - 0xda, 0x7b, 0xb, 0xed, 0x3c, 0xe8, 0xca, 0xa4, 0x64, 0xe4, 0x9b, 0x9c, - 0xa8, 0x5c, 0x5c, 0xe2, 0xa7, 0x82, 0xea, 0x4c, 0x79, 0x77, 0x4, 0xf1, - 0x0, 0x5, 0xad, 0x2f, 0x72, 0x3d, 0x95, 0xe5, 0x8, 0x50, 0x48, 0x2e, - 0x80, 0x5d, 0x54, 0x67, 0xf9, 0x41, 0xf1, 0x1d, 0xb6, 0x86, 0x6, 0x73, - 0xa, 0xaf, 0x99, 0x7d, 0x2c, 0x30, 0xa6, 0xc9, 0xbc, 0x7d, 0x39, 0x16, - 0x3, 0x55, 0x85, 0x63, 0xe8, 0x69, 0x36, 0x2a, 0xc2, 0xba, 0x5b, 0xf, - 0x49, 0x1d, 0x2, 0xb4, 0xe1, 0x12, 0xf1, 0xe6, 0x9b, 0xaf, 0xd4, 0x78, - 0xd9, 0xaf, 0x7b, 0x5f, 0x50, 0xa5, 0x86, 0x32, 0xbc, 0x36, 0xe4, 0x96, - 0x11, 0xef, 0xf8, 0xb4, 0xd4, 0x91, 0xf7, 0xd7, 0x43, 0x15, 0x28, 0x3, - 0x1e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0x35, 0x74, - 0xc4, 0xd9, 0x9c, 0x8, 0xef, 0x95, 0x6, 0x19, 0xbe, 0x72, 0xbf, 0xa1, - 0xd5, 0xa, 0xe3, 0xc1, 0x53, 0xd1, 0xf3, 0xf, 0x64, 0xbc, 0x1a, 0xc0, - 0x8d, 0xe9, 0x9e, 0xa5, 0x56, 0x3, 0x0, 0x2, 0x4, 0x0, 0x2, 0x3a, 0xa, - 0x34, 0xc8, 0xd, 0xdb, 0x3e, 0xac, 0x5c, 0xd5, 0x92, 0x38, 0x30, 0x81, - 0x4d, 0x72, 0xf9, 0xde, 0x9, 0x6b, 0xca, 0x74, 0x87, 0x79, 0xda, 0x39, - 0x7a, 0xa3, 0xb7, 0x71, 0xfe, 0x7e, 0x40, 0xc6, 0x41, 0x1a, 0xea, 0x8, - 0x2e, 0x2c, 0x5d, 0x74, 0x34, 0x73, 0x68, 0x67, 0x7d, 0xb6, 0x95, 0x45, - 0x12, 0x62, 0x37, 0xd5, 0xed, 0x78, 0xfa, 0xa0, 0x84, 0x63, 0x52, 0xf5, - 0x38, 0x3f, 0x95, 0x3, 0x0, 0xfd, 0xb7, 0x19, 0xd1, 0x24, 0xce, 0xff, - 0x58, 0x6, 0xe, 0xf5, 0x8d, 0x94, 0xa, 0x75, 0xe4, 0x3d, 0x13, 0x9d, - 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, 0xc9, 0xeb, 0x4f, 0x77, 0x3b, 0xff, - 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, 0xd2, 0x7e, 0xf5, 0x1, 0x0, 0x0, - 0x0, 0x64, 0x20, 0xcc, 0x42, 0x1e, 0x11, 0x89, 0x80, 0x5c, 0x8c, 0xec, - 0x8, 0x9d, 0x74, 0xc1, 0x98, 0xf, 0x79, 0xc0, 0x69, 0x0, 0x5a, 0x21, - 0xae, 0x40, 0xa7, 0xe5, 0x8e, 0x68, 0x77, 0xa8, 0x10, 0x7b, 0x4, 0x9, - 0x1a, 0x9a, 0x97, 0x1, 0x2, 0x90, 0xe5, 0x10, 0xa2, 0x10, 0x60, 0xad, - 0xa3, 0x39, 0x71, 0xd, 0xd, 0xdc, 0x43, 0xe4, 0x46, 0x0, 0x6c, 0x5b, - 0xc9, 0x38, 0x64, 0xda, 0xfb, 0x3, 0xcf, 0x4b, 0xa4, 0x72, 0xbe, 0xdf, - 0x5c, 0xa7, 0x1, 0x0, 0x47, 0xe7, 0xd3, 0x5d, 0x93, 0xe4, 0xb5, 0x62, - 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, 0x89, 0x52, 0xf4, 0xd9, 0x57, - 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, 0x51, 0x29, 0x71, 0x82, 0x93, - 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, 0x20, 0x1, 0x0, 0x0, 0x0, - 0x40, 0xe7, 0xa, 0x36, 0xe2, 0xce, 0x51, 0xd3, 0x1d, 0x4c, 0xf5, 0xd6, - 0x73, 0x1f, 0xa6, 0x37, 0x38, 0x64, 0x81, 0x27, 0xdb, 0x83, 0x37, 0x15, - 0xd3, 0x96, 0x52, 0xd8, 0x6d, 0x92, 0x7d, 0x48, 0x88, 0x3, 0x0, 0x1, - 0x0, 0x2, 0x0, 0x3, 0x0 -] \ No newline at end of file diff --git a/test/hash_state.in b/test/hash_state.in deleted file mode 100644 index b9d52d37..00000000 --- a/test/hash_state.in +++ /dev/null @@ -1,25 +0,0 @@ -[ - 0x2, 0x4, 0x0, 0x2, 0x3a, 0xa, 0x34, 0xc8, 0xd, 0xdb, 0x3e, 0xac, 0x5c, - 0xd5, 0x92, 0x38, 0x30, 0x81, 0x4d, 0x72, 0xf9, 0xde, 0x9, 0x6b, 0xca, - 0x74, 0x87, 0x79, 0xda, 0x39, 0x7a, 0xa3, 0xb7, 0x71, 0xfe, 0x7e, 0x40, - 0xc6, 0x41, 0x1a, 0xea, 0x8, 0x2e, 0x2c, 0x5d, 0x74, 0x34, 0x73, 0x68, - 0x67, 0x7d, 0xb6, 0x95, 0x45, 0x12, 0x62, 0x37, 0xd5, 0xed, 0x78, 0xfa, - 0xa0, 0x84, 0x63, 0x52, 0xf5, 0x38, 0x3f, 0x95, 0x3, 0x0, 0xfd, 0xb7, - 0x19, 0xd1, 0x24, 0xce, 0xff, 0x58, 0x6, 0xe, 0xf5, 0x8d, 0x94, 0xa, - 0x75, 0xe4, 0x3d, 0x13, 0x9d, 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, 0xc9, - 0xeb, 0x4f, 0x77, 0x3b, 0xff, 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, 0xd2, - 0x7e, 0xf5, 0x1, 0x0, 0x0, 0x0, 0x64, 0x20, 0xcc, 0x42, 0x1e, 0x11, - 0x89, 0x80, 0x5c, 0x8c, 0xec, 0x8, 0x9d, 0x74, 0xc1, 0x98, 0xf, 0x79, - 0xc0, 0x69, 0x0, 0x5a, 0x21, 0xae, 0x40, 0xa7, 0xe5, 0x8e, 0x68, 0x77, - 0xa8, 0x10, 0x7b, 0x4, 0x9, 0x1a, 0x9a, 0x97, 0x1, 0x2, 0x90, 0xe5, - 0x10, 0xa2, 0x10, 0x60, 0xad, 0xa3, 0x39, 0x71, 0xd, 0xd, 0xdc, 0x43, - 0xe4, 0x46, 0x0, 0x6c, 0x5b, 0xc9, 0x38, 0x64, 0xda, 0xfb, 0x3, 0xcf, - 0x4b, 0xa4, 0x72, 0xbe, 0xdf, 0x5c, 0xa7, 0x1, 0x0, 0x47, 0xe7, 0xd3, - 0x5d, 0x93, 0xe4, 0xb5, 0x62, 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, - 0x89, 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, - 0x51, 0x29, 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, - 0x20, 0x1, 0x0, 0x0, 0x0, 0x40, 0xe7, 0xa, 0x36, 0xe2, 0xce, 0x51, - 0xd3, 0x1d, 0x4c, 0xf5, 0xd6, 0x73, 0x1f, 0xa6, 0x37, 0x38, 0x64, 0x81, - 0x27, 0xdb, 0x83, 0x37, 0x15, 0xd3, 0x96, 0x52, 0xd8, 0x6d, 0x92, 0x7d, - 0x48, 0x88, - ] \ No newline at end of file diff --git a/test/metadata.in b/test/metadata.in deleted file mode 100644 index 72671fa2..00000000 --- a/test/metadata.in +++ /dev/null @@ -1,15 +0,0 @@ -[ - 0x1, 0x0, 0xd, 0x0, 0x15, 0x0, 0x0, 0x2, 0x0, 0x3, 0x1, 0x2, 0x0, 0x2, - 0x2, 0x0, 0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0, 0x3, 0x2, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, - 0x2, 0x8, 0x3, 0xa, 0x2, 0x0, 0x0, 0x0, 0xa, 0x3, 0x0, 0x0, 0x0, 0xb, - 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x3, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x40, 0x12, 0x0, 0x0, 0x40, 0x40, - 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x13, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x8, 0x40, 0x20, 0x5, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, - 0x20, 0x5, 0x0, 0xa, 0x14, 0x1e, 0x28, 0x32, 0x21, 0x11, 0x0, 0x4f, - 0x6e, 0x65, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x21, 0x15, 0x0, 0x41, 0x6e, 0x6f, 0x74, 0x68, - 0x65, 0x72, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, - ] \ No newline at end of file diff --git a/test/parent_rights.in b/test/parent_rights.in deleted file mode 100644 index 334c504c..00000000 --- a/test/parent_rights.in +++ /dev/null @@ -1,9 +0,0 @@ -[ - 0x1, 0x0, 0xf5, 0x7e, 0xd2, 0x7e, 0xe4, 0x19, 0x90, 0x72, 0xc5, 0xff, - 0x3b, 0x77, 0x4f, 0xeb, 0xc9, 0x4d, 0x26, 0xd3, 0xe4, 0xa5, 0x55, 0x9d, - 0x13, 0x3d, 0xe4, 0x75, 0xa, 0x94, 0x8d, 0xf5, 0xe, 0x6, 0x3, 0x0, 0x1, - 0x0, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0, 0x3, 0x0, 0x4, 0x0, 0x5, 0x0, 0x2, - 0x0, 0x5, 0x0, 0xa, 0x0, 0x14, 0x0, 0x1e, 0x0, 0x28, 0x0, 0x32, 0x0, - 0x3, 0x0, 0x5, 0x0, 0x64, 0x0, 0xc8, 0x0, 0x2c, 0x1, 0x90, 0x1, 0xf4, - 0x1, - ] \ No newline at end of file diff --git a/test/pedersan_state.in b/test/pedersan_state.in deleted file mode 100644 index 93774207..00000000 --- a/test/pedersan_state.in +++ /dev/null @@ -1,141 +0,0 @@ -[ - 0x1, 0x3, 0x4, 0x0, 0x3, 0x0, 0x6e, 0x5a, 0x76, 0xca, 0xd0, 0x21, 0x63, - 0xa5, 0x6, 0xe, 0xf5, 0x8d, 0x94, 0xa, 0x75, 0xe4, 0x3d, 0x13, 0x9d, - 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, 0xc9, 0xeb, 0x4f, 0x77, 0x3b, 0xff, - 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, 0xd2, 0x7e, 0xf5, 0x1, 0x0, 0x0, - 0x0, 0x8, 0xcc, 0x48, 0xfa, 0x5e, 0x5c, 0xb1, 0xd2, 0xd2, 0x46, 0x5b, - 0xd8, 0xc4, 0x37, 0xc0, 0xe0, 0x5, 0x14, 0xab, 0xd8, 0x13, 0xf9, 0xa7, - 0xdd, 0x50, 0x6a, 0x77, 0x84, 0x5, 0xa2, 0xc4, 0x3b, 0xc0, 0xa3, 0x2, - 0xdd, 0x8a, 0x81, 0xc2, 0xb1, 0x62, 0xe7, 0xb9, 0xc8, 0xec, 0xe9, 0x64, - 0xfc, 0x4f, 0x67, 0x56, 0xdb, 0x85, 0x34, 0x43, 0x97, 0x3c, 0x84, 0xf9, - 0x32, 0x45, 0x5e, 0x8c, 0x4c, 0x93, 0xd9, 0x19, 0xb, 0x68, 0x4e, 0x5a, - 0x15, 0xc7, 0x31, 0xb, 0x33, 0xa4, 0xc0, 0xbe, 0xa6, 0x11, 0xc, 0x64, - 0xa0, 0x24, 0x72, 0x79, 0xec, 0x12, 0x49, 0xc6, 0x9f, 0x94, 0xeb, 0x5, - 0x71, 0x7d, 0x81, 0x0, 0xe, 0x3f, 0x84, 0x8e, 0x9f, 0xe9, 0x68, 0x2f, - 0xa6, 0xa, 0xd8, 0x59, 0x57, 0xcf, 0x64, 0xb9, 0x56, 0xb5, 0xfc, 0xcc, - 0x2b, 0xdc, 0x9e, 0x4d, 0xdd, 0x78, 0x60, 0x63, 0x12, 0x57, 0x12, 0xcd, - 0xf3, 0x6f, 0xe2, 0xca, 0x1e, 0x19, 0x3a, 0xb, 0x10, 0xc, 0x59, 0x97, - 0xc, 0xde, 0xa8, 0x62, 0x42, 0x4a, 0x2f, 0x1e, 0xeb, 0x89, 0x98, 0xc6, - 0x31, 0x82, 0xc9, 0x4f, 0xf, 0xf1, 0xa5, 0x1a, 0x37, 0x2d, 0x92, 0x86, - 0x8c, 0xe5, 0x37, 0x3a, 0x86, 0xc4, 0x89, 0x9f, 0xf4, 0xcf, 0x10, 0x7b, - 0x9a, 0x30, 0xc0, 0x0, 0x97, 0x1e, 0x44, 0x9b, 0xb2, 0x92, 0x1d, 0x38, - 0x6e, 0x3a, 0xce, 0xea, 0x95, 0xcd, 0xcd, 0x63, 0x74, 0x5e, 0x43, 0xf, - 0xd3, 0xdd, 0x21, 0x2, 0xca, 0x91, 0xc5, 0x2d, 0x9f, 0x21, 0x7b, 0x4d, - 0x14, 0x9f, 0xf1, 0x88, 0xe5, 0x3a, 0x98, 0x6d, 0x3, 0xdd, 0x64, 0x90, - 0x73, 0x5a, 0x87, 0x1f, 0x53, 0x64, 0xe4, 0x9e, 0x48, 0xfc, 0x1e, 0x3e, - 0xcc, 0xeb, 0x5, 0xd3, 0xfd, 0x9a, 0x56, 0x5f, 0x71, 0x51, 0x39, 0xe3, - 0x10, 0xa8, 0xae, 0x20, 0xa8, 0xba, 0xca, 0x7b, 0x91, 0x6, 0xe9, 0x61, - 0x45, 0x69, 0x91, 0x94, 0xe0, 0xec, 0x50, 0xa4, 0x12, 0x58, 0xe1, 0x64, - 0xc2, 0x4c, 0x3c, 0x7f, 0x69, 0x7a, 0x7e, 0x4a, 0xee, 0xed, 0xb, 0x91, - 0x3e, 0x63, 0x71, 0x96, 0x99, 0x78, 0xf0, 0x3e, 0x40, 0x96, 0x58, 0x9a, - 0xd, 0xb9, 0x77, 0x79, 0xa2, 0xb7, 0xa3, 0x67, 0xcf, 0xc2, 0x45, 0x27, - 0xf0, 0x86, 0x3f, 0x8f, 0x60, 0xec, 0x17, 0x54, 0x4, 0xa8, 0xf1, 0xce, - 0x5f, 0xa2, 0x5b, 0xe9, 0xba, 0xb0, 0xac, 0x4f, 0x5b, 0x47, 0xbb, 0xb6, - 0xd8, 0x1, 0x7, 0x73, 0x24, 0xc4, 0x8b, 0xc8, 0xe1, 0x15, 0xe4, 0xd2, - 0x9f, 0xc5, 0x4, 0xed, 0x13, 0xc3, 0x17, 0xb8, 0xc9, 0xdd, 0x84, 0x78, - 0xea, 0x92, 0x4c, 0x41, 0x98, 0xc, 0x38, 0xc8, 0x2, 0x20, 0xeb, 0xf2, - 0x93, 0x75, 0x8f, 0xd7, 0x9d, 0x76, 0xfa, 0xfa, 0xbb, 0x5e, 0xa1, 0x98, - 0x51, 0xd6, 0xbd, 0x6, 0xa2, 0x37, 0x2, 0x89, 0x10, 0xb9, 0x84, 0x69, - 0xc7, 0xb7, 0xee, 0xec, 0xca, 0x2d, 0x13, 0xbb, 0x8f, 0xb, 0xa5, 0x9f, - 0x17, 0x6a, 0xb2, 0xef, 0x51, 0x39, 0x1f, 0xce, 0x69, 0x8c, 0xc, 0x67, - 0x67, 0x6f, 0x29, 0x29, 0x5, 0x5a, 0xcb, 0x17, 0x6a, 0x8f, 0x1b, 0xe6, - 0x1c, 0x32, 0xad, 0xf2, 0xda, 0xb3, 0xb6, 0xb8, 0x6e, 0xae, 0x28, 0x9e, - 0x7b, 0x12, 0x3f, 0x52, 0x26, 0xfd, 0x9c, 0xad, 0x2b, 0x18, 0xb2, 0x6f, - 0x33, 0xf, 0xf5, 0xab, 0x53, 0x8c, 0x9b, 0xbf, 0xca, 0xe2, 0x1f, 0xfd, - 0x91, 0xaa, 0x41, 0x26, 0x81, 0xdc, 0x1c, 0x9a, 0xd4, 0x1d, 0xec, 0xd9, - 0x48, 0x60, 0xc9, 0x7, 0x1c, 0xf8, 0x4d, 0x41, 0xfc, 0x4, 0xe, 0xf0, - 0x7d, 0xe3, 0x31, 0x7f, 0xc5, 0xcd, 0x5e, 0x84, 0x3d, 0xda, 0x92, 0xfb, - 0x71, 0xc3, 0x77, 0x2a, 0xae, 0x39, 0x65, 0x16, 0x24, 0x7d, 0x7c, 0x61, - 0xcd, 0xdd, 0xe3, 0x50, 0x54, 0x44, 0xc4, 0x30, 0x98, 0xfc, 0x62, 0xb9, - 0xad, 0x20, 0x7b, 0x2b, 0x5b, 0xf1, 0xf6, 0xe5, 0x3e, 0xf4, 0xe0, 0xaf, - 0x7a, 0xeb, 0xe6, 0xee, 0xe7, 0x21, 0xc, 0xf1, 0x54, 0xbc, 0xe7, 0xe4, - 0x19, 0xd9, 0xfd, 0x1d, 0x1b, 0x2f, 0xad, 0xeb, 0xe4, 0x27, 0x73, 0xd, - 0xcd, 0xb8, 0x7a, 0x7e, 0xe7, 0x4b, 0x8d, 0xce, 0x83, 0x91, 0x1, 0x82, - 0x62, 0xb1, 0xb0, 0xad, 0x32, 0x6f, 0xb6, 0xe2, 0xff, 0x10, 0x5c, 0x83, - 0x13, 0xa4, 0x6f, 0xe7, 0xaa, 0x7, 0xf0, 0xc4, 0x3c, 0x42, 0x51, 0xd9, - 0xc7, 0x70, 0x4, 0xf, 0x6e, 0x2c, 0x5c, 0x67, 0x2d, 0xd2, 0x3, 0x69, - 0xa, 0x45, 0x9b, 0xa9, 0x6e, 0xd0, 0x6c, 0x7e, 0xfb, 0xf3, 0x15, 0xa0, - 0x8d, 0x31, 0xb0, 0x7d, 0x83, 0xc, 0xa9, 0xbf, 0xa8, 0xcc, 0x13, 0x33, - 0x61, 0xdf, 0x2f, 0x7e, 0x4d, 0xd3, 0xe, 0x94, 0x0, 0xa4, 0x49, 0xcc, - 0xf, 0x32, 0x93, 0x1, 0xdc, 0xf1, 0x56, 0xfe, 0x14, 0xa0, 0x95, 0x96, - 0xf6, 0xe5, 0x23, 0x2, 0xb7, 0xce, 0x71, 0x2c, 0xa6, 0x7e, 0x67, 0x7a, - 0x59, 0x84, 0x5c, 0xc5, 0xbe, 0x66, 0xd4, 0x73, 0x3a, 0xbd, 0xf9, 0xa3, - 0xd4, 0x7a, 0x66, 0xaf, 0xe, 0x46, 0x2d, 0x6d, 0x2c, 0x5b, 0x31, 0xf9, - 0x51, 0x5, 0xa6, 0xa4, 0x49, 0xbd, 0xf3, 0x5, 0x6d, 0x98, 0x56, 0xa6, - 0xce, 0xea, 0x15, 0x1, 0x0, 0xa, 0xa2, 0x7f, 0x61, 0x42, 0xef, 0x52, - 0xbc, 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, 0x89, 0x52, 0xf4, 0xd9, - 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, 0x51, 0x29, 0x71, 0x82, - 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, 0x20, 0x1, 0x0, 0x0, - 0x0, 0x3, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xde, 0xbb, 0xbe, - 0xfd, 0x16, 0x83, 0xe3, 0x35, 0x29, 0x6a, 0xc, 0x86, 0xf1, 0xc8, 0x82, - 0xa2, 0xea, 0x37, 0x59, 0xf1, 0x14, 0x22, 0xb, 0xb, 0x2c, 0xf8, 0x69, - 0xe3, 0x7d, 0xec, 0x24, 0xc8, 0x0, 0xb3, 0x2a, 0x56, 0xa6, 0xc7, 0x2, - 0x56, 0x33, 0x79, 0xad, 0x65, 0xd0, 0x7a, 0x2c, 0x80, 0xe0, 0x46, 0x73, - 0xaf, 0x85, 0x59, 0x52, 0x58, 0xfc, 0x15, 0x60, 0xff, 0xd8, 0x47, 0x1a, - 0xd7, 0x32, 0x8, 0x97, 0x75, 0xf8, 0x29, 0xc8, 0xad, 0xad, 0x92, 0xad, - 0xa1, 0x7b, 0x59, 0x31, 0xed, 0xf6, 0x30, 0x64, 0xd5, 0x46, 0x78, 0xf4, - 0xeb, 0x9a, 0x6f, 0xdf, 0xe8, 0xe4, 0xcb, 0x5d, 0x95, 0xf6, 0xf4, 0xa3, - 0x2, 0x3b, 0x4d, 0x5a, 0x83, 0xe1, 0x98, 0x44, 0x23, 0xd7, 0xc8, 0xe3, - 0xc8, 0x35, 0xf, 0x42, 0xc, 0xca, 0x90, 0xc5, 0xa4, 0xa7, 0x3f, 0xea, - 0x62, 0x69, 0xe4, 0x78, 0xbc, 0x63, 0x94, 0x76, 0xfb, 0xb6, 0x64, 0xa9, - 0xf7, 0x81, 0x70, 0xc6, 0xd, 0xa3, 0x70, 0x5, 0xc1, 0xc8, 0x94, 0x7f, - 0x20, 0xff, 0x83, 0x8c, 0xc4, 0x7a, 0x26, 0xd3, 0x84, 0xab, 0x51, 0x15, - 0xfc, 0xb1, 0x57, 0x2d, 0xb3, 0x9, 0x1b, 0xc8, 0x6d, 0x32, 0xfd, 0x52, - 0x70, 0xa, 0xf1, 0x47, 0xe2, 0xc4, 0xa8, 0x5c, 0x5e, 0x95, 0x18, 0xc8, - 0x46, 0xa9, 0xa3, 0xd0, 0xda, 0x76, 0xce, 0xbf, 0xdb, 0x31, 0x27, 0x4b, - 0x68, 0x58, 0xe5, 0x36, 0x13, 0x54, 0x29, 0x94, 0x4c, 0x30, 0x23, 0x4c, - 0xc, 0x6a, 0x3a, 0x5, 0x15, 0x70, 0x97, 0x8a, 0x3e, 0xc5, 0x82, 0x96, - 0x65, 0x56, 0x69, 0xc0, 0x4d, 0x58, 0x5b, 0x8a, 0x85, 0x39, 0x84, 0x29, - 0x9b, 0xa5, 0x9b, 0xe4, 0xc4, 0x79, 0x5b, 0x8b, 0xe1, 0x17, 0x25, 0x10, - 0x22, 0x4, 0x5, 0x44, 0xe5, 0x68, 0x72, 0x80, 0x88, 0xd5, 0x23, 0x22, - 0x19, 0x8d, 0xca, 0xa5, 0x26, 0xc4, 0x73, 0xdb, 0x6, 0x96, 0xb7, 0xe, - 0x28, 0xc6, 0xa, 0xc3, 0x65, 0x5c, 0x9c, 0x3, 0xf3, 0x1d, 0xc9, 0x53, - 0x34, 0x6a, 0x85, 0x1, 0xe2, 0x3c, 0x91, 0x6d, 0x70, 0xe1, 0x4d, 0xa2, - 0xa, 0x67, 0x50, 0xb0, 0xe2, 0x12, 0x1f, 0xba, 0x68, 0xdc, 0xd, 0x35, - 0x3b, 0x32, 0xa7, 0x2b, 0xe7, 0x91, 0x6d, 0xb2, 0xe0, 0xf4, 0xb8, 0xb1, - 0x6d, 0xab, 0xa6, 0x46, 0xd5, 0x4, 0x5a, 0x5d, 0xf1, 0x8f, 0x2d, 0x52, - 0x6a, 0xb8, 0x50, 0xf3, 0x22, 0x4e, 0xb1, 0x24, 0xa8, 0xa1, 0x15, 0x34, - 0xbc, 0x3f, 0xda, 0x8c, 0xc6, 0xc8, 0x53, 0x2b, 0xd0, 0x9f, 0xa8, 0x72, - 0x3e, 0xc1, 0x6a, 0x3a, 0x51, 0xb1, 0x99, 0x80, 0x1b, 0xae, 0x2d, 0x4c, - 0x79, 0xa0, 0x10, 0x2b, 0x7, 0x4a, 0xa, 0x65, 0x3a, 0x82, 0xe4, 0x1f, - 0xbb, 0x9c, 0x6e, 0x20, 0xa5, 0x1b, 0x17, 0xdc, 0xa7, 0x6f, 0x77, 0x22, - 0xd, 0xb9, 0xc2, 0xf6, 0xa7, 0xe1, 0x8d, 0x88, 0x88, 0xdc, 0x44, 0x68, - 0xbd, 0x25, 0x42, 0x5f, 0x20, 0x1b, 0x84, 0x15, 0x56, 0x5, 0x95, 0x9c, - 0x40, 0xef, 0xa1, 0x71, 0xaa, 0xc7, 0x82, 0x8, 0x39, 0xf4, 0x58, 0xae, - 0x39, 0x50, 0xac, 0xc7, 0x53, 0xff, 0x5, 0xb0, 0x29, 0x9d, 0x54, 0x4f, - 0x8d, 0x1a, 0x81, 0x61, 0xc2, 0x71, 0xc, 0x2f, 0xdb, 0x1b, 0x1b, 0xa7, - 0x4f, 0x1a, 0x4a, 0xa2, 0xa9, 0x8c, 0x2c, 0x1, 0xe7, 0xf9, 0xf, 0x85, - 0xc1, 0x33, 0xe7, 0x39, 0x8f, 0x43, 0x40, 0x30, 0x27, 0xeb, 0xad, 0x7e, - 0xef, 0x22, 0xf8, 0xb5, 0x51, 0xe5, 0xb3, 0x7c, 0x2a, 0x45, 0x88, 0x93, - 0xac, 0xea, 0x6a, 0x51, 0x63, 0x79, 0x45, 0x35, 0xfd, 0x9d, 0xd4, 0x55, - 0x98, 0xd, 0xf4, 0x29, 0x7c, 0xfc, 0x93, 0x52, 0xa4, 0x61, 0x6c, 0x1a, - 0xcf, 0x5, 0x5a, 0x3e, 0x44, 0x82, 0x6c, 0x44, 0x7e, 0x6e, 0xb2, 0xad, - 0x5a, 0x3, 0x72, 0x2f, 0xed, 0x77, 0x44, 0x16, 0xd1, 0x59, 0xa8, 0x10, - 0x2d, 0x8, 0x6c, 0xd6, 0xb2, 0x38, 0x95, 0x4c, 0x37, 0x54, 0x2e, 0x8d, - 0xdc, 0xd6, 0x34, 0xe5, 0xe2, 0x64, 0x9b, 0x57, 0x26, 0x38, 0x28, 0xd, - 0x46, 0x7e, 0xc3, 0x1, 0xcc, 0x36, 0x48, 0xe9, 0xd1, 0x9a, 0x9f, 0x29, - 0xa1, 0xac, 0x53, 0xdd, 0xf, 0x8a, 0x51, 0x5d, 0xe3, 0x18, 0x19, 0xcf, - 0x93, 0x82, 0x95, 0x5b, 0x69, 0x8e, 0xf, 0xab, 0x2, 0x17, 0xfa, 0xa7, - 0x9, 0x35, 0xf2, 0x9, 0x39, 0xe2, 0x5b, 0x36, 0x90, 0xa8, 0x46, 0x9c, - 0xf3, 0x58, 0x29, 0x0, 0xb1, 0xb0, 0xdd, 0xdc, 0x41, 0xf6, 0xa, 0x99, - 0xe1, 0xff, 0x2b, 0xe8, 0x1d, 0x3c, 0x86, 0x8e, 0xff, 0x9f, 0xed, 0x3e, - 0x98, 0x5d, 0x24, 0xfc, 0x58, 0xd7, 0x13, 0x12, 0xa7, 0x74, 0x5e, 0x3e, - 0x44, 0x68, 0x7d, 0x11, 0x0, 0x44, 0xb1, 0x28, 0x4f, 0x85, 0x1e, 0x92, - 0x5a, 0x3c, 0xc6, 0x77, 0x70, 0x4, 0x43, 0x1c, 0x81, 0x41, 0x65, 0xd2, - 0x33, 0x77, 0x91, 0xd1, 0xab, 0xe5, 0x97, 0x90, 0x1f, 0x7b, 0xe6, 0xbb, - 0xcc, 0xb3, 0x65, 0x61, 0x57, 0x6d, 0x60, 0xa6, 0x93, 0x79, 0x3d, 0x70, - 0x43, 0x92, 0x5, 0x4b, 0x2, 0x67, 0xea, 0x78, 0x8b, 0x12, 0xba, 0x85, - 0x9c, 0x2b, 0xda, 0x7b, 0xb, 0xed, 0x3c, 0xe8, 0xca, 0xa4, 0x64, 0xe4, - 0x9b, 0x9c, 0xa8, 0x5c, 0x5c, 0xe2, 0xa7, 0x82, 0xea, 0x4c, 0x79, 0x77, - 0x4, 0xf1, 0x0, 0x5, 0xad, 0x2f, 0x72, 0x3d, 0x95, 0xe5, 0x8, 0x50, - 0x48, 0x2e, 0x80, 0x5d, 0x54, 0x67, 0xf9, 0x41, 0xf1, 0x1d, 0xb6, 0x86, - 0x6, 0x73, 0xa, 0xaf, 0x99, 0x7d, 0x2c, 0x30, 0xa6, 0xc9, 0xbc, 0x7d, - 0x39, 0x16, 0x3, 0x55, 0x85, 0x63, 0xe8, 0x69, 0x36, 0x2a, 0xc2, 0xba, - 0x5b, 0xf, 0x49, 0x1d, 0x2, 0xb4, 0xe1, 0x12, 0xf1, 0xe6, 0x9b, 0xaf, - 0xd4, 0x78, 0xd9, 0xaf, 0x7b, 0x5f, 0x50, 0xa5, 0x86, 0x32, 0xbc, 0x36, - 0xe4, 0x96, 0x11, 0xef, 0xf8, 0xb4, 0xd4, 0x91, 0xf7, 0xd7, 0x43, 0x15, - 0x28, 0x3, 0x1e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0x35, 0x74, - 0xc4, 0xd9, 0x9c, 0x8, 0xef, 0x95, 0x6, 0x19, 0xbe, 0x72, 0xbf, 0xa1, - 0xd5, 0xa, 0xe3, 0xc1, 0x53, 0xd1, 0xf3, 0xf, 0x64, 0xbc, 0x1a, 0xc0, - 0x8d, 0xe9, 0x9e, 0xa5, 0x56, - ] \ No newline at end of file diff --git a/test/test_transaction.psbt b/test/test_transaction.psbt deleted file mode 100644 index 4453cb22..00000000 --- a/test/test_transaction.psbt +++ /dev/null @@ -1,41 +0,0 @@ -[0x70, 0x73, 0x62, 0x74, 0xFF, 0x1, 0x0, 0x71, 0x2, 0x0, 0x0, 0x0, -0x1, 0xF5, 0x1A, 0x36, 0x91, 0xF7, 0x64, 0x75, 0x9D, 0x8F, 0xB1, -0x1F, 0xE6, 0x5E, 0x66, 0xB2, 0x57, 0x7A, 0xA2, 0xE9, 0x46, 0xF1, -0xBC, 0xA6, 0x86, 0x15, 0xD, 0x49, 0x94, 0x66, 0x2A, 0x6A, 0x53, -0x1, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x2, 0x1F, 0x4D, -0xD4, 0x17, 0x0, 0x0, 0x0, 0x0, 0x16, 0x0, 0x14, 0xFE, 0xD9, 0xE8, -0xB4, 0xD7, 0xA4, 0x5D, 0x37, 0xAB, 0xD1, 0x18, 0xCE, 0x1, 0x17, -0x2C, 0xA2, 0x97, 0x67, 0x13, 0xEB, 0x30, 0x75, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x16, 0x0, 0x14, 0x73, 0x87, 0x86, 0x30, 0xF8, 0x85, -0xDD, 0x8, 0xF5, 0x2B, 0x1D, 0xF7, 0x10, 0xDF, 0xBE, 0x30, 0xD, -0xC9, 0xF4, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x90, 0x2, -0x0, 0x0, 0x0, 0x1, 0x70, 0x18, 0x30, 0xB6, 0x2E, 0x59, 0x7, 0x4F, -0xCA, 0x1B, 0xA5, 0x2C, 0xD0, 0x6E, 0x4F, 0x28, 0x9F, 0x4A, 0xDF, -0x2B, 0x69, 0x14, 0xC, 0xE3, 0xF9, 0x6, 0xD9, 0x62, 0xC2, 0x76, -0x51, 0x21, 0x2, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3, -0x40, 0x9C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0x0, 0x14, 0x50, -0x19, 0xB0, 0xC9, 0x10, 0x1D, 0x2B, 0xE9, 0xE5, 0xCA, 0xC, 0x6A, -0xB0, 0xD7, 0x4E, 0x26, 0x2B, 0xC6, 0xA0, 0xEE, 0xDC, 0xC2, 0xD4, -0x17, 0x0, 0x0, 0x0, 0x0, 0x16, 0x0, 0x14, 0x0, 0xF3, 0x1C, 0xB4, -0x7B, 0xDC, 0x6D, 0xCF, 0xB1, 0x3C, 0x69, 0x60, 0xB3, 0xB0, 0xC4, -0xCC, 0x26, 0x53, 0xAD, 0xE6, 0x40, 0x9C, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x16, 0x0, 0x14, 0xDC, 0xA7, 0x8E, 0x37, 0x6C, 0xFD, 0x8C, -0x66, 0x61, 0x49, 0xAF, 0x2A, 0x22, 0xFB, 0xD4, 0x93, 0xFB, 0xE5, -0x5D, 0x5D, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1F, 0xDC, 0xC2, 0xD4, -0x17, 0x0, 0x0, 0x0, 0x0, 0x16, 0x0, 0x14, 0x0, 0xF3, 0x1C, 0xB4, -0x7B, 0xDC, 0x6D, 0xCF, 0xB1, 0x3C, 0x69, 0x60, 0xB3, 0xB0, 0xC4, -0xCC, 0x26, 0x53, 0xAD, 0xE6, 0x22, 0x6, 0x3, 0x8B, 0x8A, 0x2C, -0xD0, 0xCC, 0x47, 0xF9, 0xB9, 0xFB, 0xE, 0x73, 0xA1, 0xD7, 0x56, -0xB, 0x9A, 0xE6, 0x58, 0x6A, 0x6, 0xEA, 0x6D, 0x80, 0xDB, 0xF5, -0x57, 0x6D, 0xD2, 0xD9, 0x65, 0x82, 0x23, 0x10, 0xA5, 0x8B, 0x49, -0xA6, 0x0, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x80, 0x5, 0x0, 0x0, -0x80, 0x0, 0x22, 0x2, 0x3, 0xFA, 0x9, 0xA7, 0x84, 0xFB, 0xEF, 0x0, -0xD8, 0xF7, 0x8A, 0xC6, 0xF0, 0x85, 0xAE, 0x66, 0x9D, 0x32, 0x34, -0x51, 0xDB, 0x39, 0x4D, 0xA0, 0x82, 0xE, 0x92, 0x3C, 0xDE, 0x21, -0x8C, 0xDA, 0x53, 0x10, 0xA5, 0x8B, 0x49, 0xA6, 0x0, 0x0, 0x0, -0x80, 0x1, 0x0, 0x0, 0x80, 0xB, 0x0, 0x0, 0x80, 0x0, 0x22, 0x2, -0x2, 0xA9, 0xCA, 0xF6, 0xD2, 0xB1, 0x62, 0xBD, 0xE6, 0xA3, 0xC0, -0x6C, 0x5D, 0xAF, 0x17, 0xEE, 0xFB, 0xD9, 0x92, 0x84, 0xA1, 0x26, -0xE6, 0x54, 0xA1, 0x65, 0x44, 0x38, 0xB8, 0x26, 0x11, 0x43, 0xEE, -0x10, 0xA5, 0x8B, 0x49, 0xA6, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, -0x80, 0x8, 0x0, 0x0, 0x80, 0x0,] \ No newline at end of file diff --git a/test/transition.in b/test/transition.in deleted file mode 100644 index 46a86608..00000000 --- a/test/transition.in +++ /dev/null @@ -1,197 +0,0 @@ -[ - 0xa, 0x0, 0x1, 0x0, 0xd, 0x0, 0x15, 0x0, 0x0, 0x2, 0x0, 0x3, 0x1, 0x2, - 0x0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0, 0x3, 0x2, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x8, 0x2, 0x8, 0x3, 0xa, 0x2, 0x0, 0x0, 0x0, 0xa, 0x3, 0x0, 0x0, - 0x0, 0xb, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x3, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x40, 0x12, 0x0, 0x0, - 0x40, 0x40, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x13, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x40, 0x20, 0x5, 0x0, 0x1, 0x2, 0x3, 0x4, - 0x5, 0x20, 0x5, 0x0, 0xa, 0x14, 0x1e, 0x28, 0x32, 0x21, 0x11, 0x0, - 0x4f, 0x6e, 0x65, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x21, 0x15, 0x0, 0x41, 0x6e, 0x6f, 0x74, - 0x68, 0x65, 0x72, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x1, 0x0, 0xf5, 0x7e, 0xd2, 0x7e, 0xe4, - 0x19, 0x90, 0x72, 0xc5, 0xff, 0x3b, 0x77, 0x4f, 0xeb, 0xc9, 0x4d, 0x26, - 0xd3, 0xe4, 0xa5, 0x55, 0x9d, 0x13, 0x3d, 0xe4, 0x75, 0xa, 0x94, 0x8d, - 0xf5, 0xe, 0x6, 0x3, 0x0, 0x1, 0x0, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0, 0x3, - 0x0, 0x4, 0x0, 0x5, 0x0, 0x2, 0x0, 0x5, 0x0, 0xa, 0x0, 0x14, 0x0, 0x1e, - 0x0, 0x28, 0x0, 0x32, 0x0, 0x3, 0x0, 0x5, 0x0, 0x64, 0x0, 0xc8, 0x0, - 0x2c, 0x1, 0x90, 0x1, 0xf4, 0x1, 0x3, 0x0, 0x1, 0x0, 0x0, 0x4, 0x0, - 0x2, 0x24, 0xa5, 0xd4, 0xe1, 0xd0, 0x55, 0xa0, 0xc, 0x15, 0xc6, 0x61, - 0xcd, 0x6d, 0x6a, 0x55, 0xb8, 0x51, 0xaf, 0xfd, 0x90, 0x98, 0x9, 0x6c, - 0x3e, 0xf5, 0x31, 0xd4, 0xb, 0xee, 0x1b, 0x3c, 0x6b, 0x0, 0x53, 0x20, - 0xe, 0x17, 0xc, 0x8, 0xf2, 0x24, 0x2a, 0xd7, 0xba, 0xa0, 0x22, 0x55, - 0xb, 0x91, 0x8a, 0xd1, 0x4e, 0xe, 0xcc, 0x64, 0x12, 0x19, 0x71, 0xe3, - 0x7a, 0x19, 0x6b, 0xac, 0x43, 0xc8, 0x3, 0x0, 0xae, 0xe9, 0xa8, 0xc3, - 0x4c, 0x5d, 0x4f, 0x87, 0x6, 0xe, 0xf5, 0x8d, 0x94, 0xa, 0x75, 0xe4, - 0x3d, 0x13, 0x9d, 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, 0xc9, 0xeb, 0x4f, - 0x77, 0x3b, 0xff, 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, 0xd2, 0x7e, 0xf5, - 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0xad, 0xb1, 0x39, 0x64, 0xb, 0xb6, 0xb9, - 0x36, 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, 0x89, 0x52, 0xf4, 0xd9, - 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, 0x51, 0x29, 0x71, 0x82, - 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, 0x20, 0x1, 0x0, 0x0, - 0x0, 0x2, 0x0, 0x1, 0x3, 0x4, 0x0, 0x3, 0x0, 0x6e, 0x5a, 0x76, 0xca, - 0xd0, 0x21, 0x63, 0xa5, 0x6, 0xe, 0xf5, 0x8d, 0x94, 0xa, 0x75, 0xe4, - 0x3d, 0x13, 0x9d, 0x55, 0xa5, 0xe4, 0xd3, 0x26, 0x4d, 0xc9, 0xeb, 0x4f, - 0x77, 0x3b, 0xff, 0xc5, 0x72, 0x90, 0x19, 0xe4, 0x7e, 0xd2, 0x7e, 0xf5, - 0x1, 0x0, 0x0, 0x0, 0x8, 0xcc, 0x48, 0xfa, 0x5e, 0x5c, 0xb1, - 0xd2, 0xd2, 0x46, 0x5b, 0xd8, 0xc4, 0x37, 0xc0, 0xe0, 0x5, 0x14, 0xab, - 0xd8, 0x13, 0xf9, 0xa7, 0xdd, 0x50, 0x6a, 0x77, 0x84, 0x5, 0xa2, 0xc4, - 0x3b, 0xc0, 0xa3, 0x2, 0xdd, 0x8a, 0x81, 0xc2, 0xb1, 0x62, 0xe7, 0xb9, - 0xc8, 0xec, 0xe9, 0x64, 0xfc, 0x4f, 0x67, 0x56, 0xdb, 0x85, 0x34, 0x43, - 0x97, 0x3c, 0x84, 0xf9, 0x32, 0x45, 0x5e, 0x8c, 0x4c, 0x93, 0xd9, 0x19, - 0xb, 0x68, 0x4e, 0x5a, 0x15, 0xc7, 0x31, 0xb, 0x33, 0xa4, 0xc0, 0xbe, - 0xa6, 0x11, 0xc, 0x64, 0xa0, 0x24, 0x72, 0x79, 0xec, 0x12, 0x49, 0xc6, - 0x9f, 0x94, 0xeb, 0x5, 0x71, 0x7d, 0x81, 0x0, 0xe, 0x3f, 0x84, 0x8e, - 0x9f, 0xe9, 0x68, 0x2f, 0xa6, 0xa, 0xd8, 0x59, 0x57, 0xcf, 0x64, 0xb9, - 0x56, 0xb5, 0xfc, 0xcc, 0x2b, 0xdc, 0x9e, 0x4d, 0xdd, 0x78, 0x60, 0x63, - 0x12, 0x57, 0x12, 0xcd, 0xf3, 0x6f, 0xe2, 0xca, 0x1e, 0x19, 0x3a, 0xb, - 0x10, 0xc, 0x59, 0x97, 0xc, 0xde, 0xa8, 0x62, 0x42, 0x4a, 0x2f, 0x1e, - 0xeb, 0x89, 0x98, 0xc6, 0x31, 0x82, 0xc9, 0x4f, 0xf, 0xf1, 0xa5, 0x1a, - 0x37, 0x2d, 0x92, 0x86, 0x8c, 0xe5, 0x37, 0x3a, 0x86, 0xc4, 0x89, 0x9f, - 0xf4, 0xcf, 0x10, 0x7b, 0x9a, 0x30, 0xc0, 0x0, 0x97, 0x1e, 0x44, 0x9b, - 0xb2, 0x92, 0x1d, 0x38, 0x6e, 0x3a, 0xce, 0xea, 0x95, 0xcd, 0xcd, 0x63, - 0x74, 0x5e, 0x43, 0xf, 0xd3, 0xdd, 0x21, 0x2, 0xca, 0x91, 0xc5, 0x2d, - 0x9f, 0x21, 0x7b, 0x4d, 0x14, 0x9f, 0xf1, 0x88, 0xe5, 0x3a, 0x98, 0x6d, - 0x3, 0xdd, 0x64, 0x90, 0x73, 0x5a, 0x87, 0x1f, 0x53, 0x64, 0xe4, 0x9e, - 0x48, 0xfc, 0x1e, 0x3e, 0xcc, 0xeb, 0x5, 0xd3, 0xfd, 0x9a, 0x56, 0x5f, - 0x71, 0x51, 0x39, 0xe3, 0x10, 0xa8, 0xae, 0x20, 0xa8, 0xba, 0xca, 0x7b, - 0x91, 0x6, 0xe9, 0x61, 0x45, 0x69, 0x91, 0x94, 0xe0, 0xec, 0x50, 0xa4, - 0x12, 0x58, 0xe1, 0x64, 0xc2, 0x4c, 0x3c, 0x7f, 0x69, 0x7a, 0x7e, 0x4a, - 0xee, 0xed, 0xb, 0x91, 0x3e, 0x63, 0x71, 0x96, 0x99, 0x78, 0xf0, 0x3e, - 0x40, 0x96, 0x58, 0x9a, 0xd, 0xb9, 0x77, 0x79, 0xa2, 0xb7, 0xa3, 0x67, - 0xcf, 0xc2, 0x45, 0x27, 0xf0, 0x86, 0x3f, 0x8f, 0x60, 0xec, 0x17, 0x54, - 0x4, 0xa8, 0xf1, 0xce, 0x5f, 0xa2, 0x5b, 0xe9, 0xba, 0xb0, 0xac, 0x4f, - 0x5b, 0x47, 0xbb, 0xb6, 0xd8, 0x1, 0x7, 0x73, 0x24, 0xc4, 0x8b, 0xc8, - 0xe1, 0x15, 0xe4, 0xd2, 0x9f, 0xc5, 0x4, 0xed, 0x13, 0xc3, 0x17, 0xb8, - 0xc9, 0xdd, 0x84, 0x78, 0xea, 0x92, 0x4c, 0x41, 0x98, 0xc, 0x38, 0xc8, - 0x2, 0x20, 0xeb, 0xf2, 0x93, 0x75, 0x8f, 0xd7, 0x9d, 0x76, 0xfa, 0xfa, - 0xbb, 0x5e, 0xa1, 0x98, 0x51, 0xd6, 0xbd, 0x6, 0xa2, 0x37, 0x2, 0x89, - 0x10, 0xb9, 0x84, 0x69, 0xc7, 0xb7, 0xee, 0xec, 0xca, 0x2d, 0x13, 0xbb, - 0x8f, 0xb, 0xa5, 0x9f, 0x17, 0x6a, 0xb2, 0xef, 0x51, 0x39, 0x1f, 0xce, - 0x69, 0x8c, 0xc, 0x67, 0x67, 0x6f, 0x29, 0x29, 0x5, 0x5a, 0xcb, 0x17, - 0x6a, 0x8f, 0x1b, 0xe6, 0x1c, 0x32, 0xad, 0xf2, 0xda, 0xb3, 0xb6, 0xb8, - 0x6e, 0xae, 0x28, 0x9e, 0x7b, 0x12, 0x3f, 0x52, 0x26, 0xfd, 0x9c, 0xad, - 0x2b, 0x18, 0xb2, 0x6f, 0x33, 0xf, 0xf5, 0xab, 0x53, 0x8c, 0x9b, 0xbf, - 0xca, 0xe2, 0x1f, 0xfd, 0x91, 0xaa, 0x41, 0x26, 0x81, 0xdc, 0x1c, 0x9a, - 0xd4, 0x1d, 0xec, 0xd9, 0x48, 0x60, 0xc9, 0x7, 0x1c, 0xf8, 0x4d, 0x41, - 0xfc, 0x4, 0xe, 0xf0, 0x7d, 0xe3, 0x31, 0x7f, 0xc5, 0xcd, 0x5e, 0x84, - 0x3d, 0xda, 0x92, 0xfb, 0x71, 0xc3, 0x77, 0x2a, 0xae, 0x39, 0x65, 0x16, - 0x24, 0x7d, 0x7c, 0x61, 0xcd, 0xdd, 0xe3, 0x50, 0x54, 0x44, 0xc4, 0x30, - 0x98, 0xfc, 0x62, 0xb9, 0xad, 0x20, 0x7b, 0x2b, 0x5b, 0xf1, 0xf6, 0xe5, - 0x3e, 0xf4, 0xe0, 0xaf, 0x7a, 0xeb, 0xe6, 0xee, 0xe7, 0x21, 0xc, 0xf1, - 0x54, 0xbc, 0xe7, 0xe4, 0x19, 0xd9, 0xfd, 0x1d, 0x1b, 0x2f, 0xad, 0xeb, - 0xe4, 0x27, 0x73, 0xd, 0xcd, 0xb8, 0x7a, 0x7e, 0xe7, 0x4b, 0x8d, 0xce, - 0x83, 0x91, 0x1, 0x82, 0x62, 0xb1, 0xb0, 0xad, 0x32, 0x6f, 0xb6, 0xe2, - 0xff, 0x10, 0x5c, 0x83, 0x13, 0xa4, 0x6f, 0xe7, 0xaa, 0x7, 0xf0, 0xc4, - 0x3c, 0x42, 0x51, 0xd9, 0xc7, 0x70, 0x4, 0xf, 0x6e, 0x2c, 0x5c, 0x67, - 0x2d, 0xd2, 0x3, 0x69, 0xa, 0x45, 0x9b, 0xa9, 0x6e, 0xd0, 0x6c, 0x7e, - 0xfb, 0xf3, 0x15, 0xa0, 0x8d, 0x31, 0xb0, 0x7d, 0x83, 0xc, 0xa9, 0xbf, - 0xa8, 0xcc, 0x13, 0x33, 0x61, 0xdf, 0x2f, 0x7e, 0x4d, 0xd3, 0xe, 0x94, - 0x0, 0xa4, 0x49, 0xcc, 0xf, 0x32, 0x93, 0x1, 0xdc, 0xf1, 0x56, 0xfe, - 0x14, 0xa0, 0x95, 0x96, 0xf6, 0xe5, 0x23, 0x2, 0xb7, 0xce, 0x71, 0x2c, - 0xa6, 0x7e, 0x67, 0x7a, 0x59, 0x84, 0x5c, 0xc5, 0xbe, 0x66, 0xd4, 0x73, - 0x3a, 0xbd, 0xf9, 0xa3, 0xd4, 0x7a, 0x66, 0xaf, 0xe, 0x46, 0x2d, 0x6d, - 0x2c, 0x5b, 0x31, 0xf9, 0x51, 0x5, 0xa6, 0xa4, 0x49, 0xbd, 0xf3, 0x5, - 0x6d, 0x98, 0x56, 0xa6, 0xce, 0xea, 0x15, 0x1, 0x0, 0xa, 0xa2, 0x7f, - 0x61, 0x42, 0xef, 0x52, 0xbc, 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, - 0x89, 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, - 0x51, 0x29, 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, - 0x20, 0x1, 0x0, 0x0, 0x0, 0x3, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xde, 0xbb, 0xbe, 0xfd, 0x16, 0x83, 0xe3, 0x35, 0x29, 0x6a, - 0xc, 0x86, 0xf1, 0xc8, 0x82, 0xa2, 0xea, 0x37, 0x59, 0xf1, 0x14, 0x22, - 0xb, 0xb, 0x2c, 0xf8, 0x69, 0xe3, 0x7d, 0xec, 0x24, 0xc8, 0x0, 0xb3, - 0x2a, 0x56, 0xa6, 0xc7, 0x2, 0x56, 0x33, 0x79, 0xad, 0x65, 0xd0, 0x7a, - 0x2c, 0x80, 0xe0, 0x46, 0x73, 0xaf, 0x85, 0x59, 0x52, 0x58, 0xfc, 0x15, - 0x60, 0xff, 0xd8, 0x47, 0x1a, 0xd7, 0x32, 0x8, 0x97, 0x75, - 0xf8, 0x29, 0xc8, 0xad, 0xad, 0x92, 0xad, 0xa1, 0x7b, 0x59, 0x31, 0xed, - 0xf6, 0x30, 0x64, 0xd5, 0x46, 0x78, 0xf4, 0xeb, 0x9a, 0x6f, 0xdf, 0xe8, - 0xe4, 0xcb, 0x5d, 0x95, 0xf6, 0xf4, 0xa3, 0x2, 0x3b, 0x4d, 0x5a, 0x83, - 0xe1, 0x98, 0x44, 0x23, 0xd7, 0xc8, 0xe3, 0xc8, 0x35, 0xf, 0x42, 0xc, - 0xca, 0x90, 0xc5, 0xa4, 0xa7, 0x3f, 0xea, 0x62, 0x69, 0xe4, 0x78, 0xbc, - 0x63, 0x94, 0x76, 0xfb, 0xb6, 0x64, 0xa9, 0xf7, 0x81, 0x70, 0xc6, 0xd, - 0xa3, 0x70, 0x5, 0xc1, 0xc8, 0x94, 0x7f, 0x20, 0xff, 0x83, 0x8c, 0xc4, - 0x7a, 0x26, 0xd3, 0x84, 0xab, 0x51, 0x15, 0xfc, 0xb1, 0x57, 0x2d, 0xb3, - 0x9, 0x1b, 0xc8, 0x6d, 0x32, 0xfd, 0x52, 0x70, 0xa, 0xf1, 0x47, 0xe2, - 0xc4, 0xa8, 0x5c, 0x5e, 0x95, 0x18, 0xc8, 0x46, 0xa9, 0xa3, 0xd0, 0xda, - 0x76, 0xce, 0xbf, 0xdb, 0x31, 0x27, 0x4b, 0x68, 0x58, 0xe5, 0x36, 0x13, - 0x54, 0x29, 0x94, 0x4c, 0x30, 0x23, 0x4c, 0xc, 0x6a, 0x3a, 0x5, 0x15, - 0x70, 0x97, 0x8a, 0x3e, 0xc5, 0x82, 0x96, 0x65, 0x56, 0x69, 0xc0, 0x4d, - 0x58, 0x5b, 0x8a, 0x85, 0x39, 0x84, 0x29, 0x9b, 0xa5, 0x9b, 0xe4, 0xc4, - 0x79, 0x5b, 0x8b, 0xe1, 0x17, 0x25, 0x10, 0x22, 0x4, 0x5, 0x44, 0xe5, - 0x68, 0x72, 0x80, 0x88, 0xd5, 0x23, 0x22, 0x19, 0x8d, 0xca, 0xa5, 0x26, - 0xc4, 0x73, 0xdb, 0x6, 0x96, 0xb7, 0xe, 0x28, 0xc6, 0xa, 0xc3, 0x65, - 0x5c, 0x9c, 0x3, 0xf3, 0x1d, 0xc9, 0x53, 0x34, 0x6a, 0x85, 0x1, 0xe2, - 0x3c, 0x91, 0x6d, 0x70, 0xe1, 0x4d, 0xa2, 0xa, 0x67, 0x50, 0xb0, 0xe2, - 0x12, 0x1f, 0xba, 0x68, 0xdc, 0xd, 0x35, 0x3b, 0x32, 0xa7, 0x2b, 0xe7, - 0x91, 0x6d, 0xb2, 0xe0, 0xf4, 0xb8, 0xb1, 0x6d, 0xab, 0xa6, 0x46, 0xd5, - 0x4, 0x5a, 0x5d, 0xf1, 0x8f, 0x2d, 0x52, 0x6a, 0xb8, 0x50, 0xf3, 0x22, - 0x4e, 0xb1, 0x24, 0xa8, 0xa1, 0x15, 0x34, 0xbc, 0x3f, 0xda, 0x8c, 0xc6, - 0xc8, 0x53, 0x2b, 0xd0, 0x9f, 0xa8, 0x72, 0x3e, 0xc1, 0x6a, 0x3a, 0x51, - 0xb1, 0x99, 0x80, 0x1b, 0xae, 0x2d, 0x4c, 0x79, 0xa0, 0x10, 0x2b, 0x7, - 0x4a, 0xa, 0x65, 0x3a, 0x82, 0xe4, 0x1f, 0xbb, 0x9c, 0x6e, 0x20, 0xa5, - 0x1b, 0x17, 0xdc, 0xa7, 0x6f, 0x77, 0x22, 0xd, 0xb9, 0xc2, 0xf6, 0xa7, - 0xe1, 0x8d, 0x88, 0x88, 0xdc, 0x44, 0x68, 0xbd, 0x25, 0x42, 0x5f, 0x20, - 0x1b, 0x84, 0x15, 0x56, 0x5, 0x95, 0x9c, 0x40, 0xef, 0xa1, 0x71, 0xaa, - 0xc7, 0x82, 0x8, 0x39, 0xf4, 0x58, 0xae, 0x39, 0x50, 0xac, 0xc7, 0x53, - 0xff, 0x5, 0xb0, 0x29, 0x9d, 0x54, 0x4f, 0x8d, 0x1a, 0x81, 0x61, 0xc2, - 0x71, 0xc, 0x2f, 0xdb, 0x1b, 0x1b, 0xa7, 0x4f, 0x1a, 0x4a, 0xa2, 0xa9, - 0x8c, 0x2c, 0x1, 0xe7, 0xf9, 0xf, 0x85, 0xc1, 0x33, 0xe7, 0x39, 0x8f, - 0x43, 0x40, 0x30, 0x27, 0xeb, 0xad, 0x7e, 0xef, 0x22, 0xf8, 0xb5, 0x51, - 0xe5, 0xb3, 0x7c, 0x2a, 0x45, 0x88, 0x93, 0xac, 0xea, 0x6a, 0x51, 0x63, - 0x79, 0x45, 0x35, 0xfd, 0x9d, 0xd4, 0x55, 0x98, 0xd, 0xf4, 0x29, 0x7c, - 0xfc, 0x93, 0x52, 0xa4, 0x61, 0x6c, 0x1a, 0xcf, 0x5, 0x5a, 0x3e, 0x44, - 0x82, 0x6c, 0x44, 0x7e, 0x6e, 0xb2, 0xad, 0x5a, 0x3, 0x72, 0x2f, 0xed, - 0x77, 0x44, 0x16, 0xd1, 0x59, 0xa8, 0x10, 0x2d, 0x8, 0x6c, 0xd6, 0xb2, - 0x38, 0x95, 0x4c, 0x37, 0x54, 0x2e, 0x8d, 0xdc, 0xd6, 0x34, 0xe5, 0xe2, - 0x64, 0x9b, 0x57, 0x26, 0x38, 0x28, 0xd, 0x46, 0x7e, 0xc3, 0x1, 0xcc, - 0x36, 0x48, 0xe9, 0xd1, 0x9a, 0x9f, 0x29, 0xa1, 0xac, 0x53, 0xdd, 0xf, - 0x8a, 0x51, 0x5d, 0xe3, 0x18, 0x19, 0xcf, 0x93, 0x82, 0x95, 0x5b, 0x69, - 0x8e, 0xf, 0xab, 0x2, 0x17, 0xfa, 0xa7, 0x9, 0x35, 0xf2, 0x9, 0x39, - 0xe2, 0x5b, 0x36, 0x90, 0xa8, 0x46, 0x9c, 0xf3, 0x58, 0x29, 0x0, 0xb1, - 0xb0, 0xdd, 0xdc, 0x41, 0xf6, 0xa, 0x99, 0xe1, 0xff, 0x2b, 0xe8, 0x1d, - 0x3c, 0x86, 0x8e, 0xff, 0x9f, 0xed, 0x3e, 0x98, 0x5d, 0x24, 0xfc, 0x58, - 0xd7, 0x13, 0x12, 0xa7, 0x74, 0x5e, 0x3e, 0x44, 0x68, 0x7d, 0x11, 0x0, - 0x44, 0xb1, 0x28, 0x4f, 0x85, 0x1e, 0x92, 0x5a, 0x3c, 0xc6, 0x77, 0x70, - 0x4, 0x43, 0x1c, 0x81, 0x41, 0x65, 0xd2, 0x33, 0x77, 0x91, 0xd1, 0xab, - 0xe5, 0x97, 0x90, 0x1f, 0x7b, 0xe6, 0xbb, 0xcc, 0xb3, 0x65, 0x61, 0x57, - 0x6d, 0x60, 0xa6, 0x93, 0x79, 0x3d, 0x70, 0x43, 0x92, 0x5, 0x4b, 0x2, - 0x67, 0xea, 0x78, 0x8b, 0x12, 0xba, 0x85, 0x9c, 0x2b, 0xda, 0x7b, 0xb, - 0xed, 0x3c, 0xe8, 0xca, 0xa4, 0x64, 0xe4, 0x9b, 0x9c, 0xa8, 0x5c, 0x5c, - 0xe2, 0xa7, 0x82, 0xea, 0x4c, 0x79, 0x77, 0x4, 0xf1, 0x0, 0x5, 0xad, - 0x2f, 0x72, 0x3d, 0x95, 0xe5, 0x8, 0x50, 0x48, 0x2e, 0x80, 0x5d, 0x54, - 0x67, 0xf9, 0x41, 0xf1, 0x1d, 0xb6, 0x86, 0x6, 0x73, 0xa, 0xaf, 0x99, - 0x7d, 0x2c, 0x30, 0xa6, 0xc9, 0xbc, 0x7d, 0x39, 0x16, 0x3, 0x55, 0x85, - 0x63, 0xe8, 0x69, 0x36, 0x2a, 0xc2, 0xba, 0x5b, 0xf, 0x49, 0x1d, 0x2, - 0xb4, 0xe1, 0x12, 0xf1, 0xe6, 0x9b, 0xaf, 0xd4, 0x78, 0xd9, 0xaf, 0x7b, - 0x5f, 0x50, 0xa5, 0x86, 0x32, 0xbc, 0x36, 0xe4, 0x96, 0x11, 0xef, 0xf8, - 0xb4, 0xd4, 0x91, 0xf7, 0xd7, 0x43, 0x15, 0x28, 0x3, 0x1e, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d, 0x35, 0x74, 0xc4, 0xd9, 0x9c, - 0x8, 0xef, 0x95, 0x6, 0x19, 0xbe, 0x72, 0xbf, 0xa1, 0xd5, 0xa, 0xe3, - 0xc1, 0x53, 0xd1, 0xf3, 0xf, 0x64, 0xbc, 0x1a, 0xc0, 0x8d, 0xe9, 0x9e, - 0xa5, 0x56, 0x3, 0x0, 0x2, 0x4, 0x0, 0x2, 0x3a, 0xa, 0x34, 0xc8, 0xd, - 0xdb, 0x3e, 0xac, 0x5c, 0xd5, 0x92, 0x38, 0x30, 0x81, 0x4d, 0x72, 0xf9, - 0xde, 0x9, 0x6b, 0xca, 0x74, 0x87, 0x79, 0xda, 0x39, 0x7a, 0xa3, 0xb7, - 0x71, 0xfe, 0x7e, 0x40, 0xc6, 0x41, 0x1a, 0xea, 0x8, 0x2e, 0x2c, 0x5d, - 0x74, 0x34, 0x73, 0x68, 0x67, 0x7d, 0xb6, 0x95, 0x45, 0x12, 0x62, 0x37, - 0xd5, 0xed, 0x78, 0xfa, 0xa0, 0x84, 0x63, 0x52, 0xf5, 0x38, 0x3f, 0x95, - 0x3, 0x0, 0xfd, 0xb7, 0x19, 0xd1, 0x24, 0xce, 0xff, 0x58, 0x6, 0xe, - 0xf5, 0x8d, 0x94, 0xa, 0x75, 0xe4, 0x3d, 0x13, 0x9d, 0x55, 0xa5, 0xe4, - 0xd3, 0x26, 0x4d, 0xc9, 0xeb, 0x4f, 0x77, 0x3b, 0xff, 0xc5, 0x72, 0x90, - 0x19, 0xe4, 0x7e, 0xd2, 0x7e, 0xf5, 0x1, 0x0, 0x0, 0x0, 0x64, 0x20, - 0xcc, 0x42, 0x1e, 0x11, 0x89, 0x80, 0x5c, 0x8c, 0xec, 0x8, 0x9d, 0x74, - 0xc1, 0x98, 0xf, 0x79, 0xc0, 0x69, 0x0, 0x5a, 0x21, 0xae, 0x40, 0xa7, - 0xe5, 0x8e, 0x68, 0x77, 0xa8, 0x10, 0x7b, 0x4, 0x9, 0x1a, 0x9a, 0x97, - 0x1, 0x2, 0x90, 0xe5, 0x10, 0xa2, 0x10, 0x60, 0xad, 0xa3, 0x39, 0x71, - 0xd, 0xd, 0xdc, 0x43, 0xe4, 0x46, 0x0, 0x6c, 0x5b, 0xc9, 0x38, 0x64, - 0xda, 0xfb, 0x3, 0xcf, 0x4b, 0xa4, 0x72, 0xbe, 0xdf, 0x5c, 0xa7, 0x1, - 0x0, 0x47, 0xe7, 0xd3, 0x5d, 0x93, 0xe4, 0xb5, 0x62, 0x8e, 0xaf, 0xd3, - 0x36, 0xd, 0x65, 0x25, 0x89, 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, - 0x1f, 0x18, 0xee, 0x18, 0x51, 0x29, 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, - 0x2b, 0x1e, 0xdd, 0x1f, 0x20, 0x1, 0x0, 0x0, 0x0, 0x40, 0xe7, 0xa, - 0x36, 0xe2, 0xce, 0x51, 0xd3, 0x1d, 0x4c, 0xf5, 0xd6, 0x73, 0x1f, 0xa6, - 0x37, 0x38, 0x64, 0x81, 0x27, 0xdb, 0x83, 0x37, 0x15, 0xd3, 0x96, 0x52, - 0xd8, 0x6d, 0x92, 0x7d, 0x48, 0x88, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0, 0x3, - 0x0, -] \ No newline at end of file From 487256fa33f8b78ec5ded065dfefca446a610bc8 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:21:32 +0100 Subject: [PATCH 27/71] chore: update licensing information --- license_header | 10 ---- src/contract/assignments.rs | 100 +++++++++++++------------------- src/contract/attachment.rs | 32 +++++++---- src/contract/conceal.rs | 27 ++++++--- src/contract/data.rs | 32 +++++++---- src/contract/metadata.rs | 32 +++++++---- src/contract/mod.rs | 27 ++++++--- src/contract/nodes.rs | 41 +++++++------ src/contract/reveal.rs | 41 ++++++++----- src/contract/rights.rs | 27 ++++++--- src/contract/seal.rs | 50 +++++++++++----- src/contract/value.rs | 32 +++++++---- src/lib.rs | 27 ++++++--- src/macros.rs | 11 ---- src/schema/mod.rs | 27 ++++++--- src/schema/nodes.rs | 27 ++++++--- src/schema/occurrences.rs | 27 ++++++--- src/schema/schema.rs | 27 ++++++--- src/schema/script.rs | 27 ++++++--- src/schema/state.rs | 27 ++++++--- src/stash/anchor.rs | 32 +++++++---- src/stash/bundle.rs | 38 ++++++++---- src/stash/consignment.rs | 27 ++++++--- src/stash/graph.rs | 27 ++++++--- src/stash/mod.rs | 27 ++++++--- src/stash/stash.rs | 27 ++++++--- src/stash/unit.rs | 27 ++++++--- src/validation/mod.rs | 27 ++++++--- src/validation/schema.rs | 47 +++++++++++---- src/validation/verify.rs | 112 ++++++++++++++++++++---------------- src/vm/alure.rs | 27 ++++++--- src/vm/embedded.rs | 35 +++++++---- src/vm/mod.rs | 27 ++++++--- 33 files changed, 713 insertions(+), 418 deletions(-) delete mode 100644 license_header diff --git a/license_header b/license_header deleted file mode 100644 index fff56b63..00000000 --- a/license_header +++ /dev/null @@ -1,10 +0,0 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky -// -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. -// -// You should have received a copy of the MIT License along with this software. -// If not, see . diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index d394144a..e79c1af8 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use core::cmp::Ordering; use core::fmt::Debug; @@ -825,8 +836,8 @@ where StateType::Confidential: From<::ConcealedCommitment>, { fn eq(&self, other: &Self) -> bool { - self.to_confidential_seal() == other.to_confidential_seal() - && self.to_confidential_state() == other.to_confidential_state() + self.to_confidential_seal() == other.to_confidential_seal() && + self.to_confidential_state() == other.to_confidential_state() } } @@ -850,13 +861,13 @@ where pub fn with_seal_replaced(assignment: &Self, seal: seal::Revealed) -> Self { match assignment { - Assignment::Confidential { seal: _, state } - | Assignment::ConfidentialState { seal: _, state } => Assignment::ConfidentialState { + Assignment::Confidential { seal: _, state } | + Assignment::ConfidentialState { seal: _, state } => Assignment::ConfidentialState { seal, state: state.clone(), }, - Assignment::ConfidentialSeal { seal: _, state } - | Assignment::Revealed { seal: _, state } => Assignment::Revealed { + Assignment::ConfidentialSeal { seal: _, state } | + Assignment::Revealed { seal: _, state } => Assignment::Revealed { seal, state: state.clone(), }, @@ -888,8 +899,8 @@ where Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { state.commit_conceal().into() } - Assignment::Confidential { state, .. } - | Assignment::ConfidentialState { state, .. } => state.clone(), + Assignment::Confidential { state, .. } | + Assignment::ConfidentialState { state, .. } => state.clone(), } } @@ -1079,8 +1090,8 @@ where { fn commit_encode(&self, e: E) -> usize { self.commit_conceal().strict_encode(e).expect( - "Strict encoding must not fail for types implementing \ - ConsensusCommit via marker trait ConsensusCommitFromStrictEncoding", + "Strict encoding must not fail for types implementing ConsensusCommit via marker \ + trait ConsensusCommitFromStrictEncoding", ) } } @@ -1232,10 +1243,7 @@ mod test { // Create our allocations let ours: SealValueMap = zip_data .map(|(txid, amount)| { - ( - Revealed::from(Outpoint::new(*txid, rng.gen_range(0..=10))), - amount.clone(), - ) + (Revealed::from(Outpoint::new(*txid, rng.gen_range(0..=10))), amount.clone()) }) .collect(); @@ -1288,11 +1296,7 @@ mod test { #[test] fn test_zero_balance_nonoverflow() { - assert!(zero_balance_verify( - &[core::u64::MAX, 1], - &[1, core::u64::MAX], - 1 - )); + assert!(zero_balance_verify(&[core::u64::MAX, 1], &[1, core::u64::MAX], 1)); assert!(zero_balance_verify( &[core::u64::MAX, core::u64::MAX], &[core::u64::MAX, core::u64::MAX], @@ -1364,11 +1368,7 @@ mod test { } // Test when ours is empty - assert!(zero_balance_verify( - &multiple_amounts[2], - &multiple_amounts[2], - 0 - )); + assert!(zero_balance_verify(&multiple_amounts[2], &multiple_amounts[2], 0)); // Test when theirs is empty assert!(zero_balance_verify( @@ -1404,11 +1404,7 @@ mod test { 2 )); assert!(!zero_balance_verify(&[1, 2, 3, 4], &[1, 2, 3, 5], 2)); - assert!(!zero_balance_verify( - &[1, 2, 3, 0], - &[1, 2, 3, core::u64::MAX], - 2 - )); + assert!(!zero_balance_verify(&[1, 2, 3, 0], &[1, 2, 3, core::u64::MAX], 2)); } #[test] @@ -1457,10 +1453,7 @@ mod test { rng.gen_range(0..=output_length), ); // Check if test passes - assert!(value::Confidential::verify_commit_sum( - inputs.clone(), - outputs.clone() - )); + assert!(value::Confidential::verify_commit_sum(inputs.clone(), outputs.clone())); // Check non-equivalent amounts do not verify if input_length > 1 { @@ -1876,10 +1869,7 @@ mod test { .collect(); // Check extracted values matches with precomputed values - assert_eq!( - all_seals_confidential.to_vec(), - extracted_seals_confidential - ); + assert_eq!(all_seals_confidential.to_vec(), extracted_seals_confidential); // Precomputed concealed state data of all 4 assignments let all_state_confidential = [ @@ -1897,10 +1887,7 @@ mod test { .collect(); // Check extracted values matches with precomputed values - assert_eq!( - all_state_confidential.to_vec(), - extracted_state_confidential - ); + assert_eq!(all_state_confidential.to_vec(), extracted_state_confidential); } #[test] @@ -2218,10 +2205,7 @@ mod test { .to_declarative_assignments() .iter() .map(|assignment| { - ( - type1, - MerkleNode::hash(&CommitEncode::commit_serialize(assignment)), - ) + (type1, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) }) .collect(); @@ -2229,10 +2213,7 @@ mod test { .to_value_assignments() .iter() .map(|assignment| { - ( - type2, - MerkleNode::hash(&CommitEncode::commit_serialize(assignment)), - ) + (type2, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) }) .collect(); @@ -2240,10 +2221,7 @@ mod test { .to_data_assignments() .iter() .map(|assignment| { - ( - type3, - MerkleNode::hash(&CommitEncode::commit_serialize(assignment)), - ) + (type3, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) }) .collect(); diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index cb20c8ff..0f9ff42f 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use bitcoin_hashes::{sha256, sha256t}; use commit_verify::{CommitVerify, UntaggedProtocol}; @@ -120,9 +131,6 @@ mod test { #[test] fn test_confidential_midstate() { let midstate = tagged_hash::Midstate::with(b"rgb:container:confidential"); - assert_eq!( - midstate.into_inner().into_inner(), - MIDSTATE_CONFIDENTIAL_ATTACHMENT - ); + assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_CONFIDENTIAL_ATTACHMENT); } } diff --git a/src/contract/conceal.rs b/src/contract/conceal.rs index 7b8080c6..ccbe58d7 100644 --- a/src/contract/conceal.rs +++ b/src/contract/conceal.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use core::cmp::Ord; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; diff --git a/src/contract/data.rs b/src/contract/data.rs index 18b6e694..5b64139f 100644 --- a/src/contract/data.rs +++ b/src/contract/data.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![allow(clippy::unnecessary_cast)] @@ -173,10 +184,7 @@ mod test { #[test] fn test_confidential_midstate() { let midstate = tagged_hash::Midstate::with(b"rgb:data:confidential"); - assert_eq!( - midstate.into_inner().into_inner(), - MIDSTATE_CONFIDENTIAL_DATA - ); + assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_CONFIDENTIAL_DATA); } // Normal encode/decode testing diff --git a/src/contract/metadata.rs b/src/contract/metadata.rs index e37a2d4a..2e020310 100644 --- a/src/contract/metadata.rs +++ b/src/contract/metadata.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Convenience metadata accessor methods for Genesis and state transitions. @@ -92,10 +103,7 @@ mod test { assert_eq!(field_8, vec![2, 3]); assert_eq!(field_9, vec![2 as f32, 3 as f32]); assert_eq!(field_10, vec![2 as f64, 3 as f64]); - assert_eq!(field_11, vec![ - [1u8, 2, 3, 4, 5].to_vec(), - [10u8, 20, 30, 40, 50].to_vec() - ]); + assert_eq!(field_11, vec![[1u8, 2, 3, 4, 5].to_vec(), [10u8, 20, 30, 40, 50].to_vec()]); assert_eq!(field_12, vec![ "One Random String".to_string(), "Another Random String".to_string() diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 1e0ea333..9783dd61 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod assignments; #[macro_use] diff --git a/src/contract/nodes.rs b/src/contract/nodes.rs index b1c33b36..5489b638 100644 --- a/src/contract/nodes.rs +++ b/src/contract/nodes.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::collections::{BTreeMap, BTreeSet}; use std::num::ParseIntError; @@ -142,9 +153,7 @@ impl From for ProtocolId { impl From for ContractId { fn from(protocol_id: ProtocolId) -> Self { - ContractId::from_inner(::Inner::from_inner( - protocol_id.into_inner(), - )) + ContractId::from_inner(::Inner::from_inner(protocol_id.into_inner())) } } @@ -744,14 +753,8 @@ mod test { .unwrap(), ) .unwrap(); - assert_eq!( - assignments.get(&1u16).unwrap(), - &[1u16, 2u16, 3u16, 4u16, 5u16].to_vec() - ); - assert_eq!( - assignments.get(&2u16).unwrap(), - &[10u16, 20u16, 30u16, 40u16, 50u16].to_vec() - ); + assert_eq!(assignments.get(&1u16).unwrap(), &[1u16, 2u16, 3u16, 4u16, 5u16].to_vec()); + assert_eq!(assignments.get(&2u16).unwrap(), &[10u16, 20u16, 30u16, 40u16, 50u16].to_vec()); assert_eq!( assignments.get(&3u16).unwrap(), &[100u16, 200u16, 300u16, 400u16, 500u16].to_vec() diff --git a/src/contract/reveal.rs b/src/contract/reveal.rs index 3f40e8be..22e84469 100644 --- a/src/contract/reveal.rs +++ b/src/contract/reveal.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::collections::BTreeMap; @@ -25,7 +36,8 @@ pub trait RevealSeals { /// /// # Returns /// - /// Total number of seals revealed inside the data structure during the operation. + /// Total number of seals revealed inside the data structure during the + /// operation. fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize; } @@ -42,7 +54,8 @@ pub enum Error { /// OwnedRights has different commitment ids and can't be reveal-merged OwnedRightsMismatch, - /// Anchors has different commitment ids and can't be reveal-merged. Details: {0} + /// Anchors has different commitment ids and can't be reveal-merged. + /// Details: {0} #[from] AnchorsMismatch(dbc::anchor::MergeError), @@ -84,8 +97,8 @@ where } else { match (self, other) { // Anything + Revealed = Revealed - (_, state @ Assignment::Revealed { .. }) - | (state @ Assignment::Revealed { .. }, _) => Ok(state), + (_, state @ Assignment::Revealed { .. }) | + (state @ Assignment::Revealed { .. }, _) => Ok(state), // ConfidentialAmount + ConfidentialSeal = Revealed ( @@ -110,8 +123,8 @@ where ) => Ok(state), // Anything + Confidential = Anything - (state, Assignment::Confidential { .. }) - | (Assignment::Confidential { .. }, state) => Ok(state), + (state, Assignment::Confidential { .. }) | + (Assignment::Confidential { .. }, state) => Ok(state), } } } diff --git a/src/contract/rights.rs b/src/contract/rights.rs index 49968b1d..8c384049 100644 --- a/src/contract/rights.rs +++ b/src/contract/rights.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use core::fmt::Debug; use std::collections::{btree_map, btree_set, BTreeMap, BTreeSet}; diff --git a/src/contract/seal.rs b/src/contract/seal.rs index e7f30884..4161bb25 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Single-use-seal API specific for RGB implementation //! @@ -25,13 +36,22 @@ //! confidentiality options and ability to be linked to the witness transaction //! closing previous seal in RGB state evolution graph. //! -//! | **Type name** | **Lib** | **Witness vout** | **Blinding** | **Confidential** | **String serialization** | **Use case** | -//! | ------------------ | ------- | ----------- | -------------------- | ---------------- | ------------------------------------- | --------------------------------- | -//! | [`Outpoint`] | Bitcoin | No | No | No | `:` | Genesis control rights | -//! | [`RevealedSeal`] | BP Core | No | Yes | No | `:|~:#` | Stash | -//! | [`ConcealedSeal`] | BP Core | Implicit? | Implicit | Yes | `txob1...` | External payments | -//! | [`ExplicitSeal`] | BP Core | Yes | Yes | No | `:|~:` | Internal | -//! | [`SealEndpoint`] | RGB | Yes | Explicit or implicit | Could be | `txob1...|:~:#blinding` | Consignments | +//! | **Type name** | **Lib** | **Witness vout** | **Blinding** | +//! **Confidential** | **String serialization** | **Use case** +//! | | ------------------ | ------- | ----------- | -------------------- | +//! ---------------- | ------------------------------------- | +//! --------------------------------- | | [`Outpoint`] | Bitcoin | No +//! | No | No | `:` +//! | Genesis control rights | | [`RevealedSeal`] | BP Core | No +//! | Yes | No | +//! `:|~:#` | Stash | +//! | [`ConcealedSeal`] | BP Core | Implicit? | Implicit | Yes +//! | `txob1...` | External payments +//! | | [`ExplicitSeal`] | BP Core | Yes | Yes | No +//! | `:|~:` | Internal +//! | | [`SealEndpoint`] | RGB | Yes | Explicit or implicit | +//! Could be | `txob1...|:~:#blinding` | Consignments +//! | use std::fmt::{self, Display, Formatter}; use std::str::FromStr; diff --git a/src/contract/value.rs b/src/contract/value.rs index 45ee447a..98592884 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! This mod represents **atomic rational values** (or, simply just **value**), //! it a value representing a portion of something whole with a certain fixed @@ -341,10 +352,7 @@ mod test { let revealed_64 = Revealed::strict_decode(&AMOUNT_64[..]).unwrap(); let old_revealed = Revealed::strict_decode(&AMOUNT_65[..]).unwrap(); assert_eq!(revealed_64.cmp(&old_revealed), Ordering::Less); - assert_eq!( - revealed_64.partial_cmp(&old_revealed).unwrap(), - Ordering::Less - ); + assert_eq!(revealed_64.partial_cmp(&old_revealed).unwrap(), Ordering::Less); let coded_conf = Confidential::strict_decode(&CONFIDENTIAL_AMOUNT[..]).unwrap(); let old_conf = old_revealed.commit_conceal(); let new_conf = revealed_64.commit_conceal(); diff --git a/src/lib.rs b/src/lib.rs index a49ffb77..12fba936 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![recursion_limit = "256"] // Coding conventions diff --git a/src/macros.rs b/src/macros.rs index 10a74c82..23177b65 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,14 +1,3 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky -// -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. -// -// You should have received a copy of the MIT License along with this software. -// If not, see . - #[macro_export] macro_rules! type_map { { } => { diff --git a/src/schema/mod.rs b/src/schema/mod.rs index d3221415..fc433f38 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod nodes; #[allow(clippy::module_inception)] diff --git a/src/schema/nodes.rs b/src/schema/nodes.rs index 4cc2d7d1..54a16d95 100644 --- a/src/schema/nodes.rs +++ b/src/schema/nodes.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use amplify::confinement::{TinyOrdMap, TinyOrdSet}; diff --git a/src/schema/occurrences.rs b/src/schema/occurrences.rs index 84323969..51ebb110 100644 --- a/src/schema/occurrences.rs +++ b/src/schema/occurrences.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::io; use std::ops::RangeInclusive; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 80613ba1..3a3c7c88 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::cmp::Ordering; use std::io; diff --git a/src/schema/script.rs b/src/schema/script.rs index 710b5483..a07d1468 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![allow(clippy::unnecessary_cast)] diff --git a/src/schema/state.rs b/src/schema/state.rs index 84844d58..04fb6f21 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use strict_types::SemId; diff --git a/src/stash/anchor.rs b/src/stash/anchor.rs index d1bbc3d8..2c3ce8df 100644 --- a/src/stash/anchor.rs +++ b/src/stash/anchor.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use bp::dbc::Anchor; use commit_verify::mpc; @@ -79,10 +90,7 @@ mod test { map.insert(contract_id, node_id); // Check number of output remains same - assert_eq!( - source_psbt.unsigned_tx.output.len(), - witness_psbt.unsigned_tx.output.len() - ); + assert_eq!(source_psbt.unsigned_tx.output.len(), witness_psbt.unsigned_tx.output.len()); // Check output values remains unchanged assert_eq!( diff --git a/src/stash/bundle.rs b/src/stash/bundle.rs index 3d3fa193..e33a2a5b 100644 --- a/src/stash/bundle.rs +++ b/src/stash/bundle.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::collections::{btree_map, BTreeMap, BTreeSet}; @@ -34,7 +45,8 @@ impl sha256t::Tag for BundleIdTag { } } -/// Unique state transition bundle identifier equivalent to the bundle commitment hash +/// Unique state transition bundle identifier equivalent to the bundle +/// commitment hash #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -226,7 +238,13 @@ impl TransitionBundle { pub fn inputs_for(&self, node_id: NodeId) -> Option<&BTreeSet> { self.revealed .iter() - .find_map(|(ts, inputs)| if ts.node_id() == node_id { Some(inputs) } else { None }) + .find_map(|(ts, inputs)| { + if ts.node_id() == node_id { + Some(inputs) + } else { + None + } + }) .or_else(|| self.concealed.get(&node_id)) } diff --git a/src/stash/consignment.rs b/src/stash/consignment.rs index 4e14f7e3..d818fa2f 100644 --- a/src/stash/consignment.rs +++ b/src/stash/consignment.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::collections::BTreeSet; diff --git a/src/stash/graph.rs b/src/stash/graph.rs index 562de42d..1329246e 100644 --- a/src/stash/graph.rs +++ b/src/stash/graph.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Common API for accessing RGB contract node graph, including individual state //! transitions, extensions, genesis, outputs, assignments & single-use-seal diff --git a/src/stash/mod.rs b/src/stash/mod.rs index e5c5fce2..b6aa1086 100644 --- a/src/stash/mod.rs +++ b/src/stash/mod.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Data structures and APIs related to RGB data storage and data exchange //! tasks. diff --git a/src/stash/stash.rs b/src/stash/stash.rs index a49f890e..f996da02 100644 --- a/src/stash/stash.rs +++ b/src/stash/stash.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! API for working with stash: storage of RGB contract client-side-validated //! data and data containers. diff --git a/src/stash/unit.rs b/src/stash/unit.rs index ad974d72..2655756f 100644 --- a/src/stash/unit.rs +++ b/src/stash/unit.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Definition of and operations with state transition units ([`Unit`]) diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 05e40385..5ec19277 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use core::iter::FromIterator; use core::ops::AddAssign; diff --git a/src/validation/schema.rs b/src/validation/schema.rs index 6df414eb..9daafa2a 100644 --- a/src/validation/schema.rs +++ b/src/validation/schema.rs @@ -1,3 +1,25 @@ +// RGB Core Library: consensus layer for RGB smart contracts. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + /// Trait used for internal schema validation against some root schema pub trait SchemaVerify { fn schema_verify(&self, root: &Self) -> crate::validation::Status; @@ -230,7 +252,7 @@ mod _validation { node_id, transition_type, ), - ) + ); } Some(transition_type) => transition_type, }; @@ -260,7 +282,7 @@ mod _validation { node_id, extension_type, ), - ) + ); } Some(extension_type) => extension_type, }; @@ -357,8 +379,10 @@ mod _validation { )); } - let _field = self.field_types.get(field_type_id) - .expect("If the field were absent, the schema would not be able to pass the internal validation and we would not reach this point"); + let _field = self.field_types.get(field_type_id).expect( + "If the field were absent, the schema would not be able to pass the internal \ + validation and we would not reach this point", + ); for _data in set { // TODO: Run strict type validation /* @@ -469,10 +493,10 @@ mod _validation { )); } - let assignment = &self - .owned_right_types - .get(owned_type_id) - .expect("If the assignment were absent, the schema would not be able to pass the internal validation and we would not reach this point"); + let assignment = &self.owned_right_types.get(owned_type_id).expect( + "If the assignment were absent, the schema would not be able to pass the \ + internal validation and we would not reach this point", + ); match owned_rights.get(owned_type_id) { None => {} @@ -677,8 +701,8 @@ mod _validation { { let mut status = validation::Status::new(); match data { - Assignment::Confidential { state, .. } - | Assignment::ConfidentialState { state, .. } => { + Assignment::Confidential { state, .. } | + Assignment::ConfidentialState { state, .. } => { let a: &dyn Any = state.as_any(); match self { StateSchema::Declarative => { @@ -708,7 +732,8 @@ mod _validation { )); } - // TODO: When other homomorphic formats will be added, + // TODO: When other homomorphic formats will be + // added, // add information to the status like with // hashed data below } diff --git a/src/validation/verify.rs b/src/validation/verify.rs index 8f8068c6..2d7a812a 100644 --- a/src/validation/verify.rs +++ b/src/validation/verify.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use core::iter::FromIterator; use core::ops::AddAssign; @@ -105,8 +116,8 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> if end_transitions .iter() .filter(|(n, _)| n.node_id() == node_id) - .count() - > 0 + .count() > + 0 { status.add_warning(Warning::EndpointDuplication(node_id, *seal_endpoint)); } else { @@ -449,53 +460,52 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> seal_index: u16, ) { // Getting bitcoin transaction outpoint for the current ancestor ... -> - if let Some(outpoint) = match ( - variant.revealed_seal_at(seal_index), - self.anchor_index.get(&ancestor_id), - ) { - (Err(_), _) => { - self.status.add_failure(Failure::TransitionParentWrongSeal { - node_id, - ancestor_id, - assignment_type, - seal_index, - }); - None - } - (Ok(None), _) => { - // Everything is ok, but we have incomplete data (confidential), - // thus can't do a full verification and have to report the - // failure - eprintln!("{:#?}", variant); - self.status - .add_failure(Failure::TransitionParentConfidentialSeal { + if let Some(outpoint) = + match (variant.revealed_seal_at(seal_index), self.anchor_index.get(&ancestor_id)) { + (Err(_), _) => { + self.status.add_failure(Failure::TransitionParentWrongSeal { node_id, ancestor_id, assignment_type, seal_index, }); - None - } - ( - Ok(Some(seal::Revealed { - txid: Some(txid), - vout, - .. - })), - None, - ) => { - // We are at genesis, so the outpoint must contain tx - Some(bp::Outpoint::new(txid!(txid), vout)) - } - (Ok(Some(_)), None) => { - // This can't happen, since if we have a node in the index - // and the node is not genesis, we always have an anchor - unreachable!() + None + } + (Ok(None), _) => { + // Everything is ok, but we have incomplete data (confidential), + // thus can't do a full verification and have to report the + // failure + eprintln!("{:#?}", variant); + self.status + .add_failure(Failure::TransitionParentConfidentialSeal { + node_id, + ancestor_id, + assignment_type, + seal_index, + }); + None + } + ( + Ok(Some(seal::Revealed { + txid: Some(txid), + vout, + .. + })), + None, + ) => { + // We are at genesis, so the outpoint must contain tx + Some(bp::Outpoint::new(txid!(txid), vout)) + } + (Ok(Some(_)), None) => { + // This can't happen, since if we have a node in the index + // and the node is not genesis, we always have an anchor + unreachable!() + } + /* -> ... so we can check that the bitcoin transaction + * references it as one of its inputs */ + (Ok(Some(seal)), Some(anchor)) => Some(outpoint!(seal.outpoint_or(anchor.txid))), } - /* -> ... so we can check that the bitcoin transaction - * references it as one of its inputs */ - (Ok(Some(seal)), Some(anchor)) => Some(outpoint!(seal.outpoint_or(anchor.txid))), - } { + { if !witness_tx .inputs .iter() diff --git a/src/vm/alure.rs b/src/vm/alure.rs index e1b3c08f..54d03016 100644 --- a/src/vm/alure.rs +++ b/src/vm/alure.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![allow(clippy::unusual_byte_groupings)] diff --git a/src/vm/embedded.rs b/src/vm/embedded.rs index 2128749c..d9a7e2e0 100644 --- a/src/vm/embedded.rs +++ b/src/vm/embedded.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #![allow(dead_code)] @@ -243,8 +254,8 @@ mod node { NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_NFT) => { nft_issue(current_meta, previous_owned_rights, current_owned_rights) } - NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_BURN) - | NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_REPLACE) => { + NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_BURN) | + NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_REPLACE) => { proof_of_burn(current_meta) } NodeSubtype::StateTransition(TRANSITION_TYPE_RIGHTS_SPLIT) => { @@ -426,8 +437,8 @@ mod node { if prev.value != curr.value { return Err(HandlerError::NonEqualState); } - } else if prev.to_confidential_state().commitment - != curr.to_confidential_state().commitment + } else if prev.to_confidential_state().commitment != + curr.to_confidential_state().commitment { return Err(HandlerError::ConfidentialState); } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index c0641849..0c577030 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -1,13 +1,24 @@ -// RGB Core Library: a reference implementation of RGB smart contract standards. -// Written in 2019-2022 by -// Dr. Maxim Orlovsky +// RGB Core Library: consensus layer for RGB smart contracts. // -// To the extent possible under law, the author(s) have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. +// SPDX-License-Identifier: Apache-2.0 // -// You should have received a copy of the MIT License along with this software. -// If not, see . +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! API for interfacing different virtual machines //! From 8175508cb7fe4162c3cd5bf5e44f08b1eb4e3e76 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:24:40 +0100 Subject: [PATCH 28/71] ci: update to match other projects --- .github/FUNDING.yml | 2 +- .github/workflows/build.yml | 25 +------------------------ .github/workflows/lint.yml | 2 +- contrib/depCargo.toml | 5 ----- 4 files changed, 3 insertions(+), 31 deletions(-) delete mode 100644 contrib/depCargo.toml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 97c7dedf..d309edc6 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ # These are supported funding model platforms -github: [dr-orlovsky] +github: [lnp-bp, dr-orlovsky] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15353c18..e784120e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,7 +71,7 @@ jobs: strategy: fail-fast: false matrix: - toolchain: [ nightly, beta, stable, 1.59.0 ] + toolchain: [ nightly, beta, stable, 1.66.0 ] steps: - uses: actions/checkout@v2 - name: Install rust ${{ matrix.toolchain }} @@ -84,26 +84,3 @@ jobs: with: command: check args: --workspace --all-targets --all-features - dependency: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install latest stable - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - name: Create dependency - run: | - cargo new dep_test - cp contrib/depCargo.toml dep_test/Cargo.toml - cd dep_test - - name: Build dependency - uses: actions-rs/cargo@v1 - with: - command: check - args: --verbose - - name: Clean up - run: | - cd .. - rm -rf dep_test diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f3eba157..b8979f05 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -39,7 +39,7 @@ jobs: name: Clippy with: command: clippy - args: --workspace --all-features + args: --workspace --all-features --all-targets doc: runs-on: ubuntu-latest steps: diff --git a/contrib/depCargo.toml b/contrib/depCargo.toml deleted file mode 100644 index 061f41b2..00000000 --- a/contrib/depCargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -# This is an add-on that must be added to any dependency using this library - -rgb-core = { path = "..", features = ["all"] } - -[workspace] From 4a504c7eda88b89520b8501b91bc32f32a29a210 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:25:26 +0100 Subject: [PATCH 29/71] chore: update unused dependencies --- Cargo.lock | 158 ++++++++--------------------------------------------- Cargo.toml | 10 +--- 2 files changed, 27 insertions(+), 141 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 540b9f50..2d84b266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.10.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6d717a98f205e67c0fad3702b561fbb9cf405da8c24d88ab8459cd311bd067" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "bech32", "bitcoin_hashes", "curve25519-dalek", @@ -18,17 +18,6 @@ dependencies = [ "serde", ] -[[package]] -name = "amplify" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "116019a174e912931d5b19ca7ab6a22596d12cdb1320358fad3368f0aba135a9" -dependencies = [ - "amplify_derive 2.11.3", - "amplify_num 0.4.1", - "amplify_syn 1.1.6", -] - [[package]] name = "amplify" version = "4.0.0-beta.13" @@ -36,8 +25,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4030ef5731f8cab39af812fc4df7a29b2a46bd40fe5dd5b903865a27368e85" dependencies = [ "amplify_apfloat", - "amplify_derive 4.0.0-alpha.5", - "amplify_num 0.5.0", + "amplify_derive", + "amplify_num", "amplify_syn 1.1.6", "ascii", "serde", @@ -54,22 +43,10 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a958199f6993a34e74b9d22b22709e5c6e527e901d7083b24f0a532445dbfc84" dependencies = [ - "amplify_num 0.5.0", + "amplify_num", "bitflags", ] -[[package]] -name = "amplify_derive" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3de270e75f27a4468a7c344070109046656e85cb522141f7d40ab4b83803ac" -dependencies = [ - "amplify_syn 1.1.6", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "amplify_derive" version = "4.0.0-alpha.5" @@ -82,12 +59,6 @@ dependencies = [ "syn", ] -[[package]] -name = "amplify_num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27d3d00d3d115395a7a8a4dc045feb7aa82b641e485f7e15f4e67ac16f4f56d" - [[package]] name = "amplify_num" version = "0.5.0" @@ -184,17 +155,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" -[[package]] -name = "bitcoin" -version = "0.29.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" -dependencies = [ - "bech32", - "bitcoin_hashes", - "secp256k1 0.24.3", -] - [[package]] name = "bitcoin_hashes" version = "0.11.0" @@ -239,14 +199,14 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75939aecb6e7ad3e30622d8fba00ccdf3cdc78f2325840629ee53cd792548be9" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "bp-dbc", "bp-primitives", "bp-seals", "commit_verify", "serde", "single_use_seals", - "strict_encoding 2.0.0-beta.5", + "strict_encoding", ] [[package]] @@ -255,12 +215,12 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d67f8173cc60f6671df19a170021a4f3a179f828b2114ba0415124dd8abd07f" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "bp-primitives", "commit_verify", "secp256k1 0.26.0", "serde", - "strict_encoding 2.0.0-beta.5", + "strict_encoding", ] [[package]] @@ -269,11 +229,11 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aab03dbc8e2cf19594d3a267cccfc0fd2595ce0818babf39b9e817cb7683e1e4" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "commit_verify", "secp256k1 0.26.0", "serde", - "strict_encoding 2.0.0-beta.5", + "strict_encoding", ] [[package]] @@ -282,14 +242,14 @@ version = "0.10.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "463f314e2c6370104c40356fc96cd464bd0f02aba1a2ffd83dc524e4ecf58d41" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "baid58", "bp-dbc", "bp-primitives", "commit_verify", "rand", "single_use_seals", - "strict_encoding 2.0.0-beta.5", + "strict_encoding", ] [[package]] @@ -323,12 +283,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", - "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.45", - "wasm-bindgen", "winapi", ] @@ -348,11 +305,11 @@ version = "0.10.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7ce27ce9d56cac2631f9701984dc4fd162abbd7b563d97e4440db56f7282cc9" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "bitcoin_hashes", "rand", "serde", - "strict_encoding 2.0.0-beta.5", + "strict_encoding", ] [[package]] @@ -496,18 +453,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "encoding_derive_helpers" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2293d9a54744b73b753fad2e3c16295345504dc230696ee8aa5dbfd276ab4" -dependencies = [ - "amplify 3.13.0", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "fnv" version = "1.0.7" @@ -708,9 +653,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -768,15 +713,13 @@ name = "rgb-core" version = "0.10.0-alpha.1" dependencies = [ "aluvm", - "amplify 4.0.0-beta.13", + "amplify", "baid58", "bp-core", "commit_verify", "secp256k1-zkp", "serde", - "serde_json", - "strict_encoding 2.0.0-beta.5", - "strict_encoding_test", + "strict_encoding", "strict_types", ] @@ -798,7 +741,6 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ - "bitcoin_hashes", "rand", "secp256k1-sys 0.6.1", ] @@ -908,7 +850,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros", - "time 0.3.17", + "time", ] [[package]] @@ -942,20 +884,7 @@ version = "0.10.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ea7651417b98128263b5c3d2dc836400eecd7f4fba8470d4ca17f129f9a1b4a" dependencies = [ - "amplify_derive 4.0.0-alpha.5", -] - -[[package]] -name = "strict_encoding" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be7060b49729cd0b9b2391114632ef64c363a4055d91de049f5555b466193bb" -dependencies = [ - "amplify 3.13.0", - "bitcoin", - "bitcoin_hashes", - "chrono", - "strict_encoding_derive 0.9.0", + "amplify_derive", ] [[package]] @@ -964,22 +893,10 @@ version = "2.0.0-beta.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8ce22c5bba8139f2182001358188f145b40b177a9a442545cf15574335fba88" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "half", "serde", - "strict_encoding_derive 2.0.0-beta.2", -] - -[[package]] -name = "strict_encoding_derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34c9cabafb397fc1144463228ad4ba57c3c670a0117505fe59b15d8c74449716" -dependencies = [ - "amplify_syn 1.1.6", - "encoding_derive_helpers", - "proc-macro2", - "syn", + "strict_encoding_derive", ] [[package]] @@ -995,30 +912,20 @@ dependencies = [ "syn", ] -[[package]] -name = "strict_encoding_test" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc369cd865314a3416556e3669d3f2d2e41c6e80cc838208c84a34f74d79234" -dependencies = [ - "amplify 3.13.0", - "strict_encoding 0.9.0", -] - [[package]] name = "strict_types" version = "1.0.0-beta.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11170f93c7f969209d86c4a3a6a7a6b333772890a7303647e5e055800840df9b" dependencies = [ - "amplify 4.0.0-beta.13", + "amplify", "baid58", "blake3", "half", "serde", "serde_with", "serde_yaml", - "strict_encoding 2.0.0-beta.5", + "strict_encoding", ] [[package]] @@ -1063,17 +970,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.17" @@ -1146,12 +1042,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 7be41fcb..52b84005 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,19 +18,15 @@ name = "rgb" path = "src/lib.rs" [dependencies] -amplify = { version = "~4.0.0-beta.13", features = ["apfloat"] } -bp-core = { version = "~0.10.0-beta.1" } +amplify = "~4.0.0-beta.13" strict_encoding = "2.0.0-beta.5" strict_types = "1.0.0-beta.3" aluvm = "0.10.0-alpha.1" commit_verify = { version = "~0.10.0-beta.2", features = ["rand"] } +bp-core = { version = "~0.10.0-beta.1" } +secp256k1-zkp = { version = "~0.7.0", features = ["rand-std", "global-context"] } baid58 = "~0.1.0" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } -secp256k1-zkp = { version = "~0.7.0", features = ["rand-std", "global-context"] } - -[dev-dependencies] -serde_json = "1" -strict_encoding_test = "0.9.0" [features] default = [] From 9a2976af7031848799283f7bed8b8429f87946a9 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:28:40 +0100 Subject: [PATCH 30/71] chore: update license and MSRV --- Cargo.toml | 9 +-- LICENSE | 223 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 206 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52b84005..d7024145 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,21 +1,20 @@ [package] name = "rgb-core" version = "0.10.0-alpha.1" -license = "MIT" authors = ["Dr Maxim Orlovsky "] -description = "RGB Core Library: consensus & verification for private & scalable client-validated smart contracts on Bitcoin & Lightning" +description = "RGB Core Library: confidential & scalable smart contracts on Bitcoin & Lightning (consensus layer)" repository = "https://github.com/RGB-WG/rgb-core" homepage = "https://rgb.tech" keywords = ["bitcoin", "lightning", "rgb", "smart-contracts", "lnp-bp"] categories = ["cryptography::cryptocurrencies"] readme = "README.md" +license = "Apache-2.0" edition = "2021" -rust-version = "1.59.0" -exclude = [".github", "contrib"] +rust-version = "1.66.0" +exclude = [".github"] [lib] name = "rgb" -path = "src/lib.rs" [dependencies] amplify = "~4.0.0-beta.13" diff --git a/LICENSE b/LICENSE index 39054caf..6ef93b8e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,202 @@ -MIT License - -Copyright (c) 2019-2022 LNP/BP Standards Association - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019-2023 LNP/BP Standards Association, Switzerland + Copyright 2019-2023 Dr Maxim Orlovsky + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From f9bb5f413e7e4a6000705292261fdb00cc867027 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:30:10 +0100 Subject: [PATCH 31/71] chore: add community standards --- CODE_OF_CONDUCT.md | 2 +- CONTRIBUTING.md | 196 +++++++++++++++++++++++++++++++++++++++++++++ DCO | 28 +++++++ MAINTAINERS.md | 6 ++ MANIFEST.yml | 14 ++++ README.md | 2 +- SECURITY.md | 59 ++++++++++++++ codecov.yml | 10 ++- 8 files changed, 311 insertions(+), 6 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 DCO create mode 100644 MAINTAINERS.md create mode 100644 MANIFEST.yml create mode 100644 SECURITY.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 105d219c..784426e3 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -15,5 +15,5 @@ participation. Actions within the technical scope of the project (code quality, spamming etc), as well as interaction with other maintainers and contributors of course is a factor of the access to the project development and lifecycle. The decision in -these cases will be maid by the project maintainers, with the right of veto or +these cases will be made by the project maintainers, with the right of veto or overriding vote reserved for the original project author, Maxim Orlovsky. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..66acff98 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,196 @@ +Contributing guidelines +======================= + +Contributions are very welcome. When contributing code, please follow these +simple guidelines. + +#### Table Of Contents +- [Contribution workflow](#contribution-workflow) + * [Proposing changes](#proposing-changes) + * [Preparing PRs](#preparing-prs) + * [Peer review](#peer-review) +- [Coding conventions](#coding-conventions) +- [Security](#security) +- [Testing](#testing) +- [Going further](#going-further) + +Overview +-------- + +* Before adding any code dependencies, check with the maintainers if this is okay. +* Write properly formatted comments: they should be English sentences, eg: + + // Return the current UNIX time. + +* Read the DCO and make sure all commits are signed off, using `git commit -s`. +* Follow the guidelines when proposing code changes (see below). +* Write properly formatted git commits (see below). +* Run the tests with `cargo test --workspace --all-features`. +* Make sure you run `rustfmt` on your code (see below details). +* Please don't file an issue to ask a question. Each repository - or + GitHub organization has a "Discussions" with Q&A section; please post your + questions there. You'll get faster results by using this channel. + +Contribution Workflow +--------------------- +The codebase is maintained using the "contributor workflow" where everyone +without exception contributes patch proposals using "pull requests". This +facilitates social contribution, easy testing and peer review. + +To contribute a patch, the workflow is a as follows: + +1. Fork Repository +2. Create topic branch +3. Commit patches + +In general commits should be atomic and diffs should be easy to read. For this +reason do not mix any formatting fixes or code moves with actual code changes. +Further, each commit, individually, should compile and pass tests, in order to +ensure git bisect and other automated tools function properly. + +When adding a new feature thought must be given to the long term technical debt. +Every new features should be covered by unit tests. + +When refactoring, structure your PR to make it easy to review and don't hesitate +to split it into multiple small, focused PRs. + +Commits should cover both the issue fixed and the solution's rationale. +These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in +mind. + +To facilitate communication with other contributors, the project is making use +of GitHub's "assignee" field. First check that no one is assigned and then +comment suggesting that you're working on it. If someone is already assigned, +don't hesitate to ask if the assigned party or previous commenters are still +working on it if it has been awhile. + +### Proposing changes + +When proposing changes via a pull-request or patch: + +* Isolate changes in separate commits to make the review process easier. +* Don't make unrelated changes, unless it happens to be an obvious improvement to + code you are touching anyway ("boyscout rule"). +* Rebase on `master` when needed. +* Keep your changesets small, specific and uncontroversial, so that they can be + merged more quickly. +* If the change is substantial or requires re-architecting certain parts of the + codebase, write a proposal in English first, and get consensus on that before + proposing the code changes. + +### Preparing PRs + +The main library development happens in the `master` branch. This branch must +always compile without errors (using Travis CI). All external contributions are +made within PRs into this branch. + +Prerequisites that a PR must satisfy for merging into the `master` branch: +* the tip of any PR branch must compile and pass unit tests with no errors, with + every feature combination (including compiling the fuzztests) on MSRV, stable + and nightly compilers (this is partially automated with CI, so the rule + is that we will not accept commits which do not pass GitHub CI); +* contain all necessary tests for the introduced functional (either as a part of + commits, or, more preferably, as separate commits, so that it's easy to + reorder them during review and check that the new tests fail without the new + code); +* contain all inline docs for newly introduced API and pass doc tests; +* be based on the recent `master` tip from the original repository at. + +NB: reviewers may run more complex test/CI scripts, thus, satisfying all the +requirements above is just a preliminary, but not necessary sufficient step for +getting the PR accepted as a valid candidate PR for the `master` branch. + +Additionally, to the `master` branch some repositories may have `develop` branch +for any experimental developments. This branch may not compile and should not be +used by any projects depending on the library. + +### Writing Git commit messages + +A properly formed git commit subject line should always be able to complete the +following sentence: + + If applied, this commit will _____ + +In addition, it should be capitalized and *must not* include a period. + +For example, the following message is well formed: + + Add support for .gif files + +While these ones are **not**: `Adding support for .gif files`, +`Added support for .gif files`. + +When it comes to formatting, here's a model git commit message[1]: + + Capitalized, short (50 chars or less) summary + + More detailed explanatory text, if necessary. Wrap it to about 72 + characters or so. In some contexts, the first line is treated as the + subject of an email and the rest of the text as the body. The blank + line separating the summary from the body is critical (unless you omit + the body entirely); tools like rebase can get confused if you run the + two together. + + Write your commit message in the imperative: "Fix bug" and not "Fixed bug" + or "Fixes bug." This convention matches up with commit messages generated + by commands like git merge and git revert. + + Further paragraphs come after blank lines. + + - Bullet points are okay, too. + + - Typically a hyphen or asterisk is used for the bullet, followed by a + single space, with blank lines in between, but conventions vary here. + + - Use a hanging indent. + +### Peer review + +Anyone may participate in peer review which is expressed by comments in the pull +request. Typically reviewers will review the code for obvious errors, as well as +test out the patch set and opine on the technical merits of the patch. PR should +be reviewed first on the conceptual level before focusing on code style or +grammar fixes. + +Coding Conventions +------------------ +Our CI enforces [clippy's](https://github.com/rust-lang/rust-clippy) +[default linting](https://rust-lang.github.io/rust-clippy/rust-1.52.0/index.html) +and [rustfmt](https://github.com/rust-lang/rustfmt) formatting defined by rules +in [.rustfmt.toml](./.rustfmt.toml). The linter should be run with current +stable rust compiler, while formatter requires nightly version due to the use of +unstable formatting parameters. + +If you use rustup, to lint locally you may run the following instructions: + +```console +rustup component add clippy +rustup component add fmt +cargo +stable clippy --workspace --all-features +cargo +nightly fmt --all +``` + +Security +-------- +Responsible disclosure of security vulnerabilities helps prevent user loss of +privacy. If you believe a vulnerability may affect other implementations, please +inform them. Guidelines for a responsible disclosure can be found in +[SECURITY.md](./SECURITY.md) file in the project root. + +Note that some of our projects are currently considered "pre-production". +Such projects can be distinguished by the absence of `SECURITY.md`. In such +cases there are no special handling of security issues; please simply open +an issue on GitHub. + +Going further +------------- +You may be interested in Jon Atack guide on +[How to review Bitcoin Core PRs][Review] and [How to make Bitcoin Core PRs][PR]. +While there are differences between the projects in terms of context and +maturity, many of the suggestions offered apply to this project. + +Overall, have fun :) + +[1]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +[Review]: https://github.com/jonatack/bitcoin-development/blob/master/how-to-review-bitcoin-core-prs.md +[PR]: https://github.com/jonatack/bitcoin-development/blob/master/how-to-make-bitcoin-core-prs.md diff --git a/DCO b/DCO new file mode 100644 index 00000000..69175c98 --- /dev/null +++ b/DCO @@ -0,0 +1,28 @@ +Developer's Certificate of Origin 1.1 +Copyright © 2004, 2006 The Linux Foundation and its contributors. + +--- + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 00000000..a3af1e08 --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,6 @@ +Maxim Orlovsky +--------------- +- GitHub: [@dr-orlovsky](https://github.com/dr-orlovsky) +- GPG: `EAE730CEC0C663763F028A5860094BAF18A26EC9` +- SSH: `BoSGFzbyOKC7Jm28MJElFboGepihCpHop60nS8OoG/A` +- EMail: [dr@orlovsky.ch](mailto:dr@orlovsky.ch) diff --git a/MANIFEST.yml b/MANIFEST.yml new file mode 100644 index 00000000..6ec60bd5 --- /dev/null +++ b/MANIFEST.yml @@ -0,0 +1,14 @@ +Name: strict_encoding +Type: Library +Kind: Free software +License: Apache-2.0 +Language: Rust +Compiler: 1.66 +Author: Maxim Orlovsky +Maintained: UBIDECO Institute, Switzerland +Maintainers: + Maxim Orlovsky: + GitHub: @dr-orlovsky + GPG: EAE730CEC0C663763F028A5860094BAF18A26EC9 + SSH: BoSGFzbyOKC7Jm28MJElFboGepihCpHop60nS8OoG/A + EMail: dr@orlovsky.ch diff --git a/README.md b/README.md index 8928cf64..73f092a2 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![crates.io](https://img.shields.io/crates/v/rgb-core)](https://crates.io/crates/rgb-core) [![Docs](https://docs.rs/rgb-core/badge.svg)](https://docs.rs/rgb-core) [![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) -[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) +[![Apache-2 licensed](https://img.shields.io/crates/l/rgb-core)](./LICENSE) RGB is confidential & scalable client-validated smart contracts for Bitcoin & Lightning. To learn more about RGB please check [RGB blueprint][Blueprint] and diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..22101c1e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,59 @@ +# Security + +We take the security of our software products and services seriously, which +includes all source code repositories managed through our GitHub organizations. + +If you believe you have found a security vulnerability in any of our repository +that meets [definition of a security vulnerability][definition], please report +it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the repository maintainers by sending a **GPG +encrypted e-mail** to _all maintainers of a specific repo_ using their GPG keys. + +A list of repository maintainers and their keys and e-mail addresses are +provided inside MAINTANERS.md file and MANIFEST.yml, with the latter also +included in the README.md as a manifest block, which looks in the following way: + +```yaml +Name: +... +Maintained: +Maintainers: + : + GPG: + EMail: + : + ... +``` + +You should receive a response within 72 hours. If for some reason you do not, +please follow up via email to ensure we received your original message. + +Please include the requested information listed below (as much as you can +provide) to help us better understand the nature and scope of the possible +issue: + +* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +We follow the principle of [Coordinated Vulnerability Disclosure][disclosure]. + +[definition]: https://aka.ms/opensource/security/definition +[disclosure]: https://aka.ms/opensource/security/cvd diff --git a/codecov.yml b/codecov.yml index e0184107..240d7310 100644 --- a/codecov.yml +++ b/codecov.yml @@ -5,13 +5,15 @@ coverage: precision: 1 round: nearest range: "0...95" - # TODO #30: Update codecov default requirements after release status: project: default: - target: 0% + target: 75% threshold: 1% + branches: + - master patch: default: - target: 0% - threshold: 1% \ No newline at end of file + target: 60% + threshold: 1% + only_pulls: true From fea5648936c39394c29442145ff686c8708278b7 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:46:46 +0100 Subject: [PATCH 32/71] chore: style conventions and docs feature gate --- Cargo.toml | 3 +++ src/lib.rs | 7 ++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d7024145..e3daa7cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,6 @@ serde = [ "aluvm/serde", "secp256k1-zkp/serde" ] + +[package.metadata.docs.rs] +features = [ "all" ] diff --git a/src/lib.rs b/src/lib.rs index 12fba936..3634ca16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,8 +20,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![recursion_limit = "256"] -// Coding conventions #![deny( non_upper_case_globals, non_camel_case_types, @@ -29,10 +27,9 @@ unused_mut, unused_imports, dead_code, - //missing_docs + // TODO: Uncomment missing_docs )] -// TODO: Upgrade tests to use new strict_encoding_test crate -#![cfg_attr(test, allow(deprecated))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #[macro_use] extern crate amplify; From 4165a2cd41ffa423e2c4efc934182d507e315ea8 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:48:08 +0100 Subject: [PATCH 33/71] chore: refactor module hierarchy --- src/ext.rs | 1 - src/lib.rs | 7 +- src/macros.rs | 25 -- src/validation/vm.rs | 93 +++++++ src/vm/alure.rs | 28 -- src/vm/embedded.rs | 631 ------------------------------------------- src/vm/mod.rs | 48 ---- 7 files changed, 94 insertions(+), 739 deletions(-) delete mode 100644 src/ext.rs delete mode 100644 src/macros.rs create mode 100644 src/validation/vm.rs delete mode 100644 src/vm/embedded.rs diff --git a/src/ext.rs b/src/ext.rs deleted file mode 100644 index f9cf4cc3..00000000 --- a/src/ext.rs +++ /dev/null @@ -1 +0,0 @@ -//! Parts which need to be moved to other crates diff --git a/src/lib.rs b/src/lib.rs index 3634ca16..fe7305f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,16 +40,11 @@ extern crate strict_encoding; #[macro_use] extern crate serde_crate as serde; -pub(crate) mod ext; - // pub mod contract; pub mod schema; // pub mod stash; -// pub mod verify; // pub mod validation; -// pub mod vm; -// #[macro_use] -// mod macros; +pub mod vm; pub const LIB_NAME_RGB: &str = "RGB"; diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index 23177b65..00000000 --- a/src/macros.rs +++ /dev/null @@ -1,25 +0,0 @@ -#[macro_export] -macro_rules! type_map { - { } => { - { - ::std::collections::BTreeMap::new() - } - }; - - { $($key:expr => $value:expr),+ } => { - { - let mut m = ::std::collections::BTreeMap::new(); - $( - m.insert($key.into(), $value); - )+ - m - } - } -} - -#[macro_export] -macro_rules! field { - ($type:ident, $value:expr) => { - vec![::rgb::data::Revealed::$type($value)] - }; -} diff --git a/src/validation/vm.rs b/src/validation/vm.rs new file mode 100644 index 00000000..4261d092 --- /dev/null +++ b/src/validation/vm.rs @@ -0,0 +1,93 @@ +// RGB Core Library: consensus layer for RGB smart contracts. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::validation::Failure; +use crate::{ + validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, ValidationScript, +}; + +/// Trait for concrete types wrapping virtual machines to be used from inside +/// RGB schema validation routines. +pub trait Validate { + /// Validates state change in a contract node. + #[allow(clippy::too_many_arguments)] + fn validate( + &self, + node_id: NodeId, + node_subtype: NodeSubtype, + previous_owned_rights: &OwnedRights, + current_owned_rights: &OwnedRights, + previous_public_rights: &PublicRights, + current_public_rights: &PublicRights, + current_meta: &Metadata, + ) -> Result<(), validation::Failure>; +} + +impl Validate for ValidationScript { + fn validate( + &self, + node_id: NodeId, + node_subtype: NodeSubtype, + previous_owned_rights: &OwnedRights, + current_owned_rights: &OwnedRights, + previous_public_rights: &PublicRights, + current_public_rights: &PublicRights, + current_meta: &Metadata, + ) -> Result<(), validation::Failure> { + match self { + ValidationScript::AluVM(script) => alure::Runtime::new(script).validate( + node_id, + node_subtype, + previous_owned_rights, + current_owned_rights, + previous_public_rights, + current_public_rights, + current_meta, + ), + } + } +} + +impl<'script> Validate for Runtime<'script> { + #[allow(unused_variables)] + fn validate( + &self, + node_id: NodeId, + node_subtype: NodeSubtype, + previous_owned_rights: &OwnedRights, + current_owned_rights: &OwnedRights, + previous_public_rights: &PublicRights, + current_public_rights: &PublicRights, + current_meta: &Metadata, + ) -> Result<(), Failure> { + // TODO: Implement validation with AluVM + /* + let mut vm = Vm::::new(); + if vm.run(self.script) { + Ok(()) + } else { + Err(Failure::ScriptFailure(node_id)) + } + */ + Ok(()) + } +} diff --git a/src/vm/alure.rs b/src/vm/alure.rs index 54d03016..8ef1f6af 100644 --- a/src/vm/alure.rs +++ b/src/vm/alure.rs @@ -32,9 +32,6 @@ use aluvm::reg::CoreRegs; use aluvm::Vm; */ -use crate::validation::Failure; -use crate::{Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, Validate}; - /* pub const INSTR_NOOP: u8 = 0b11_000_000; pub const INSTR_ISAE_FROM: u8 = 0b11_000_000; @@ -102,28 +99,3 @@ pub struct Runtime<'script> { impl<'script> Runtime<'script> { pub fn new(script: &'script ValidationScript) -> Self { Runtime { script } } } - -impl<'script> Validate for Runtime<'script> { - #[allow(unused_variables)] - fn validate( - &self, - node_id: NodeId, - node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - previous_public_rights: &PublicRights, - current_public_rights: &PublicRights, - current_meta: &Metadata, - ) -> Result<(), Failure> { - // TODO: Implement validation with AluVM - /* - let mut vm = Vm::::new(); - if vm.run(self.script) { - Ok(()) - } else { - Err(Failure::ScriptFailure(node_id)) - } - */ - Ok(()) - } -} diff --git a/src/vm/embedded.rs b/src/vm/embedded.rs deleted file mode 100644 index d9a7e2e0..00000000 --- a/src/vm/embedded.rs +++ /dev/null @@ -1,631 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![allow(dead_code)] - -//! Implementation of the embedded state machine - -use amplify::Wrapper; -use commit_verify::CommitConceal; - -use super::Validate; -use crate::{ - schema, validation, value, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, - TypedAssignments, -}; - -/// Constants which are common to different schemata and can be recognized -/// by the software even if the specific schema is unknown, since this type ids -/// are reserved to a specific semantic meaning -/// -/// These constants are also used by embedded validation procedures representing -/// standard metadata fields, state and transition types analyzed by them -pub mod constants { - /// Ticker of the asset - pub const FIELD_TYPE_TICKER: u16 = 0x00; - - /// Contract or asset name - pub const FIELD_TYPE_NAME: u16 = 0x01; - - /// Ricardian contract text - pub const FIELD_TYPE_CONTRACT_TEXT: u16 = 0x02; - - /// Decimal precision for some sort of amount values used in a contract - pub const FIELD_TYPE_PRECISION: u16 = 0x03; - - /// Timestamp used in genesis to indicate moment of contract creation - pub const FIELD_TYPE_TIMESTAMP: u16 = 0x04; - - /// Generic comment about the contract or a state transitions - pub const FIELD_TYPE_COMMENTARY: u16 = 0x05; - - /// Data attached to a state transition in binary format - pub const FIELD_TYPE_DATA: u16 = 0x10; - - /// Format of the attached data, schema-specific - pub const FIELD_TYPE_DATA_FORMAT: u16 = 0x11; - - /// [`FieldType`] that is used by validation procedures checking the issued - /// supply & inflation - pub const FIELD_TYPE_ISSUED_SUPPLY: u16 = 0xA0; - - /// [`FieldType`] that is used by validation procedures checking proofs of - /// burn. Must contain amount of the burned supply, expressed as - /// revealed [`crate::value::Revealed`] data - pub const FIELD_TYPE_BURN_SUPPLY: u16 = 0xB0; - - /// [`FieldType`] that is used by validation procedures checking proofs of - /// burn. Must contain [`bp::Outpoint`] consensus-encoded data. - pub const FIELD_TYPE_BURN_UTXO: u16 = 0xB1; - - /// [`FieldType`] that is used by validation procedures checking proofs of - /// burn. Must contain binary data ([`crate::data::Revealed::Bytes`]) - pub const FIELD_TYPE_HISTORY_PROOF: u16 = 0xB2; - - /// [`FieldType`] that is used by validation procedures checking proofs of - /// burn. Must contain format of the provided proofs defined in - /// [`HistoryProofFormat`] - pub const FIELD_TYPE_HISTORY_PROOF_FORMAT: u16 = 0xB3; - - /// [`FieldType`] that is used by validation procedures checking proofs of - /// reserves. Must contain [`wallet::descriptor::Expanded`] strict encoded - /// data. - pub const FIELD_TYPE_LOCK_DESCRIPTOR: u16 = 0xC0; - - /// [`FieldType`] that is used by validation procedures checking proofs of - /// reserves. Must contain [`bp::Outpoint`] consensus-encoded data - pub const FIELD_TYPE_LOCK_UTXO: u16 = 0xC1; - - /// Description of the asset - pub const FIELD_TYPE_DESCRIPTION: u16 = 0xC2; - - /// Parent ID of the asset - pub const FIELD_TYPE_PARENT_ID: u16 = 0xC3; - - // -------- - - /// Renomination of the contract parameters - pub const STATE_TYPE_RENOMINATION_RIGHT: u16 = 0x01; - - /// [`OwnedRightType`] that is used by the validation procedures checking - /// asset inflation (applies to both fungible and non-fungible assets) - pub const STATE_TYPE_INFLATION_RIGHT: u16 = 0xA0; - - /// [`OwnedRightType`] that is used by validation procedures checking for - /// the equivalence relations between previous and new asset ownership - /// (applies to both fungible and non-fungible assets). - /// - /// NB: STATE_TYPE_OWNERSHIP_RIGHT + N where N = 1..9 are reserved for - /// custom forms of ownership (like "engraved ownership" for NFT tokens) - pub const STATE_TYPE_OWNERSHIP_RIGHT: u16 = 0xA1; - - /// Right to engrave an NFT token - pub const STATE_TYPE_ENGRAVING_RIGHT: u16 = 0xA2; - - /// Right to define epochs of asset replacement - pub const STATE_TYPE_ISSUE_EPOCH_RIGHT: u16 = 0xAA; - - /// Right to replace some of the state issued under the contract - pub const STATE_TYPE_ISSUE_REPLACEMENT_RIGHT: u16 = 0xAB; - - /// Right to replace some of the state issued under the contract - pub const STATE_TYPE_ISSUE_REVOCATION_RIGHT: u16 = 0xAC; - - // -------- - - /// Transitions transferring ownership of a homomorphic value - pub const TRANSITION_TYPE_VALUE_TRANSFER: u16 = 0x00; - - /// Transitions transferring ownership of a non-fungible identifiable state - pub const TRANSITION_TYPE_IDENTITY_TRANSFER: u16 = 0x01; - - /// Transition performing renomination of contract metadata - pub const TRANSITION_TYPE_RENOMINATION: u16 = 0x1010; - - /// [`TransitionType`] that is used by the validation procedures checking - /// asset inflation (applies to both fungible and non-fungible assets) - pub const TRANSITION_TYPE_ISSUE_FUNGIBLE: u16 = 0x10A0; - - /// Transition that defines certain grouping of other issue-related - /// operations - pub const TRANSITION_TYPE_ISSUE_EPOCH: u16 = 0x10A1; - - /// Transition burning some of the issued contract state. - /// - /// NB: It is not the same as [`TRANSITION_TYPE_RIGHTS_TERMINATION`], which - /// terminates ability to utilize some rights (but not the state) - pub const TRANSITION_TYPE_ISSUE_BURN: u16 = 0x10A2; - - /// Transition replacing some of the previously issued state with the new - /// one - pub const TRANSITION_TYPE_ISSUE_REPLACE: u16 = 0x10A3; - - /// Transition engraving an NFT token - pub const TRANSITION_TYPE_ENGRAVING: u16 = 0x10A4; - - /// Transition issuing NFT token - pub const TRANSITION_TYPE_ISSUE_NFT: u16 = 0x10AF; - - /// Transition performing split of rights assigned to the same UTXO by - /// a mistake - pub const TRANSITION_TYPE_RIGHTS_SPLIT: u16 = 0x8000; - - /// Transition making certain rights void without executing the right itself - pub const TRANSITION_TYPE_RIGHTS_TERMINATION: u16 = 0x8001; -} -use constants::*; - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error)] -#[display(doc_comments)] -#[repr(u16)] -pub enum HandlerError { - /// validation operation is not yet implemented in the embedded VM - NotImplemented = 0, - - /// asset inflation/excessive issue is detected when it is prohibited by - /// the contract schema rules (this inflation can be both negative, i.e. - /// deflation, or positive, i.e. true inflation) - Inflation, - - /// inconsistent schema data - /// - /// NB: Generally we do not validate the schema at the level of VM (the - /// validation must happen before), but in some cases when we retrieve data - /// and get results which must be prevented by the schema we - /// report this error. - /// - /// Occurrence of this error possible means that RGB library code has a - /// bug, since schema MUST be validated before any of the VM methods - /// are called - #[display("inconsistent schema data")] - BrokenSchema, - - /// non-equal input and output assignment types are found when type match - /// is required - NonEqualTypes, - - /// non-equal state data are found when state equivalence is required - NonEqualState, - - /// non-equal number of state assignments when assignments are required to - /// be translated one-to-one in state transition - NonEqualAssignmentCount, - - /// confidential state data are found in location where state equivalence - /// must be checked and the provided state commitments do not match - ConfidentialState, - - /// sum of assigned values overflows schema-allowed bit dimension - ValueOverflow, - - /// wrong format for byte-encoded data - DataEncoding, - - /// incorrect field value - FieldValue, -} - -/// Embedded action handlers for contract nodes processed by the embedded state -/// machine -mod node { - use super::*; - - pub fn validate( - node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - _previous_public_rights: &PublicRights, - _current_public_rights: &PublicRights, - current_meta: &Metadata, - ) -> Result<(), HandlerError> { - for (field_type, fields) in current_meta { - for data in fields { - meta::validate(*field_type, data)?; - } - } - - match node_subtype { - NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_FUNGIBLE) => { - fungible_issue(current_meta, previous_owned_rights, current_owned_rights) - } - NodeSubtype::StateTransition(TRANSITION_TYPE_VALUE_TRANSFER) => Ok(()), - NodeSubtype::StateTransition(TRANSITION_TYPE_IDENTITY_TRANSFER) => { - input_output_count_eq(previous_owned_rights, current_owned_rights) - } - NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_NFT) => { - nft_issue(current_meta, previous_owned_rights, current_owned_rights) - } - NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_BURN) | - NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_REPLACE) => { - proof_of_burn(current_meta) - } - NodeSubtype::StateTransition(TRANSITION_TYPE_RIGHTS_SPLIT) => { - input_output_value_eq(previous_owned_rights, current_owned_rights) - } - // NodeSubtype::StateTransition(..) => Self::proof_of_reserve(current_meta), - _ => Ok(()), - } - } - - /// Fungible asset inflation/issue control - /// - /// Checks that inflation of a fungible asset produces no more than was - /// allowed by [`crate::schema::constants::STATE_TYPE_INFLATION_RIGHT`], - /// i.e. that the sum of all outputs with - /// [`crate::schema::constants::STATE_TYPE_OWNED_AMOUNT`] and - /// [`crate::schema::constants::STATE_TYPE_INFLATION_RIGHT`] types is no - /// more than that value - plus validates bulletproof data. - /// - /// Also validates that the sum of the issued asset is equal to the amount - /// specified in the [`crate::schema::constants::FIELD_TYPE_ISSUED_SUPPLY`] - /// metadata field - fn fungible_issue( - meta: &Metadata, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - ) -> Result<(), HandlerError> { - let issued = meta.u64(FIELD_TYPE_ISSUED_SUPPLY).into_iter().sum(); - - // [SECURITY-CRITICAL]: First we need to validate that we do not issue - // more assets than allowed by our issue rights - let allowed_inflation: u64 = previous_owned_rights - .assignments_by_type(STATE_TYPE_INFLATION_RIGHT) - .as_revealed_state_values() - .map_err(|_| HandlerError::ConfidentialState)? - .into_iter() - .map(|revealed| revealed.value) - .sum(); - let future_inflation: u64 = current_owned_rights - .assignments_by_type(STATE_TYPE_INFLATION_RIGHT) - .as_revealed_state_values() - .map_err(|_| HandlerError::ConfidentialState)? - .into_iter() - .map(|revealed| revealed.value) - .sum(); - if issued + future_inflation != allowed_inflation { - return Err(HandlerError::Inflation); - } - - // [SECURITY-CRITICAL]: Second, we need to make sure that the amount of - // assigned assets are equal to the number of - // issued assets - let mut inputs = previous_owned_rights - .assignments_by_type(STATE_TYPE_OWNERSHIP_RIGHT) - .to_confidential_state_pedersen() - .into_iter() - .map(|v| v.commitment) - .collect::>(); - let outputs = current_owned_rights - .assignments_by_type(STATE_TYPE_OWNERSHIP_RIGHT) - .to_confidential_state_pedersen() - .into_iter() - .map(|v| v.commitment) - .collect(); - // [SECURITY-CRITICAL]: Adding amount that has to be issued as another - // input - inputs.push( - value::Revealed { - value: issued, - blinding: secp256k1_zkp::ONE_KEY.into(), - } - .commit_conceal() - .commitment, - ); - if !value::Confidential::verify_commit_sum(outputs, inputs) { - return Err(HandlerError::Inflation); - } - - Ok(()) - } - - /// NFT asset secondary issue control - /// - /// Checks that inflation of a fungible asset produces no more than was - /// allowed by [`crate::schema::constants::STATE_TYPE_INFLATION_RIGHT`], - /// i.e. that the sum of all outputs with - /// [`crate::schema::constants::STATE_TYPE_OWNED_AMOUNT`] type is no more - /// than that value - fn nft_issue( - _meta: &Metadata, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - ) -> Result<(), HandlerError> { - let issued = current_owned_rights - .assignments_by_type(STATE_TYPE_OWNERSHIP_RIGHT) - .len(); - - // [SECURITY-CRITICAL]: We need to validate that we do not issue more - // asset items than allowed by our issue rights - let allowed_inflation = previous_owned_rights - .assignments_by_type(STATE_TYPE_INFLATION_RIGHT) - .as_revealed_state_values() - .map_err(|_| HandlerError::ConfidentialState)? - .len(); - - let future_inflation = current_owned_rights - .assignments_by_type(STATE_TYPE_INFLATION_RIGHT) - .as_revealed_state_values() - .map_err(|_| HandlerError::ConfidentialState)? - .len(); - - if issued + future_inflation != allowed_inflation { - return Err(HandlerError::Inflation); - } - - Ok(()) - } - - /// Proof-of-burn verification - /// - /// Currently not implemented in RGBv0 and always validates to FALSE - fn proof_of_burn(_meta: &Metadata) -> Result<(), HandlerError> { - Err(HandlerError::NotImplemented) - } - - /// Proof-of-reserve verification - /// - /// Currently not implemented in RGBv0 and always validates to FALSE - fn proof_of_reserve(meta: &Metadata) -> Result<(), HandlerError> { - let _descriptor_data = meta - .bytes(FIELD_TYPE_LOCK_DESCRIPTOR) - .first() - .cloned() - .ok_or(HandlerError::BrokenSchema)?; - // let _descriptor = - // descriptors::Expanded::strict_deserialize(descriptor_data) - // .map_err(|_| HandlerError::DataEncoding)?; - // TODO #81: Implement blockchain access for the VM - Err(HandlerError::NotImplemented) - } - - /// Rights split. - /// - /// We must allocate exactly one or none rights per each right used as input - /// (i.e. closed seal); plus we need to control that sum of inputs is equal - /// to the sum of outputs for each of state types having assigned - /// confidential amounts - fn input_output_value_eq( - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - ) -> Result<(), HandlerError> { - let prev = previous_owned_rights.as_inner(); - let curr = current_owned_rights.as_inner(); - if prev.len() != curr.len() { - return Err(HandlerError::NonEqualTypes); - } - - for ((prev_type, prev_assignments), (curr_type, curr_assignments)) in prev.iter().zip(curr) - { - if prev_type != curr_type { - return Err(HandlerError::NonEqualTypes); - } - if prev_assignments.state_type() != curr_assignments.state_type() { - return Err(HandlerError::BrokenSchema); - } - if prev_assignments.len() != curr_assignments.len() { - return Err(HandlerError::NonEqualAssignmentCount); - } - - match (prev_assignments, curr_assignments) { - (TypedAssignments::Void(_), TypedAssignments::Void(_)) => { - // This is valid, so passing validation step - } - (TypedAssignments::Value(prev), TypedAssignments::Value(curr)) => { - for (prev, curr) in prev.iter().zip(curr.iter()) { - if let (Some(prev), Some(curr)) = - (prev.as_revealed_state(), curr.as_revealed_state()) - { - if prev.value != curr.value { - return Err(HandlerError::NonEqualState); - } - } else if prev.to_confidential_state().commitment != - curr.to_confidential_state().commitment - { - return Err(HandlerError::ConfidentialState); - } - } - } - (TypedAssignments::Data(prev), TypedAssignments::Data(curr)) => { - for (prev, curr) in prev.iter().zip(curr.iter()) { - if prev.to_confidential_state() != curr.to_confidential_state() { - return Err(HandlerError::NonEqualState); - } - } - } - (_, _) => unreachable!("assignment formats are equal as checked above"), - } - } - - Ok(()) - } - - /// NFT/identity transfer control - /// - /// Checks that all identities are transferred once and only once, i.e. - /// that the _number_ of - /// [`crate::schema::constants::STATE_TYPE_OWNED_DATA`] inputs is equal - /// to the _number_ of outputs of this type. - fn input_output_count_eq( - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - ) -> Result<(), HandlerError> { - let prev = previous_owned_rights.as_inner(); - let curr = current_owned_rights.as_inner(); - if prev.len() != curr.len() { - return Err(HandlerError::NonEqualTypes); - } - - for ((prev_type, prev_assignments), (curr_type, curr_assignments)) in prev.iter().zip(curr) - { - if prev_type != curr_type { - return Err(HandlerError::NonEqualTypes); - } - if prev_assignments.len() != curr_assignments.len() { - return Err(HandlerError::NonEqualAssignmentCount); - } - } - - Ok(()) - } -} - -/// Embedded action handlers for state assignments processed by the embedded -/// state machine -mod assignment { - use super::*; - - pub fn validate( - node_subtype: NodeSubtype, - owned_rights_type: schema::OwnedRightType, - previous_state: &TypedAssignments, - current_state: &TypedAssignments, - _current_meta: &Metadata, - ) -> Result<(), HandlerError> { - match (node_subtype, owned_rights_type) { - ( - NodeSubtype::StateTransition(TRANSITION_TYPE_VALUE_TRANSFER), - STATE_TYPE_OWNERSHIP_RIGHT, - ) => validate_pedersen_sum(previous_state, current_state), - ( - NodeSubtype::StateTransition(TRANSITION_TYPE_ISSUE_FUNGIBLE) | NodeSubtype::Genesis, - STATE_TYPE_INFLATION_RIGHT, - ) => validate_no_overflow(current_state), - _ => Ok(()), - } - } - - /// Non-inflationary fungible asset transfer control - /// - /// Checks that the sum of pedersen commitments in the inputs of type - /// [`crate::schema::constants::STATE_TYPE_OWNED_AMOUNT`] equal to the sum - /// of the outputs of the same type, plus validates bulletproof data - fn validate_pedersen_sum( - previous_state: &TypedAssignments, - current_state: &TypedAssignments, - ) -> Result<(), HandlerError> { - let inputs = previous_state - .to_confidential_state_pedersen() - .into_iter() - .map(|v| v.commitment) - .collect(); - let outputs = current_state - .to_confidential_state_pedersen() - .into_iter() - .map(|v| v.commitment) - .collect(); - - // [CONSENSUS-CRITICAL]: - // [SECURITY-CRITICAL]: Validation of the absence of inflation of the - // asset - // NB: Bulletproofs are validated by the schema for all state which - // contains bulletproof data - if !value::Confidential::verify_commit_sum(inputs, outputs) { - Err(HandlerError::Inflation) - } else { - Ok(()) - } - } - - /// Control that multiple rights assigning additive state value do not allow - /// maximum allowed bit dimensionality - fn validate_no_overflow(current_state: &TypedAssignments) -> Result<(), HandlerError> { - current_state - .as_revealed_state_values() - .map_err(|_| HandlerError::ConfidentialState)? - .into_iter() - .map(|v| v.value) - .try_fold(0u64, |sum, value| sum.checked_add(value)) - .ok_or(HandlerError::ValueOverflow) - .map(|_| ()) - } -} - -mod meta { - use super::*; - use crate::data; - use crate::schema::FieldType; - - /// Validates that field value is withing the allowed ranges. - pub fn validate(field_type: FieldType, value: &data::Revealed) -> Result<(), HandlerError> { - match (field_type, value) { - (FIELD_TYPE_TICKER, data::Revealed::AsciiString(s)) - if s.is_empty() || s.len() > 8 || s.to_ascii_uppercase() != s.to_string() => - { - Err(HandlerError::FieldValue) - } - (FIELD_TYPE_NAME, data::Revealed::AsciiString(s)) if s.is_empty() || s.len() > 256 => { - Err(HandlerError::FieldValue) - } - (FIELD_TYPE_PRECISION, data::Revealed::U8(s)) if *s > 18 => { - Err(HandlerError::FieldValue) - } - (FIELD_TYPE_TIMESTAMP, data::Revealed::I64(s)) if *s < 1602340666 => { - Err(HandlerError::FieldValue) - } - (_, _) => Ok(()), - } - } -} - -#[derive(Debug, Default)] -pub struct EmbeddedVm; - -impl EmbeddedVm { - pub fn new() -> EmbeddedVm { EmbeddedVm } -} - -impl Validate for EmbeddedVm { - fn validate( - &self, - node_id: NodeId, - node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - previous_public_rights: &PublicRights, - current_public_rights: &PublicRights, - current_meta: &Metadata, - ) -> Result<(), validation::Failure> { - node::validate( - node_subtype, - previous_owned_rights, - current_owned_rights, - previous_public_rights, - current_public_rights, - current_meta, - ) - .map_err(|_| validation::Failure::ScriptFailure(node_id))?; - - for (state_type, current_state) in current_owned_rights.iter() { - let previous_state = previous_owned_rights.assignments_by_type(*state_type); - assignment::validate( - node_subtype, - *state_type, - previous_state, - current_state, - current_meta, - ) - .map_err(|_| validation::Failure::ScriptFailure(node_id))?; - } - - Ok(()) - } -} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 0c577030..e3ab0707 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -26,51 +26,3 @@ // pub mod embedded; pub mod alure; - -// pub use embedded::EmbeddedVm; - -use crate::{ - validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, ValidationScript, -}; - -/// Trait for concrete types wrapping virtual machines to be used from inside -/// RGB schema validation routines. -pub trait Validate { - /// Validates state change in a contract node. - #[allow(clippy::too_many_arguments)] - fn validate( - &self, - node_id: NodeId, - node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - previous_public_rights: &PublicRights, - current_public_rights: &PublicRights, - current_meta: &Metadata, - ) -> Result<(), validation::Failure>; -} - -impl Validate for ValidationScript { - fn validate( - &self, - node_id: NodeId, - node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - previous_public_rights: &PublicRights, - current_public_rights: &PublicRights, - current_meta: &Metadata, - ) -> Result<(), validation::Failure> { - match self { - ValidationScript::AluVM(script) => alure::Runtime::new(script).validate( - node_id, - node_subtype, - previous_owned_rights, - current_owned_rights, - previous_public_rights, - current_public_rights, - current_meta, - ), - } - } -} From 9dc14b2c2e8948c52333afd084171636ecef78e5 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 02:54:17 +0100 Subject: [PATCH 34/71] vm: enable back main types --- src/lib.rs | 11 +++++------ src/schema/mod.rs | 2 +- src/schema/schema.rs | 6 +++--- src/schema/script.rs | 10 +++++----- src/vm/alure.rs | 11 +++-------- 5 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fe7305f2..a4e27107 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,7 +61,7 @@ pub mod prelude { };*/ pub use schema::{ ExtensionSchema, ExtensionType, NodeSubtype, NodeType, PublicRightType, - PublicRightsStructure, Schema, SchemaId, ValidationScript, VmType, + PublicRightsStructure, Schema, SchemaId, Scripts, VmType, }; pub use super::schema; @@ -69,11 +69,10 @@ pub mod prelude { bundle, AnchoredBundle, BundleId, ConcealAnchors, ConcealTransitions, Consignment, ConsignmentEndpoint, ConsistencyError, GraphApi, Stash, TransitionBundle, }; - pub use validation::{Validator, Validity}; - pub use vm::Validate; - - pub use super::{vm}; - use super::*;*/ + pub use validation::{Validator, Validity, Validate}; + */ + pub use super::vm; + // use super::*; } pub use prelude::*; diff --git a/src/schema/mod.rs b/src/schema/mod.rs index fc433f38..59c2be1f 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -33,5 +33,5 @@ pub use nodes::{ }; pub use occurrences::{Occurrences, OccurrencesMismatch}; pub use schema::{ExtensionType, FieldType, Schema, SchemaId, TransitionType}; -pub use script::{ValidationScript, VmType}; +pub use script::{Scripts, VmType}; pub use state::{DiscreteFiniteFieldFormat, StateSchema}; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 3a3c7c88..bae5d1e1 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -35,8 +35,8 @@ use strict_encoding::{ use strict_types::SemId; use super::{ - ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, StateSchema, TransitionSchema, - ValidationScript, + ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, Scripts, StateSchema, + TransitionSchema, }; use crate::LIB_NAME_RGB; @@ -101,7 +101,7 @@ pub struct Schema { /// Type system pub type_system: MediumVec, // TODO: TypeSystem, /// Validation code. - pub script: ValidationScript, + pub script: Scripts, } impl PartialEq for Schema { diff --git a/src/schema/script.rs b/src/schema/script.rs index a07d1468..ace7a5d3 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -43,7 +43,7 @@ pub enum VmType { #[derive(StrictType, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB, tags = order)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub enum ValidationScript { +pub enum Scripts { /// AluVM: pure functional register-based virtual machine designed for RGB /// and multiparty computing. /// @@ -56,14 +56,14 @@ pub enum ValidationScript { AluVM(MediumVec), } -impl Default for ValidationScript { - fn default() -> Self { ValidationScript::AluVM(none!()) } +impl Default for Scripts { + fn default() -> Self { Scripts::AluVM(none!()) } } -impl ValidationScript { +impl Scripts { pub fn vm_type(&self) -> VmType { match self { - ValidationScript::AluVM(_) => VmType::AluVM, + Scripts::AluVM(_) => VmType::AluVM, } } } diff --git a/src/vm/alure.rs b/src/vm/alure.rs index 8ef1f6af..214468ca 100644 --- a/src/vm/alure.rs +++ b/src/vm/alure.rs @@ -22,17 +22,13 @@ #![allow(clippy::unusual_byte_groupings)] -/* use std::collections::BTreeSet; use std::ops::RangeInclusive; use aluvm::isa::{Bytecode, BytecodeError, ExecStep, InstructionSet}; use aluvm::program::{CodeEofError, LibSite, Read, Write}; use aluvm::reg::CoreRegs; -use aluvm::Vm; - */ -/* pub const INSTR_NOOP: u8 = 0b11_000_000; pub const INSTR_ISAE_FROM: u8 = 0b11_000_000; pub const INSTR_ISAE_TO: u8 = 0b11_000_000; @@ -87,15 +83,14 @@ impl Bytecode for RgbIsa { }) } } -*/ -pub type ValidationScript = Vec; // aluvm::Program; +pub type AluLib = aluvm::Program; pub struct Runtime<'script> { #[allow(dead_code)] - script: &'script ValidationScript, + lib: &'script AluLib, } impl<'script> Runtime<'script> { - pub fn new(script: &'script ValidationScript) -> Self { Runtime { script } } + pub fn new(lib: &'script AluLib) -> Self { Runtime { lib } } } From e1a64856b3bea49c454f88c8db5498aff017badc Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 12:32:24 +0100 Subject: [PATCH 35/71] contract: refactor seals and conceal modules --- Cargo.lock | 24 +++--- Cargo.toml | 4 + doc/seals.md | 24 ++++++ src/contract/conceal.rs | 110 ++++++++++-------------- src/contract/data.rs | 180 --------------------------------------- src/contract/mod.rs | 49 ++++++----- src/contract/seal.rs | 181 +++++++++++++++++++++++----------------- src/lib.rs | 2 +- 8 files changed, 217 insertions(+), 357 deletions(-) create mode 100644 doc/seals.md diff --git a/Cargo.lock b/Cargo.lock index 2d84b266..1f0f36b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,9 +20,9 @@ dependencies = [ [[package]] name = "amplify" -version = "4.0.0-beta.13" +version = "4.0.0-beta.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4030ef5731f8cab39af812fc4df7a29b2a46bd40fe5dd5b903865a27368e85" +checksum = "a2cc2aa6bd36c9cd67fdebb50adf4ec4551ef58420a5700227e2bde5e64384d9" dependencies = [ "amplify_apfloat", "amplify_derive", @@ -196,8 +196,7 @@ dependencies = [ [[package]] name = "bp-core" version = "0.10.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75939aecb6e7ad3e30622d8fba00ccdf3cdc78f2325840629ee53cd792548be9" +source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" dependencies = [ "amplify", "bp-dbc", @@ -212,8 +211,7 @@ dependencies = [ [[package]] name = "bp-dbc" version = "0.10.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67f8173cc60f6671df19a170021a4f3a179f828b2114ba0415124dd8abd07f" +source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" dependencies = [ "amplify", "bp-primitives", @@ -226,8 +224,7 @@ dependencies = [ [[package]] name = "bp-primitives" version = "0.10.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aab03dbc8e2cf19594d3a267cccfc0fd2595ce0818babf39b9e817cb7683e1e4" +source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" dependencies = [ "amplify", "commit_verify", @@ -239,8 +236,7 @@ dependencies = [ [[package]] name = "bp-seals" version = "0.10.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463f314e2c6370104c40356fc96cd464bd0f02aba1a2ffd83dc524e4ecf58d41" +source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" dependencies = [ "amplify", "baid58", @@ -248,6 +244,7 @@ dependencies = [ "bp-primitives", "commit_verify", "rand", + "serde", "single_use_seals", "strict_encoding", ] @@ -302,8 +299,7 @@ dependencies = [ [[package]] name = "commit_verify" version = "0.10.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ce27ce9d56cac2631f9701984dc4fd162abbd7b563d97e4440db56f7282cc9" +source = "git+https://github.com/LNP-BP/client_side_validation#54332543981486178dd6536a5b1ace50cf20ac71" dependencies = [ "amplify", "bitcoin_hashes", @@ -818,9 +814,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a" dependencies = [ "itoa", "ryu", diff --git a/Cargo.toml b/Cargo.toml index e3daa7cf..c7dac849 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,3 +43,7 @@ serde = [ [package.metadata.docs.rs] features = [ "all" ] + +[patch.crates-io] +bp-core = { git = "https://github.com/BP-WG/bp-core" } +commit_verify = { git = "https://github.com/LNP-BP/client_side_validation" } diff --git a/doc/seals.md b/doc/seals.md new file mode 100644 index 00000000..2d6bcb9b --- /dev/null +++ b/doc/seals.md @@ -0,0 +1,24 @@ +# Single-use-seal API specific for RGB implementation + +Based on LNP/BP client-side-validation single-use-seals API (see +[`lnpbp::seals`]). RGB single-use-seal implementation differs in the fact +that seals are organized into a graph; thus a seal may be defined as +pointing witness transaction closing some other seal, which is meaningless +with LNP/BP seals. + +Single-use-seals in RGB are used for holding assigned state, i.e. *state* + +*seal definition* = *assignment*. Closing of the single-use-seal invalidates +the assigned state. + +Single-use-seals in RGB can have multiple forms because of the +confidentiality options and ability to be linked to the witness transaction +closing previous seal in RGB state evolution graph. + +| **Type name** | **Lib** | **Txid** | **Blinding** | **Confidential** | **String serialization** | **Use case** | +| ----------------- | -------- | --------- | ------------ | ---------------- | --------------------------------------- | ------------- | +| [`Outpoint`] | BP Core | Required | No | No | `:` | Genesis | +| [`RevealedSeal`] | BP Core | Required | Yes | No | `:<|~>:#` | Stash | +| [`ConcealedSeal`] | BP Core | Unknown | Implicit | Yes | `txob:#` | Ext. payments | +| [`ExplicitSeal`] | BP Core | Optional | Yes | No | `:<|~>:` | Internal | +| [`VoutSeal`] | RGB Core | Absent | Yes | No | `:~:#` | SealEndpoint | +| [`SealEndpoint`] | RGB Core | Optional | Varies | Could be | `|` | Consignments | diff --git a/src/contract/conceal.rs b/src/contract/conceal.rs index ccbe58d7..dc8946e9 100644 --- a/src/contract/conceal.rs +++ b/src/contract/conceal.rs @@ -21,20 +21,46 @@ // limitations under the License. use core::cmp::Ord; -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet}; +use std::hash::Hash; + +use amplify::confinement::{Collection, Confined}; use super::seal; +/// Trait which must be implemented by all data structures having seals in their +/// hierarchy. pub trait ConcealSeals { + /// Request to conceal all seals from a given subset of seals. + /// + /// # Returns + /// + /// Number of seals instances which were concealed. fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize; } +/// Trait which must be implemented by all data structures having state data. pub trait ConcealState { + /// Request to conceal all state. + /// + /// # Returns + /// + /// Count of state atoms which were concealed. fn conceal_state(&mut self) -> usize { self.conceal_state_except(&[]) } + + /// Request to conceal all of the state except given subset. + /// + /// The function doesn't requires that the state from the subset should + /// be a revealed state; if the state atom is concealed than it is just + /// ignored. + /// + /// # Returns + /// + /// Count of state atoms which were concealed. fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize; } -impl ConcealSeals for Vec +impl ConcealSeals for Confined, MIN, MAX> where T: ConcealSeals { fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { @@ -43,57 +69,34 @@ where T: ConcealSeals } } -impl ConcealSeals for BTreeSet +impl ConcealSeals for Confined, MIN, MAX> where T: ConcealSeals + Ord + Clone { fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; - let mut new_self = BTreeSet::::new(); - for item in self.iter() { - let mut new_item = item.clone(); - count += new_item.conceal_seals(seals); - new_self.insert(new_item); - } - *self = new_self; - count - } -} - -impl ConcealSeals for BTreeMap -where V: ConcealSeals -{ - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - self.iter_mut() - .fold(0usize, |sum, item| sum + item.1.conceal_seals(seals)) - } -} - -impl ConcealSeals for HashSet -where T: ConcealSeals + Ord + Clone + std::hash::Hash -{ - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - let mut new_self = HashSet::::new(); + let mut new_self = BTreeSet::::with_capacity(self.len()); for item in self.iter() { let mut new_item = item.clone(); count += new_item.conceal_seals(seals); new_self.insert(new_item); } - *self = new_self; + *self = Confined::try_from(new_self).expect("same size"); count } } -impl ConcealSeals for HashMap -where V: ConcealSeals +impl ConcealSeals for Confined, MIN, MAX> +where + K: Ord + Hash, + V: ConcealSeals, { fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - self.iter_mut() + self.keyed_values_mut() .fold(0usize, |sum, item| sum + item.1.conceal_seals(seals)) } } -impl ConcealState for Vec +impl ConcealState for Confined, MIN, MAX> where T: ConcealState { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { @@ -102,52 +105,29 @@ where T: ConcealState } } -impl ConcealState for BTreeSet +impl ConcealState for Confined, MIN, MAX> where T: ConcealState + Ord + Clone { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; - let mut new_self = BTreeSet::::new(); + let mut new_self = BTreeSet::::with_capacity(self.len()); for item in self.iter() { let mut new_item = item.clone(); count += new_item.conceal_state_except(seals); new_self.insert(new_item); } - *self = new_self; + *self = Confined::try_from(new_self).expect("same size"); count } } -impl ConcealState for BTreeMap -where V: ConcealState +impl ConcealState for Confined, MIN, MAX> +where + K: Ord + Hash, + V: ConcealState, { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - self.iter_mut() - .fold(0usize, |sum, item| sum + item.1.conceal_state_except(seals)) - } -} - -impl ConcealState for HashSet -where T: ConcealState + Ord + Clone + std::hash::Hash -{ - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - let mut new_self = HashSet::::new(); - for item in self.iter() { - let mut new_item = item.clone(); - count += new_item.conceal_state_except(seals); - new_self.insert(new_item); - } - *self = new_self; - count - } -} - -impl ConcealState for HashMap -where V: ConcealState -{ - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - self.iter_mut() + self.keyed_values_mut() .fold(0usize, |sum, item| sum + item.1.conceal_state_except(seals)) } } diff --git a/src/contract/data.rs b/src/contract/data.rs index 5b64139f..ad0e8479 100644 --- a/src/contract/data.rs +++ b/src/contract/data.rs @@ -20,8 +20,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![allow(clippy::unnecessary_cast)] - use core::any::Any; use core::fmt::Debug; use std::io; @@ -47,9 +45,6 @@ impl CommitConceal for Void { fn commit_conceal(&self) -> Self::ConcealedCommitment { self.clone() } } -impl CommitEncode for Void { - fn commit_encode(&self, _e: E) -> usize { 0 } -} #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, AsAny)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] @@ -70,23 +65,6 @@ impl commit_encode::Strategy for Revealed { type Strategy = commit_encode::strategies::UsingConceal; } -// "rgb:data:confidential" -static MIDSTATE_CONFIDENTIAL_DATA: [u8; 32] = [ - 151, 235, 12, 105, 100, 154, 61, 159, 108, 179, 41, 229, 218, 159, 57, 12, 233, 248, 167, 213, - 228, 9, 202, 215, 27, 84, 249, 215, 93, 189, 75, 146, -]; - -/// Tag used for [`Confidential`] hash value of the data -pub struct ConfidentialTag; - -impl sha256t::Tag for ConfidentialTag { - #[inline] - fn engine() -> sha256::HashEngine { - let midstate = sha256::Midstate::from_inner(MIDSTATE_CONFIDENTIAL_DATA); - sha256::HashEngine::from_midstate(midstate, 64) - } -} - /// Blind version of transaction outpoint-based single-use-seal #[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] @@ -102,161 +80,3 @@ impl ConfidentialState for Confidential {} impl AsAny for Confidential { fn as_any(&self) -> &dyn Any { self as &dyn Any } } - -#[cfg(test)] -mod test { - use amplify::Wrapper; - use commit_verify::tagged_hash; - - use super::super::test::test_confidential; - use super::*; - - // Hard coded test vectors - static U_8: [u8; 2] = [0x0, 0x8]; - static U_16: [u8; 3] = [0x1, 0x10, 0x0]; - static U_32: [u8; 5] = [0x2, 0x20, 0x0, 0x0, 0x0]; - static U_64: [u8; 9] = [0x3, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]; - static I_8: [u8; 2] = [0x8, 0x8]; - static I_16: [u8; 3] = [0x9, 0x10, 0x0]; - static I_32: [u8; 5] = [0xa, 0x20, 0x0, 0x0, 0x0]; - static I_64: [u8; 9] = [0xb, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]; - static F_32: [u8; 5] = [0x12, 0x14, 0xae, 0x2, 0x42]; - static F_64: [u8; 9] = [0x13, 0x7b, 0x14, 0xae, 0x47, 0xe1, 0x2a, 0x50, 0x40]; - static BYTES: [u8; 36] = [ - 0x20, 0x21, 0x0, 0x7c, 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0xe, 0x29, 0xce, 0x32, - 0x5a, 0xf, 0x46, 0x79, 0xef, 0x87, 0x28, 0x8e, 0xd7, 0x3c, 0xe4, 0x7f, 0xc4, 0xf5, 0xc7, - 0x9d, 0x19, 0xeb, 0xfa, 0x57, 0xda, - ]; - static STRING: [u8; 20] = [ - 0x21, 0x11, 0x0, 0x45, 0x54, 0x48, 0x20, 0x49, 0x53, 0x20, 0x41, 0x20, 0x53, 0x45, 0x43, - 0x55, 0x52, 0x49, 0x54, 0x59, - ]; - - static U8_CONCEALED: [u8; 32] = [ - 161, 96, 17, 80, 21, 40, 216, 159, 16, 118, 181, 5, 129, 1, 104, 13, 140, 180, 187, 73, - 167, 191, 192, 20, 193, 188, 208, 129, 106, 33, 92, 39, - ]; - static U16_CONCEALED: [u8; 32] = [ - 80, 54, 157, 249, 250, 32, 49, 160, 128, 1, 178, 23, 207, 113, 37, 140, 67, 7, 13, 62, 216, - 70, 81, 20, 180, 35, 104, 112, 98, 181, 18, 102, - ]; - static U32_CONCEALED: [u8; 32] = [ - 121, 102, 29, 211, 144, 20, 177, 201, 217, 150, 2, 207, 78, 113, 204, 38, 38, 105, 164, 68, - 227, 224, 14, 236, 77, 60, 101, 225, 174, 12, 230, 161, - ]; - static U64_CONCEALED: [u8; 32] = [ - 80, 99, 180, 211, 149, 79, 160, 168, 50, 150, 54, 190, 65, 240, 179, 156, 212, 5, 211, 72, - 82, 27, 87, 184, 156, 76, 44, 148, 102, 137, 212, 28, - ]; - static I8_CONCEALED: [u8; 20] = [ - 0xf5, 0x39, 0x1f, 0xf2, 0x83, 0x2b, 0xc6, 0xb1, 0x78, 0x59, 0x54, 0x14, 0x28, 0xbf, 0xc1, - 0x49, 0xf6, 0xcf, 0xd7, 0x78, - ]; - static I16_CONCEALED: [u8; 20] = [ - 0x61, 0x0, 0xc2, 0x37, 0x7, 0x97, 0x33, 0xf, 0xcf, 0xbb, 0x40, 0xcb, 0xad, 0xf7, 0x81, - 0x7e, 0x10, 0xd, 0x55, 0xa5, - ]; - static I32_CONCEALED: [u8; 20] = [ - 0xaa, 0xbe, 0x9b, 0x73, 0xf8, 0xfa, 0x84, 0x9d, 0x28, 0x79, 0x8b, 0x5c, 0x13, 0x91, 0xe9, - 0xbf, 0xc8, 0xa4, 0x2a, 0xc3, - ]; - static I64_CONCEALED: [u8; 20] = [ - 0xd, 0x56, 0xef, 0xcb, 0x53, 0xba, 0xd5, 0x52, 0xb, 0xc6, 0xea, 0x4f, 0xe1, 0xa8, 0x56, - 0x42, 0x3d, 0x66, 0x34, 0xc5, - ]; - static F32_CONCEALED: [u8; 20] = [ - 0xa2, 0xb0, 0x80, 0x82, 0xa9, 0x52, 0xa5, 0x41, 0xb8, 0xbd, 0x2, 0xd4, 0x29, 0xf0, 0x90, - 0xca, 0x8b, 0xa4, 0x5d, 0xfc, - ]; - static F64_CONCEALED: [u8; 20] = [ - 0x5f, 0xe8, 0xdd, 0xd4, 0xca, 0x55, 0x41, 0x14, 0x50, 0x24, 0xcf, 0x85, 0x8c, 0xb4, 0x11, - 0x5d, 0x9f, 0x8a, 0xaf, 0x87, - ]; - static BYTES_CONCEALED: [u8; 20] = [ - 0xf, 0x33, 0xe5, 0xdf, 0x8, 0x7c, 0x5c, 0xef, 0x5f, 0xae, 0xbe, 0x76, 0x76, 0xd9, 0xe7, - 0xa6, 0xb8, 0x2b, 0x4a, 0x99, - ]; - static STRING_CONCEALED: [u8; 20] = [ - 0xf8, 0x3b, 0x1b, 0xcd, 0xd8, 0x82, 0x55, 0xe1, 0xf9, 0x37, 0x52, 0xeb, 0x20, 0x90, 0xfe, - 0xa9, 0x14, 0x4f, 0x8a, 0xe1, - ]; - - #[test] - fn test_confidential_midstate() { - let midstate = tagged_hash::Midstate::with(b"rgb:data:confidential"); - assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_CONFIDENTIAL_DATA); - } - - // Normal encode/decode testing - /* - #[test] - #[ignore] - fn test_encoding() { - test_encode!( - (U_8, Revealed), - (U_16, Revealed), - (U_32, Revealed), - (U_64, Revealed), - (I_8, Revealed), - (I_16, Revealed), - (I_32, Revealed), - (I_64, Revealed), - (F_32, Revealed), - (F_64, Revealed), - (BYTES, Revealed), - (STRING, Revealed) - ); - } - - // Garbage data encode/decode testing - #[test] - #[ignore] - fn test_garbage() { - let err = "Revealed"; - test_garbage_exhaustive!(150..255; - (U_8, Revealed, err), - (U_16, Revealed, err), - (U_32, Revealed, err), - (U_64, Revealed, err), - (I_8, Revealed, err), - (I_16, Revealed, err), - (I_32, Revealed, err), - (I_64, Revealed, err), - (F_32, Revealed, err), - (F_64, Revealed, err), - (BYTES, Revealed, err), - (STRING, Revealed, err) - ); - } - */ - - #[test] - #[ignore] - fn test_conf1() { - macro_rules! test_confidential { - ($(($revealed:ident, $conf:ident, $T:ty)),*) => ( - { - $( - test_confidential::<$T>(&$revealed[..], &$conf[..], &$conf[..]); - )* - } - ); - } - - test_confidential!( - (U_8, U8_CONCEALED, Revealed), - (U_16, U16_CONCEALED, Revealed), - (U_32, U32_CONCEALED, Revealed), - (U_64, U64_CONCEALED, Revealed), - (I_8, I8_CONCEALED, Revealed), - (I_16, I16_CONCEALED, Revealed), - (I_32, I32_CONCEALED, Revealed), - (I_64, I64_CONCEALED, Revealed), - (F_32, F32_CONCEALED, Revealed), - (F_64, F64_CONCEALED, Revealed), - (F_64, F64_CONCEALED, Revealed), - (BYTES, BYTES_CONCEALED, Revealed), - (STRING, STRING_CONCEALED, Revealed) - ); - } -} diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 9783dd61..e9898aa8 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -20,55 +20,60 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod assignments; -#[macro_use] -pub mod data; -mod conceal; -mod metadata; -pub mod nodes; -pub mod reveal; -mod rights; pub mod seal; -pub mod value; -pub mod attachment; -pub(self) use assignments::EMPTY_ASSIGNMENTS; +mod conceal; +// pub mod reveal; + +// #[macro_use] +// pub mod data; +// mod assignments; +// mod metadata; +// pub mod nodes; +// mod rights; +// pub mod value; +// pub mod attachment; + +pub use conceal::{ConcealSeals, ConcealState}; +// pub use reveal::{MergeReveal, RevealSeals}; + +/*pub(self) use assignments::EMPTY_ASSIGNMENTS; pub use assignments::{ Assignment, AttachmentStrategy, ConfidentialState, DeclarativeStrategy, EndpointValueMap, HashStrategy, PedersenStrategy, RevealedState, SealValueMap, State, StateType, TypedAssignments, }; pub use attachment::AttachmentId; -pub use conceal::{ConcealSeals, ConcealState}; pub use metadata::Metadata; pub use nodes::{ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, Transition}; -pub use reveal::{MergeReveal, RevealSeals}; pub use rights::{OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights}; pub(crate) use rights::{OwnedRightsInner, PublicRightsInner}; pub use seal::{IntoRevealedSeal, SealEndpoint}; pub use value::{AtomicValue, Bulletproofs}; +*/ -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error, From)] +/// Errors retrieving state data. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error, From)] #[display(doc_comments)] pub enum StateRetrievalError { - /// The requested state has a mismatched data type + /// the requested state has a mismatched data type. StateTypeMismatch, - /// Some of the requested data are confidential, when they must be present - /// in revealed form + /// some of the requested data are confidential, when they must be present + /// in revealed form. #[from(ConfidentialDataError)] ConfidentialData, } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error)] #[display(doc_comments)] -/// The requested data are not present +/// the requested data are not present. pub struct NoDataError; -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error)] #[display(doc_comments)] -/// Some of the requested data are confidential, when they must be present in -/// revealed form +/// some of the requested data are confidential, when they must be present in +/// revealed form. pub struct ConfidentialDataError; #[cfg(test)] diff --git a/src/contract/seal.rs b/src/contract/seal.rs index 4161bb25..9fc3d0f5 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -20,38 +20,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Single-use-seal API specific for RGB implementation -//! -//! Based on LNP/BP client-side-validation single-use-seals API (see -//! [`lnpbp::seals`]). RGB single-use-seal implementation differs in the fact -//! that seals are organized into a graph; thus a seal may be defined as -//! pointing witness transaction closing some other seal, which is meaningless -//! with LNP/BP seals. -//! -//! Single-use-seals in RGB are used for holding assigned state, i.e. *state* + -//! *seal definition* = *assignment*. Closing of the single-use-seal invalidates -//! the assigned state. -//! -//! Single-use-seals in RGB can have multiple forms because of the -//! confidentiality options and ability to be linked to the witness transaction -//! closing previous seal in RGB state evolution graph. -//! -//! | **Type name** | **Lib** | **Witness vout** | **Blinding** | -//! **Confidential** | **String serialization** | **Use case** -//! | | ------------------ | ------- | ----------- | -------------------- | -//! ---------------- | ------------------------------------- | -//! --------------------------------- | | [`Outpoint`] | Bitcoin | No -//! | No | No | `:` -//! | Genesis control rights | | [`RevealedSeal`] | BP Core | No -//! | Yes | No | -//! `:|~:#` | Stash | -//! | [`ConcealedSeal`] | BP Core | Implicit? | Implicit | Yes -//! | `txob1...` | External payments -//! | | [`ExplicitSeal`] | BP Core | Yes | Yes | No -//! | `:|~:` | Internal -//! | | [`SealEndpoint`] | RGB | Yes | Explicit or implicit | -//! Could be | `txob1...|:~:#blinding` | Consignments -//! | +#![doc = include_str!("../../doc/seals.md")] use std::fmt::{self, Display, Formatter}; use std::str::FromStr; @@ -59,14 +28,98 @@ use std::str::FromStr; use bp::seals::txout::blind::{ConcealedSeal, ParseError, RevealedSeal}; pub use bp::seals::txout::blind::{ConcealedSeal as Confidential, RevealedSeal as Revealed}; use bp::seals::txout::CloseMethod; +use bp::secp256k1::rand::thread_rng; +use bp::Vout; +use commit_verify::Conceal; use secp256k1_zkp::rand::RngCore; +use crate::LIB_NAME_RGB; + /// Trait for types supporting conversion to a [`RevealedSeal`] pub trait IntoRevealedSeal { /// Converts seal into [`RevealedSeal`] type. fn into_revealed_seal(self) -> RevealedSeal; } +/// Seal definition which re-uses witness transaction id of some other seal, +/// which is not known at the moment of seal construction. Thus, the definition +/// has only information about output number. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "camelCase") +)] +pub struct VoutSeal { + /// Commitment to the specific seal close method [`CloseMethod`] which must + /// be used to close this seal. + pub method: CloseMethod, + + /// Tx output number, which should be always known. + pub vout: Vout, + + /// Blinding factor providing confidentiality of the seal definition. + /// Prevents rainbow table bruteforce attack based on the existing + /// blockchain txid set. + pub blinding: u64, +} + +impl VoutSeal { + /// Creates new seal definition for the provided output number and seal + /// closing method. Uses `thread_rng` to initialize blinding factor. + #[inline] + pub fn new(method: CloseMethod, vout: impl Into) -> Self { + VoutSeal::with(method, vout, thread_rng().next_u64()) + } + + /// Creates new opret-seal seal definition for the provided output number + /// and seal closing method. Uses `thread_rng` to initialize blinding + /// factor. + #[inline] + pub fn new_opret(vout: impl Into) -> Self { VoutSeal::new(CloseMethod::OpretFirst, vout) } + + /// Creates new tapret-seal seal definition for the provided output number + /// and seal closing method. Uses `thread_rng` to initialize blinding + /// factor. + #[inline] + pub fn new_tapret(vout: impl Into) -> Self { + VoutSeal::new(CloseMethod::TapretFirst, vout) + } + + /// Reconstructs previously defined opret seal given an output number and a + /// previously generated blinding factor. + #[inline] + pub fn with_opret(vout: impl Into, blinding: u64) -> Self { + VoutSeal::with(CloseMethod::OpretFirst, vout, blinding) + } + + /// Reconstructs previously defined tapret seal given an output number and a + /// previously generated blinding factor. + #[inline] + pub fn with_tapret(vout: impl Into, blinding: u64) -> Self { + VoutSeal::with(CloseMethod::TapretFirst, vout, blinding) + } + + /// Reconstructs previously defined seal given method, an output number and + /// a previously generated blinding factor. + #[inline] + pub fn with(method: CloseMethod, vout: impl Into, blinding: u64) -> Self { + VoutSeal { + method, + vout: vout.into(), + blinding, + } + } +} + +impl From for RevealedSeal { + fn from(seal: VoutSeal) -> Self { + RevealedSeal::with_vout(seal.method, seal.vout, seal.blinding) + } +} + /// Seal endpoint is a confidential seal which may be linked to the witness /// transaction, but does not contain information about its id. /// @@ -78,82 +131,60 @@ pub trait IntoRevealedSeal { /// Seal endpoint is required in situations where sender assigns state to the /// witness transaction output on behalf of receiver #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = { Self::ConcealedUtxo(strict_dumb!()) })] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "snake_case") + serde(crate = "serde_crate", rename_all = "camelCase") )] pub enum SealEndpoint { /// External transaction output in concealed form (see /// [`seal::Confidential`]) #[from] + #[strict_type(tag = 0)] ConcealedUtxo(ConcealedSeal), /// Seal contained within the witness transaction - WitnessVout { - method: CloseMethod, - vout: u32, - blinding: u64, - }, + #[strict_type(tag = 1)] + WitnessVout(VoutSeal), } impl From for SealEndpoint { fn from(seal: RevealedSeal) -> Self { match seal.txid { - None => SealEndpoint::WitnessVout { - method: seal.method, - vout: seal.vout, - blinding: seal.blinding, - }, - Some(_) => SealEndpoint::ConcealedUtxo(seal.commit_conceal()), + None => { + SealEndpoint::WitnessVout(VoutSeal::with(seal.method, seal.vout, seal.blinding)) + } + Some(_) => SealEndpoint::ConcealedUtxo(seal.conceal()), } } } impl SealEndpoint { - /// Constructs [`SealEndpoint`] for the witness transaction output using - /// provided random number generator for creating blinding factor - pub fn with(method: CloseMethod, vout: u32, rng: &mut impl RngCore) -> SealEndpoint { - SealEndpoint::WitnessVout { - method, - vout, - blinding: rng.next_u64(), - } + /// Constructs [`SealEndpoint`] for the witness transaction. Uses + /// `thread_rng` to initialize blinding factor. + pub fn new_vout(method: CloseMethod, vout: impl Into) -> SealEndpoint { + SealEndpoint::WitnessVout(VoutSeal::new(method, vout)) } } -impl CommitConceal for SealEndpoint { - type ConcealedCommitment = Confidential; +impl Conceal for SealEndpoint { + type Concealed = Confidential; - fn commit_conceal(&self) -> Self::ConcealedCommitment { + fn conceal(&self) -> Self::Concealed { match *self { SealEndpoint::ConcealedUtxo(hash) => hash, - SealEndpoint::WitnessVout { - method, - vout, - blinding, - } => RevealedSeal { - method, - txid: None, - vout, - blinding, - } - .commit_conceal(), + SealEndpoint::WitnessVout(seal) => RevealedSeal::from(seal).conceal(), } } } impl Display for SealEndpoint { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - SealEndpoint::ConcealedUtxo(seal) => Display::fmt(seal, f), - SealEndpoint::WitnessVout { - method, - vout, - blinding, - } => { - write!(f, "{}:~:{}#{}", method, vout, blinding) - } + match *self { + SealEndpoint::ConcealedUtxo(ref seal) => Display::fmt(seal, f), + SealEndpoint::WitnessVout(seal) => Display::fmt(&RevealedSeal::from(seal), f), } } } diff --git a/src/lib.rs b/src/lib.rs index a4e27107..81af252d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,7 @@ extern crate strict_encoding; #[macro_use] extern crate serde_crate as serde; -// pub mod contract; +pub mod contract; pub mod schema; // pub mod stash; // pub mod validation; From 359e699a965d0df0ed3ac1e6afc35253a58d0e68 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 14:47:59 +0100 Subject: [PATCH 36/71] contract: refactor additive values module --- Cargo.lock | 5 +- Cargo.toml | 6 +- src/contract/assignments.rs | 15 +- src/contract/mod.rs | 19 +- src/contract/value.rs | 398 ++++++++++++++++++++++-------------- src/schema/state.rs | 3 +- 6 files changed, 270 insertions(+), 176 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f0f36b6..b5c254f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -739,6 +739,7 @@ checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ "rand", "secp256k1-sys 0.6.1", + "serde", ] [[package]] @@ -885,9 +886,9 @@ dependencies = [ [[package]] name = "strict_encoding" -version = "2.0.0-beta.5" +version = "2.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ce22c5bba8139f2182001358188f145b40b177a9a442545cf15574335fba88" +checksum = "f0e6e5cd3593dc19835c8caa34db3400ac2e69a6044f1086b5802b2bd51e1067" dependencies = [ "amplify", "half", diff --git a/Cargo.toml b/Cargo.toml index c7dac849..48380d3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,12 +18,12 @@ name = "rgb" [dependencies] amplify = "~4.0.0-beta.13" -strict_encoding = "2.0.0-beta.5" +strict_encoding = "2.0.0-rc.1" strict_types = "1.0.0-beta.3" aluvm = "0.10.0-alpha.1" commit_verify = { version = "~0.10.0-beta.2", features = ["rand"] } bp-core = { version = "~0.10.0-beta.1" } -secp256k1-zkp = { version = "~0.7.0", features = ["rand-std", "global-context"] } +secp256k1-zkp = { version = "~0.7.0", features = ["use-rand", "rand-std", "global-context"] } baid58 = "~0.1.0" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } @@ -38,7 +38,7 @@ serde = [ "commit_verify/serde", "bp-core/serde", "aluvm/serde", - "secp256k1-zkp/serde" + "secp256k1-zkp/use-serde" ] [package.metadata.docs.rs] diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index e79c1af8..0516245c 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -719,10 +719,6 @@ impl ConcealState for TypedAssignments { } } -pub trait ConfidentialState: Debug + Clone + AsAny {} - -pub trait RevealedState: Debug + CommitConceal + Clone + AsAny {} - pub trait State: Debug { type Confidential: ConfidentialState; type Revealed: RevealedState; @@ -1453,22 +1449,19 @@ mod test { rng.gen_range(0..=output_length), ); // Check if test passes - assert!(value::Confidential::verify_commit_sum(inputs.clone(), outputs.clone())); + assert!(value::Confidential::verify_commit_sum(&inputs, &outputs)); // Check non-equivalent amounts do not verify if input_length > 1 { assert_eq!( - value::Confidential::verify_commit_sum( - inputs[..(input_length - 1)].to_vec(), - outputs - ), + value::Confidential::verify_commit_sum(&inputs[..(input_length - 1)], &outputs), false ); } else if output_length > 1 { assert_eq!( value::Confidential::verify_commit_sum( - inputs, - outputs[..(output_length - 1)].to_vec() + &inputs, + &outputs[..(output_length - 1)] ), false ); diff --git a/src/contract/mod.rs b/src/contract/mod.rs index e9898aa8..331f1753 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -25,13 +25,13 @@ pub mod seal; mod conceal; // pub mod reveal; +pub mod value; // #[macro_use] // pub mod data; // mod assignments; // mod metadata; // pub mod nodes; // mod rights; -// pub mod value; // pub mod attachment; pub use conceal::{ConcealSeals, ConcealState}; @@ -49,8 +49,21 @@ pub use nodes::{ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, Tran pub use rights::{OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights}; pub(crate) use rights::{OwnedRightsInner, PublicRightsInner}; pub use seal::{IntoRevealedSeal, SealEndpoint}; -pub use value::{AtomicValue, Bulletproofs}; */ +pub use value::{ + BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, + ValueAtom, +}; + +/// Marker trait for types of state which are just a commitment to the actual +/// state data. +pub trait ConfidentialState: core::fmt::Debug + Clone + amplify::AsAny {} + +/// Marker trait for types of state holding explicit state data. +pub trait RevealedState: + core::fmt::Debug + commit_verify::Conceal + Clone + amplify::AsAny +{ +} /// Errors retrieving state data. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error, From)] @@ -81,6 +94,8 @@ pub(crate) mod test { use commit_verify::{CommitConceal, CommitEncode}; use strict_encoding::{StrictDecode, StrictEncode}; + pub use super::value::test_helpers::*; + pub fn test_confidential(data: &[u8], encoded: &[u8], commitment: &[u8]) where T: CommitConceal + StrictDecode + StrictEncode + Clone + CommitEncode, diff --git a/src/contract/value.rs b/src/contract/value.rs index 98592884..91ee9273 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -31,147 +31,164 @@ //! using elliptic curve homomorphic cryptography such as Pedesen commitments. use core::cmp::Ordering; +use core::fmt::Debug; +use core::str::FromStr; use std::io; -use std::str::FromStr; +use std::io::Write; +use std::num::ParseIntError; +use std::ops::Deref; // We do not import particular modules to keep aware with namespace prefixes // that we do not use the standard secp256k1zkp library -use amplify::hex::{Error, FromHex}; -use amplify::Wrapper; -use bitcoin_hashes::sha256::Midstate; -use bitcoin_hashes::{sha256, Hash}; -use commit_verify::{CommitEncode, CommitVerify, CommitmentProtocol}; +use amplify::{Array, AsAny, Bytes32, Wrapper}; +use baid58::ToBaid58; +use bp::secp256k1::rand::thread_rng; +use bp::Sha256; +use commit_verify::{CommitEncode, CommitStrategy, CommitVerify, Conceal, UntaggedProtocol}; use secp256k1_zkp::rand::{Rng, RngCore}; -use secp256k1_zkp::{PedersenCommitment, SECP256K1}; +use secp256k1_zkp::SECP256K1; +use strict_encoding::{ + DecodeError, ReadTuple, StrictDecode, StrictDumb, StrictEncode, TypedRead, TypedWrite, + WriteTuple, +}; use super::{ConfidentialState, RevealedState}; +use crate::LIB_NAME_RGB; -pub type AtomicValue = u64; +/// An atom of an additive state, which thus can be monomorphically encrypted. +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] +#[display(inner)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = custom)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename = "camelCase") +)] +pub enum ValueAtom { + /// 64-bit value. + #[from] + #[strict_type(tag = 8)] // Matches strict types U64 primitive value + Bits64(u64), + // When/if adding more variants do not forget to re-write FromStr impl +} -impl From for AtomicValue { +impl Default for ValueAtom { + fn default() -> Self { ValueAtom::Bits64(0) } +} + +impl From for ValueAtom { fn from(revealed: Revealed) -> Self { revealed.value } } -/// Proof for Pedersen commitment: a blinding key -#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] +impl FromStr for ValueAtom { + type Err = ParseIntError; + fn from_str(s: &str) -> Result { s.parse().map(ValueAtom::Bits64) } +} + +/// Blinding factor used in creating Pedersen commitment to an [`AtomicValue`]. +/// +/// Knowledge of the blinding factor is important to reproduce the commitment +/// process if the original value is kept. +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +#[display(Self::to_baid58)] +// TODO: Implement FromStr +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) + serde(crate = "serde_crate", from = "secp256k1_zkp::SecretKey") )] -#[display(LowerHex)] -#[wrapper(FromStr, LowerHex, UpperHex, BorrowSlice)] -pub struct BlindingFactor(Slice32); +pub struct BlindingFactor(Bytes32); -impl AsRef<[u8]> for BlindingFactor { - #[inline] - fn as_ref(&self) -> &[u8] { &self.0[..] } +impl Deref for BlindingFactor { + type Target = [u8; 32]; + fn deref(&self) -> &Self::Target { self.0.as_inner() } +} + +impl ToBaid58<32> for BlindingFactor { + const HRP: &'static str = "blfc"; + fn to_baid58_payload(&self) -> [u8; 32] { self.0.into_inner() } } impl From for BlindingFactor { - fn from(key: secp256k1_zkp::SecretKey) -> Self { - Self::from_inner(Slice32::from_inner(*key.as_ref())) - } + fn from(key: secp256k1_zkp::SecretKey) -> Self { Self(Bytes32::from_inner(*key.as_ref())) } } impl From for secp256k1_zkp::SecretKey { fn from(bf: BlindingFactor) -> Self { - secp256k1_zkp::SecretKey::from_slice(bf.into_inner().as_inner()) + secp256k1_zkp::SecretKey::from_slice(bf.0.as_inner()) .expect("blinding factor is an invalid secret key") } } -impl FromHex for BlindingFactor { - fn from_byte_iter(iter: I) -> Result - where I: Iterator> + ExactSizeIterator + DoubleEndedIterator { - Slice32::from_byte_iter(iter).map(BlindingFactor::from_inner) +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error)] +#[display(doc_comments)] +/// value provided for a blinding factor overflows prime field order for +/// Secp256k1 curve. +pub struct FieldOrderOverflow; + +impl TryFrom<[u8; 32]> for BlindingFactor { + type Error = FieldOrderOverflow; + + fn try_from(array: [u8; 32]) -> Result { + secp256k1_zkp::SecretKey::from_slice(&array) + .map_err(|_| FieldOrderOverflow) + .map(Self::from) } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, AsAny)] +/// State item for a homomorphically-encryptable state. +/// +/// Consists of the 64-bit value and +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[display("{value}#{blinding}")] pub struct Revealed { /// Original value in smallest indivisible units - pub value: AtomicValue, + pub value: ValueAtom, /// Blinding factor used in Pedersen commitment pub blinding: BlindingFactor, } impl Revealed { - /// Convenience constructor. - pub fn with(value: AtomicValue, blinding: impl Into) -> Self { + /// Constructs new state using the provided value and random generator for + /// creating blinding factor. + pub fn new(value: ValueAtom, rng: &mut R) -> Self { Self { value, - blinding: blinding.into(), - } - } -} - -/// Error parsing RGB revealed value from string. The string must has form of -/// `#` -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum RevealedParseError { - /// No `#` separator between value and blinding factor found while - /// parsing RGB revealed value - NoSeparator, - - /// No blinding factor is present within RGB revealed value string - /// representation - NoBlindingFactor, - - /// Extra component within RGB revealed value string representation - /// following value and blinding factor - ExtraComponent, - - /// Error parsing atomic value representation of RGB revealed value, which - /// has to be an integer - #[from(std::num::ParseIntError)] - AtomicInt, - - /// Error parsing Pedersen commitment inside RGB revealed value string - /// representation. The commitment must be a hex-encoded - #[from(amplify::hex::Error)] - PedersenHex, -} - -impl FromStr for Revealed { - type Err = RevealedParseError; - - fn from_str(s: &str) -> Result { - let mut split = s.split('#'); - match (split.next(), split.next(), split.next()) { - (Some(v), Some(b), None) => Ok(Revealed { - value: v.parse()?, - blinding: BlindingFactor::from_hex(b)?, - }), - (None, ..) => Err(RevealedParseError::NoSeparator), - (Some(_), None, _) => Err(RevealedParseError::NoBlindingFactor), - (_, _, Some(_)) => Err(RevealedParseError::ExtraComponent), + blinding: BlindingFactor::from(secp256k1_zkp::SecretKey::new(rng)), } } -} -impl Revealed { - pub fn with_amount(amount: AtomicValue, rng: &mut R) -> Self { + /// Convenience constructor. + pub fn with(value: ValueAtom, blinding: impl Into) -> Self { Self { - value: amount, - blinding: BlindingFactor::from(secp256k1_zkp::SecretKey::new(rng)), + value, + blinding: blinding.into(), } } } impl RevealedState for Revealed {} -impl CommitConceal for Revealed { - type ConcealedCommitment = Confidential; +impl Conceal for Revealed { + type Concealed = Confidential; - fn commit_conceal(&self) -> Self::ConcealedCommitment { Confidential::commit(self) } + fn conceal(&self) -> Self::Concealed { + // TODO: Remove panic upon integration of bulletproofs library + panic!( + "current version of RGB Core doesn't support production of bulletproofs. The method \ + leading to this panic must not be used for now." + ); + // Confidential::commit(self) + } } -impl commit_encode::Strategy for Revealed { - type Strategy = commit_encode::strategies::UsingConceal; +impl CommitStrategy for Revealed { + type Strategy = commit_verify::strategies::ConcealStrict; } impl PartialOrd for Revealed { @@ -193,108 +210,175 @@ impl Ord for Revealed { } } -#[derive(Clone, Debug, Eq, PartialEq, Hash, AsAny)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct Confidential { - // TODO: make fields private to provide type guarantees on the data validity - pub commitment: PedersenCommitment, - pub bulletproof: Box<[u8]>, -} - -impl ConfidentialState for Confidential {} +/// Opaque type holding pedersen commitment for an [`ValueAtom`]. +#[derive(Wrapper, Copy, Clone, Eq, PartialEq, Hash, Debug, From)] +#[wrapper(Deref, FromStr, Display, LowerHex)] +#[derive(StrictType)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct PedersenCommitment(secp256k1_zkp::PedersenCommitment); -/* -impl StrictEncode for Confidential { - fn strict_encode(&self, mut e: E) -> Result { - let len = self.bulletproof.len() as u16; - self.commitment.serialize().strict_encode(&mut e)?; - self.bulletproof.strict_encode(e)?; - Ok(len as usize + 33 + 2) +impl StrictDumb for PedersenCommitment { + fn strict_dumb() -> Self { + secp256k1_zkp::PedersenCommitment::from_slice(&[1u8; 32]) + .expect("hardcoded pedersen commitment value") + .into() } } -impl StrictDecode for Confidential { - fn strict_decode(mut d: D) -> Result { - let commitment = <[u8; 33]>::strict_decode(&mut d)?; - let commitment = PedersenCommitment::from_slice(&commitment).map_err(|_| { - strict_encoding::Error::DataIntegrityError(s!("invalid pedersen commitment data")) - })?; - let bulletproof = Box::<[u8]>::strict_decode(d)?; - Ok(Self { - commitment, - bulletproof, - }) +impl StrictEncode for PedersenCommitment { + fn strict_encode(&self, writer: W) -> io::Result { + writer.write_tuple::(|w| Ok(w.write_field(&self.0.serialize())?.complete())) } } - */ -impl CommitEncode for Confidential { - fn commit_encode(&self, mut e: E) -> usize { - // We do not commit to the bulletproof! - self.commitment.serialize().as_ref().commit_encode(&mut e) +impl StrictDecode for PedersenCommitment { + fn strict_decode(reader: &mut impl TypedRead) -> Result { + reader.read_tuple(|r| { + let commitment = r.read_field::<[u8; 33]>()?; + secp256k1_zkp::PedersenCommitment::from_slice(&commitment) + .map_err(|_| { + DecodeError::DataIntegrityError(s!("invalid pedersen commitment data")) + }) + .map(PedersenCommitment::from_inner) + }) } } -/// Commitment protocol -pub enum Bulletproofs {} - -impl CommitmentProtocol for Bulletproofs { - const HASH_TAG_MIDSTATE: Option = None; +impl CommitStrategy for PedersenCommitment { + type Strategy = commit_verify::strategies::Strict; } -impl CommitVerify for Confidential { +impl CommitVerify for PedersenCommitment { fn commit(revealed: &Revealed) -> Self { use secp256k1_zkp::{Generator, Tag, Tweak}; - // TODO: provide type-level guarantees on Revealed that the blinding - // factor is valid by making fields private and checking the value - // on deserialization let blinding = Tweak::from_inner(revealed.blinding.0.into_inner()) - .map_err(|_| BulletproofsError::InvalidBlinding(revealed.blinding)) - .expect("the provided blinding factor is faked"); - let value = revealed.value; + .expect("type guarantees of BlindingFactor are broken"); + let value = match revealed.value { + ValueAtom::Bits64(value) => value, + }; - // TODO: Check that we create a correct generator value. + // TODO: Check that we create correct generator value. let g = secp256k1_zkp::PublicKey::from_secret_key(SECP256K1, &secp256k1_zkp::ONE_KEY); - let h = sha256::Hash::hash(&g.serialize_uncompressed()); - let tag = Tag::from(h.into_inner()); + let h = Sha256::digest(&g.serialize_uncompressed()); + let tag = Tag::from(h); let generator = Generator::new_unblinded(SECP256K1, tag); - let commitment = PedersenCommitment::new(&SECP256K1, value, blinding, generator); - Confidential { - commitment, - // TODO: We can't produce valid bulletproofs today - bulletproof: Box::default(), + secp256k1_zkp::PedersenCommitment::new(&SECP256K1, value, blinding, generator).into() + } +} + +/// A dumb placeholder for a future bulletproofs. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct NoiseDumb(Array); + +impl Default for NoiseDumb { + fn default() -> Self { + let mut dumb = [0u8; 512]; + thread_rng().fill(&mut dumb); + NoiseDumb(dumb.into()) + } +} + +/// Range proof value. +/// +/// Range proofs must be used alongside [`PedersenCommitment`]s to ensure that +/// the value do not overflow on arithmetic operations with the commitments. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = custom)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +pub enum RangeProof { + /// Value used when bulletproofs library is not available. + /// + /// Always fails validation if no source value is given. + #[strict_type(tag = 0xFF)] + Placeholder(NoiseDumb), +} + +impl Default for RangeProof { + fn default() -> Self { RangeProof::Placeholder(default!()) } +} + +/// Confidential version of the additive state. +/// +/// See also revealed version [`Revealed`]. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename = "camelCase") +)] +pub struct Confidential { + /// Pedersen commitment to the original [`ValueAtom`]. + pub commitment: PedersenCommitment, + /// Range proof for the [`ValueAtom`] not exceeding type boundaries. + pub range_proof: RangeProof, +} + +impl ConfidentialState for Confidential {} + +impl Confidential { + /// Verifies bulletproof against the commitment. + pub fn verify(&self) -> bool { + match self.range_proof { + RangeProof::Placeholder(_) => false, } } } -#[derive(Copy, Clone, Debug, Display, Error)] +impl CommitEncode for Confidential { + fn commit_encode(&self, e: &mut impl Write) { + // We do not commit to the range proofs! + self.commitment.commit_encode(e) + } +} + +/// Errors verifying range proofs. +#[derive(Copy, Clone, PartialEq, Eq, Debug, Display, Error)] #[display(doc_comments)] -pub enum BulletproofsError { +pub enum RangeProofError { /// invalid blinding factor {0}. InvalidBlinding(BlindingFactor), /// bulletproofs verification is not implemented in RGB Core v0.10. Please /// update your software and try again, or ask your software producer to use /// latest RGB release. - Unimplemented, + BulletproofsAbsent, } impl Confidential { - pub fn verify_bullet_proof(&self) -> Result { - Err(BulletproofsError::Unimplemented) + /// Verifies validity of the range proof. + pub fn verify_range_proof(&self) -> Result { + Err(RangeProofError::BulletproofsAbsent) } +} + +#[cfg(test)] +pub(crate) mod test_helpers { + use super::*; - pub fn verify_commit_sum( - positive: Vec, - negative: Vec, + pub fn verify_commit_sum>( + positive: impl IntoIterator, + negative: impl IntoIterator, ) -> bool { - secp256k1_zkp::verify_commitments_sum_to_equal( - secp256k1_zkp::SECP256K1, - &positive, - &negative, - ) + let positive = positive.into_iter().map(C::into).collect::>(); + let negative = negative.into_iter().map(C::into).collect::>(); + secp256k1_zkp::verify_commitments_sum_to_equal(SECP256K1, &positive, &negative) } } @@ -360,7 +444,7 @@ mod test { assert_ne!(old_conf, new_conf); // Test confidential addition - assert!(coded_conf.verify_bullet_proof().is_ok()); + assert!(coded_conf.verify_range_proof().is_ok()); } #[test] @@ -409,8 +493,8 @@ mod test { .collect(); assert!(Confidential::verify_commit_sum( - commitments[..positive.len()].to_vec(), - commitments[positive.len()..].to_vec() + commitments[..positive.len()], + commitments[positive.len()..] )); // Create Revealed amounts with wrong positive values @@ -434,8 +518,8 @@ mod test { // Ensure commit sum verification fails for wrong positive values assert!(!Confidential::verify_commit_sum( - wrong_commitments[..positive.len()].to_vec(), - wrong_commitments[positive.len()..].to_vec() + wrong_commitments[..positive.len()], + wrong_commitments[positive.len()..] )); } diff --git a/src/schema/state.rs b/src/schema/state.rs index 04fb6f21..d95c94c5 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -20,6 +20,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use strict_encoding::constants::U64; use strict_types::SemId; use crate::LIB_NAME_RGB; @@ -58,5 +59,5 @@ pub enum StateSchema { #[repr(u8)] pub enum DiscreteFiniteFieldFormat { #[default] - Unsigned64Bit = 64, + Unsigned64Bit = U64.into_code(), } From 55ff2155b540a75e92eeac821c47d707c3bb43ef Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 19:13:53 +0100 Subject: [PATCH 37/71] contract: refactor attachments --- Cargo.lock | 24 +++++- Cargo.toml | 3 +- src/contract/attachment.rs | 172 ++++++++++++++++++------------------- src/contract/mod.rs | 12 +-- src/contract/value.rs | 29 +++++-- src/schema/schema.rs | 19 ++-- 6 files changed, 148 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5c254f9..c5d22657 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,6 +137,17 @@ dependencies = [ "mnemonic", ] +[[package]] +name = "baid58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a05192bd44b6cced6d9f89b98d82fba5d1df844332e34d4888ec6ba5b28a487" +dependencies = [ + "base58", + "blake3", + "mnemonic", +] + [[package]] name = "base58" version = "0.2.0" @@ -239,7 +250,7 @@ version = "0.10.0-beta.1" source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" dependencies = [ "amplify", - "baid58", + "baid58 0.1.0", "bp-dbc", "bp-primitives", "commit_verify", @@ -600,6 +611,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + [[package]] name = "mnemonic" version = "1.0.1" @@ -710,9 +727,10 @@ version = "0.10.0-alpha.1" dependencies = [ "aluvm", "amplify", - "baid58", + "baid58 0.2.0", "bp-core", "commit_verify", + "mime", "secp256k1-zkp", "serde", "strict_encoding", @@ -916,7 +934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11170f93c7f969209d86c4a3a6a7a6b333772890a7303647e5e055800840df9b" dependencies = [ "amplify", - "baid58", + "baid58 0.1.0", "blake3", "half", "serde", diff --git a/Cargo.toml b/Cargo.toml index 48380d3e..4bdf1859 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,8 @@ aluvm = "0.10.0-alpha.1" commit_verify = { version = "~0.10.0-beta.2", features = ["rand"] } bp-core = { version = "~0.10.0-beta.1" } secp256k1-zkp = { version = "~0.7.0", features = ["use-rand", "rand-std", "global-context"] } -baid58 = "~0.1.0" +baid58 = "~0.2.0" +mime = "0.3.16" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } [features] diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index 0f9ff42f..8a5e9cc9 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -20,117 +20,117 @@ // See the License for the specific language governing permissions and // limitations under the License. -use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::{CommitVerify, UntaggedProtocol}; - -use crate::{ConfidentialState, RevealedState}; - -// "rgb:container:id" -static MIDSTATE_ATTACHMENT_ID: [u8; 32] = [ - 12, 61, 136, 60, 191, 129, 135, 229, 141, 35, 41, 161, 203, 125, 0, 101, 109, 136, 50, 236, 7, - 101, 59, 39, 148, 207, 63, 236, 255, 48, 24, 171, -]; -// "rgb:container:confidential" -static MIDSTATE_CONFIDENTIAL_ATTACHMENT: [u8; 32] = [ - 91, 91, 44, 25, 205, 155, 231, 106, 244, 163, 175, 204, 49, 17, 129, 52, 227, 151, 9, 5, 246, - 42, 1, 226, 126, 43, 141, 177, 84, 100, 61, 108, -]; - -/// Tag used for [`AttachmentId`] hash type -pub struct AttachmentIdTag; - -impl sha256t::Tag for AttachmentIdTag { - #[inline] - fn engine() -> sha256::HashEngine { - let midstate = sha256::Midstate::from_inner(MIDSTATE_ATTACHMENT_ID); - sha256::HashEngine::from_midstate(midstate, 64) - } -} +use std::str::FromStr; + +use amplify::confinement::TinyString; +use amplify::{Bytes32, RawArray}; +use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; +use bp::secp256k1::rand::{thread_rng, RngCore}; +use bp::Sha256; +use commit_verify::{CommitStrategy, CommitVerify, Conceal, UntaggedProtocol}; +use strict_encoding::{StrictEncode, StrictWriter}; + +use super::{ConfidentialState, RevealedState}; +use crate::LIB_NAME_RGB; /// Unique data attachment identifier +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From, AsAny)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[display(Self::to_baid58)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[wrapper(Debug, Display, BorrowSlice)] -pub struct AttachmentId(sha256t::Hash); - -impl CommitVerify for AttachmentId -where Msg: AsRef<[u8]> -{ - #[inline] - fn commit(msg: &Msg) -> AttachmentId { AttachmentId::hash(msg) } +pub struct AttachId( + #[from] + #[from([u8; 32])] + Bytes32, +); + +impl CommitStrategy for AttachId { + type Strategy = commit_verify::strategies::Strict; } -/// Tag used for [`Confidential`] hash type -pub struct ConfidentialAttachmentTag; - -impl sha256t::Tag for ConfidentialAttachmentTag { - #[inline] - fn engine() -> sha256::HashEngine { - let midstate = sha256::Midstate::from_inner(MIDSTATE_CONFIDENTIAL_ATTACHMENT); - sha256::HashEngine::from_midstate(midstate, 64) - } +impl ToBaid58<32> for AttachId { + const HRI: &'static str = "att"; + fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() } } +impl FromBaid58<32> for AttachId {} -/// Confidential representation of data attachment information -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From, AsAny)] -#[wrapper(Debug, Display, BorrowSlice)] -pub struct Confidential(sha256t::Hash); - -impl ConfidentialState for Confidential {} - -impl Confidential { - pub fn attachment_id(&self) -> AttachmentId { self.consensus_commit() } +impl FromStr for AttachId { + type Err = Baid58ParseError; + fn from_str(s: &str) -> Result { Self::from_baid58_str(s) } } -#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, AsAny, Display)] +#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[display("{id}~{mime}")] pub struct Revealed { - pub id: AttachmentId, - pub mime: String, + pub id: AttachId, + /// We do not enforce a MIME standard since non-standard types can be also + /// used + pub media_type: TinyString, pub salt: u64, } -impl CommitConceal for Revealed { - type ConcealedCommitment = Confidential; - - fn commit_conceal(&self) -> Self::ConcealedCommitment { - Confidential::hash( - &strict_serialize(self).expect("Encoding of predefined data types must not fail"), - ) +impl Revealed { + /// Creates new revealed attachment for the attachment id and MIME type. + /// Uses `thread_rng` to initialize [`Revealed::salt`]. + pub fn new(id: AttachId, media_type: impl Into) -> Self { + Self { + id, + media_type: media_type.into(), + salt: thread_rng().next_u64(), + } } } -impl commit_encode::Strategy for Revealed { - type Strategy = commit_encode::strategies::UsingConceal; -} impl RevealedState for Revealed {} -#[cfg(test)] -mod test { - use amplify::Wrapper; - use commit_verify::tagged_hash; +impl Conceal for Revealed { + type Concealed = Confidential; - use super::*; + fn conceal(&self) -> Self::Concealed { Confidential::commit(self) } +} +impl CommitStrategy for Revealed { + type Strategy = commit_verify::strategies::ConcealStrict; +} - #[test] - fn test_attachment_id_midstate() { - let midstate = tagged_hash::Midstate::with(b"rgb:container:id"); - assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_ATTACHMENT_ID); - } +/// Confidential version of an attachment information. +/// +/// See also revealed version [`Revealed`]. +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, AsAny)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct Confidential( + #[from] + #[from([u8; 32])] + Bytes32, +); + +impl ConfidentialState for Confidential {} + +impl CommitStrategy for Confidential { + type Strategy = commit_verify::strategies::Strict; +} - #[test] - fn test_confidential_midstate() { - let midstate = tagged_hash::Midstate::with(b"rgb:container:confidential"); - assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_CONFIDENTIAL_ATTACHMENT); +// TODO: Consider changing untagged protocol to a tagged version +impl CommitVerify for Confidential { + fn commit(msg: &Revealed) -> Self { + // TODO: Move this algo together with Sha256 type to client_side_validation + let mut engine = Sha256::default(); + let w = StrictWriter::with(u32::MAX as usize, &mut engine); + msg.strict_encode(w).ok(); + engine.finish().into() } } diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 331f1753..71d01dd7 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -26,16 +26,21 @@ mod conceal; // pub mod reveal; pub mod value; +pub mod attachment; // #[macro_use] // pub mod data; // mod assignments; // mod metadata; // pub mod nodes; // mod rights; -// pub mod attachment; +pub use attachment::AttachId; pub use conceal::{ConcealSeals, ConcealState}; // pub use reveal::{MergeReveal, RevealSeals}; +pub use value::{ + BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, + ValueAtom, +}; /*pub(self) use assignments::EMPTY_ASSIGNMENTS; pub use assignments::{ @@ -43,17 +48,12 @@ pub use assignments::{ HashStrategy, PedersenStrategy, RevealedState, SealValueMap, State, StateType, TypedAssignments, }; -pub use attachment::AttachmentId; pub use metadata::Metadata; pub use nodes::{ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, Transition}; pub use rights::{OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights}; pub(crate) use rights::{OwnedRightsInner, PublicRightsInner}; pub use seal::{IntoRevealedSeal, SealEndpoint}; */ -pub use value::{ - BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, - ValueAtom, -}; /// Marker trait for types of state which are just a commitment to the actual /// state data. diff --git a/src/contract/value.rs b/src/contract/value.rs index 91ee9273..336ce0dd 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -38,10 +38,10 @@ use std::io::Write; use std::num::ParseIntError; use std::ops::Deref; +use amplify::hex::{Error, FromHex, ToHex}; // We do not import particular modules to keep aware with namespace prefixes // that we do not use the standard secp256k1zkp library -use amplify::{Array, AsAny, Bytes32, Wrapper}; -use baid58::ToBaid58; +use amplify::{hex, Array, AsAny, Bytes32, Wrapper}; use bp::secp256k1::rand::thread_rng; use bp::Sha256; use commit_verify::{CommitEncode, CommitStrategy, CommitVerify, Conceal, UntaggedProtocol}; @@ -63,7 +63,7 @@ use crate::LIB_NAME_RGB; #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename = "camelCase") + serde(crate = "serde_crate", rename_all = "camelCase") )] pub enum ValueAtom { /// 64-bit value. @@ -91,8 +91,7 @@ impl FromStr for ValueAtom { /// Knowledge of the blinding factor is important to reproduce the commitment /// process if the original value is kept. #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -#[display(Self::to_baid58)] -// TODO: Implement FromStr +#[display(Self::to_hex)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr( @@ -107,9 +106,21 @@ impl Deref for BlindingFactor { fn deref(&self) -> &Self::Target { self.0.as_inner() } } -impl ToBaid58<32> for BlindingFactor { - const HRP: &'static str = "blfc"; - fn to_baid58_payload(&self) -> [u8; 32] { self.0.into_inner() } +impl ToHex for BlindingFactor { + fn to_hex(&self) -> String { self.0.to_hex() } +} + +impl FromHex for BlindingFactor { + fn from_hex(s: &str) -> Result { Bytes32::from_hex(s).map(Self) } + fn from_byte_iter(_: I) -> Result + where I: Iterator> + ExactSizeIterator + DoubleEndedIterator { + unreachable!() + } +} + +impl FromStr for BlindingFactor { + type Err = hex::Error; + fn from_str(s: &str) -> Result { Self::from_hex(s) } } impl From for BlindingFactor { @@ -321,7 +332,7 @@ impl Default for RangeProof { #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename = "camelCase") + serde(crate = "serde_crate", rename_all = "camelCase") )] pub struct Confidential { /// Pedersen commitment to the original [`ValueAtom`]. diff --git a/src/schema/schema.rs b/src/schema/schema.rs index bae5d1e1..b6ddcdae 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -22,12 +22,13 @@ use std::cmp::Ordering; use std::io; +use std::str::FromStr; use amplify::confinement::{MediumVec, TinyOrdMap, TinyOrdSet}; use amplify::flags::FlagVec; use amplify::{Bytes32, RawArray}; -use baid58::ToBaid58; -use commit_verify::{strategies, CommitStrategy, CommitmentId}; +use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; +use commit_verify::{CommitStrategy, CommitmentId}; use strict_encoding::{ DecodeError, ReadTuple, StrictDecode, StrictEncode, StrictProduct, StrictTuple, StrictType, TypeName, TypedRead, TypedWrite, WriteTuple, @@ -48,7 +49,7 @@ pub type TransitionType = u16; /// /// Schema identifier commits to all of the schema data. #[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] -#[wrapper(Deref, BorrowSlice, FromStr, Hex, Index, RangeOps)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] #[display(Self::to_baid58)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB)] @@ -64,13 +65,19 @@ pub struct SchemaId( ); impl CommitStrategy for SchemaId { - type Strategy = strategies::Strict; + type Strategy = commit_verify::strategies::Strict; } impl ToBaid58<32> for SchemaId { - const HRP: &'static str = "sch"; + const HRI: &'static str = "sch"; fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() } } +impl FromBaid58<32> for SchemaId {} + +impl FromStr for SchemaId { + type Err = Baid58ParseError; + fn from_str(s: &str) -> Result { Self::from_baid58_str(s) } +} #[derive(Clone, Eq, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] @@ -117,7 +124,7 @@ impl PartialOrd for Schema { } impl CommitStrategy for Schema { - type Strategy = strategies::Strict; + type Strategy = commit_verify::strategies::Strict; } impl CommitmentId for Schema { From c6f3efe5b5d1cfa557b777c861b97c0424abf97e Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 20:02:52 +0100 Subject: [PATCH 38/71] refactor to use new commit_verify CommitVerify API --- Cargo.lock | 11 +++++------ src/contract/attachment.rs | 16 ++++------------ src/contract/value.rs | 5 +++-- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c5d22657..a1c41021 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ dependencies = [ [[package]] name = "bp-core" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" +source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" dependencies = [ "amplify", "bp-dbc", @@ -222,7 +222,7 @@ dependencies = [ [[package]] name = "bp-dbc" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" +source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" dependencies = [ "amplify", "bp-primitives", @@ -235,7 +235,7 @@ dependencies = [ [[package]] name = "bp-primitives" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" +source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" dependencies = [ "amplify", "commit_verify", @@ -247,7 +247,7 @@ dependencies = [ [[package]] name = "bp-seals" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#12d2c69149058a1e715490b85e1d50ce6ede0ba2" +source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" dependencies = [ "amplify", "baid58 0.1.0", @@ -310,10 +310,9 @@ dependencies = [ [[package]] name = "commit_verify" version = "0.10.0-beta.2" -source = "git+https://github.com/LNP-BP/client_side_validation#54332543981486178dd6536a5b1ace50cf20ac71" +source = "git+https://github.com/LNP-BP/client_side_validation#4e0d5b3e89055b7ce2d7013d82a97f9d0eae58bd" dependencies = [ "amplify", - "bitcoin_hashes", "rand", "serde", "strict_encoding", diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index 8a5e9cc9..29d5f6df 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -26,9 +26,8 @@ use amplify::confinement::TinyString; use amplify::{Bytes32, RawArray}; use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; use bp::secp256k1::rand::{thread_rng, RngCore}; -use bp::Sha256; -use commit_verify::{CommitStrategy, CommitVerify, Conceal, UntaggedProtocol}; -use strict_encoding::{StrictEncode, StrictWriter}; +use commit_verify::{CommitStrategy, CommitVerify, Conceal, StrictEncodedProtocol}; +use strict_encoding::StrictEncode; use super::{ConfidentialState, RevealedState}; use crate::LIB_NAME_RGB; @@ -124,13 +123,6 @@ impl CommitStrategy for Confidential { type Strategy = commit_verify::strategies::Strict; } -// TODO: Consider changing untagged protocol to a tagged version -impl CommitVerify for Confidential { - fn commit(msg: &Revealed) -> Self { - // TODO: Move this algo together with Sha256 type to client_side_validation - let mut engine = Sha256::default(); - let w = StrictWriter::with(u32::MAX as usize, &mut engine); - msg.strict_encode(w).ok(); - engine.finish().into() - } +impl CommitVerify for Confidential { + fn commit(revealed: &Revealed) -> Self { Bytes32::commit(revealed).into() } } diff --git a/src/contract/value.rs b/src/contract/value.rs index 336ce0dd..75ac8136 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -43,8 +43,9 @@ use amplify::hex::{Error, FromHex, ToHex}; // that we do not use the standard secp256k1zkp library use amplify::{hex, Array, AsAny, Bytes32, Wrapper}; use bp::secp256k1::rand::thread_rng; -use bp::Sha256; -use commit_verify::{CommitEncode, CommitStrategy, CommitVerify, Conceal, UntaggedProtocol}; +use commit_verify::{ + CommitEncode, CommitStrategy, CommitVerify, Conceal, Sha256, UntaggedProtocol, +}; use secp256k1_zkp::rand::{Rng, RngCore}; use secp256k1_zkp::SECP256K1; use strict_encoding::{ From 878c5fa23ab228e5a0528620fb37220d5672a6e2 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 20:07:43 +0100 Subject: [PATCH 39/71] contract: refactor structured data --- src/contract/data.rs | 76 +++++++++++++++++++++++++------------------- src/contract/mod.rs | 3 +- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/src/contract/data.rs b/src/contract/data.rs index ad0e8479..2a24e2ea 100644 --- a/src/contract/data.rs +++ b/src/contract/data.rs @@ -20,18 +20,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -use core::any::Any; use core::fmt::Debug; -use std::io; -use amplify::AsAny; -use bitcoin_hashes::{sha256, sha256t}; -use commit_verify::CommitEncode; +use amplify::confinement::SmallVec; +use amplify::{AsAny, Bytes32}; +use commit_verify::{CommitStrategy, CommitVerify, Conceal, StrictEncodedProtocol}; use super::{ConfidentialState, RevealedState}; +use crate::LIB_NAME_RGB; /// Struct using for storing Void (i.e. absent) state -#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Display, AsAny)] +#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Display, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[display("void")] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Void(); @@ -40,43 +41,54 @@ impl ConfidentialState for Void {} impl RevealedState for Void {} -impl CommitConceal for Void { - type ConcealedCommitment = Void; - - fn commit_conceal(&self) -> Self::ConcealedCommitment { self.clone() } +impl Conceal for Void { + type Concealed = Void; + fn conceal(&self) -> Self::Concealed { *self } +} +impl CommitStrategy for Void { + type Strategy = commit_verify::strategies::Strict; } #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct Revealed(Vec); +pub struct Revealed(SmallVec); impl RevealedState for Revealed {} -impl CommitConceal for Revealed { - type ConcealedCommitment = Confidential; - - fn commit_conceal(&self) -> Self::ConcealedCommitment { - Confidential::hash( - &strict_serialize(self).expect("Encoding of predefined data types must not fail"), - ) - } +impl Conceal for Revealed { + type Concealed = Confidential; + fn conceal(&self) -> Self::Concealed { Confidential::commit(self) } } -impl commit_encode::Strategy for Revealed { - type Strategy = commit_encode::strategies::UsingConceal; +impl CommitStrategy for Revealed { + type Strategy = commit_verify::strategies::ConcealStrict; } -/// Blind version of transaction outpoint-based single-use-seal -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[wrapper(Debug, Display, BorrowSlice)] -pub struct Confidential(sha256t::Hash); - -impl commit_encode::Strategy for Confidential { - type Strategy = commit_encode::strategies::UsingStrict; -} +/// Confidential version of an structured state data. +/// +/// See also revealed version [`Revealed`]. +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, AsAny)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct Confidential( + #[from] + #[from([u8; 32])] + Bytes32, +); impl ConfidentialState for Confidential {} -impl AsAny for Confidential { - fn as_any(&self) -> &dyn Any { self as &dyn Any } +impl CommitStrategy for Confidential { + type Strategy = commit_verify::strategies::Strict; +} + +impl CommitVerify for Confidential { + fn commit(revealed: &Revealed) -> Self { Bytes32::commit(revealed).into() } } diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 71d01dd7..3f1be6f4 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -27,8 +27,7 @@ mod conceal; pub mod value; pub mod attachment; -// #[macro_use] -// pub mod data; +pub mod data; // mod assignments; // mod metadata; // pub mod nodes; From 4fc6faefa976935e7a51f7fd42d0be31ac7e9505 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 20:09:18 +0100 Subject: [PATCH 40/71] schema: rename state types --- src/schema/mod.rs | 2 +- src/schema/state.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/schema/mod.rs b/src/schema/mod.rs index 59c2be1f..94df4412 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -34,4 +34,4 @@ pub use nodes::{ pub use occurrences::{Occurrences, OccurrencesMismatch}; pub use schema::{ExtensionType, FieldType, Schema, SchemaId, TransitionType}; pub use script::{Scripts, VmType}; -pub use state::{DiscreteFiniteFieldFormat, StateSchema}; +pub use state::{StateSchema, ValueType}; diff --git a/src/schema/state.rs b/src/schema/state.rs index d95c94c5..4b0bd53b 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -36,9 +36,9 @@ use crate::LIB_NAME_RGB; pub enum StateSchema { #[strict_type(dumb)] Declarative, - DiscreteFiniteField(DiscreteFiniteFieldFormat), - CustomData(SemId), - DataContainer, + Arithmetic(ValueType), + Structured(SemId), + Attachment, } /// Today we support only a single format of confidential data, because of the @@ -57,7 +57,7 @@ pub enum StateSchema { serde(crate = "serde_crate", rename_all = "camelCase") )] #[repr(u8)] -pub enum DiscreteFiniteFieldFormat { +pub enum ValueType { #[default] Unsigned64Bit = U64.into_code(), } From 751726aa8b91d8ea9e24b08f8cc0f2f249d84bd0 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 20:21:19 +0100 Subject: [PATCH 41/71] contract: refactor metadata --- src/contract/metadata.rs | 191 ++++----------------------------------- src/contract/mod.rs | 4 +- 2 files changed, 22 insertions(+), 173 deletions(-) diff --git a/src/contract/metadata.rs b/src/contract/metadata.rs index 2e020310..e02a8bdc 100644 --- a/src/contract/metadata.rs +++ b/src/contract/metadata.rs @@ -22,186 +22,35 @@ //! Convenience metadata accessor methods for Genesis and state transitions. -use std::collections::BTreeMap; - +use amplify::confinement::{Confined, TinyOrdMap, U8}; use amplify::Wrapper; +use strict_encoding::StrictDumb; use super::data; -use crate::schema; - -type MetadataInner = BTreeMap>; +use crate::{schema, LIB_NAME_RGB}; -/// Transition & genesis metadata fields -#[derive(Wrapper, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, From)] +#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, From)] +#[wrapper(Deref)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -pub struct Metadata(MetadataInner); - -// TODO #107: Improve other iterators for contract collection types. -impl<'me> IntoIterator for &'me Metadata { - type Item = (&'me schema::FieldType, &'me Vec); - type IntoIter = std::collections::btree_map::Iter<'me, schema::FieldType, Vec>; +pub struct FieldValues(Confined, 1, U8>); - fn into_iter(self) -> Self::IntoIter { self.0.iter() } +impl StrictDumb for FieldValues { + fn strict_dumb() -> Self { Self(confined_vec!(data::Revealed::strict_dumb())) } } -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] -pub struct MetadataLeaf(pub schema::FieldType, pub data::Revealed); - -#[cfg(test)] -mod test { - use amplify::Wrapper; - use bitcoin_hashes::Hash; - use commit_verify::merkle::MerkleNode; - use commit_verify::{merklize, CommitEncode}; - use secp256k1_zkp::rand::{thread_rng, RngCore}; - use strict_encoding::{StrictDecode, StrictEncode}; - use strict_encoding_test::test_vec_decoding_roundtrip; - - use super::*; - //use lnpbp::commit_verify::CommitVerify; - - // Hard coded sample metadata object as shown below - // Metadata({13: {U8(2), U8(3), U16(2), U32(2), U32(3), - // U64(2), U64(3), I8(2), I8(3), I32(2), I32(3), - // I64(2), I64(3), F32(2.0), F32(3.0), F64(2.0), - // F64(3.0), Bytes([1, 2, 3, 4, 5]), Bytes([10, 20, 30, 40, 50]), - // String("One Random String"), String("Another Random String")}}) - // It has Field_type = 13 with only single U16 and no I16 data types. - static METADATA: [u8; 161] = include!("../../test/metadata.in"); - - #[test] - #[ignore] - fn test_extraction() { - let metadata = Metadata::strict_decode(&METADATA[..]).unwrap(); - - let field_type = 13 as schema::FieldType; - - let field_1 = metadata.u8(field_type); - let field_2 = metadata.u16(field_type); - let field_3 = metadata.u32(field_type); - let field_4 = metadata.u64(field_type); - let field_5 = metadata.i8(field_type); - let field_6 = metadata.i16(field_type); - let field_7 = metadata.i32(field_type); - let field_8 = metadata.i64(field_type); - let field_9 = metadata.f32(field_type); - let field_10 = metadata.f64(field_type); - let field_11 = metadata.bytes(field_type); - let field_12 = metadata.unicode_string(field_type); - - assert_eq!(field_1, vec![2, 3]); - assert_eq!(field_2, vec![2]); - assert_eq!(field_3, vec![2, 3]); - assert_eq!(field_4, vec![2, 3]); - assert_eq!(field_5, vec![2, 3]); - assert_eq!(field_6, Vec::::new()); - assert_eq!(field_7, vec![2, 3]); - assert_eq!(field_8, vec![2, 3]); - assert_eq!(field_9, vec![2 as f32, 3 as f32]); - assert_eq!(field_10, vec![2 as f64, 3 as f64]); - assert_eq!(field_11, vec![[1u8, 2, 3, 4, 5].to_vec(), [10u8, 20, 30, 40, 50].to_vec()]); - assert_eq!(field_12, vec![ - "One Random String".to_string(), - "Another Random String".to_string() - ]); - } - - #[test] - #[ignore] - fn test_encode_decode_meta() { - let _: Metadata = test_vec_decoding_roundtrip(METADATA).unwrap(); - } - - #[test] - #[ignore] - #[should_panic(expected = "UnexpectedEof")] - fn test_eof_metadata() { - let mut data = METADATA.clone(); - data[0] = 0x36 as u8; - Metadata::strict_decode(&data[..]).unwrap(); - } - - #[test] - #[ignore] - fn test_iteration_field() { - let metadata = Metadata::strict_decode(&METADATA[..]).unwrap(); - let field_values = metadata.f32(13 as schema::FieldType); - - assert_eq!(field_values.into_iter().sum::(), 5f32); - } - - #[test] - fn test_commitencoding_field() { - let mut rng = thread_rng(); - let mut data1 = Vec::new(); - data1.push(data::Revealed::U8(rng.next_u64() as u8)); - data1.push(data::Revealed::U16(rng.next_u64() as u16)); - data1.push(data::Revealed::U32(rng.next_u64() as u32)); - data1.push(data::Revealed::U64(rng.next_u64() as u64)); - - let mut data2 = Vec::new(); - data2.push(data::Revealed::I8(rng.next_u64() as i8)); - data2.push(data::Revealed::I16(rng.next_u64() as i16)); - data2.push(data::Revealed::I32(rng.next_u64() as i32)); - data2.push(data::Revealed::I64(rng.next_u64() as i64)); - - let mut byte_vec = vec![]; - for i in 0..10 { - byte_vec.insert(i, rng.next_u32() as u8); - } - - let mut data3 = Vec::new(); - data3.push(data::Revealed::F32(rng.next_u32() as f32)); - data3.push(data::Revealed::F64(rng.next_u32() as f64)); - data3.push(data::Revealed::Bytes(byte_vec)); - data3.push(data::Revealed::UnicodeString("Random String".to_string())); - - let field1 = 1 as schema::FieldType; - let field2 = 2 as schema::FieldType; - let field3 = 3 as schema::FieldType; - - let mut metadata_inner = BTreeMap::new(); - metadata_inner.insert(field1, data1.clone()); - metadata_inner.insert(field2, data2.clone()); - metadata_inner.insert(field3, data3.clone()); - - let metadata = Metadata::from_inner(metadata_inner); - - let mut original_encoding = vec![]; - metadata - .to_merkle_source() - .consensus_commit() - .commit_encode(&mut original_encoding); - - // Hand calculate the encoding - // create the leaves - let vec_1: Vec<(schema::FieldType, data::Revealed)> = - data1.iter().map(|data| (field1, data.clone())).collect(); - let vec_2: Vec<(schema::FieldType, data::Revealed)> = - data2.iter().map(|data| (field2, data.clone())).collect(); - let vec_3: Vec<(schema::FieldType, data::Revealed)> = - data3.iter().map(|data| (field3, data.clone())).collect(); - - // combine all the leaves - let vec_4 = [vec_1, vec_2, vec_3].concat(); - - // create MerkleNodes from each leaf - let nodes: Vec = vec_4 - .iter() - .map(|item| MerkleNode::hash(&StrictEncode::strict_serialize(item).unwrap())) - .collect(); - - // compute merkle root of all the nodes - let (root, _) = merklize(MetadataLeaf::MERKLE_NODE_PREFIX, nodes); - - // Commit encode the root - let handmade_encoding = root.commit_serialize(); - - // This should match with original encoding - assert_eq!(original_encoding, handmade_encoding); - } -} +#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, Default, From)] +#[wrapper(Deref)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct Metadata(TinyOrdMap); diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 3f1be6f4..5e645b2d 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -28,10 +28,10 @@ mod conceal; pub mod value; pub mod attachment; pub mod data; +mod metadata; // mod assignments; -// mod metadata; -// pub mod nodes; // mod rights; +// pub mod nodes; pub use attachment::AttachId; pub use conceal::{ConcealSeals, ConcealState}; From 85d5d8284e28a6dd08f28b94a4e8e922d6659391 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 21:03:35 +0100 Subject: [PATCH 42/71] contract: refactor owned state --- src/contract/assignments.rs | 1662 ----------------- src/contract/{metadata.rs => global_state.rs} | 0 src/contract/mod.rs | 26 +- src/contract/{nodes.rs => operations.rs} | 0 src/contract/owned_state.rs | 763 ++++++++ .../{conceal.rs => reveal_conceal.rs} | 12 + src/contract/{reveal.rs => reveal_merge.rs} | 0 7 files changed, 794 insertions(+), 1669 deletions(-) rename src/contract/{metadata.rs => global_state.rs} (100%) rename src/contract/{nodes.rs => operations.rs} (100%) create mode 100644 src/contract/owned_state.rs rename src/contract/{conceal.rs => reveal_conceal.rs} (90%) rename src/contract/{reveal.rs => reveal_merge.rs} (100%) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 0516245c..c0806958 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -36,31 +36,6 @@ use crate::contract::attachment; use crate::value::BlindingFactor; use crate::{AtomicValue, ConfidentialDataError, RevealSeals, StateRetrievalError}; -pub(super) static EMPTY_ASSIGNMENTS: Lazy = Lazy::new(TypedAssignments::default); - -/// Allocation map using unique set of seal definitions -pub type SealValueMap = BTreeMap; - -/// Allocation map using unique set of blinded consignment endpoints -pub type EndpointValueMap = BTreeMap; - -/// Categories of the state -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub enum StateType { - /// No state data - Void, - - /// Value-based state, i.e. which can be committed to with a Pedersen - /// commitment - Value, - - /// State defined with custom data - Data, - - /// Attached data container - Attachment, -} - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr( feature = "serde", @@ -78,125 +53,7 @@ impl Default for TypedAssignments { fn default() -> Self { TypedAssignments::Void(vec![]) } } -/// Errors happening during [`TypedAssignments::zero_balanced`] procedure. All -/// of them indicate either invalid/crafted input arguments, or failures in the -/// source of randomness. -#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] -#[display(doc_comments)] -pub enum MalformedInput { - /// both our and their allocations are empty; at least one value must be - /// provided in any of them. - NoOutput, - - /// random number generator produced non-random blinding factor {0} which is - /// an inverse of the sum of the previously produced keys. - RandomInverseKeys, - - /// one of inputs has an invalid blinding factor {0} exceeding field prime - /// order. - InvalidInputBlinding(BlindingFactor), - - /// invalid input blinding factors, which sum up to the inversion of their - /// own selves. - MalformedInputBlindings, - - /// blinding factors provided as an input are invalid; specifically they sum - /// above the prime field order. This means the attempt to spend an invalid - /// contract state; check that your program use validated data only. - InputBlindingsInvalid, - - /// sum of randomly generated blinding factors perfectly equals the sum of - /// input blinding factors. This indicates that the random generator is - /// failed or hacked. - RandomnessFailure, -} - impl TypedAssignments { - pub fn zero_balanced( - inputs: Vec, - allocations_ours: BTreeMap, - allocations_theirs: BTreeMap, - ) -> Result { - use secp256k1_zkp::{Scalar, SecretKey}; - - if allocations_ours.len() + allocations_theirs.len() == 0 { - return Err(MalformedInput::NoOutput); - } - - // Generate random blinding factors - let mut rng = secp256k1_zkp::rand::thread_rng(); - // We will compute the last blinding factors from all others so they - // sum up to 0, so we need to generate only n - 1 random factors - let count = allocations_theirs.len() + allocations_ours.len(); - let mut blinding_factors = Vec::<_>::with_capacity(count); - let mut blinding_output_sum = Scalar::ZERO; - for _ in 0..(count - 1) { - let bf = SecretKey::new(&mut rng); - blinding_output_sum = bf - .add_tweak(&blinding_output_sum) - .map_err(|_| MalformedInput::RandomInverseKeys)? - .into(); - blinding_factors.push(bf); - } - let blinding_input_sum = inputs.iter().try_fold(Scalar::ZERO, |acc, val| { - let sk = SecretKey::from_slice(val.blinding.as_ref()) - .map_err(|_| MalformedInput::InvalidInputBlinding(val.blinding))?; - sk.add_tweak(&acc) - .map_err(|_| MalformedInput::MalformedInputBlindings) - .map(Scalar::from) - })?; - - if inputs.is_empty() { - // if we have no inputs, we assign a random last blinding factor - blinding_factors.push(SecretKey::new(&mut rng)); - } else { - // the last blinding factor must be a correction value - let input_sum = SecretKey::from_slice(&blinding_input_sum.to_be_bytes()) - .map_err(|_| MalformedInput::InputBlindingsInvalid)?; - let mut blinding_correction = input_sum.negate(); - blinding_correction = blinding_correction - .add_tweak(&blinding_output_sum) - .map_err(|_| MalformedInput::RandomnessFailure)?; - // We need the last factor to be equal to the difference - blinding_factors.push(blinding_correction.negate()); - } - - let mut blinding_iter = blinding_factors.into_iter(); - let mut set: Vec> = allocations_ours - .into_iter() - .zip(blinding_iter.by_ref()) - .map(|((seal, amount), blinding)| { - Assignment::revealed(seal, value::Revealed::with(amount, blinding)) - }) - .collect(); - set.extend(allocations_theirs.into_iter().zip(blinding_iter).map( - |((seal_proto, amount), blinding)| { - let state = value::Revealed::with(amount, blinding); - match seal_proto { - SealEndpoint::ConcealedUtxo(seal) => { - Assignment::ConfidentialSeal { seal, state } - } - SealEndpoint::WitnessVout { - method, - vout, - blinding, - } => Assignment::Revealed { - // TODO: Add convenience constructor to `seal::Revealed` - seal: seal::Revealed { - method, - txid: None, - vout, - blinding, - }, - state, - }, - } - }, - )); - - Ok(Self::Value(set)) - } - #[inline] pub fn state_type(&self) -> StateType { match self { @@ -718,1522 +575,3 @@ impl ConcealState for TypedAssignments { .conceal_state_except(seals) } } - -pub trait State: Debug { - type Confidential: ConfidentialState; - type Revealed: RevealedState; -} - -#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct DeclarativeStrategy; -impl State for DeclarativeStrategy { - type Confidential = data::Void; - type Revealed = data::Void; -} - -#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct PedersenStrategy; -impl State for PedersenStrategy { - type Confidential = value::Confidential; - type Revealed = value::Revealed; -} - -#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct HashStrategy; -impl State for HashStrategy { - type Confidential = data::Confidential; - type Revealed = data::Revealed; -} - -#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct AttachmentStrategy; -impl State for AttachmentStrategy { - type Confidential = attachment::Confidential; - type Revealed = attachment::Revealed; -} - -/// 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)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "snake_case") -)] -pub enum Assignment -where - StateType: State, - // Deterministic ordering requires Eq operation, so the confidential - // state must have it - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - Confidential { - seal: seal::Confidential, - state: StateType::Confidential, - }, - Revealed { - seal: seal::Revealed, - state: StateType::Revealed, - }, - ConfidentialSeal { - seal: seal::Confidential, - state: StateType::Revealed, - }, - ConfidentialState { - seal: seal::Revealed, - state: StateType::Confidential, - }, -} - -impl std::hash::Hash for Assignment -where - Self: Clone, - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - fn hash(&self, state: &mut H) { state.write(&self.consensus_commit()[..]) } -} - -// Consensus-critical! -// Assignment indexes are part of the transition ancestor's commitment, so -// here we use deterministic ordering based on hash values of the concealed -// seal data contained within the assignment -impl PartialOrd for Assignment -where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - fn partial_cmp(&self, other: &Self) -> Option { - self.to_confidential_seal() - .partial_cmp(&other.to_confidential_seal()) - } -} - -impl Ord for Assignment -where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - fn cmp(&self, other: &Self) -> Ordering { - self.to_confidential_seal() - .cmp(&other.to_confidential_seal()) - } -} - -impl PartialEq for Assignment -where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - fn eq(&self, other: &Self) -> bool { - self.to_confidential_seal() == other.to_confidential_seal() && - self.to_confidential_state() == other.to_confidential_state() - } -} - -impl Eq for Assignment -where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ -} - -impl Assignment -where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - pub fn revealed(seal: seal::Revealed, state: StateType::Revealed) -> Self { - Assignment::Revealed { seal, state } - } - - pub fn with_seal_replaced(assignment: &Self, seal: seal::Revealed) -> Self { - match assignment { - Assignment::Confidential { seal: _, state } | - Assignment::ConfidentialState { seal: _, state } => Assignment::ConfidentialState { - seal, - state: state.clone(), - }, - Assignment::ConfidentialSeal { seal: _, state } | - Assignment::Revealed { seal: _, state } => Assignment::Revealed { - seal, - state: state.clone(), - }, - } - } - - pub fn to_confidential_seal(&self) -> seal::Confidential { - match self { - Assignment::Revealed { seal, .. } | Assignment::ConfidentialState { seal, .. } => { - seal.commit_conceal() - } - Assignment::Confidential { seal, .. } | Assignment::ConfidentialSeal { seal, .. } => { - *seal - } - } - } - - pub fn revealed_seal(&self) -> Option { - match self { - Assignment::Revealed { seal, .. } | Assignment::ConfidentialState { seal, .. } => { - Some(*seal) - } - Assignment::Confidential { .. } | Assignment::ConfidentialSeal { .. } => None, - } - } - - pub fn to_confidential_state(&self) -> StateType::Confidential { - match self { - Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { - state.commit_conceal().into() - } - Assignment::Confidential { state, .. } | - Assignment::ConfidentialState { state, .. } => state.clone(), - } - } - - pub fn as_revealed_state(&self) -> Option<&StateType::Revealed> { - match self { - Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { - Some(state) - } - Assignment::Confidential { .. } | Assignment::ConfidentialState { .. } => None, - } - } - - pub fn as_revealed(&self) -> Option<(&seal::Revealed, &StateType::Revealed)> { - match self { - Assignment::Revealed { seal, state } => Some((seal, state)), - _ => None, - } - } - - pub fn to_revealed(&self) -> Option<(seal::Revealed, StateType::Revealed)> { - match self { - Assignment::Revealed { seal, state } => Some((*seal, state.clone())), - _ => None, - } - } - - pub fn into_revealed(self) -> Option<(seal::Revealed, StateType::Revealed)> { - match self { - Assignment::Revealed { seal, state } => Some((seal, state)), - _ => None, - } - } -} - -impl CommitConceal for Assignment -where - Self: Clone, - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - type ConcealedCommitment = Self; - - fn commit_conceal(&self) -> Self::ConcealedCommitment { - match self { - Assignment::Confidential { .. } => self.clone(), - Assignment::ConfidentialState { seal, state } => Self::Confidential { - seal: seal.commit_conceal(), - state: state.clone(), - }, - Assignment::Revealed { seal, state } => Self::Confidential { - seal: seal.commit_conceal(), - state: state.commit_conceal().into(), - }, - Assignment::ConfidentialSeal { seal, state } => Self::Confidential { - seal: *seal, - state: state.commit_conceal().into(), - }, - } - } -} - -impl RevealSeals for Assignment -where - StateType: State, - StateType::Revealed: CommitConceal, - StateType::Confidential: PartialEq + Eq, - ::Confidential: - From<::ConcealedCommitment>, -{ - fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize { - let known_seals: HashMap = known_seals - .iter() - .map(|rev| (rev.commit_conceal(), *rev)) - .collect(); - - let mut counter = 0; - match self { - Assignment::Confidential { seal, state } => { - if let Some(reveal) = known_seals.get(seal) { - *self = Assignment::ConfidentialState { - seal: *reveal, - state: state.clone(), - }; - counter += 1; - }; - } - Assignment::ConfidentialSeal { seal, state } => { - if let Some(reveal) = known_seals.get(seal) { - *self = Assignment::Revealed { - seal: *reveal, - state: state.clone(), - }; - counter += 1; - }; - } - _ => {} - } - counter - } -} - -impl ConcealSeals for Assignment -where - StateType: State, - StateType::Revealed: CommitConceal, - StateType::Confidential: PartialEq + Eq, - ::Confidential: - From<::ConcealedCommitment>, -{ - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - match self { - Assignment::Confidential { .. } | Assignment::ConfidentialSeal { .. } => 0, - Assignment::ConfidentialState { seal, state } => { - if seals.contains(&seal.commit_conceal()) { - *self = Assignment::::Confidential { - state: state.clone(), - seal: seal.commit_conceal(), - }; - 1 - } else { - 0 - } - } - Assignment::Revealed { seal, state } => { - if seals.contains(&seal.commit_conceal()) { - *self = Assignment::::ConfidentialSeal { - state: state.clone(), - seal: seal.commit_conceal(), - }; - 1 - } else { - 0 - } - } - } - } -} - -impl ConcealState for Assignment -where - StateType: State, - StateType::Revealed: CommitConceal, - StateType::Confidential: PartialEq + Eq, - ::Confidential: - From<::ConcealedCommitment>, -{ - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - match self { - Assignment::Confidential { .. } | Assignment::ConfidentialState { .. } => 0, - Assignment::ConfidentialSeal { seal, state } => { - if seals.contains(seal) { - 0 - } else { - *self = Assignment::::Confidential { - state: state.commit_conceal().into(), - seal: *seal, - }; - 1 - } - } - Assignment::Revealed { seal, state } => { - if seals.contains(&seal.commit_conceal()) { - 0 - } else { - *self = Assignment::::ConfidentialState { - state: state.commit_conceal().into(), - seal: *seal, - }; - 1 - } - } - } - } -} - -// We can't use `UsingConceal` strategy here since it relies on the -// `commit_encode` of the concealed type, and here the concealed type is again -// `OwnedState`, leading to a recurrency. So we use `strict_encode` of the -// concealed data. -impl CommitEncode for Assignment -where - Self: Clone, - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - fn commit_encode(&self, e: E) -> usize { - self.commit_conceal().strict_encode(e).expect( - "Strict encoding must not fail for types implementing ConsensusCommit via marker \ - trait ConsensusCommitFromStrictEncoding", - ) - } -} - -impl ConsensusCommit for Assignment -where - Self: Clone, - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::ConcealedCommitment>, -{ - type Commitment = MerkleNode; -} - -#[cfg(test)] -mod test { - use std::collections::BTreeMap; - - use bitcoin::blockdata::transaction::Outpoint; - use bitcoin_hashes::hex::{FromHex, ToHex}; - use bitcoin_hashes::{sha256, Hash}; - use bp::seals::txout::TxoSeal; - use commit_verify::merkle::MerkleNode; - use commit_verify::{merklize, CommitConceal, CommitEncode, ToMerkleSource}; - use secp256k1_zkp::rand::{thread_rng, Rng, RngCore}; - use secp256k1_zkp::{PedersenCommitment, SecretKey}; - use strict_encoding_test::test_vec_decoding_roundtrip; - - 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 - // [Revealed, Confidential, ConfidentialSeal, ConfidentialState] - static HASH_VARIANT: [u8; 267] = include!("../../test/hash_state.in"); - - static PEDERSAN_VARIANT: [u8; 1664] = include!("../../test/pedersan_state.in"); - - static DECLARATIVE_VARIANT: [u8; 161] = include!("../../test/declarative_state.in"); - - static PARENT_RIGHTS: [u8; 78] = include!("../../test/parent_rights.in"); - - // Real data used for creation of above variants - // Used in tests to ensure operations of AssignmentVariants gives - // deterministic results - - // Txids to generate seals - static TXID_VEC: [&str; 4] = [ - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e", - "f57ed27ee4199072c5ff3b774febc94d26d3e4a5559d133de4750a948df50e06", - "12072893d951c633dcafb4d3074d1fc41c5e6e64b8d53e3b0705c41bc6679d54", - "8f75db9f89c7c75f0a54322f18cd4d557ae75c24a8e5a95eae13fe26edc2d789", - ]; - - // State data used in CustomData type Assignments - static STATE_DATA: [&str; 4] = [ - "e70a36e2ce51d31d4cf5d6731fa63738648127db833715d39652d86d927d4888", - "408e331ebce96ca98cfb7b8a6286a79300379eed6395636e6d103017d474039f", - "c6411aea082e2c5d74347368677db69545126237d5ed78faa0846352f5383f95", - "277fb00655e2523424677686c24d90fba6b70869050ae204782e8ef0ab8049c6", - ]; - - // Confidential seals for Declarative Assignments - static DECLARATIVE_OUTPOINT_HASH: [&str; 4] = [ - "58f3ea4817a12aa6f1007d5b3d24dd2940ce40f8498029e05f1dc6465b3d65b4", - "6b3c1bee0bd431f53e6c099890fdaf51b8556a6dcd61c6150ca055d0e1d4a524", - "9a17566abc006cf335fd96d8f8a4136526d85493a85ebe875abbbee19795c496", - "c843ac6b197ae371191264cc0e4ed18a910b5522a0bad72a24f2080c170e2053", - ]; - - // Confidential seals for Pedersan type Assignments - static PEDERSAN_OUTPOINT_HASH: [&str; 4] = [ - "281543d7f791d4b4f8ef1196e436bc3286a5505f7bafd978d4af9be6f112e1b4", - "32d71a47d8ff6015fc58525985af7346e0802c7ad065ad79335602c7a6562ab3", - "68955a27e1ffde810fcfdd18697eb59aa4f7b0afde2a8193cd28184b729b5195", - "698c43d973bec68540e6df67137785e40be6d29def4888ada3cd7b7884b37f62", - ]; - - // Confidential seals for CustomData type Assignments - static HASH_OUTPOINT_HASH: [&str; 4] = [ - "7efe71b7a37a39da798774ca6b09def9724d81303892d55cac3edb0dc8340a3a", - "9565d29461c863e013c26d176a9929307286963322849a1dc6c978e5c70c8d52", - "9b64a3024632f0517d8a608cb29902f7083eab0ac25d2827a5ef27e9a68b18f9", - "dc0d0d7139a3ad6010a210e5900201979a1a09047b10a877688ee5a740ae215a", - ]; - - // Generic encode-decode testing - #[test] - #[ignore] - fn test_encoded_data() { - let _: TypedAssignments = test_vec_decoding_roundtrip(HASH_VARIANT).unwrap(); - let _: TypedAssignments = test_vec_decoding_roundtrip(PEDERSAN_VARIANT).unwrap(); - let _: TypedAssignments = test_vec_decoding_roundtrip(DECLARATIVE_VARIANT).unwrap(); - } - - // Generic garbage value testing - /* - #[test] - #[ignore] - fn test_garbage_dec() { - let err = "StateType"; - test_garbage_exhaustive!(4..255; (DECLARATIVE_VARIANT, AssignmentVec, err), - (HASH_VARIANT, AssignmentVec, err), - (DECLARATIVE_VARIANT, AssignmentVec, err)); - } - */ - - #[test] - #[ignore] - #[should_panic(expected = "UnsupportedDataStructure")] - fn test_garbage_ped_2() { - let mut bytes = PEDERSAN_VARIANT.clone(); - bytes[1] = 0x02; - - TypedAssignments::strict_decode(&bytes[..]).unwrap(); - } - - fn zero_balance( - input_amounts: &[u64], - output_amounts: &[u64], - partition: usize, - ) -> (Vec, Vec) { - let mut rng = thread_rng(); - - // Create revealed amount from input amounts - let input_revealed: Vec = input_amounts[..] - .into_iter() - .map(|amount| value::Revealed::with_amount(*amount, &mut rng)) - .collect(); - - // Allocate Txid vector of size of the output vector - let mut txid_vec: Vec = Vec::with_capacity(output_amounts.len()); - - // Fill the txid vector with random txids. - for _ in 0..output_amounts.len() { - let mut bytes: [u8; 32] = [0; 32]; - rng.fill(&mut bytes[..]); - let txid = bitcoin::Txid::from_hex(&bytes.to_vec().to_hex()[..]).unwrap(); - txid_vec.push(txid); - } - - // Take first two amounts to create our allocations - let zip_data = txid_vec[..partition] - .iter() - .zip(output_amounts[..partition].iter()); - - // Create our allocations - let ours: SealValueMap = zip_data - .map(|(txid, amount)| { - (Revealed::from(Outpoint::new(*txid, rng.gen_range(0..=10))), amount.clone()) - }) - .collect(); - - // Take next two amounts for their allocations - let zip_data2 = txid_vec[partition..] - .iter() - .zip(output_amounts[partition..].iter()); - - // Create their allocations - let theirs: EndpointValueMap = zip_data2 - .map(|(txid, amount)| { - ( - SealEndpoint::ConcealedUtxo( - Revealed::from(Outpoint::new(*txid, rng.gen_range(0..=10))) - .commit_conceal(), - ), - amount.clone(), - ) - }) - .collect(); - - // Balance both the allocations against input amounts - let balanced = - TypedAssignments::zero_balanced(input_revealed.clone(), ours, theirs).unwrap(); - - // Extract balanced confidential output amounts - let outputs: Vec = balanced - .to_confidential_state_pedersen() - .iter() - .map(|confidential| confidential.commitment) - .collect(); - - // Create confidential input amounts - let inputs: Vec = input_revealed - .iter() - .map(|revealed| revealed.commit_conceal().commitment) - .collect(); - - (inputs, outputs) - } - - fn zero_balance_verify( - input_amounts: &[u64], - output_amounts: &[u64], - partition: usize, - ) -> bool { - let (inputs, outputs) = zero_balance(input_amounts, output_amounts, partition); - value::Confidential::verify_commit_sum(inputs, outputs) - } - - #[test] - fn test_zero_balance_nonoverflow() { - assert!(zero_balance_verify(&[core::u64::MAX, 1], &[1, core::u64::MAX], 1)); - assert!(zero_balance_verify( - &[core::u64::MAX, core::u64::MAX], - &[core::u64::MAX, core::u64::MAX], - 1 - )); - assert!(zero_balance_verify( - &[core::u32::MAX as u64, core::u32::MAX as u64], - &[core::u32::MAX as u64 + core::u32::MAX as u64], - 1 - )); - assert!(zero_balance_verify( - &[core::u32::MAX as u64, core::u32::MAX as u64, core::u64::MAX], - &[core::u64::MAX, (core::u32::MAX as u64) * 2], - 1 - )); - } - - #[test] - fn test_zero_balance_single() { - // test equal inputs and outputs - let single_amounts = vec![ - [0u64], - [1u64], - [core::u16::MAX as u64], - [core::u32::MAX as u64], - [core::u64::MAX - 1u64], - [core::u64::MAX], - ]; - - for vec in single_amounts.iter() { - assert!(zero_balance_verify(vec, vec, 0)); - assert!(zero_balance_verify(vec, vec, 1)); - assert!(zero_balance_verify(vec, vec, vec.len() / 2)); - assert!(zero_balance_verify(vec, vec, vec.len() / 2 + 1)); - } - } - - #[test] - fn test_zero_balance_double() { - let double_amounts = vec![[(core::u32::MAX - 1) as u64, (core::u32::MAX - 1) as u64], [ - core::u32::MAX as u64, - core::u32::MAX as u64, - ]]; - - for vec in double_amounts.iter() { - assert!(zero_balance_verify(vec, vec, 0)); - assert!(zero_balance_verify(vec, vec, 1)); - assert!(zero_balance_verify(vec, vec, vec.len() / 2)); - assert!(zero_balance_verify(vec, vec, vec.len() / 2 + 1)); - } - } - - #[test] - fn test_zero_balance_multiple() { - let multiple_amounts = vec![ - [0u64, 0u64, 0u64, 0u64], - [0u64, 1u64, 0u64, 1u64], - [1u64, 2u64, 3u64, core::u64::MAX], - [10u64, 20u64, 30u64, 40u64], - [0u64, 197642u64, core::u64::MAX, 476543u64], - [core::u64::MAX, core::u64::MAX, core::u64::MAX, core::u64::MAX], - ]; - - for vec in multiple_amounts.iter() { - assert!(zero_balance_verify(vec, vec, 0)); - assert!(zero_balance_verify(vec, vec, 1)); - assert!(zero_balance_verify(vec, vec, vec.len() / 2)); - assert!(zero_balance_verify(vec, vec, vec.len() / 2 + 1)); - } - - // Test when ours is empty - assert!(zero_balance_verify(&multiple_amounts[2], &multiple_amounts[2], 0)); - - // Test when theirs is empty - assert!(zero_balance_verify( - &multiple_amounts[4], - &multiple_amounts[4], - multiple_amounts[4].len() - )); - } - - #[test] - fn test_zero_balance_negative() { - // Test when input.sum() != output.sum() - // When they only differ by 1 - // When they differ by core::u64::MAX - assert!(!zero_balance_verify( - &[0u64, 1u64, 0u64, 1u64], - &[1u64, 2u64, 3u64, core::u64::MAX], - 2 - )); - assert!(!zero_balance_verify( - &[1u64, 2u64, 3u64, core::u64::MAX], - &[10u64, 20u64, 30u64, 40u64], - 2 - )); - assert!(!zero_balance_verify( - &[10u64, 20u64, 30u64, 40u64], - &[0u64, 197642u64, core::u64::MAX, 476543u64], - 2 - )); - assert!(!zero_balance_verify( - &[0u64, 197642u64, core::u64::MAX, 476543u64], - &[core::u64::MAX, core::u64::MAX, core::u64::MAX, core::u64::MAX], - 2 - )); - assert!(!zero_balance_verify(&[1, 2, 3, 4], &[1, 2, 3, 5], 2)); - assert!(!zero_balance_verify(&[1, 2, 3, 0], &[1, 2, 3, core::u64::MAX], 2)); - } - - #[test] - fn test_zero_balance_random() { - let mut rng = thread_rng(); - - // Test random inputs and outputs - // Randomly distributed between ours and theirs allocation - for _ in 0..5 { - // Randomly generate number of amounts between 1 to 20 - let input_length = rng.gen_range(1..=20); - - // Randomly fill the amount vector - let mut input_amounts = vec![0; input_length]; - for index in 0..input_length { - // keep the amount value low for faster testing - input_amounts[index] = rng.gen_range::(100_000..=100_000_000_000); - } - let input_sum: u64 = input_amounts.iter().sum(); - - // Create an output amount vector such that - // input.sum() = output.sum(), but - // input.count() != output.count() - - let mut output_amounts = vec![0u64; rng.gen_range(1..=20)]; - let output_length = output_amounts.len(); - - // Add random values to output amounts until the last element - for index in 0..output_length - 1 { - output_amounts[index] = rng.gen_range::(100_000..=100_000_000_000); - } - let output_sum: u64 = output_amounts.iter().sum(); - - // Balance input and output amount vector based on their sums - if input_sum == output_sum { - continue; - } else if output_sum > input_sum { - input_amounts[input_length - 1] += output_sum - input_sum; - } else { - output_amounts[output_length - 1] += input_sum - output_sum; - } - - let (inputs, outputs) = zero_balance( - &input_amounts[..], - &output_amounts[..], - rng.gen_range(0..=output_length), - ); - // Check if test passes - assert!(value::Confidential::verify_commit_sum(&inputs, &outputs)); - - // Check non-equivalent amounts do not verify - if input_length > 1 { - assert_eq!( - value::Confidential::verify_commit_sum(&inputs[..(input_length - 1)], &outputs), - false - ); - } else if output_length > 1 { - assert_eq!( - value::Confidential::verify_commit_sum( - &inputs, - &outputs[..(output_length - 1)] - ), - false - ); - } - } - } - - #[test] - #[ignore] - fn test_identification() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Check correct types are being identified - // and wrong types return false - assert!(declarative_type.is_declarative()); - assert!(pedersan_type.has_value()); - assert!(hash_type.has_data()); - assert!(!declarative_type.has_data()); - assert!(!declarative_type.has_value()); - assert!(!pedersan_type.is_declarative()); - assert!(!pedersan_type.has_data()); - assert!(!hash_type.is_declarative()); - assert!(!hash_type.has_value()); - } - - #[test] - #[ignore] - fn test_extraction() { - let mut declarative_type = - TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let mut pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let mut hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Check Correct type extraction works - assert!(!declarative_type.to_declarative_assignments().is_empty()); - assert!(!pedersan_type.to_value_assignments().is_empty()); - assert!(!hash_type.to_data_assignments().is_empty()); - - // Check wrong type extraction doesn't work - assert!(declarative_type.to_value_assignments().is_empty()); - assert!(declarative_type.clone().into_data_assignments().is_empty()); - assert!(pedersan_type.to_declarative_assignments().is_empty()); - assert!(pedersan_type.clone().into_data_assignments().is_empty()); - assert!(hash_type.to_declarative_assignments().is_empty()); - assert!(hash_type.clone().into_value_assignments().is_empty()); - - // Check correct mutable type extraction works - assert!(declarative_type.declarative_assignments_mut().is_some()); - assert!(pedersan_type.value_assignments_mut().is_some()); - assert!(hash_type.data_assignments_mut().is_some()); - - // Check wrong mutable type extraction doesn't work - assert!(declarative_type.value_assignments_mut().is_none()); - assert!(declarative_type.data_assignments_mut().is_none()); - assert!(pedersan_type.declarative_assignments_mut().is_none()); - assert!(pedersan_type.data_assignments_mut().is_none()); - assert!(hash_type.declarative_assignments_mut().is_none()); - assert!(hash_type.value_assignments_mut().is_none()); - } - - #[test] - #[ignore] - fn test_seal_extraction() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Extract a specific Txid from each variants - let txid_1 = match declarative_type - .revealed_seal_at(2) - .unwrap() - .unwrap() - .outpoint() - { - Some(outpoint) => Some(outpoint.txid), - _ => None, - } - .unwrap() - .to_hex(); - - let txid_2 = match pedersan_type - .revealed_seal_at(0) - .unwrap() - .unwrap() - .outpoint() - { - Some(outpoint) => Some(outpoint.txid), - _ => None, - } - .unwrap() - .to_hex(); - - let txid_3 = match hash_type.revealed_seal_at(1).unwrap().unwrap().outpoint() { - Some(outpoint) => Some(outpoint.txid), - _ => None, - } - .unwrap() - .to_hex(); - - // Check extracted Txids matches with predetermined values - assert_eq!(txid_1, TXID_VEC[1]); - assert_eq!(txid_2, TXID_VEC[1]); - assert_eq!(txid_3, TXID_VEC[1]); - } - - #[test] - #[ignore] - fn test_known_seals() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Extract known Txids from each variants - let mut dec_txids: Vec = declarative_type - .filter_revealed_seals() - .iter() - .map(|revealed| { - match revealed.outpoint() { - Some(outpoint) => Some(outpoint.txid), - _ => None, - } - .unwrap() - .to_hex() - }) - .collect(); - - let mut ped_txids: Vec = pedersan_type - .filter_revealed_seals() - .iter() - .map(|revealed| { - match revealed.outpoint() { - Some(outpoint) => Some(outpoint.txid), - _ => None, - } - .unwrap() - .to_hex() - }) - .collect(); - - let mut hash_txids: Vec = hash_type - .filter_revealed_seals() - .iter() - .map(|revealed| { - match revealed.outpoint() { - Some(outpoint) => Some(outpoint.txid), - _ => None, - } - .unwrap() - .to_hex() - }) - .collect(); - - // Sort the extracted Txids - dec_txids.sort(); - ped_txids.sort(); - hash_txids.sort(); - - // Predetermined values - let mut sorted_txid = TXID_VEC[..2].to_vec().clone(); - sorted_txid.sort(); - - // Check extracted values matches with predetermined values - assert_eq!(dec_txids, sorted_txid); - assert_eq!(ped_txids, sorted_txid); - assert_eq!(hash_txids, sorted_txid); - } - - #[test] - #[ignore] - fn test_all_seals() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Extract seals from all variants and conceal them - let mut dec_hashes: Vec = declarative_type - .to_confidential_seals() - .iter() - .map(|hash| hash.to_hex()) - .collect(); - - let mut ped_hashes: Vec = pedersan_type - .to_confidential_seals() - .iter() - .map(|hash| hash.to_hex()) - .collect(); - - let mut hash_hashes: Vec = hash_type - .to_confidential_seals() - .iter() - .map(|hash| hash.to_hex()) - .collect(); - - // Sort the concealed seals - dec_hashes.sort(); - ped_hashes.sort(); - hash_hashes.sort(); - - // Check extracted values matches with precomputed values - assert_eq!(dec_hashes, DECLARATIVE_OUTPOINT_HASH); - assert_eq!(ped_hashes, PEDERSAN_OUTPOINT_HASH); - assert_eq!(hash_hashes, HASH_OUTPOINT_HASH); - } - - #[test] - #[ignore] - fn test_known_state_homomorphic() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Extract known states from pedersan type variant - let states = pedersan_type.filter_revealed_state_values(); - - // Check the amounts matches with precomputed values - assert_eq!(states[0].value, 10); - assert_eq!(states[1].value, 30); - - // Precomputed blinding factors - let blind_1: Vec = - Vec::from_hex("debbbefd1683e335296a0c86f1c882a2ea3759f114220b0b2cf869e37dec24c8") - .unwrap(); - let blind_2: Vec = - Vec::from_hex("5d3574c4d99c08ef950619be72bfa1d50ae3c153d1f30f64bc1ac08de99ea556") - .unwrap(); - - // Check blinding factor matches with precomputed values - assert_eq!( - SecretKey::from(states[0].blinding), - SecretKey::from_slice(&blind_1[..]).unwrap() - ); - assert_eq!( - SecretKey::from(states[1].blinding), - SecretKey::from_slice(&blind_2[..]).unwrap() - ); - - // Check no values returned for declarative and custom data type - // variants - assert_eq!(declarative_type.filter_revealed_state_values().len(), 0); - assert_eq!(hash_type.filter_revealed_state_values().len(), 0); - } - - #[test] - #[ignore] - fn test_known_state_data() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Extract known states from custom data type variant - let data_set = hash_type.filter_revealed_state_data(); - - // Create state data from precomputed values - 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); - assert_eq!(data_set[1].to_owned(), data_2); - - // Check no values returned for declarative and pedersan type variants - assert_eq!(declarative_type.filter_revealed_state_data().len(), 0); - assert_eq!(pedersan_type.filter_revealed_state_data().len(), 0); - } - - #[test] - #[ignore] - fn test_all_state_pedersan() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Extract state data for pedersan type and conceal them - let conf_amounts = pedersan_type.to_confidential_state_pedersen(); - - // Check extracted values matches with precomputed values - assert_eq!( - conf_amounts[0].commitment, - PedersenCommitment::from_slice( - &Vec::from_hex( - "08cc48fa5e5cb1d2d2465bd8c437c0e00514abd813f9a7dd506a778405a2c43bc0" - ) - .unwrap() - ) - .unwrap() - ); - assert_eq!( - conf_amounts[1].commitment, - PedersenCommitment::from_slice( - &Vec::from_hex( - "091e1b9e7605fc214806f3af3eba13947b91f47bac729f5def5e8fbd530112bed1" - ) - .unwrap() - ) - .unwrap() - ); - assert_eq!( - conf_amounts[2].commitment, - PedersenCommitment::from_slice( - &Vec::from_hex( - "089775f829c8adad92ada17b5931edf63064d54678f4eb9a6fdfe8e4cb5d95f6f4" - ) - .unwrap() - ) - .unwrap() - ); - - // Check no values returned for declarative and hash type - assert_eq!(declarative_type.to_confidential_state_pedersen().len(), 0); - assert_eq!(hash_type.to_confidential_state_pedersen().len(), 0); - } - - #[test] - #[ignore] - fn test_all_state_hashed() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // Extract state data from hash type variant and conceal them - let extracted_states = hash_type.to_confidential_state_hashed(); - - // Precomputed concealed state data - let expected: [&str; 4] = [ - "fa6eae3e74de3e5dd92f58ac753d02b613daaaab", - "6420cc421e1189805c8cec089d74c1980f79c069", - "43e446006c5bc93864dafb03cf4ba472bedf5ca7", - "69b01b4d96d00ceff2599eb089e4c7b979961fec", - ]; - - // Check extracted values matches with precomputed values - assert_eq!( - extracted_states - .iter() - .map(|hash| hash.to_hex()) - .collect::>(), - expected - ); - - // Check no values returned for declarative and pedersan types - assert_eq!(declarative_type.to_confidential_state_hashed().len(), 0); - assert_eq!(pedersan_type.to_confidential_state_hashed().len(), 0); - } - - #[test] - #[ignore] - fn test_conceal() { - // Only hash type is considered for concealment operations because - // Declarative type has void state data - // Pedersan type has very large concealed state data which slows down - // the test - let mut hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // CommitConceal all without any exception - // This will create 2 Confidential and 2 ConfidentialState type - // Assignments - assert_eq!(2, hash_type.conceal_state()); - - // Precomputed values of revealed seals in 2 ConfidentialState type - // Assignments - let known_txid: [&str; 2] = [ - "f57ed27ee4199072c5ff3b774febc94d26d3e4a5559d133de4750a948df50e06", - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e", - ]; - - // Extracted seal values - let extracted_txid: Vec = hash_type - .filter_revealed_seals() - .iter() - .map(|revealed| { - match revealed.outpoint() { - Some(outpoint) => Some(outpoint.txid), - _ => None, - } - .unwrap() - .to_hex() - }) - .collect(); - - // Check extracted values matches with precomputed values - assert_eq!(known_txid.to_vec(), extracted_txid); - - // Precomputed of concealed seals of all 4 assignments - let all_seals_confidential: [&str; 4] = [ - "7efe71b7a37a39da798774ca6b09def9724d81303892d55cac3edb0dc8340a3a", - "9565d29461c863e013c26d176a9929307286963322849a1dc6c978e5c70c8d52", - "dc0d0d7139a3ad6010a210e5900201979a1a09047b10a877688ee5a740ae215a", - "9b64a3024632f0517d8a608cb29902f7083eab0ac25d2827a5ef27e9a68b18f9", - ]; - - // Extract concealed seals - let extracted_seals_confidential: Vec = hash_type - .to_confidential_seals() - .iter() - .map(|hash| hash.to_hex()) - .collect(); - - // Check extracted values matches with precomputed values - assert_eq!(all_seals_confidential.to_vec(), extracted_seals_confidential); - - // Precomputed concealed state data of all 4 assignments - let all_state_confidential = [ - "fa6eae3e74de3e5dd92f58ac753d02b613daaaab", - "6420cc421e1189805c8cec089d74c1980f79c069", - "43e446006c5bc93864dafb03cf4ba472bedf5ca7", - "69b01b4d96d00ceff2599eb089e4c7b979961fec", - ]; - - // Extract concealed state data - let extracted_state_confidential: Vec = hash_type - .to_confidential_state_hashed() - .iter() - .map(|confidential| confidential.to_hex()) - .collect(); - - // Check extracted values matches with precomputed values - assert_eq!(all_state_confidential.to_vec(), extracted_state_confidential); - } - - #[test] - #[ignore] - fn test_len() { - let declarative_type = TypedAssignments::strict_decode(&DECLARATIVE_VARIANT[..]).unwrap(); - let pedersan_type = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]).unwrap(); - let hash_type = TypedAssignments::strict_decode(&HASH_VARIANT[..]).unwrap(); - - // All variants have 4 assignments in them - assert_eq!(declarative_type.len(), 4); - assert_eq!(pedersan_type.len(), 4); - assert_eq!(hash_type.len(), 4); - } - - #[test] - fn test_encoding_ancestor() { - let _: ParentOwnedRights = test_vec_decoding_roundtrip(PARENT_RIGHTS).unwrap(); - } - - #[test] - #[should_panic(expected = "UnexpectedEof")] - fn test_garbage_ancestor() { - let mut data = PARENT_RIGHTS.clone(); - data[0] = 0x36 as u8; - ParentOwnedRights::strict_decode(&data[..]).unwrap(); - } - - // This doesn't use the merkelize() function - // And constructs the flow by hand for a single element - // merkelization process - #[test] - fn test_parent_rights_encoding_simple() { - // Create the simplest possible ancestor structure - // Parent Rights = Map> - let mut assignment = BTreeMap::new(); - let data = 0u16; - let ty = 2 as schema::OwnedRightType; - assignment.insert(ty, vec![data]); - - let nodeid = NodeId::default(); - let mut parent_rights = ParentOwnedRights::default(); - parent_rights.as_mut().insert(nodeid, assignment); - - let mut original_commit = vec![]; - parent_rights - .to_merkle_source() - .commit_encode(&mut original_commit); // Merkelizes the structure into buf - - // Perform encoding by hand - // We only have one leaf tupple - // leaf = (NodqeId::default(), ty, 0u16); - - // Encode the leaf via strict encoding - let mut encoded_leaf = vec![]; - NodeId::default().strict_encode(&mut encoded_leaf).unwrap(); - ty.strict_encode(&mut encoded_leaf).unwrap(); - 0u16.strict_encode(&mut encoded_leaf).unwrap(); - - // take the hash of the encoded data as a MerkleNode - let merkle_node = MerkleNode::hash(&encoded_leaf[..]); - - // merkelize the node with correct tag - let (root, _) = merklize("parent_owned_right", [merkle_node]); - - // Commit encode the resulting merkle root - let handmade_commit = root.commit_serialize(); - - // This should match with original encoding - assert_eq!(original_commit, handmade_commit); - } - - /* - // Helper to create merkleroot from single merklenode - fn merkle_single(m: MerkleNode) -> MerkleNode { - let mut engine2 = MerkleNode::engine(); - let tag = format!("{}:merkle:{}", "", 0); - let tag_hash = sha256::Hash::hash(tag.as_bytes()); - engine2.input(&tag_hash[..]); - engine2.input(&tag_hash[..]); - m.strict_encode(&mut engine2).unwrap(); - 0u8.strict_encode(&mut engine2).unwrap(); - MerkleNode::from_engine(engine2) - } - */ - - // This uses merkelize() function handle multiple values - #[test] - fn test_ancestor_encoding_complex() { - // Create three random vector as assignment variants - let mut vec1 = vec![]; - let mut rng = thread_rng(); - for i in 0..6 { - vec1.insert(i, rng.next_u64() as u16); - } - - let mut vec2 = vec![]; - let mut rng = thread_rng(); - for i in 0..17 { - vec2.insert(i, rng.next_u64() as u16); - } - - let mut vec3 = vec![]; - let mut rng = thread_rng(); - for i in 0..11 { - vec3.insert(i, rng.next_u64() as u16); - } - - // Create 3 assignment type - let type1 = 1 as schema::OwnedRightType; - let type2 = 2 as schema::OwnedRightType; - let type3 = 3 as schema::OwnedRightType; - - // Create 1 NodeID - let node_id = NodeId::default(); - - // Construct assignments - let mut assignments = BTreeMap::new(); - assignments.insert(type1, vec1.clone()); - assignments.insert(type2, vec2.clone()); - assignments.insert(type3, vec3.clone()); - - // Construct ancestor - let mut parent_rights = ParentOwnedRights::default(); - parent_rights.as_mut().insert(node_id, assignments); - - // get the commit encoding - let mut original_commit = vec![]; - parent_rights - .to_merkle_source() - .commit_encode(&mut original_commit); - - // Make commitment by hand - // Create the leaf tupples - - let vec_1: Vec<(NodeId, schema::OwnedRightType, u16)> = vec1 - .iter() - .map(|i| (NodeId::default(), type1, *i)) - .collect(); - let vec_2: Vec<(NodeId, schema::OwnedRightType, u16)> = vec2 - .iter() - .map(|i| (NodeId::default(), type2, *i)) - .collect(); - let vec_3: Vec<(NodeId, schema::OwnedRightType, u16)> = vec3 - .iter() - .map(|i| (NodeId::default(), type3, *i)) - .collect(); - - // Combine all to create the final tupple list - let vec_4: Vec<(NodeId, schema::OwnedRightType, u16)> = [vec_1, vec_2, vec_3].concat(); - - // Strict encode each tupple - // hash the encoding - // convert each hash into a MerkleNode - let nodes: Vec = vec_4 - .into_iter() - .map(|item| -> MerkleNode { - let mut e = vec![]; - item.0.strict_encode(&mut e).unwrap(); - item.1.strict_encode(&mut e).unwrap(); - item.2.strict_encode(&mut e).unwrap(); - - MerkleNode::hash(&e[..]) - }) - .collect(); - - // Calculate Merkle Root for the the above nodes - let (root, _) = merklize("parent_owned_right", nodes); - - // Commit encode the root - let handmade_commit = root.commit_serialize(); - - // This should match with the original encoding - assert_eq!(original_commit, handmade_commit); - } - - #[test] - fn test_commitencode_assignments() { - //Create Declerative variant - - let mut rng = thread_rng(); - - let txid_vec: Vec = TXID_VEC - .iter() - .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) - .collect(); - - let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: data::Void(), - }; - - let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(Outpoint::new(txid_vec[1], 2)), - state: data::Void(), - }; - - let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(Outpoint::new(txid_vec[2], 3)).commit_conceal(), - state: data::Void(), - }; - - let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(Outpoint::new(txid_vec[3], 4)).commit_conceal(), - state: data::Void(), - }; - - let mut set = Vec::new(); - - set.push(assignment_1); - set.push(assignment_2); - set.push(assignment_3); - set.push(assignment_4); - - let declarative_variant = TypedAssignments::Void(set); - - // Create Pedersan Variant - - let txid_vec: Vec = TXID_VEC - .iter() - .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) - .collect(); - - let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: value::Revealed::with_amount(10u64, &mut rng), - }; - - let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), - state: value::Revealed::with_amount(20u64, &mut rng).commit_conceal(), - }; - - let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), - state: value::Revealed::with_amount(30u64, &mut rng), - }; - - let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), - state: value::Revealed::with_amount(10u64, &mut rng).commit_conceal(), - }; - - let mut set = Vec::new(); - - set.push(assignment_1); - set.push(assignment_2); - set.push(assignment_3); - set.push(assignment_4); - - let pedersen_variant = TypedAssignments::Value(set); - - // Create Hash variant - let txid_vec: Vec = TXID_VEC - .iter() - .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) - .collect(); - - let state_data_vec: Vec = STATE_DATA - .iter() - .map(|data| data::Revealed::Bytes(sha256::Hash::from_hex(data).unwrap().to_vec())) - .collect(); - - let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: state_data_vec[0].clone(), - }; - - let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), - state: state_data_vec[1].clone().commit_conceal(), - }; - - let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), - state: state_data_vec[2].clone(), - }; - - let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), - state: state_data_vec[3].clone().commit_conceal(), - }; - - let mut set = Vec::new(); - - set.push(assignment_1); - set.push(assignment_2); - set.push(assignment_3); - set.push(assignment_4); - - let hash_variant = TypedAssignments::Data(set); - - // Create assignemnts - - let type1 = 1 as schema::OwnedRightType; - let type2 = 2 as schema::OwnedRightType; - let type3 = 3 as schema::OwnedRightType; - let mut owned_rights = OwnedRights::default(); - owned_rights - .as_mut() - .insert(type1, declarative_variant.clone()); - owned_rights - .as_mut() - .insert(type2, pedersen_variant.clone()); - owned_rights.as_mut().insert(type3, hash_variant.clone()); - - let mut original_encoding = vec![]; - owned_rights - .to_merkle_source() - .commit_encode(&mut original_encoding); - - // Hand calculate commitment - // create individual leaves - let declarative_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = declarative_variant - .to_declarative_assignments() - .iter() - .map(|assignment| { - (type1, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) - }) - .collect(); - - let pedersan_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = pedersen_variant - .to_value_assignments() - .iter() - .map(|assignment| { - (type2, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) - }) - .collect(); - - let hash_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = hash_variant - .to_data_assignments() - .iter() - .map(|assignment| { - (type3, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) - }) - .collect(); - - // Combine all of them in a single collection - let all_leaves = [declarative_leaves, pedersan_leaves, hash_leaves].concat(); - - // create MerkleNodes from each leaf - let nodes: Vec = all_leaves - .iter() - .map(|item| MerkleNode::hash(&CommitEncode::commit_serialize(item))) - .collect(); - - // compute merkle root of all the nodes - let (root, _) = merklize("owned_right", nodes); - - // Commit encode the root - let handmade_encoding = root.commit_serialize(); - - // This should match with original encoding - assert_eq!(original_encoding, handmade_encoding); - } -} diff --git a/src/contract/metadata.rs b/src/contract/global_state.rs similarity index 100% rename from src/contract/metadata.rs rename to src/contract/global_state.rs diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 5e645b2d..7a9d9b41 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -22,19 +22,23 @@ pub mod seal; -mod conceal; -// pub mod reveal; +mod reveal_conceal; +// pub mod reveal+merge; pub mod value; pub mod attachment; pub mod data; -mod metadata; +mod global_state; +mod owned_state; // mod assignments; // mod rights; // pub mod nodes; pub use attachment::AttachId; -pub use conceal::{ConcealSeals, ConcealState}; +pub use global_state::{FieldValues, Metadata}; +pub use owned_state::{Assignment, State, StateType}; +pub use reveal_conceal::{ConcealSeals, ConcealState, RevealSeals}; +use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; // pub use reveal::{MergeReveal, RevealSeals}; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, @@ -47,7 +51,6 @@ pub use assignments::{ HashStrategy, PedersenStrategy, RevealedState, SealValueMap, State, StateType, TypedAssignments, }; -pub use metadata::Metadata; pub use nodes::{ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, Transition}; pub use rights::{OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights}; pub(crate) use rights::{OwnedRightsInner, PublicRightsInner}; @@ -56,11 +59,20 @@ pub use seal::{IntoRevealedSeal, SealEndpoint}; /// Marker trait for types of state which are just a commitment to the actual /// state data. -pub trait ConfidentialState: core::fmt::Debug + Clone + amplify::AsAny {} +pub trait ConfidentialState: + core::fmt::Debug + StrictDumb + StrictEncode + StrictDecode + Clone + amplify::AsAny +{ +} /// Marker trait for types of state holding explicit state data. pub trait RevealedState: - core::fmt::Debug + commit_verify::Conceal + Clone + amplify::AsAny + core::fmt::Debug + + StrictDumb + + commit_verify::Conceal + + StrictEncode + + StrictDecode + + Clone + + amplify::AsAny { } diff --git a/src/contract/nodes.rs b/src/contract/operations.rs similarity index 100% rename from src/contract/nodes.rs rename to src/contract/operations.rs diff --git a/src/contract/owned_state.rs b/src/contract/owned_state.rs new file mode 100644 index 00000000..1acc14f3 --- /dev/null +++ b/src/contract/owned_state.rs @@ -0,0 +1,763 @@ +// RGB Core Library: consensus layer for RGB smart contracts. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::cmp::Ordering; +use core::fmt::Debug; +use std::collections::HashMap; +use std::io; + +use commit_verify::{CommitEncode, Conceal}; +use strict_encoding::{StrictEncode, StrictWriter}; + +use super::{ + attachment, data, seal, value, ConcealSeals, ConcealState, ConfidentialState, RevealSeals, + RevealedState, +}; +use crate::LIB_NAME_RGB; + +/// Categories of the state +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +pub enum StateType { + /// No state data + Void, + + /// Value-based state, i.e. which can be committed to with a Pedersen + /// commitment + Value, + + /// State defined with custom data + Data, + + /// Attached data container + Attachment, +} +pub trait State: Debug { + type Confidential: ConfidentialState; + type Revealed: RevealedState; +} + +#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] +pub struct DeclarativeStrategy; +impl State for DeclarativeStrategy { + type Confidential = data::Void; + type Revealed = data::Void; +} + +#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] +pub struct PedersenStrategy; +impl State for PedersenStrategy { + type Confidential = value::Confidential; + type Revealed = value::Revealed; +} + +#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] +pub struct HashStrategy; +impl State for HashStrategy { + type Confidential = data::Confidential; + type Revealed = data::Revealed; +} + +#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] +pub struct AttachmentStrategy; +impl State for AttachmentStrategy { + type Confidential = attachment::Confidential; + type Revealed = attachment::Revealed; +} + +/// 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, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type( + lib = LIB_NAME_RGB, + tags = custom, + dumb = { Self::Confidential { seal: strict_dumb!(), state: strict_dumb!() } } +)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "snake_case") +)] +pub enum Assignment +where + StateType: State, + // Deterministic ordering requires Eq operation, so the confidential + // state must have it + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + #[strict_type(tag = 0x00)] + Confidential { + seal: seal::Confidential, + state: StateType::Confidential, + }, + #[strict_type(tag = 0x04)] + Revealed { + seal: seal::Revealed, + state: StateType::Revealed, + }, + #[strict_type(tag = 0x02)] + ConfidentialSeal { + seal: seal::Confidential, + state: StateType::Revealed, + }, + #[strict_type(tag = 0x01)] + ConfidentialState { + seal: seal::Revealed, + state: StateType::Confidential, + }, +} + +// Consensus-critical! +// Assignment indexes are part of the transition ancestor's commitment, so +// here we use deterministic ordering based on hash values of the concealed +// seal data contained within the assignment +impl PartialOrd for Assignment +where + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + fn partial_cmp(&self, other: &Self) -> Option { + self.to_confidential_seal() + .partial_cmp(&other.to_confidential_seal()) + } +} + +impl Ord for Assignment +where + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + fn cmp(&self, other: &Self) -> Ordering { + self.to_confidential_seal() + .cmp(&other.to_confidential_seal()) + } +} + +impl PartialEq for Assignment +where + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + fn eq(&self, other: &Self) -> bool { + self.to_confidential_seal() == other.to_confidential_seal() && + self.to_confidential_state() == other.to_confidential_state() + } +} + +impl Eq for Assignment +where + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ +} + +impl Assignment +where + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + pub fn revealed(seal: seal::Revealed, state: StateType::Revealed) -> Self { + Assignment::Revealed { seal, state } + } + + pub fn with_seal_replaced(assignment: &Self, seal: seal::Revealed) -> Self { + match assignment { + Assignment::Confidential { seal: _, state } | + Assignment::ConfidentialState { seal: _, state } => Assignment::ConfidentialState { + seal, + state: state.clone(), + }, + Assignment::ConfidentialSeal { seal: _, state } | + Assignment::Revealed { seal: _, state } => Assignment::Revealed { + seal, + state: state.clone(), + }, + } + } + + pub fn to_confidential_seal(&self) -> seal::Confidential { + match self { + Assignment::Revealed { seal, .. } | Assignment::ConfidentialState { seal, .. } => { + seal.conceal() + } + Assignment::Confidential { seal, .. } | Assignment::ConfidentialSeal { seal, .. } => { + *seal + } + } + } + + pub fn revealed_seal(&self) -> Option { + match self { + Assignment::Revealed { seal, .. } | Assignment::ConfidentialState { seal, .. } => { + Some(*seal) + } + Assignment::Confidential { .. } | Assignment::ConfidentialSeal { .. } => None, + } + } + + pub fn to_confidential_state(&self) -> StateType::Confidential { + match self { + Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { + state.conceal().into() + } + Assignment::Confidential { state, .. } | + Assignment::ConfidentialState { state, .. } => state.clone(), + } + } + + pub fn as_revealed_state(&self) -> Option<&StateType::Revealed> { + match self { + Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { + Some(state) + } + Assignment::Confidential { .. } | Assignment::ConfidentialState { .. } => None, + } + } + + pub fn as_revealed(&self) -> Option<(&seal::Revealed, &StateType::Revealed)> { + match self { + Assignment::Revealed { seal, state } => Some((seal, state)), + _ => None, + } + } + + pub fn to_revealed(&self) -> Option<(seal::Revealed, StateType::Revealed)> { + match self { + Assignment::Revealed { seal, state } => Some((*seal, state.clone())), + _ => None, + } + } + + pub fn into_revealed(self) -> Option<(seal::Revealed, StateType::Revealed)> { + match self { + Assignment::Revealed { seal, state } => Some((seal, state)), + _ => None, + } + } +} + +impl Conceal for Assignment +where + Self: Clone, + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + type Concealed = Self; + + fn conceal(&self) -> Self::Concealed { + match self { + Assignment::Confidential { .. } => self.clone(), + Assignment::ConfidentialState { seal, state } => Self::Confidential { + seal: seal.conceal(), + state: state.clone(), + }, + Assignment::Revealed { seal, state } => Self::Confidential { + seal: seal.conceal(), + state: state.conceal().into(), + }, + Assignment::ConfidentialSeal { seal, state } => Self::Confidential { + seal: *seal, + state: state.conceal().into(), + }, + } + } +} + +impl RevealSeals for Assignment +where + StateType: State, + StateType::Revealed: Conceal, + StateType::Confidential: PartialEq + Eq, + ::Confidential: From<::Concealed>, +{ + fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize { + let known_seals: HashMap = known_seals + .iter() + .map(|rev| (rev.conceal(), *rev)) + .collect(); + + let mut counter = 0; + match self { + Assignment::Confidential { seal, state } => { + if let Some(reveal) = known_seals.get(seal) { + *self = Assignment::ConfidentialState { + seal: *reveal, + state: state.clone(), + }; + counter += 1; + }; + } + Assignment::ConfidentialSeal { seal, state } => { + if let Some(reveal) = known_seals.get(seal) { + *self = Assignment::Revealed { + seal: *reveal, + state: state.clone(), + }; + counter += 1; + }; + } + _ => {} + } + counter + } +} + +impl ConcealSeals for Assignment +where + StateType: State, + StateType::Revealed: Conceal, + StateType::Confidential: PartialEq + Eq, + ::Confidential: From<::Concealed>, +{ + fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { + match self { + Assignment::Confidential { .. } | Assignment::ConfidentialSeal { .. } => 0, + Assignment::ConfidentialState { seal, state } => { + if seals.contains(&seal.conceal()) { + *self = Assignment::::Confidential { + state: state.clone(), + seal: seal.conceal(), + }; + 1 + } else { + 0 + } + } + Assignment::Revealed { seal, state } => { + if seals.contains(&seal.conceal()) { + *self = Assignment::::ConfidentialSeal { + state: state.clone(), + seal: seal.conceal(), + }; + 1 + } else { + 0 + } + } + } + } +} + +impl ConcealState for Assignment +where + StateType: State, + StateType::Revealed: Conceal, + StateType::Confidential: PartialEq + Eq, + ::Confidential: From<::Concealed>, +{ + fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { + match self { + Assignment::Confidential { .. } | Assignment::ConfidentialState { .. } => 0, + Assignment::ConfidentialSeal { seal, state } => { + if seals.contains(seal) { + 0 + } else { + *self = Assignment::::Confidential { + state: state.conceal().into(), + seal: *seal, + }; + 1 + } + } + Assignment::Revealed { seal, state } => { + if seals.contains(&seal.conceal()) { + 0 + } else { + *self = Assignment::::ConfidentialState { + state: state.conceal().into(), + seal: *seal, + }; + 1 + } + } + } + } +} + +// We can't use `UsingConceal` strategy here since it relies on the +// `commit_encode` of the concealed type, and here the concealed type is again +// `OwnedState`, leading to a recurrency. So we use `strict_encode` of the +// concealed data. +impl CommitEncode for Assignment +where + Self: Clone, + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + fn commit_encode(&self, e: &mut impl io::Write) { + let w = StrictWriter::with(u32::MAX as usize, e); + self.conceal().strict_encode(w).ok(); + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_encoding_ancestor() { + let _: ParentOwnedRights = test_vec_decoding_roundtrip(PARENT_RIGHTS).unwrap(); + } + + #[test] + #[should_panic(expected = "UnexpectedEof")] + fn test_garbage_ancestor() { + let mut data = PARENT_RIGHTS.clone(); + data[0] = 0x36 as u8; + ParentOwnedRights::strict_decode(&data[..]).unwrap(); + } + + // This doesn't use the merkelize() function + // And constructs the flow by hand for a single element + // merkelization process + #[test] + fn test_parent_rights_encoding_simple() { + // Create the simplest possible ancestor structure + // Parent Rights = Map> + let mut assignment = BTreeMap::new(); + let data = 0u16; + let ty = 2 as schema::OwnedRightType; + assignment.insert(ty, vec![data]); + + let nodeid = NodeId::default(); + let mut parent_rights = ParentOwnedRights::default(); + parent_rights.as_mut().insert(nodeid, assignment); + + let mut original_commit = vec![]; + parent_rights + .to_merkle_source() + .commit_encode(&mut original_commit); // Merkelizes the structure into buf + + // Perform encoding by hand + // We only have one leaf tupple + // leaf = (NodqeId::default(), ty, 0u16); + + // Encode the leaf via strict encoding + let mut encoded_leaf = vec![]; + NodeId::default().strict_encode(&mut encoded_leaf).unwrap(); + ty.strict_encode(&mut encoded_leaf).unwrap(); + 0u16.strict_encode(&mut encoded_leaf).unwrap(); + + // take the hash of the encoded data as a MerkleNode + let merkle_node = MerkleNode::hash(&encoded_leaf[..]); + + // merkelize the node with correct tag + let (root, _) = merklize("parent_owned_right", [merkle_node]); + + // Commit encode the resulting merkle root + let handmade_commit = root.commit_serialize(); + + // This should match with original encoding + assert_eq!(original_commit, handmade_commit); + } + + /* + // Helper to create merkleroot from single merklenode + fn merkle_single(m: MerkleNode) -> MerkleNode { + let mut engine2 = MerkleNode::engine(); + let tag = format!("{}:merkle:{}", "", 0); + let tag_hash = sha256::Hash::hash(tag.as_bytes()); + engine2.input(&tag_hash[..]); + engine2.input(&tag_hash[..]); + m.strict_encode(&mut engine2).unwrap(); + 0u8.strict_encode(&mut engine2).unwrap(); + MerkleNode::from_engine(engine2) + } + */ + + // This uses merkelize() function handle multiple values + #[test] + fn test_ancestor_encoding_complex() { + // Create three random vector as assignment variants + let mut vec1 = vec![]; + let mut rng = thread_rng(); + for i in 0..6 { + vec1.insert(i, rng.next_u64() as u16); + } + + let mut vec2 = vec![]; + let mut rng = thread_rng(); + for i in 0..17 { + vec2.insert(i, rng.next_u64() as u16); + } + + let mut vec3 = vec![]; + let mut rng = thread_rng(); + for i in 0..11 { + vec3.insert(i, rng.next_u64() as u16); + } + + // Create 3 assignment type + let type1 = 1 as schema::OwnedRightType; + let type2 = 2 as schema::OwnedRightType; + let type3 = 3 as schema::OwnedRightType; + + // Create 1 NodeID + let node_id = NodeId::default(); + + // Construct assignments + let mut assignments = BTreeMap::new(); + assignments.insert(type1, vec1.clone()); + assignments.insert(type2, vec2.clone()); + assignments.insert(type3, vec3.clone()); + + // Construct ancestor + let mut parent_rights = ParentOwnedRights::default(); + parent_rights.as_mut().insert(node_id, assignments); + + // get the commit encoding + let mut original_commit = vec![]; + parent_rights + .to_merkle_source() + .commit_encode(&mut original_commit); + + // Make commitment by hand + // Create the leaf tupples + + let vec_1: Vec<(NodeId, schema::OwnedRightType, u16)> = vec1 + .iter() + .map(|i| (NodeId::default(), type1, *i)) + .collect(); + let vec_2: Vec<(NodeId, schema::OwnedRightType, u16)> = vec2 + .iter() + .map(|i| (NodeId::default(), type2, *i)) + .collect(); + let vec_3: Vec<(NodeId, schema::OwnedRightType, u16)> = vec3 + .iter() + .map(|i| (NodeId::default(), type3, *i)) + .collect(); + + // Combine all to create the final tupple list + let vec_4: Vec<(NodeId, schema::OwnedRightType, u16)> = [vec_1, vec_2, vec_3].concat(); + + // Strict encode each tupple + // hash the encoding + // convert each hash into a MerkleNode + let nodes: Vec = vec_4 + .into_iter() + .map(|item| -> MerkleNode { + let mut e = vec![]; + item.0.strict_encode(&mut e).unwrap(); + item.1.strict_encode(&mut e).unwrap(); + item.2.strict_encode(&mut e).unwrap(); + + MerkleNode::hash(&e[..]) + }) + .collect(); + + // Calculate Merkle Root for the the above nodes + let (root, _) = merklize("parent_owned_right", nodes); + + // Commit encode the root + let handmade_commit = root.commit_serialize(); + + // This should match with the original encoding + assert_eq!(original_commit, handmade_commit); + } + + #[test] + fn test_commitencode_assignments() { + //Create Declerative variant + + let mut rng = thread_rng(); + + let txid_vec: Vec = TXID_VEC + .iter() + .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) + .collect(); + + let assignment_1 = Assignment::::Revealed { + seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), + state: data::Void(), + }; + + let assignment_2 = Assignment::::ConfidentialState { + seal: Revealed::from(Outpoint::new(txid_vec[1], 2)), + state: data::Void(), + }; + + let assignment_3 = Assignment::::ConfidentialSeal { + seal: Revealed::from(Outpoint::new(txid_vec[2], 3)).commit_conceal(), + state: data::Void(), + }; + + let assignment_4 = Assignment::::Confidential { + seal: Revealed::from(Outpoint::new(txid_vec[3], 4)).commit_conceal(), + state: data::Void(), + }; + + let mut set = Vec::new(); + + set.push(assignment_1); + set.push(assignment_2); + set.push(assignment_3); + set.push(assignment_4); + + let declarative_variant = TypedAssignments::Void(set); + + // Create Pedersan Variant + + let txid_vec: Vec = TXID_VEC + .iter() + .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) + .collect(); + + let assignment_1 = Assignment::::Revealed { + seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), + state: value::Revealed::with_amount(10u64, &mut rng), + }; + + let assignment_2 = Assignment::::ConfidentialState { + seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), + state: value::Revealed::with_amount(20u64, &mut rng).commit_conceal(), + }; + + let assignment_3 = Assignment::::ConfidentialSeal { + seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), + state: value::Revealed::with_amount(30u64, &mut rng), + }; + + let assignment_4 = Assignment::::Confidential { + seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), + state: value::Revealed::with_amount(10u64, &mut rng).commit_conceal(), + }; + + let mut set = Vec::new(); + + set.push(assignment_1); + set.push(assignment_2); + set.push(assignment_3); + set.push(assignment_4); + + let pedersen_variant = TypedAssignments::Value(set); + + // Create Hash variant + let txid_vec: Vec = TXID_VEC + .iter() + .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) + .collect(); + + let state_data_vec: Vec = STATE_DATA + .iter() + .map(|data| data::Revealed::Bytes(sha256::Hash::from_hex(data).unwrap().to_vec())) + .collect(); + + let assignment_1 = Assignment::::Revealed { + seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), + state: state_data_vec[0].clone(), + }; + + let assignment_2 = Assignment::::ConfidentialState { + seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), + state: state_data_vec[1].clone().commit_conceal(), + }; + + let assignment_3 = Assignment::::ConfidentialSeal { + seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), + state: state_data_vec[2].clone(), + }; + + let assignment_4 = Assignment::::Confidential { + seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), + state: state_data_vec[3].clone().commit_conceal(), + }; + + let mut set = Vec::new(); + + set.push(assignment_1); + set.push(assignment_2); + set.push(assignment_3); + set.push(assignment_4); + + let hash_variant = TypedAssignments::Data(set); + + // Create assignemnts + + let type1 = 1 as schema::OwnedRightType; + let type2 = 2 as schema::OwnedRightType; + let type3 = 3 as schema::OwnedRightType; + let mut owned_rights = OwnedRights::default(); + owned_rights + .as_mut() + .insert(type1, declarative_variant.clone()); + owned_rights + .as_mut() + .insert(type2, pedersen_variant.clone()); + owned_rights.as_mut().insert(type3, hash_variant.clone()); + + let mut original_encoding = vec![]; + owned_rights + .to_merkle_source() + .commit_encode(&mut original_encoding); + + // Hand calculate commitment + // create individual leaves + let declarative_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = declarative_variant + .to_declarative_assignments() + .iter() + .map(|assignment| { + (type1, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) + }) + .collect(); + + let pedersan_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = pedersen_variant + .to_value_assignments() + .iter() + .map(|assignment| { + (type2, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) + }) + .collect(); + + let hash_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = hash_variant + .to_data_assignments() + .iter() + .map(|assignment| { + (type3, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) + }) + .collect(); + + // Combine all of them in a single collection + let all_leaves = [declarative_leaves, pedersan_leaves, hash_leaves].concat(); + + // create MerkleNodes from each leaf + let nodes: Vec = all_leaves + .iter() + .map(|item| MerkleNode::hash(&CommitEncode::commit_serialize(item))) + .collect(); + + // compute merkle root of all the nodes + let (root, _) = merklize("owned_right", nodes); + + // Commit encode the root + let handmade_encoding = root.commit_serialize(); + + // This should match with original encoding + assert_eq!(original_encoding, handmade_encoding); + } +} diff --git a/src/contract/conceal.rs b/src/contract/reveal_conceal.rs similarity index 90% rename from src/contract/conceal.rs rename to src/contract/reveal_conceal.rs index dc8946e9..366e16da 100644 --- a/src/contract/conceal.rs +++ b/src/contract/reveal_conceal.rs @@ -28,6 +28,18 @@ use amplify::confinement::{Collection, Confined}; use super::seal; +pub trait RevealSeals { + /// Reveals previously known seal information (replacing blind UTXOs with + /// unblind ones). Function is used when a peer receives consignments + /// containing concealed seals for the outputs owned by the peer. + /// + /// # Returns + /// + /// Total number of seals revealed inside the data structure during the + /// operation. + fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize; +} + /// Trait which must be implemented by all data structures having seals in their /// hierarchy. pub trait ConcealSeals { diff --git a/src/contract/reveal.rs b/src/contract/reveal_merge.rs similarity index 100% rename from src/contract/reveal.rs rename to src/contract/reveal_merge.rs From d98b503377c867c59ef3cf648b321356ceb20a6b Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 21:29:52 +0100 Subject: [PATCH 43/71] contract: refactor assignments --- src/contract/assignments.rs | 134 +++++++++++++----------------------- src/contract/mod.rs | 10 +-- src/contract/owned_state.rs | 14 +++- 3 files changed, 62 insertions(+), 96 deletions(-) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index c0806958..8cf2b75c 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -20,21 +20,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use core::cmp::Ordering; -use core::fmt::Debug; -use std::collections::{BTreeMap, HashMap}; -use std::hash::Hasher; -use std::io; - -use amplify::AsAny; +use amplify::confinement::{Confined, TinyVec}; use commit_verify::merkle::MerkleNode; -use commit_verify::CommitEncode; -use once_cell::sync::Lazy; +use commit_verify::CommitmentId; -use super::{data, seal, value, ConcealSeals, ConcealState, NoDataError, SealEndpoint}; -use crate::contract::attachment; -use crate::value::BlindingFactor; -use crate::{AtomicValue, ConfidentialDataError, RevealSeals, StateRetrievalError}; +use crate::contract::owned_state::{ + AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy, +}; +use crate::contract::{ + attachment, data, seal, value, Assignment, ConcealSeals, ConcealState, ConfidentialDataError, + NoDataError, RevealSeals, StateRetrievalError, StateType, +}; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr( @@ -43,14 +39,15 @@ use crate::{AtomicValue, ConfidentialDataError, RevealSeals, StateRetrievalError serde(crate = "serde_crate", rename_all = "snake_case") )] pub enum TypedAssignments { - Void(Vec>), - Value(Vec>), - Data(Vec>), - Attachment(Vec>), + // TODO: Consider using non-empty variants + Void(TinyVec>), + Value(TinyVec>), + Data(TinyVec>), + Attachment(TinyVec>), } impl Default for TypedAssignments { - fn default() -> Self { TypedAssignments::Void(vec![]) } + fn default() -> Self { TypedAssignments::Void(default!()) } } impl TypedAssignments { @@ -77,43 +74,7 @@ impl TypedAssignments { pub fn is_attachment(&self) -> bool { matches!(self, TypedAssignments::Attachment(_)) } #[inline] - pub fn declarative_assignments_mut( - &mut self, - ) -> Option<&mut Vec>> { - match self { - TypedAssignments::Void(set) => Some(set), - _ => None, - } - } - - #[inline] - pub fn value_assignments_mut(&mut self) -> Option<&mut Vec>> { - match self { - TypedAssignments::Value(set) => Some(set), - _ => None, - } - } - - #[inline] - pub fn data_assignments_mut(&mut self) -> Option<&mut Vec>> { - match self { - TypedAssignments::Data(set) => Some(set), - _ => None, - } - } - - #[inline] - pub fn attachment_assignments_mut( - &mut self, - ) -> Option<&mut Vec>> { - match self { - TypedAssignments::Attachment(set) => Some(set), - _ => None, - } - } - - #[inline] - pub fn to_declarative_assignments(&self) -> Vec> { + pub fn to_declarative_assignments(&self) -> TinyVec> { match self { TypedAssignments::Void(set) => set.clone(), _ => Default::default(), @@ -121,7 +82,7 @@ impl TypedAssignments { } #[inline] - pub fn to_value_assignments(&self) -> Vec> { + pub fn to_value_assignments(&self) -> TinyVec> { match self { TypedAssignments::Value(set) => set.clone(), _ => Default::default(), @@ -129,7 +90,7 @@ impl TypedAssignments { } #[inline] - pub fn to_data_assignments(&self) -> Vec> { + pub fn to_data_assignments(&self) -> TinyVec> { match self { TypedAssignments::Data(set) => set.clone(), _ => Default::default(), @@ -137,7 +98,7 @@ impl TypedAssignments { } #[inline] - pub fn to_attachment_assignments(&self) -> Vec> { + pub fn to_attachment_assignments(&self) -> TinyVec> { match self { TypedAssignments::Attachment(set) => set.clone(), _ => Default::default(), @@ -145,7 +106,7 @@ impl TypedAssignments { } #[inline] - pub fn into_declarative_assignments(self) -> Vec> { + pub fn into_declarative_assignments(self) -> TinyVec> { match self { TypedAssignments::Void(set) => set, _ => Default::default(), @@ -153,7 +114,7 @@ impl TypedAssignments { } #[inline] - pub fn into_value_assignments(self) -> Vec> { + pub fn into_value_assignments(self) -> TinyVec> { match self { TypedAssignments::Value(set) => set, _ => Default::default(), @@ -161,7 +122,7 @@ impl TypedAssignments { } #[inline] - pub fn into_data_assignments(self) -> Vec> { + pub fn into_data_assignments(self) -> TinyVec> { match self { TypedAssignments::Data(set) => set, _ => Default::default(), @@ -169,7 +130,7 @@ impl TypedAssignments { } #[inline] - pub fn into_attachment_assignments(self) -> Vec> { + pub fn into_attachment_assignments(self) -> TinyVec> { match self { TypedAssignments::Attachment(set) => set, _ => Default::default(), @@ -487,23 +448,23 @@ impl TypedAssignments { } } - pub fn consensus_commitments(&self) -> Vec { + pub fn commitment_leaves(&self) -> Vec { match self { TypedAssignments::Void(vec) => vec .iter() - .map(Assignment::::consensus_commit) + .map(Assignment::::commitment_id) .collect(), TypedAssignments::Value(vec) => vec .iter() - .map(Assignment::::consensus_commit) + .map(Assignment::::commitment_id) .collect(), TypedAssignments::Data(vec) => vec .iter() - .map(Assignment::::consensus_commit) + .map(Assignment::::commitment_id) .collect(), TypedAssignments::Attachment(vec) => vec .iter() - .map(Assignment::::consensus_commit) + .map(Assignment::::commitment_id) .collect(), } } @@ -516,35 +477,32 @@ impl RevealSeals for TypedAssignments { TypedAssignments::Void(_) => {} TypedAssignments::Value(set) => { *self = TypedAssignments::Value( - set.iter() - .map(|assignment| { - let mut assignment = assignment.clone(); - counter += assignment.reveal_seals(known_seals); - assignment - }) - .collect(), + Confined::try_from_iter(set.iter().map(|assignment| { + let mut assignment = assignment.clone(); + counter += assignment.reveal_seals(known_seals); + assignment + })) + .expect("same size"), ); } TypedAssignments::Data(set) => { *self = TypedAssignments::Data( - set.iter() - .map(|assignment| { - let mut assignment = assignment.clone(); - counter += assignment.reveal_seals(known_seals); - assignment - }) - .collect(), + Confined::try_from_iter(set.iter().map(|assignment| { + let mut assignment = assignment.clone(); + counter += assignment.reveal_seals(known_seals); + assignment + })) + .expect("same size"), ); } TypedAssignments::Attachment(set) => { *self = TypedAssignments::Attachment( - set.iter() - .map(|assignment| { - let mut assignment = assignment.clone(); - counter += assignment.reveal_seals(known_seals); - assignment - }) - .collect(), + Confined::try_from_iter(set.iter().map(|assignment| { + let mut assignment = assignment.clone(); + counter += assignment.reveal_seals(known_seals); + assignment + })) + .expect("same size"), ); } } diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 7a9d9b41..f046cd67 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -23,17 +23,18 @@ pub mod seal; mod reveal_conceal; -// pub mod reveal+merge; +// pub mod reveal_merge; pub mod value; pub mod attachment; pub mod data; mod global_state; mod owned_state; -// mod assignments; +mod assignments; // mod rights; // pub mod nodes; +pub use assignments::TypedAssignments; pub use attachment::AttachId; pub use global_state::{FieldValues, Metadata}; pub use owned_state::{Assignment, State, StateType}; @@ -46,11 +47,6 @@ pub use value::{ }; /*pub(self) use assignments::EMPTY_ASSIGNMENTS; -pub use assignments::{ - Assignment, AttachmentStrategy, ConfidentialState, DeclarativeStrategy, EndpointValueMap, - HashStrategy, PedersenStrategy, RevealedState, SealValueMap, State, StateType, - TypedAssignments, -}; pub use nodes::{ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, Transition}; pub use rights::{OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights}; pub(crate) use rights::{OwnedRightsInner, PublicRightsInner}; diff --git a/src/contract/owned_state.rs b/src/contract/owned_state.rs index 1acc14f3..19453fd2 100644 --- a/src/contract/owned_state.rs +++ b/src/contract/owned_state.rs @@ -25,7 +25,8 @@ use core::fmt::Debug; use std::collections::HashMap; use std::io; -use commit_verify::{CommitEncode, Conceal}; +use commit_verify::merkle::MerkleNode; +use commit_verify::{CommitEncode, CommitmentId, Conceal}; use strict_encoding::{StrictEncode, StrictWriter}; use super::{ @@ -418,6 +419,17 @@ where } } +impl CommitmentId for Assignment +where + Self: Clone, + StateType: State, + StateType::Confidential: PartialEq + Eq, + StateType::Confidential: From<::Concealed>, +{ + const TAG: [u8; 32] = *b"urn:lnpbp:rgb:owned-state:v1#23A"; + type Id = MerkleNode; +} + #[cfg(test)] mod test { #[test] From bd2a47a38284a2bc6c1bf65bb83a5c7953dd6a80 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 22:46:45 +0100 Subject: [PATCH 44/71] contract: remove unneeded commit implementations for id types --- src/contract/attachment.rs | 4 ---- src/schema/schema.rs | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/contract/attachment.rs b/src/contract/attachment.rs index 29d5f6df..52642b87 100644 --- a/src/contract/attachment.rs +++ b/src/contract/attachment.rs @@ -49,10 +49,6 @@ pub struct AttachId( Bytes32, ); -impl CommitStrategy for AttachId { - type Strategy = commit_verify::strategies::Strict; -} - impl ToBaid58<32> for AttachId { const HRI: &'static str = "att"; fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() } diff --git a/src/schema/schema.rs b/src/schema/schema.rs index b6ddcdae..8dd4bb34 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -64,10 +64,6 @@ pub struct SchemaId( Bytes32, ); -impl CommitStrategy for SchemaId { - type Strategy = commit_verify::strategies::Strict; -} - impl ToBaid58<32> for SchemaId { const HRI: &'static str = "sch"; fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() } From 84e4aa340af9ca5d1b6fa044ffc896e2d2eb34d4 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 22:47:07 +0100 Subject: [PATCH 45/71] contract: remove legacy modules --- .../{reveal_conceal.rs => conceal.rs} | 0 src/contract/mod.rs | 16 +- src/contract/reveal_merge.rs | 348 ------------------ src/contract/rights.rs | 204 ---------- src/temp.rs | 52 --- 5 files changed, 4 insertions(+), 616 deletions(-) rename src/contract/{reveal_conceal.rs => conceal.rs} (100%) delete mode 100644 src/contract/reveal_merge.rs delete mode 100644 src/contract/rights.rs delete mode 100644 src/temp.rs diff --git a/src/contract/reveal_conceal.rs b/src/contract/conceal.rs similarity index 100% rename from src/contract/reveal_conceal.rs rename to src/contract/conceal.rs diff --git a/src/contract/mod.rs b/src/contract/mod.rs index f046cd67..fb33f73f 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -22,7 +22,7 @@ pub mod seal; -mod reveal_conceal; +mod conceal; // pub mod reveal_merge; pub mod value; @@ -31,28 +31,20 @@ pub mod data; mod global_state; mod owned_state; mod assignments; -// mod rights; -// pub mod nodes; +pub mod operations; pub use assignments::TypedAssignments; pub use attachment::AttachId; +pub use conceal::{ConcealSeals, ConcealState, RevealSeals}; pub use global_state::{FieldValues, Metadata}; pub use owned_state::{Assignment, State, StateType}; -pub use reveal_conceal::{ConcealSeals, ConcealState, RevealSeals}; +pub use seal::{IntoRevealedSeal, SealEndpoint}; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; -// pub use reveal::{MergeReveal, RevealSeals}; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, ValueAtom, }; -/*pub(self) use assignments::EMPTY_ASSIGNMENTS; -pub use nodes::{ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, Transition}; -pub use rights::{OwnedRights, ParentOwnedRights, ParentPublicRights, PublicRights}; -pub(crate) use rights::{OwnedRightsInner, PublicRightsInner}; -pub use seal::{IntoRevealedSeal, SealEndpoint}; -*/ - /// Marker trait for types of state which are just a commitment to the actual /// state data. pub trait ConfidentialState: diff --git a/src/contract/reveal_merge.rs b/src/contract/reveal_merge.rs deleted file mode 100644 index 22e84469..00000000 --- a/src/contract/reveal_merge.rs +++ /dev/null @@ -1,348 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::collections::BTreeMap; - -use amplify::Wrapper; -use bp::dbc; - -use super::OwnedRightsInner; -use crate::schema::NodeType; -use crate::{seal, Assignment, OwnedRights, State, TypedAssignments}; - -pub trait RevealSeals { - /// Reveals previously known seal information (replacing blind UTXOs with - /// unblind ones). Function is used when a peer receives consignments - /// containing concealed seals for the outputs owned by the peer. - /// - /// # Returns - /// - /// Total number of seals revealed inside the data structure during the - /// operation. - fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize; -} - -/// Merge Error generated in merging operation -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, From, Error)] -#[display(doc_comments)] -pub enum Error { - /// Owned State has different commitment ids and can't be reveal-merged - OwnedStateMismatch, - - /// Assignment has different commitment ids and can't be reveal-merged - AssignmentMismatch, - - /// OwnedRights has different commitment ids and can't be reveal-merged - OwnedRightsMismatch, - - /// Anchors has different commitment ids and can't be reveal-merged. - /// Details: {0} - #[from] - AnchorsMismatch(dbc::anchor::MergeError), - - /// Node of type {0} has different commitment ids and can't be - /// reveal-merged - NodeMismatch(NodeType), -} - -/// A trait to merge two structures modifying the revealed status -/// of the first one. The merge operation will **consume** both the structures -/// and return a new structure with revealed states. -/// -/// The resulting structure will depend on the reveal status of both of the -/// variant. And the most revealed condition among the two will be selected -/// Usage: prevent hiding already known previous state data by merging -/// incoming new consignment in stash. -/// -/// The follwoing conversion logic is intended by this trait: -/// -/// merge(Revealed, Anything) => Revealed -/// merge(ConfidentialSeal, ConfidentialAmount) => Revealed -/// merge(ConfidentialAmount, ConfidentialSeal) => Revealed -/// merge(Confidential, Anything) => Anything -pub trait MergeReveal: Sized { - fn merge_reveal(self, other: Self) -> Result; -} - -impl MergeReveal for Assignment -where - Self: Clone, - STATE: State, - STATE::Confidential: PartialEq + Eq, - STATE::Confidential: From<::ConcealedCommitment>, -{ - fn merge_reveal(self, other: Self) -> Result { - // if self and other is different through error - if self.commit_serialize() != other.commit_serialize() { - Err(Error::OwnedStateMismatch) - } else { - match (self, other) { - // Anything + Revealed = Revealed - (_, state @ Assignment::Revealed { .. }) | - (state @ Assignment::Revealed { .. }, _) => Ok(state), - - // ConfidentialAmount + ConfidentialSeal = Revealed - ( - Assignment::ConfidentialSeal { state, .. }, - Assignment::ConfidentialState { seal, .. }, - ) => Ok(Assignment::Revealed { seal, state }), - - // ConfidentialSeal + ConfidentialAmount = Revealed - ( - Assignment::ConfidentialState { seal, .. }, - Assignment::ConfidentialSeal { state, .. }, - ) => Ok(Assignment::Revealed { seal, state }), - - // if self and other is of same variant return self - ( - state @ Assignment::ConfidentialState { .. }, - Assignment::ConfidentialState { .. }, - ) => Ok(state), - ( - state @ Assignment::ConfidentialSeal { .. }, - Assignment::ConfidentialSeal { .. }, - ) => Ok(state), - - // Anything + Confidential = Anything - (state, Assignment::Confidential { .. }) | - (Assignment::Confidential { .. }, state) => Ok(state), - } - } - } -} - -impl MergeReveal for TypedAssignments { - fn merge_reveal(self, other: Self) -> Result { - if self.consensus_commitments() != other.consensus_commitments() { - Err(Error::AssignmentMismatch) - } else { - match (self, other) { - (TypedAssignments::Void(first_vec), TypedAssignments::Void(second_vec)) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssignments::Void(result)) - } - - (TypedAssignments::Value(first_vec), TypedAssignments::Value(second_vec)) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssignments::Value(result)) - } - - (TypedAssignments::Data(first_vec), TypedAssignments::Data(second_vec)) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssignments::Data(result)) - } - - ( - TypedAssignments::Attachment(first_vec), - TypedAssignments::Attachment(second_vec), - ) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssignments::Attachment(result)) - } - // No other patterns possible, should not reach here - _ => { - unreachable!("Assignments::consensus_commitments is broken") - } - } - } - } -} - -impl MergeReveal for OwnedRights { - fn merge_reveal(self, other: Self) -> Result { - if self.to_merkle_source().commit_serialize() != other.to_merkle_source().commit_serialize() - { - return Err(Error::OwnedRightsMismatch); - } - let mut result: OwnedRightsInner = BTreeMap::new(); - for (first, second) in self - .into_inner() - .into_iter() - .zip(other.into_inner().into_iter()) - { - result.insert(first.0, first.1.merge_reveal(second.1)?); - } - Ok(OwnedRights::from_inner(result)) - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::strict_encoding::StrictDecode; - use crate::{ConcealState, HashStrategy, PedersenStrategy}; - - // Hard coded test vectors of Assignment Variants - // Each Variant contains 4 types of Assignments - // [Revealed, Confidential, ConfidentialSeal, ConfidentialState] - static HASH_VARIANT: [u8; 267] = include!("../../test/hash_state.in"); - - static PEDERSAN_VARIANT: [u8; 1664] = include!("../../test/pedersan_state.in"); - - #[test] - #[ignore] - fn test_into_revealed_state() { - let ass = TypedAssignments::strict_decode(&PEDERSAN_VARIANT[..]) - .unwrap() - .into_value_assignments(); - - let rev = ass[1].clone(); - - // Check Revealed + Anything = Revealed - - // Revealed + Revealed = Revealed - let mut merged = rev.clone().merge_reveal(rev.clone()).unwrap(); - assert_eq!(merged, rev); - - // Revealed + Confidential = Revealed - let conf = rev.commit_conceal(); - merged = rev.clone().merge_reveal(conf.clone()).unwrap(); - assert_eq!(merged, rev); - - // Revealed + Confidential State = Revealed - let mut conf_state = rev.clone(); - conf_state.conceal_state(); - merged = rev.clone().merge_reveal(conf_state.clone()).unwrap(); - assert_eq!(merged, rev); - - // Revealed + Confidential Seal = Revealed - let seal = rev.to_confidential_seal(); - let conf_seal = Assignment::::ConfidentialSeal { - seal, - state: rev.as_revealed_state().unwrap().clone(), - }; - merged = rev.clone().merge_reveal(conf_seal.clone()).unwrap(); - assert_eq!(merged, rev); - - // Check Confidential Seal + Condfidential State = Revealed - merged = conf_seal.clone().merge_reveal(conf_state.clone()).unwrap(); - assert_eq!(merged, rev); - - // Check Condifential State + Confidential Seal = Revealed - merged = conf_state.clone().merge_reveal(conf_seal.clone()).unwrap(); - assert_eq!(merged, rev); - - // Check Confidential + Anything = Anything - // Confidential + Reveal = Reveal - merged = conf.clone().merge_reveal(rev.clone()).unwrap(); - assert_eq!(merged, rev); - - // Confidential + Confidential Seal = Confidential Seal - merged = conf.clone().merge_reveal(conf_seal.clone()).unwrap(); - assert_eq!(merged, conf_seal); - - // Confidential + Confidential State = Confidential State - merged = conf.clone().merge_reveal(conf_state.clone()).unwrap(); - assert_eq!(merged, conf_state); - - // Confidential + Confidential = Confidential - merged = conf.clone().merge_reveal(conf.clone()).unwrap(); - assert_eq!(merged, conf); - } - - #[test] - #[ignore] - fn test_into_revealed_assignements_ownedstates() { - let assignment = TypedAssignments::strict_decode(&HASH_VARIANT[..]) - .unwrap() - .to_data_assignments(); - - // Get a revealed state - let rev = assignment[3].clone(); - - // Compute different exposure of the same state - let conf = rev.clone().commit_conceal(); - - let seal = rev.to_confidential_seal(); - - let conf_seal = Assignment::::ConfidentialSeal { - seal, - state: rev.as_revealed_state().unwrap().clone(), - }; - - let mut conf_state = rev.clone(); - conf_state.conceal_state(); - - // Create assignment for testing - let test_variant_1 = vec![rev.clone(), conf_seal, conf_state, conf.clone()]; - let assignment_1 = TypedAssignments::Data(test_variant_1.clone()); - - // Create assignment 2 for testing - // which is reverse of assignment 1 - let mut test_variant_2 = test_variant_1.clone(); - test_variant_2.reverse(); - let assignmnet_2 = TypedAssignments::Data(test_variant_2); - - // Performing merge revelaing - let merged = assignment_1 - .clone() - .merge_reveal(assignmnet_2.clone()) - .unwrap(); - - // After merging all the states expeected be revealed - for state in merged.to_data_assignments() { - assert_eq!(state, rev); - } - - // Test against confidential merging - // Confidential + Anything = Anything - let test_variant_3 = vec![conf.clone(), conf.clone(), conf.clone(), conf.clone()]; - let assignment_3 = TypedAssignments::Data(test_variant_3); - - // merge with assignment 1 - let merged = assignment_3 - .clone() - .merge_reveal(assignment_1.clone()) - .unwrap(); - - assert_eq!(assignment_1, merged); - - // test for OwnedRights structure - let test_owned_rights_1: OwnedRights = bmap! { 1u16 => assignment_1.clone() }.into(); - let test_owned_rights_2: OwnedRights = bmap! { 1u16 => assignmnet_2.clone()}.into(); - - // Perform merge - let merged = test_owned_rights_1 - .clone() - .merge_reveal(test_owned_rights_2.clone()) - .unwrap(); - - // after merge operation all the states will be revealed - let states = vec![rev.clone(), rev.clone(), rev.clone(), rev.clone()]; - let assgn = TypedAssignments::Data(states); - let expected_rights: OwnedRights = bmap! {1u16 => assgn}.into(); - - assert_eq!(merged, expected_rights); - } -} diff --git a/src/contract/rights.rs b/src/contract/rights.rs deleted file mode 100644 index 8c384049..00000000 --- a/src/contract/rights.rs +++ /dev/null @@ -1,204 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use core::fmt::Debug; -use std::collections::{btree_map, btree_set, BTreeMap, BTreeSet}; - -use amplify::Wrapper; -use commit_verify::merkle::MerkleNode; - -use super::{NodeId, TypedAssignments, EMPTY_ASSIGNMENTS}; -use crate::schema; - -/// Holds definition of valencies for contract nodes, which is a set of -/// allowed valencies types -pub(crate) type PublicRightsInner = BTreeSet; -pub(crate) type OwnedRightsInner = BTreeMap; -pub(crate) type ParentOwnedRightsInner = - BTreeMap>>; -pub(crate) type ParentPublicRightsInner = BTreeMap>; - -#[derive(Wrapper, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, From)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct OwnedRights(OwnedRightsInner); - -impl OwnedRights { - pub fn iter(&self) -> btree_map::Iter<'_, schema::OwnedRightType, TypedAssignments> { - self.0.iter() - } - - pub fn iter_mut(&mut self) -> btree_map::IterMut<'_, schema::OwnedRightType, TypedAssignments> { - self.0.iter_mut() - } - - pub fn assignments_by_type( - &self, - owned_rights_type: schema::OwnedRightType, - ) -> &TypedAssignments { - self.0.get(&owned_rights_type).unwrap_or(&EMPTY_ASSIGNMENTS) - } -} - -impl IntoIterator for OwnedRights { - type Item = ::Item; - type IntoIter = ::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } -} - -impl<'a> IntoIterator for &'a OwnedRights { - type Item = <&'a OwnedRightsInner as IntoIterator>::Item; - type IntoIter = <&'a OwnedRightsInner as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.iter() } -} - -impl<'a> IntoIterator for &'a mut OwnedRights { - type Item = <&'a mut OwnedRightsInner as IntoIterator>::Item; - type IntoIter = <&'a mut OwnedRightsInner as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.iter_mut() } -} - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct PublicRights(PublicRightsInner); - -impl PublicRights { - pub fn iter(&self) -> btree_set::Iter<'_, schema::PublicRightType> { self.0.iter() } -} - -impl IntoIterator for PublicRights { - type Item = ::Item; - type IntoIter = ::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } -} - -impl<'a> IntoIterator for &'a PublicRights { - type Item = <&'a PublicRightsInner as IntoIterator>::Item; - type IntoIter = <&'a PublicRightsInner as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.iter() } -} - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct ParentOwnedRights(ParentOwnedRightsInner); - -impl ParentOwnedRights { - pub fn iter(&self) -> btree_map::Iter<'_, NodeId, BTreeMap>> { - self.0.iter() - } - - pub fn iter_mut( - &mut self, - ) -> btree_map::IterMut<'_, NodeId, BTreeMap>> { - self.0.iter_mut() - } -} - -impl IntoIterator for ParentOwnedRights { - type Item = ::Item; - type IntoIter = ::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } -} - -impl<'a> IntoIterator for &'a ParentOwnedRights { - type Item = <&'a ParentOwnedRightsInner as IntoIterator>::Item; - type IntoIter = <&'a ParentOwnedRightsInner as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.iter() } -} - -impl<'a> IntoIterator for &'a mut ParentOwnedRights { - type Item = <&'a mut ParentOwnedRightsInner as IntoIterator>::Item; - type IntoIter = <&'a mut ParentOwnedRightsInner as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.iter_mut() } -} - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct ParentPublicRights(ParentPublicRightsInner); - -impl ParentPublicRights { - pub fn iter(&self) -> btree_map::Iter<'_, NodeId, BTreeSet> { - self.0.iter() - } - - pub fn iter_mut( - &mut self, - ) -> btree_map::IterMut<'_, NodeId, BTreeSet> { - self.0.iter_mut() - } -} - -impl IntoIterator for ParentPublicRights { - type Item = ::Item; - type IntoIter = ::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } -} - -impl<'a> IntoIterator for &'a ParentPublicRights { - type Item = <&'a ParentPublicRightsInner as IntoIterator>::Item; - type IntoIter = <&'a ParentPublicRightsInner as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.iter() } -} - -impl<'a> IntoIterator for &'a mut ParentPublicRights { - type Item = <&'a mut ParentPublicRightsInner as IntoIterator>::Item; - type IntoIter = <&'a mut ParentPublicRightsInner as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { self.0.iter_mut() } -} - -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub struct PublicRightsLeaf(pub schema::PublicRightType); - -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub struct OwnedRightsLeaf(pub schema::OwnedRightType, pub MerkleNode); - -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub struct ParentPublicRightsLeaf(pub NodeId, pub schema::PublicRightType); - -#[derive(Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub struct ParentOwnedRightsLeaf(pub NodeId, pub schema::OwnedRightType, pub u16); diff --git a/src/temp.rs b/src/temp.rs deleted file mode 100644 index 2be57bba..00000000 --- a/src/temp.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! Temporary module for refactoring period - -use bp::{Tx, Txid}; - -#[macro_export] -macro_rules! txid { - ($old:expr) => { - $old.to_string().parse().unwrap() - }; -} - -#[macro_export] -macro_rules! outpoint { - ($old:expr) => { - bp::Outpoint { - txid: txid!($old.txid), - vout: $old.vout.into(), - } - }; -} - -#[macro_export] -macro_rules! tx { - ($old:expr) => { - serde_json::from_str(&serde_json::to_string($old).unwrap()).unwrap() - }; -} - -#[derive(Debug, Display, Error)] -#[display(doc_comments)] -/// transaction {0} is not mined -pub struct TxResolverError(Txid); - -pub trait ResolveTx { - fn resolve_tx(&self, txid: Txid) -> Result; -} - -// TODO: Change values according to the standard -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Default)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[repr(u32)] -pub enum Chain { - #[default] - #[display("mainnet")] - Bitcoin = 0x00, - #[display("testnet")] - Testnet3 = 0x8000_0000, - #[display("regtest")] - Regtest = 0x8000_0001, - #[display("signet")] - Signet = 0x8000_0002, -} From 96eac1decf2ea0942a11c33869f9aaa037119a6e Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 22:47:39 +0100 Subject: [PATCH 46/71] contract: refactor assignments to have up to 2^16 items per type --- src/contract/assignments.rs | 43 +++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 8cf2b75c..7cbd9485 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -20,19 +20,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -use amplify::confinement::{Confined, TinyVec}; +use amplify::confinement::{Confined, MediumVec}; use commit_verify::merkle::MerkleNode; use commit_verify::CommitmentId; -use crate::contract::owned_state::{ - AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy, -}; -use crate::contract::{ +use super::owned_state::{AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy}; +use super::{ attachment, data, seal, value, Assignment, ConcealSeals, ConcealState, ConfidentialDataError, NoDataError, RevealSeals, StateRetrievalError, StateType, }; +use crate::LIB_NAME_RGB; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = Self::Void(strict_dumb!()))] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -40,14 +41,14 @@ use crate::contract::{ )] pub enum TypedAssignments { // TODO: Consider using non-empty variants - Void(TinyVec>), - Value(TinyVec>), - Data(TinyVec>), - Attachment(TinyVec>), -} - -impl Default for TypedAssignments { - fn default() -> Self { TypedAssignments::Void(default!()) } + #[strict_type(tag = 0x00)] + Void(MediumVec>), + #[strict_type(tag = 0x01)] + Value(MediumVec>), + #[strict_type(tag = 0x02)] + Data(MediumVec>), + #[strict_type(tag = 0xFF)] + Attachment(MediumVec>), } impl TypedAssignments { @@ -74,7 +75,7 @@ impl TypedAssignments { pub fn is_attachment(&self) -> bool { matches!(self, TypedAssignments::Attachment(_)) } #[inline] - pub fn to_declarative_assignments(&self) -> TinyVec> { + pub fn to_declarative_assignments(&self) -> MediumVec> { match self { TypedAssignments::Void(set) => set.clone(), _ => Default::default(), @@ -82,7 +83,7 @@ impl TypedAssignments { } #[inline] - pub fn to_value_assignments(&self) -> TinyVec> { + pub fn to_value_assignments(&self) -> MediumVec> { match self { TypedAssignments::Value(set) => set.clone(), _ => Default::default(), @@ -90,7 +91,7 @@ impl TypedAssignments { } #[inline] - pub fn to_data_assignments(&self) -> TinyVec> { + pub fn to_data_assignments(&self) -> MediumVec> { match self { TypedAssignments::Data(set) => set.clone(), _ => Default::default(), @@ -98,7 +99,7 @@ impl TypedAssignments { } #[inline] - pub fn to_attachment_assignments(&self) -> TinyVec> { + pub fn to_attachment_assignments(&self) -> MediumVec> { match self { TypedAssignments::Attachment(set) => set.clone(), _ => Default::default(), @@ -106,7 +107,7 @@ impl TypedAssignments { } #[inline] - pub fn into_declarative_assignments(self) -> TinyVec> { + pub fn into_declarative_assignments(self) -> MediumVec> { match self { TypedAssignments::Void(set) => set, _ => Default::default(), @@ -114,7 +115,7 @@ impl TypedAssignments { } #[inline] - pub fn into_value_assignments(self) -> TinyVec> { + pub fn into_value_assignments(self) -> MediumVec> { match self { TypedAssignments::Value(set) => set, _ => Default::default(), @@ -122,7 +123,7 @@ impl TypedAssignments { } #[inline] - pub fn into_data_assignments(self) -> TinyVec> { + pub fn into_data_assignments(self) -> MediumVec> { match self { TypedAssignments::Data(set) => set, _ => Default::default(), @@ -130,7 +131,7 @@ impl TypedAssignments { } #[inline] - pub fn into_attachment_assignments(self) -> TinyVec> { + pub fn into_attachment_assignments(self) -> MediumVec> { match self { TypedAssignments::Attachment(set) => set, _ => Default::default(), From 10dced1200f164cb3287193f7b9a975236b86b3d Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Feb 2023 23:02:32 +0100 Subject: [PATCH 47/71] contract: refactor operations --- Cargo.lock | 8 +- src/contract/operations.rs | 571 ++++++++++--------------------------- 2 files changed, 151 insertions(+), 428 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1c41021..76671ee4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ dependencies = [ [[package]] name = "bp-core" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" +source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" dependencies = [ "amplify", "bp-dbc", @@ -222,7 +222,7 @@ dependencies = [ [[package]] name = "bp-dbc" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" +source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" dependencies = [ "amplify", "bp-primitives", @@ -235,7 +235,7 @@ dependencies = [ [[package]] name = "bp-primitives" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" +source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" dependencies = [ "amplify", "commit_verify", @@ -247,7 +247,7 @@ dependencies = [ [[package]] name = "bp-seals" version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#6546e537afdd1bab120748a0bc3f92167367a8e6" +source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" dependencies = [ "amplify", "baid58 0.1.0", diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 5489b638..041df2f9 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -24,54 +24,43 @@ use std::collections::{BTreeMap, BTreeSet}; use std::num::ParseIntError; use std::str::FromStr; -use amplify::{AsAny, Wrapper}; -use bitcoin_hashes::{sha256, sha256t, Hash}; +use amplify::confinement::{TinyOrdMap, TinyOrdSet, TinyVec}; +use amplify::hex::{FromHex, ToHex}; +use amplify::{hex, AsAny, Bytes32, RawArray, Wrapper}; +use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; use bp::seals::txout::TxoSeal; -use bp::{Outpoint, Txid}; -use commit_verify::mpc::ProtocolId; -use commit_verify::{CommitVerify, UntaggedProtocol}; -use once_cell::sync::Lazy; - -use super::{ - ConcealSeals, ConcealState, OwnedRights, OwnedRightsInner, ParentOwnedRights, - ParentPublicRights, PublicRights, PublicRightsInner, TypedAssignments, -}; -use crate::reveal::{self, MergeReveal}; +use bp::{Chain, Outpoint, Txid}; +use commit_verify::{mpc, CommitStrategy, CommitmentId}; + +use super::{seal, ConcealSeals, ConcealState, ConfidentialDataError, Metadata, TypedAssignments}; use crate::schema::{ - ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, TransitionType, -}; -use crate::temp::Chain; -use crate::{ - outpoint, schema, seal, txid, ConfidentialDataError, Metadata, PublicRightType, SchemaId, + self, ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, PublicRightType, + SchemaId, TransitionType, }; +use crate::LIB_NAME_RGB; -static EMPTY_OWNED_RIGHTS: Lazy = Lazy::new(ParentOwnedRights::default); -static EMPTY_PUBLIC_RIGHTS: Lazy = Lazy::new(ParentPublicRights::default); - -/// Midstate for a tagged hash engine. Equals to a single SHA256 hash of -/// the value of two concatenated SHA256 hashes for `rgb:node` prefix string. -static MIDSTATE_NODE_ID: [u8; 32] = [ - 0x90, 0xd0, 0xc4, 0x9b, 0xa6, 0xb8, 0xa, 0x5b, 0xbc, 0xba, 0x19, 0x9, 0xdc, 0xbd, 0x5a, 0x58, - 0x55, 0x6a, 0xe2, 0x16, 0xa5, 0xee, 0xb7, 0x3c, 0x1, 0xe0, 0x86, 0x91, 0x22, 0x43, 0x12, 0x9f, -]; - -pub const RGB_CONTRACT_ID_HRP: &str = "rgb"; - +/// RGB contract node output pointer, defined by the node ID and output number. #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[display("{node_id}/{ty}/{no}")] -/// RGB contract node output pointer, defined by the node ID and output -/// number. pub struct NodeOutpoint { pub node_id: NodeId, pub ty: OwnedRightType, pub no: u16, } +impl NodeOutpoint { + pub fn new(node_id: NodeId, ty: u16, no: u16) -> NodeOutpoint { + NodeOutpoint { node_id, ty, no } + } +} + #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] #[display(inner)] pub enum OutpointParseError { #[from] - InvalidNodeId(bitcoin_hashes::hex::Error), + InvalidNodeId(amplify::hex::Error), InvalidType(ParseIntError), @@ -98,67 +87,68 @@ impl FromStr for NodeOutpoint { } } -/// Tag used for [`NodeId`] and [`ContractId`] hash types -pub struct NodeIdTag; - -impl sha256t::Tag for NodeIdTag { - #[inline] - fn engine() -> sha256::HashEngine { - let midstate = sha256::Midstate::from_inner(MIDSTATE_NODE_ID); - sha256::HashEngine::from_midstate(midstate, 64) - } -} - -impl NodeOutpoint { - pub fn new(node_id: NodeId, ty: u16, no: u16) -> NodeOutpoint { - NodeOutpoint { node_id, ty, no } - } -} +pub type PublicRights = TinyOrdSet; +pub type OwnedRights = TinyOrdMap; +pub type ParentOwnedRights = TinyOrdMap>>; +pub type ParentPublicRights = TinyOrdMap>; /// Unique node (genesis, extensions & state transition) identifier equivalent /// to the commitment hash -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[wrapper(Debug, Display, BorrowSlice)] -pub struct NodeId(sha256t::Hash); - -impl CommitVerify for NodeId -where Msg: AsRef<[u8]> -{ - #[inline] - fn commit(msg: &Msg) -> NodeId { NodeId::hash(msg) } -} - -impl commit_encode::Strategy for NodeId { - type Strategy = commit_encode::strategies::UsingStrict; -} +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[display(Self::to_hex)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct NodeId( + #[from] + #[from([u8; 32])] + Bytes32, +); impl FromStr for NodeId { - type Err = bitcoin_hashes::hex::Error; - - fn from_str(s: &str) -> Result { Ok(NodeId::from_inner(s.parse()?)) } + type Err = hex::Error; + fn from_str(s: &str) -> Result { Self::from_hex(s) } } /// Unique contract identifier equivalent to the contract genesis commitment -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[wrapper(Debug, BorrowSlice)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct ContractId(sha256t::Hash); +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[display(Self::to_baid58)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct ContractId( + #[from] + #[from([u8; 32])] + Bytes32, +); -impl From for ProtocolId { - fn from(contract_id: ContractId) -> Self { - ProtocolId::from_inner(contract_id.into_inner().into_inner()) - } +impl ToBaid58<32> for ContractId { + const HRI: &'static str = "rgb"; + fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() } } +impl FromBaid58<32> for ContractId {} -impl From for ContractId { - fn from(protocol_id: ProtocolId) -> Self { - ContractId::from_inner(::Inner::from_inner(protocol_id.into_inner())) - } +impl FromStr for ContractId { + type Err = Baid58ParseError; + fn from_str(s: &str) -> Result { Self::from_baid58_str(s) } } -impl commit_encode::Strategy for ContractId { - type Strategy = commit_encode::strategies::UsingStrict; +impl From for ContractId { + fn from(id: mpc::ProtocolId) -> Self { ContractId(id.into_inner()) } +} + +impl From for mpc::ProtocolId { + fn from(id: ContractId) -> Self { mpc::ProtocolId::from_inner(id.into_inner()) } } /// RGB contract node API, defined as trait @@ -232,7 +222,7 @@ pub trait Node: AsAny { fn parent_public_right_types(&self) -> Vec { self.parent_public_rights() .values() - .flat_map(BTreeSet::iter) + .flat_map(|v| v.iter()) .copied() .collect() } @@ -284,7 +274,7 @@ pub trait Node: AsAny { fn parent_owned_right_types(&self) -> Vec { self.parent_owned_rights() .values() - .flat_map(BTreeMap::keys) + .flat_map(|v| v.keys()) .copied() .collect() } @@ -361,16 +351,18 @@ pub trait Node: AsAny { let mut res: BTreeMap = bmap! {}; for (ty, assignments) in self.owned_rights() { for (seal, node_output) in assignments.revealed_seal_outputs() { - let outpoint = seal.outpoint_or(txid!(witness_txid)); + let outpoint = seal.outpoint_or(witness_txid); let node_outpoint = NodeOutpoint::new(node_id, *ty, node_output); - res.insert(node_outpoint, outpoint!(outpoint)); + res.insert(node_outpoint, outpoint); } } res } } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, AsAny)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Genesis { schema_id: SchemaId, @@ -380,7 +372,9 @@ pub struct Genesis { public_rights: PublicRights, } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, AsAny)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Extension { extension_type: ExtensionType, @@ -391,21 +385,22 @@ pub struct Extension { public_rights: PublicRights, } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, AsAny)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Transition { transition_type: TransitionType, metadata: Metadata, parent_owned_rights: ParentOwnedRights, owned_rights: OwnedRights, - parent_public_rights: ParentPublicRights, public_rights: PublicRights, } impl ConcealState for Genesis { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; - for (_, assignment) in self.owned_rights_mut().iter_mut() { + for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { count += assignment.conceal_state_except(seals); } count @@ -415,7 +410,7 @@ impl ConcealState for Genesis { impl ConcealState for Extension { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; - for (_, assignment) in self.owned_rights_mut().iter_mut() { + for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { count += assignment.conceal_state_except(seals); } count @@ -425,51 +420,71 @@ impl ConcealState for Extension { impl ConcealState for Transition { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; - for (_, assignment) in self.owned_rights_mut().iter_mut() { + for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { count += assignment.conceal_state_except(seals); } count } } -impl ConcealSeals for Transition { +impl ConcealSeals for Genesis { fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; - for (_, assignment) in self.owned_rights_mut().iter_mut() { + for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { count += assignment.conceal_seals(seals); } count } } -impl MergeReveal for Genesis { - fn merge_reveal(mut self, other: Self) -> Result { - if self.consensus_commit() != other.consensus_commit() { - return Err(reveal::Error::NodeMismatch(NodeType::Genesis)); +impl ConcealSeals for Transition { + fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { + let mut count = 0; + for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { + count += assignment.conceal_seals(seals); } - self.owned_rights = self.owned_rights.merge_reveal(other.owned_rights)?; - Ok(self) + count } } -impl MergeReveal for Transition { - fn merge_reveal(mut self, other: Self) -> Result { - if self.consensus_commit() != other.consensus_commit() { - return Err(reveal::Error::NodeMismatch(NodeType::StateTransition)); +impl ConcealSeals for Extension { + fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { + let mut count = 0; + for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { + count += assignment.conceal_seals(seals); } - self.owned_rights = self.owned_rights.merge_reveal(other.owned_rights)?; - Ok(self) + count } } -impl MergeReveal for Extension { - fn merge_reveal(mut self, other: Self) -> Result { - if self.consensus_commit() != other.consensus_commit() { - return Err(reveal::Error::NodeMismatch(NodeType::StateExtension)); - } - self.owned_rights = self.owned_rights.merge_reveal(other.owned_rights)?; - Ok(self) - } +impl CommitStrategy for Genesis { + // TODO: Use merklization + type Strategy = commit_verify::strategies::Strict; +} + +impl CommitmentId for Genesis { + const TAG: [u8; 32] = *b"urn:lnpbp:rgb:genesis:v01#202302"; + type Id = ContractId; +} + +impl CommitStrategy for Transition { + // TODO: Use merklization + type Strategy = commit_verify::strategies::Strict; +} + +impl CommitmentId for Transition { + const TAG: [u8; 32] = *b"urn:lnpbp:rgb:transition:v01#32A"; + type Id = NodeId; +} + +impl CommitStrategy for Extension { + // TODO: Use merklization + type Strategy = commit_verify::strategies::Strict; +} + +impl CommitmentId for Extension { + const TAG: [u8; 32] = *b"urn:lnpbp:rgb:extension:v01#2023"; + type Id = NodeId; } impl Node for Genesis { @@ -480,7 +495,7 @@ impl Node for Genesis { fn subtype(&self) -> NodeSubtype { NodeSubtype::Genesis } #[inline] - fn node_id(&self) -> NodeId { self.clone().consensus_commit() } + fn node_id(&self) -> NodeId { NodeId(self.commitment_id().into_inner()) } #[inline] fn contract_id(&self) -> Option { @@ -494,10 +509,14 @@ impl Node for Genesis { fn extension_type(&self) -> Option { None } #[inline] - fn parent_owned_rights(&self) -> &ParentOwnedRights { &EMPTY_OWNED_RIGHTS } + fn parent_owned_rights(&self) -> &ParentOwnedRights { + panic!("genesis can't close previous single-use-seals") + } #[inline] - fn parent_public_rights(&self) -> &ParentPublicRights { &EMPTY_PUBLIC_RIGHTS } + fn parent_public_rights(&self) -> &ParentPublicRights { + panic!("genesis can't extend previous state") + } #[inline] fn metadata(&self) -> &Metadata { &self.metadata } @@ -523,7 +542,7 @@ impl Node for Extension { fn subtype(&self) -> NodeSubtype { NodeSubtype::StateExtension(self.extension_type) } #[inline] - fn node_id(&self) -> NodeId { self.clone().consensus_commit() } + fn node_id(&self) -> NodeId { self.commitment_id() } #[inline] fn contract_id(&self) -> Option { Some(self.contract_id) } @@ -535,7 +554,9 @@ impl Node for Extension { fn extension_type(&self) -> Option { Some(self.extension_type) } #[inline] - fn parent_owned_rights(&self) -> &ParentOwnedRights { &EMPTY_OWNED_RIGHTS } + fn parent_owned_rights(&self) -> &ParentOwnedRights { + panic!("extension can't close previous single-use-seals") + } #[inline] fn parent_public_rights(&self) -> &ParentPublicRights { &self.parent_public_rights } @@ -564,7 +585,7 @@ impl Node for Transition { fn subtype(&self) -> NodeSubtype { NodeSubtype::StateTransition(self.transition_type) } #[inline] - fn node_id(&self) -> NodeId { self.clone().consensus_commit() } + fn node_id(&self) -> NodeId { self.commitment_id() } #[inline] fn contract_id(&self) -> Option { None } @@ -579,7 +600,9 @@ impl Node for Transition { fn parent_owned_rights(&self) -> &ParentOwnedRights { &self.parent_owned_rights } #[inline] - fn parent_public_rights(&self) -> &ParentPublicRights { &self.parent_public_rights } + fn parent_public_rights(&self) -> &ParentPublicRights { + panic!("state transitions can't extend previous state") + } #[inline] fn metadata(&self) -> &Metadata { &self.metadata } @@ -602,15 +625,15 @@ impl Genesis { schema_id: SchemaId, chain: Chain, metadata: Metadata, - owned_rights: OwnedRightsInner, - public_rights: PublicRightsInner, + owned_rights: OwnedRights, + public_rights: PublicRights, ) -> Self { Self { schema_id, chain, metadata, - owned_rights: owned_rights.into(), - public_rights: public_rights.into(), + owned_rights, + public_rights, } } @@ -648,7 +671,6 @@ impl Transition { pub fn with( transition_type: impl Into, metadata: Metadata, - parent_public_rights: ParentPublicRights, owned_rights: OwnedRights, public_rights: PublicRights, parent_owned_rights: ParentOwnedRights, @@ -656,7 +678,6 @@ impl Transition { Self { transition_type: transition_type.into(), metadata, - parent_public_rights, parent_owned_rights, owned_rights, public_rights, @@ -665,301 +686,3 @@ impl Transition { pub fn transition_type(&self) -> schema::TransitionType { self.transition_type } } - -#[cfg(test)] -mod test { - use std::io::Write; - - use bitcoin_hashes::hex::ToHex; - use commit_verify::{tagged_hash, CommitConceal, TaggedHash}; - use lnpbp::chain::{Chain, GENESIS_HASH_MAINNET}; - use strict_encoding::{strict_serialize, StrictDecode, StrictEncode}; - use strict_encoding_test::test_vec_decoding_roundtrip; - - use super::*; - - #[test] - fn test_node_id_midstate() { - let midstate = tagged_hash::Midstate::with(b"rgb:node"); - assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_NODE_ID); - } - - #[test] - #[ignore] - fn test_transition_node_id() { - fn conceal_transition(transition: &mut Transition) { - for (_, assignments) in transition.owned_rights_mut().iter_mut() { - match assignments { - TypedAssignments::Void(set) => { - for assignment in set { - *assignment = assignment.commit_conceal(); - } - } - TypedAssignments::Value(set) => { - for assignment in set { - *assignment = assignment.commit_conceal(); - } - } - TypedAssignments::Data(set) => { - for assignment in set { - *assignment = assignment.commit_conceal(); - } - } - TypedAssignments::Attachment(set) => { - for assignment in set { - *assignment = assignment.commit_conceal(); - } - } - } - } - } - - let transition = Transition::strict_decode(&TRANSITION[..]).unwrap(); - let mut concealed_transition = transition.clone(); - conceal_transition(&mut concealed_transition); - - assert_eq!(transition.node_id(), concealed_transition.node_id()); - } - - #[test] - #[ignore] - fn test_node_attributes() { - let genesis = Genesis::strict_decode(&GENESIS[..]).unwrap(); - let transition = Transition::strict_decode(&TRANSITION[..]).unwrap(); - - // Typeid/Nodeid test - assert_eq!( - genesis.node_id().to_hex(), - "977e9d7344aec3f01aca1a05b3f328fe91aa252481433e7cd87b22dbb48cd01c" - ); - assert_eq!( - transition.node_id().to_hex(), - "52776d37dfce78a3d075f8c79c2c40ed6d95d271c74f7aea910c17218255aa68" - ); - - assert_eq!(genesis.transition_type(), None); - assert_eq!(transition.transition_type(), 10); - - // Ancestor test - - assert_eq!(genesis.parent_owned_rights(), &ParentOwnedRights::default()); - - let ancestor_trn = transition.parent_owned_rights(); - let assignments = ancestor_trn - .get( - &NodeId::from_hex( - "060ef58d940a75e43d139d55a5e4d3264dc9eb4f773bffc5729019e47ed27ef5", - ) - .unwrap(), - ) - .unwrap(); - assert_eq!(assignments.get(&1u16).unwrap(), &[1u16, 2u16, 3u16, 4u16, 5u16].to_vec()); - assert_eq!(assignments.get(&2u16).unwrap(), &[10u16, 20u16, 30u16, 40u16, 50u16].to_vec()); - assert_eq!( - assignments.get(&3u16).unwrap(), - &[100u16, 200u16, 300u16, 400u16, 500u16].to_vec() - ); - - // Metadata test - - let gen_meta = genesis.metadata(); - - let tran_meta = transition.metadata(); - - assert_eq!(gen_meta, tran_meta); - - let u8_from_gen = gen_meta.u8(13 as schema::FieldType); - - assert_eq!(u8_from_gen, [2u8, 3u8].to_vec()); - - let string_from_tran = tran_meta.unicode_string(13 as schema::FieldType); - - assert_eq!(string_from_tran[0], "One Random String".to_string()); - - // Assignments test - - let gen_assignments = genesis.owned_rights(); - let tran_assingmnets = transition.owned_rights(); - - assert_eq!(gen_assignments, tran_assingmnets); - - assert!(gen_assignments.get(&1u16).unwrap().is_declarative()); - assert!(gen_assignments.get(&2u16).unwrap().has_value()); - assert!(tran_assingmnets.get(&3u16).unwrap().has_data()); - - let seal1 = gen_assignments - .get(&2u16) - .unwrap() - .revealed_seal_at(1) - .unwrap() - .unwrap(); - - let txid = seal1.txid.unwrap(); - - assert_eq!( - txid.to_hex(), - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e".to_string() - ); - - let seal2 = tran_assingmnets - .get(&3u16) - .unwrap() - .revealed_seal_at(1) - .unwrap() - .unwrap(); - - let txid = seal2.txid.unwrap(); - - assert_eq!( - txid.to_hex(), - "f57ed27ee4199072c5ff3b774febc94d26d3e4a5559d133de4750a948df50e06".to_string() - ); - - // Field Types - let gen_fields = genesis.field_types(); - let tran_fields = transition.field_types(); - - assert_eq!(gen_fields, tran_fields); - - assert_eq!(gen_fields, vec![13u16]); - - // Assignment types - let gen_ass_types = genesis.owned_right_types(); - let tran_ass_types = transition.owned_right_types(); - - assert_eq!(gen_ass_types, tran_ass_types); - - assert_eq!(gen_ass_types, bset![1u16, 2, 3]); - - // assignment by types - let assignment_gen = genesis.owned_rights_by_type(3).unwrap(); - let assignment_tran = transition.owned_rights_by_type(1).unwrap(); - - assert!(assignment_gen.has_data()); - assert!(assignment_tran.is_declarative()); - - // All seal confidentials - let gen_seals = genesis.to_confiential_seals(); - let tran_seals = transition.to_confiential_seals(); - - assert_eq!(gen_seals, tran_seals); - - assert_eq!( - gen_seals[0].to_hex(), - "6b3c1bee0bd431f53e6c099890fdaf51b8556a6dcd61c6150ca055d0e1d4a524".to_string() - ); - assert_eq!( - tran_seals[3].to_hex(), - "58f3ea4817a12aa6f1007d5b3d24dd2940ce40f8498029e05f1dc6465b3d65b4".to_string() - ); - - // Known seals - let known_gen_seals = genesis.filter_revealed_seals(); - let known_seals_tran = transition.filter_revealed_seals(); - - assert_eq!(known_gen_seals, known_seals_tran); - - let txid1 = known_gen_seals[2].txid.unwrap(); - - let txid2 = known_gen_seals[3].txid.unwrap(); - - assert_eq!( - txid1.to_hex(), - "f57ed27ee4199072c5ff3b774febc94d26d3e4a5559d133de4750a948df50e06".to_string() - ); - assert_eq!( - txid2.to_hex(), - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e".to_string() - ); - - // Known seals by type - let dec_gen_seals = genesis.filter_revealed_seals_by_type(1); - let hash_tran_seals = transition.filter_revealed_seals_by_type(3); - - let txid1 = dec_gen_seals[0].txid.unwrap(); - - assert_eq!( - txid1.to_hex(), - "f57ed27ee4199072c5ff3b774febc94d26d3e4a5559d133de4750a948df50e06".to_string() - ); - - let txid2 = hash_tran_seals[1].txid.unwrap(); - - assert_eq!( - txid2.to_hex(), - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e".to_string() - ); - } - - #[test] - #[ignore] - fn test_autoconceal_node() { - let mut genesis = Genesis::strict_decode(&GENESIS[..]).unwrap(); - let mut transition = Transition::strict_decode(&TRANSITION[..]).unwrap(); - - assert_eq!( - genesis.clone().consensus_commit(), - NodeId::from_hex("977e9d7344aec3f01aca1a05b3f328fe91aa252481433e7cd87b22dbb48cd01c") - .unwrap() - ); - assert_eq!( - transition.clone().consensus_commit(), - NodeId::from_hex("52776d37dfce78a3d075f8c79c2c40ed6d95d271c74f7aea910c17218255aa68") - .unwrap() - ); - - genesis.conceal_state(); - transition.conceal_state(); - - assert_eq!( - genesis.clone().consensus_commit(), - NodeId::from_hex("977e9d7344aec3f01aca1a05b3f328fe91aa252481433e7cd87b22dbb48cd01c") - .unwrap() - ); - assert_eq!( - transition.clone().consensus_commit(), - NodeId::from_hex("52776d37dfce78a3d075f8c79c2c40ed6d95d271c74f7aea910c17218255aa68") - .unwrap() - ); - } - - #[test] - #[ignore] - #[cfg(feature = "serde")] - fn test_id_serde() { - let genesis: Genesis = Genesis::strict_decode(&GENESIS[..]).unwrap(); - let contract_id = genesis.contract_id(); - assert_eq!( - contract_id.to_string(), - "rgb1rnggedxmyfaaslp7gwqjgfd2j8lz3uanq5dv5xhscwhyguua06tskhgfdg" - ); - assert_eq!( - serde_json::to_string(&contract_id).unwrap(), - "\"rgb1rnggedxmyfaaslp7gwqjgfd2j8lz3uanq5dv5xhscwhyguua06tskhgfdg\"" - ); - } - - #[test] - #[ignore] - fn test_genesis_impl() { - let genesis: Genesis = Genesis::strict_decode(&GENESIS[..]).unwrap(); - - let contractid = genesis.contract_id(); - let schemaid = genesis.schema_id(); - let chain = genesis.chain(); - - assert_eq!( - contractid, - ContractId::from_hex( - "977e9d7344aec3f01aca1a05b3f328fe91aa252481433e7cd87b22dbb48cd01c" - ) - .unwrap() - ); - assert_eq!( - schemaid, - SchemaId::from_hex("8eafd3360d65258952f4d9575eac1b1f18ee185129718293b6d7622b1edd1f20") - .unwrap() - ); - assert_eq!(chain, &Chain::Mainnet); - } -} From 430dd8ccb0b809624b074eeb0b2e57b1572ad865 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 00:31:30 +0100 Subject: [PATCH 48/71] contract: refactor transition bundles --- src/{stash => contract}/anchor.rs | 0 src/contract/assignments.rs | 34 +-- src/contract/bundle.rs | 167 ++++++++++++ src/contract/mod.rs | 78 ++---- src/contract/operations.rs | 10 + src/contract/value.rs | 14 - src/lib.rs | 20 +- src/stash/bundle.rs | 323 ----------------------- src/stash/mod.rs | 51 ---- src/stash/stash.rs | 134 ---------- src/stash/unit.rs | 125 --------- src/{stash => validation}/consignment.rs | 17 ++ src/{stash => validation}/graph.rs | 0 src/validation/mod.rs | 9 +- 14 files changed, 241 insertions(+), 741 deletions(-) rename src/{stash => contract}/anchor.rs (100%) create mode 100644 src/contract/bundle.rs delete mode 100644 src/stash/bundle.rs delete mode 100644 src/stash/mod.rs delete mode 100644 src/stash/stash.rs delete mode 100644 src/stash/unit.rs rename src/{stash => validation}/consignment.rs (74%) rename src/{stash => validation}/graph.rs (100%) diff --git a/src/stash/anchor.rs b/src/contract/anchor.rs similarity index 100% rename from src/stash/anchor.rs rename to src/contract/anchor.rs diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 7cbd9485..f3ad1b4d 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -27,7 +27,7 @@ use commit_verify::CommitmentId; use super::owned_state::{AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy}; use super::{ attachment, data, seal, value, Assignment, ConcealSeals, ConcealState, ConfidentialDataError, - NoDataError, RevealSeals, StateRetrievalError, StateType, + RevealSeals, StateRetrievalError, StateType, UnknownDataError, }; use crate::LIB_NAME_RGB; @@ -167,23 +167,27 @@ impl TypedAssignments { } } - /// If seal definition does not exist, returns [`NoDataError`]. If the + /// If seal definition does not exist, returns [`UnknownDataError`]. If the /// seal is confidential, returns `Ok(None)`; otherwise returns revealed /// seal data packed as `Ok(Some(`[`seal::Revealed`]`))` - pub fn revealed_seal_at(&self, index: u16) -> Result, NoDataError> { + pub fn revealed_seal_at(&self, index: u16) -> Result, UnknownDataError> { Ok(match self { - TypedAssignments::Void(vec) => { - vec.get(index as usize).ok_or(NoDataError)?.revealed_seal() - } - TypedAssignments::Value(vec) => { - vec.get(index as usize).ok_or(NoDataError)?.revealed_seal() - } - TypedAssignments::Data(vec) => { - vec.get(index as usize).ok_or(NoDataError)?.revealed_seal() - } - TypedAssignments::Attachment(vec) => { - vec.get(index as usize).ok_or(NoDataError)?.revealed_seal() - } + TypedAssignments::Void(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), + TypedAssignments::Value(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), + TypedAssignments::Data(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), + TypedAssignments::Attachment(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), }) } diff --git a/src/contract/bundle.rs b/src/contract/bundle.rs new file mode 100644 index 00000000..21b70a3e --- /dev/null +++ b/src/contract/bundle.rs @@ -0,0 +1,167 @@ +// RGB Core Library: consensus layer for RGB smart contracts. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use amplify::confinement::{Confined, TinyOrdMap, TinyOrdSet}; +use amplify::{Bytes32, Wrapper}; +use commit_verify::{mpc, CommitStrategy, CommitmentId}; + +use super::{seal, ConcealSeals, ConcealState, Node, NodeId, RevealSeals, Transition}; +use crate::LIB_NAME_RGB; + +/// Unique state transition bundle identifier equivalent to the bundle +/// commitment hash +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct BundleId( + #[from] + #[from([u8; 32])] + Bytes32, +); + +pub trait ConcealTransitions { + fn conceal_transitions(&mut self) -> usize { self.conceal_transitions_except(&[]) } + fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize; +} + +impl From for mpc::Message { + fn from(id: BundleId) -> Self { mpc::Message::from_inner(id.into_inner()) } +} + +impl From for BundleId { + fn from(id: mpc::Message) -> Self { BundleId(id.into_inner()) } +} + +#[derive(Clone, PartialEq, Eq, Debug, AsAny)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +pub struct TransitionBundle { + // TODO: #141 Provide type guarantees on the sum of revealed and concealed transitions + pub revealed: TinyOrdMap>, + pub concealed: TinyOrdMap>, +} + +impl ConcealTransitions for TransitionBundle { + fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize { + let mut concealed = bmap! {}; + self.revealed = + Confined::try_from_iter(self.revealed.iter().filter_map(|(transition, inputs)| { + let node_id = transition.node_id(); + if !node_ids.contains(&node_id) { + concealed.insert(node_id, inputs.clone()); + None + } else { + Some((transition.clone(), inputs.clone())) + } + })) + .expect("same size"); + let count = concealed.len(); + self.concealed.extend(concealed).expect("todo: issue #141"); + count + } +} + +impl ConcealState for TransitionBundle { + fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { + let mut counter = 0; + self.revealed = + Confined::try_from_iter(self.revealed.iter().map(|(transition, inputs)| { + let mut transition = transition.clone(); + counter += transition.conceal_state_except(seals); + (transition, inputs.clone()) + })) + .expect("same size"); + counter + } +} + +impl ConcealSeals for TransitionBundle { + fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { + let mut counter = 0; + self.revealed = + Confined::try_from_iter(self.revealed.iter().map(|(transition, inputs)| { + let mut transition = transition.clone(); + counter += transition.conceal_seals(seals); + (transition, inputs.clone()) + })) + .expect("same size"); + counter + } +} + +impl RevealSeals for TransitionBundle { + fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize { + let mut counter = 0; + self.revealed = + Confined::try_from_iter(self.revealed.iter().map(|(transition, inputs)| { + let mut transition = transition.clone(); + for (_, assignment) in transition.owned_rights_mut().keyed_values_mut() { + counter += assignment.reveal_seals(known_seals); + } + (transition, inputs.clone()) + })) + .expect("same size"); + counter + } +} + +impl CommitStrategy for TransitionBundle { + type Strategy = commit_verify::strategies::Strict; +} + +impl CommitmentId for TransitionBundle { + const TAG: [u8; 32] = *b"urn:lnpbp:rgb:bundle:v1#20230306"; + type Id = BundleId; +} + +impl TransitionBundle { + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> usize { self.concealed.len() + self.revealed.len() } + + pub fn bundle_id(&self) -> BundleId { self.commitment_id() } +} + +impl TransitionBundle { + pub fn validate(&self) -> bool { + let mut used_inputs = bset! {}; + for set in self.revealed.values() { + if used_inputs.intersection(set).count() > 0 { + return false; + } + used_inputs.extend(set); + } + for set in self.concealed.values() { + if used_inputs.intersection(set).count() > 0 { + return false; + } + used_inputs.extend(set); + } + true + } +} diff --git a/src/contract/mod.rs b/src/contract/mod.rs index fb33f73f..56a62267 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -23,7 +23,6 @@ pub mod seal; mod conceal; -// pub mod reveal_merge; pub mod value; pub mod attachment; @@ -31,15 +30,20 @@ pub mod data; mod global_state; mod owned_state; mod assignments; -pub mod operations; +mod operations; +mod bundle; pub use assignments::TypedAssignments; pub use attachment::AttachId; +pub use bundle::{BundleId, ConcealTransitions, TransitionBundle}; pub use conceal::{ConcealSeals, ConcealState, RevealSeals}; pub use global_state::{FieldValues, Metadata}; +pub use operations::{ + ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, OutpointParseError, OwnedRights, + ParentOwnedRights, ParentPublicRights, PublicRights, Transition, +}; pub use owned_state::{Assignment, State, StateType}; pub use seal::{IntoRevealedSeal, SealEndpoint}; -use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, ValueAtom, @@ -48,19 +52,24 @@ pub use value::{ /// Marker trait for types of state which are just a commitment to the actual /// state data. pub trait ConfidentialState: - core::fmt::Debug + StrictDumb + StrictEncode + StrictDecode + Clone + amplify::AsAny + core::fmt::Debug + + strict_encoding::StrictDumb + + strict_encoding::StrictEncode + + strict_encoding::StrictDecode + + amplify::AsAny + + Clone { } /// Marker trait for types of state holding explicit state data. pub trait RevealedState: core::fmt::Debug - + StrictDumb + + strict_encoding::StrictDumb + + strict_encoding::StrictEncode + + strict_encoding::StrictDecode + commit_verify::Conceal - + StrictEncode - + StrictDecode - + Clone + amplify::AsAny + + Clone { } @@ -80,61 +89,10 @@ pub enum StateRetrievalError { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error)] #[display(doc_comments)] /// the requested data are not present. -pub struct NoDataError; +pub struct UnknownDataError; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error)] #[display(doc_comments)] /// some of the requested data are confidential, when they must be present in /// revealed form. pub struct ConfidentialDataError; - -#[cfg(test)] -pub(crate) mod test { - use commit_verify::{CommitConceal, CommitEncode}; - use strict_encoding::{StrictDecode, StrictEncode}; - - pub use super::value::test_helpers::*; - - pub fn test_confidential(data: &[u8], encoded: &[u8], commitment: &[u8]) - where - T: CommitConceal + StrictDecode + StrictEncode + Clone + CommitEncode, - ::ConcealedCommitment: StrictDecode + StrictEncode + Eq, - { - // Create the Revealed Structure from data bytes - let revealed = T::strict_decode(data).unwrap(); - - // CommitConceal the Revealed structure into Confidential - let confidential = revealed.commit_conceal(); - - // Strict_encode Confidential data - let mut confidential_encoded = vec![]; - confidential - .strict_encode(&mut confidential_encoded) - .unwrap(); - - // strict_encode Revealed data - let mut revealed_encoded: Vec = vec![]; - revealed.strict_encode(&mut revealed_encoded).unwrap(); - - // Assert encoded Confidential matches precomputed vector - assert_eq!(encoded, &confidential_encoded[..]); - - // Assert encoded Confidential and Revealed are not equal - assert_ne!(confidential_encoded.to_vec(), revealed_encoded); - - // commit_encode Revealed structure - let mut commit_encoded_revealed = vec![]; - revealed.clone().commit_encode(&mut commit_encoded_revealed); - - if encoded == commitment { - // Assert commit_encode and encoded Confidential matches - assert_eq!(commit_encoded_revealed, confidential_encoded); - } else { - // Assert commit_encode and encoded Confidential does not match - assert_ne!(commit_encoded_revealed, confidential_encoded); - } - - // Assert commit_encode and precomputed Confidential matches - assert_eq!(commit_encoded_revealed, commitment); - } -} diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 041df2f9..776d6c18 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -20,6 +20,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; use std::num::ParseIntError; use std::str::FromStr; @@ -397,6 +398,15 @@ pub struct Transition { public_rights: PublicRights, } +// TODO: Remove after TransitionBundling refactoring +impl Ord for Transition { + fn cmp(&self, other: &Self) -> Ordering { self.node_id().cmp(&other.node_id()) } +} + +impl PartialOrd for Transition { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +} + impl ConcealState for Genesis { fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { let mut count = 0; diff --git a/src/contract/value.rs b/src/contract/value.rs index 75ac8136..f5d67c16 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -380,20 +380,6 @@ impl Confidential { } } -#[cfg(test)] -pub(crate) mod test_helpers { - use super::*; - - pub fn verify_commit_sum>( - positive: impl IntoIterator, - negative: impl IntoIterator, - ) -> bool { - let positive = positive.into_iter().map(C::into).collect::>(); - let negative = negative.into_iter().map(C::into).collect::>(); - secp256k1_zkp::verify_commitments_sum_to_equal(SECP256K1, &positive, &negative) - } -} - #[cfg(test)] mod test { use secp256k1_zkp::{rand, Scalar, SecretKey}; diff --git a/src/lib.rs b/src/lib.rs index 81af252d..b68a0e34 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![allow(unused_braces)] // Rust compiler can't properly parse derivation macros #![deny( non_upper_case_globals, non_camel_case_types, @@ -43,26 +44,15 @@ extern crate serde_crate as serde; pub mod contract; pub mod schema; // pub mod stash; -// pub mod validation; +pub mod validation; pub mod vm; pub const LIB_NAME_RGB: &str = "RGB"; pub mod prelude { pub use bp::dbc::{Anchor, AnchorId}; - /*pub use contract::{ - data, reveal, seal, value, Assignment, AtomicValue, AttachmentId, AttachmentStrategy, - Bulletproofs, ConcealSeals, ConcealState, ConfidentialDataError, ConfidentialState, - ContractId, DeclarativeStrategy, EndpointValueMap, Extension, Genesis, HashStrategy, - IntoRevealedSeal, MergeReveal, Metadata, NoDataError, Node, NodeId, NodeOutpoint, - OwnedRights, ParentOwnedRights, ParentPublicRights, PedersenStrategy, PublicRights, - RevealSeals, RevealedState, SealEndpoint, SealValueMap, State, StateRetrievalError, - StateType, Transition, TypedAssignments, - };*/ - pub use schema::{ - ExtensionSchema, ExtensionType, NodeSubtype, NodeType, PublicRightType, - PublicRightsStructure, Schema, SchemaId, Scripts, VmType, - }; + pub use contract::*; + pub use schema::*; pub use super::schema; /*pub use stash::{ @@ -72,7 +62,7 @@ pub mod prelude { pub use validation::{Validator, Validity, Validate}; */ pub use super::vm; - // use super::*; + use super::*; } pub use prelude::*; diff --git a/src/stash/bundle.rs b/src/stash/bundle.rs deleted file mode 100644 index e33a2a5b..00000000 --- a/src/stash/bundle.rs +++ /dev/null @@ -1,323 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::collections::{btree_map, BTreeMap, BTreeSet}; - -use amplify::Wrapper; -use bitcoin_hashes::{sha256, sha256t, Hash}; -use commit_verify::{mpc, CommitVerify, UntaggedProtocol}; - -use crate::{seal, ConcealSeals, ConcealState, Node, NodeId, RevealSeals, Transition}; - -// "rgb:bundle" -static MIDSTATE_BUNDLE_ID: [u8; 32] = [ - 219, 42, 125, 118, 252, 62, 163, 226, 43, 104, 76, 97, 218, 62, 92, 108, 200, 133, 207, 235, - 35, 72, 210, 0, 122, 143, 80, 88, 238, 145, 95, 89, -]; - -/// Tag used for [`BundleId`] hash type -pub struct BundleIdTag; - -impl sha256t::Tag for BundleIdTag { - #[inline] - fn engine() -> sha256::HashEngine { - let midstate = sha256::Midstate::from_inner(MIDSTATE_BUNDLE_ID); - sha256::HashEngine::from_midstate(midstate, 64) - } -} - -/// Unique state transition bundle identifier equivalent to the bundle -/// commitment hash -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From)] -#[wrapper(Debug, Display, BorrowSlice)] -pub struct BundleId(sha256t::Hash); - -impl CommitVerify for BundleId -where Msg: AsRef<[u8]> -{ - #[inline] - fn commit(msg: &Msg) -> BundleId { BundleId::hash(msg) } -} - -pub trait ConcealTransitions { - fn conceal_transitions(&mut self) -> usize { self.conceal_transitions_except(&[]) } - fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize; -} - -impl From for mpc::Message { - fn from(id: BundleId) -> Self { mpc::Message::from_inner(id.into_inner()) } -} - -impl From for BundleId { - fn from(id: mpc::Message) -> Self { BundleId(sha256t::Hash::from_inner(id.into_inner())) } -} - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error)] -#[display(doc_comments)] -pub enum RevealError { - /// the provided state transition is not a part of the bundle - UnrelatedTransition, -} - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error)] -#[display("attempt to construct transition bundle with no transitions given")] -pub struct NoDataError; - -#[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct TransitionBundle { - revealed: BTreeMap>, - concealed: BTreeMap>, -} - -/* -impl StrictDecode for TransitionBundle { - fn strict_decode(mut d: D) -> Result { - let bundle = strict_decode_self!(d; revealed, concealed); - if bundle.revealed.is_empty() && bundle.concealed.is_empty() { - return Err(strict_encoding::Error::DataIntegrityError(s!( - "transition bundle without any transitions" - ))); - } - Ok(bundle) - } -} - */ - -impl ConcealTransitions for TransitionBundle { - fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize { - let mut concealed = bmap! {}; - self.revealed = self - .revealed - .iter() - .filter_map(|(transition, inputs)| { - let node_id = transition.node_id(); - if !node_ids.contains(&node_id) { - concealed.insert(node_id, inputs.clone()); - None - } else { - Some((transition.clone(), inputs.clone())) - } - }) - .collect(); - let count = concealed.len(); - self.concealed.extend(concealed); - count - } -} - -impl ConcealState for TransitionBundle { - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - let mut counter = 0; - self.revealed = self - .revealed_iter() - .map(|(transition, inputs)| { - let mut transition = transition.clone(); - counter += transition.conceal_state_except(seals); - (transition, inputs.clone()) - }) - .collect::>(); - counter - } -} - -impl ConcealSeals for TransitionBundle { - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - let mut counter = 0; - self.revealed = self - .revealed_iter() - .map(|(transition, inputs)| { - let mut transition = transition.clone(); - counter += transition.conceal_seals(seals); - (transition, inputs.clone()) - }) - .collect::>(); - counter - } -} - -impl RevealSeals for TransitionBundle { - fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize { - let mut counter = 0; - self.revealed = self - .revealed_iter() - .map(|(transition, inputs)| { - let mut transition = transition.clone(); - for (_, assignment) in transition.owned_rights_mut().iter_mut() { - counter += assignment.reveal_seals(known_seals); - } - (transition, inputs.clone()) - }) - .collect::>(); - counter - } -} - -impl TryFrom>> for TransitionBundle { - type Error = NoDataError; - - fn try_from(revealed: BTreeMap>) -> Result { - if revealed.is_empty() { - return Err(NoDataError); - } - Ok(TransitionBundle { - revealed, - concealed: empty!(), - }) - } -} - -impl TryFrom>> for TransitionBundle { - type Error = NoDataError; - fn try_from(concealed: BTreeMap>) -> Result { - if concealed.is_empty() { - return Err(NoDataError); - } - Ok(TransitionBundle { - revealed: empty!(), - concealed, - }) - } -} - -impl TransitionBundle { - pub fn with( - revealed: BTreeMap>, - concealed: BTreeMap>, - ) -> Result { - if revealed.is_empty() && concealed.is_empty() { - return Err(NoDataError); - } - Ok(TransitionBundle { - revealed, - concealed, - }) - } - - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> usize { self.concealed.len() + self.revealed.len() } - - pub fn bundle_id(&self) -> BundleId { self.consensus_commit() } - - pub fn node_ids(&self) -> BTreeSet { - self.concealed - .keys() - .copied() - .chain(self.revealed.keys().map(Transition::node_id)) - .collect() - } - - pub fn contains_id(&self, node_id: NodeId) -> bool { - self.is_concealed(node_id) || self.is_revealed(node_id) - } - - pub fn inputs_for(&self, node_id: NodeId) -> Option<&BTreeSet> { - self.revealed - .iter() - .find_map(|(ts, inputs)| { - if ts.node_id() == node_id { - Some(inputs) - } else { - None - } - }) - .or_else(|| self.concealed.get(&node_id)) - } - - pub fn is_revealed(&self, node_id: NodeId) -> bool { - self.revealed.keys().any(|ts| ts.node_id() == node_id) - } - - pub fn is_concealed(&self, node_id: NodeId) -> bool { self.concealed.contains_key(&node_id) } - - pub fn reveal_transition(&mut self, transition: Transition) -> Result { - let id = transition.node_id(); - if let Some(inputs) = self.concealed.remove(&id) { - self.revealed.insert(transition, inputs); - Ok(true) - } else if self.revealed.contains_key(&transition) { - Ok(false) - } else { - Err(RevealError::UnrelatedTransition) - } - } - - pub fn revealed_iter(&self) -> btree_map::Iter> { - self.revealed.iter() - } - - pub fn into_revealed_iter(self) -> btree_map::IntoIter> { - self.revealed.into_iter() - } - - pub fn concealed_iter(&self) -> btree_map::Iter> { self.concealed.iter() } - - pub fn into_concealed_iter(self) -> btree_map::IntoIter> { - self.concealed.into_iter() - } - - pub fn known_transitions(&self) -> btree_map::Keys> { - self.revealed.keys() - } - - pub fn known_node_ids(&self) -> BTreeSet { - self.known_transitions().map(Transition::node_id).collect() - } -} - -impl TransitionBundle { - pub fn validate(&self) -> bool { - let mut used_inputs = bset! {}; - for set in self.revealed.values() { - if used_inputs.intersection(set).count() > 0 { - return false; - } - used_inputs.extend(set); - } - for set in self.concealed.values() { - if used_inputs.intersection(set).count() > 0 { - return false; - } - used_inputs.extend(set); - } - true - } -} - -#[cfg(test)] -mod test { - use amplify::Wrapper; - use commit_verify::tagged_hash; - - use super::*; - - #[test] - fn test_bundle_id_midstate() { - let midstate = tagged_hash::Midstate::with(b"rgb:bundle"); - assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_BUNDLE_ID); - } -} diff --git a/src/stash/mod.rs b/src/stash/mod.rs deleted file mode 100644 index b6aa1086..00000000 --- a/src/stash/mod.rs +++ /dev/null @@ -1,51 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Data structures and APIs related to RGB data storage and data exchange -//! tasks. -//! -//! There are two main APIs which may be used to access RGB contract data (both -//! client-side-validated and data containers): [`Stash`] API and [`GraphAPI`]. -//! They differ in the fact that [`Stash`] manages long-term persistance of -//! large-volume data, while [`GraphAPI`] is used by the data structures fitting -//! into the computer memory (`Consignment`s and `Disclosure`s of the standard -//! library). -//! -//! These data structures are not part of the client-side-validation -//! commitments (like [`ConsensusCommit`] and [`CommitEncode`]), however, some -//! of them MAY participate client-side-validation process (see -//! `Consignments`) or MAY have a restricted forms of validation (see -//! `Disclosure`), while others are constantly maintained in valid state by -//! the data management procedures ([`Stash`]). - -mod anchor; -mod graph; -#[allow(clippy::module_inception)] -mod stash; -pub mod bundle; -mod consignment; - -pub use anchor::ConcealAnchors; -pub use bundle::{BundleId, ConcealTransitions, TransitionBundle}; -pub use consignment::{AnchoredBundle, Consignment, ConsignmentEndpoint}; -pub use graph::{ConsistencyError, GraphApi}; -pub use stash::Stash; diff --git a/src/stash/stash.rs b/src/stash/stash.rs deleted file mode 100644 index f996da02..00000000 --- a/src/stash/stash.rs +++ /dev/null @@ -1,134 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! API for working with stash: storage of RGB contract client-side-validated -//! data and data containers. -//! -//! Client-side-validated data, and (especially) data containers may grow large -//! (multiple gigabytes) and can't be fit in a memory as a single data -//! structure. Thus, we utilize a special API which abstracts the specific stash -//! storage mechanism (file-based, SQL or NoSQL database, special disk -//! partitions, cloud-provided storage, like with Bifrost protocol, etc). -//! With this API the data can be accessed using iterators or by providing the -//! specific data id. -//! -//! NB: Stash implementations must be able to operate multiple independent RGB -//! contract. - -use bp::dbc::{Anchor, AnchorId}; -use bp::Outpoint; -use commit_verify::mpc; - -use crate::temp::ResolveTx; -use crate::{ContractId, Extension, Genesis, NodeId, Schema, SchemaId, Transition}; - -/// Top-level structure used by client wallets to manage all known RGB smart -/// contracts and related data. -/// -/// Stash operates blobs, so it does not keep in the memory whole copy of all -/// data. Access to the underlying data structures happens through iterators: -/// - [`Stash::ContractIterator`] -/// -/// Stash API is an alternative to the RGB contract data access API provided by -/// [`crate::GraphApi`], which is implemented by the structures keeping all the -/// data in memory ([`Consignment`] and [`Disclosure`]). -pub trait Stash { - /// Error type returned by different stash functions - type Error: std::error::Error; - - /// Iterator implementation able to run over known schemata and subschemata - type SchemaIterator: Iterator; - /// Iterator implementation able to run over all contract geneses - type GenesisIterator: Iterator; - /// Iterator implementation able to run over all known anchors - type AnchorIterator: Iterator>; - /// Iterator implementation able to run over all state transitions under - /// particular contract - type TransitionIterator: Iterator; - /// Iterator implementation able to run over all state extensions under - /// particular contract - type ExtensionIterator: Iterator; - /// Iterator implementation able to run over all node ids under - /// particular contract - type NodeIdIterator: Iterator; - - /// Returns schema or subschema matching the provided id, if any, or - /// storage-specific error otherwise - fn get_schema(&self, schema_id: SchemaId) -> Result; - - /// Returns genesis matching the provided id, if any, or storage-specific - /// error otherwise - fn get_genesis(&self, contract_id: ContractId) -> Result; - - /// Returns state transition matching the provided `node_id`, if any, or - /// storage-specific error otherwise. - /// - /// NB: Here the state transition is identified by the node id and not - /// relates to a specific contract_id. To get the transitions by a contract - /// id please use transition iterator. - fn get_transition(&self, node_id: NodeId) -> Result; - - /// Returns state extension matching the provided `node_id`, if any, or - /// storage-specific error otherwise. - /// - /// NB: Here the state extension is identified by the node id and not - /// relates to a specific contract_id. To get the extensions by a contract - /// id please use extension iterator. - fn get_extension(&self, node_id: NodeId) -> Result; - - /// Returns anchor matching the provided `anchor_id`, if any, or - /// storage-specific error otherwise. - /// - /// NB: Anchors may be related to multiple contract ids; specific set of the - /// contracts to which this anchor is related to may be known from the - /// anchor data, unless they are kept in the confidential form. See - /// [`Anchor`] documentation for the details. - fn get_anchor(&self, anchor_id: AnchorId) -> Result, Self::Error>; - - /// Iterator over all contract geneses (i.e. iterator over all known RGB - /// contracts). - fn genesis_iter(&self) -> Self::GenesisIterator; - - /// Iterator over all known anchors - /// - /// NB: each anchor may be related to multiple contracts, thus here we do - /// not provide contract id constraint for the iterator. - fn anchor_iter(&self) -> Self::AnchorIterator; - - /// Iterator over all known state transition under particular RGB contract - fn transition_iter(&self, contract_id: ContractId) -> Self::TransitionIterator; - - /// Iterator over all known state extensions under particular RGB contract - fn extension_iter(&self, contract_id: ContractId) -> Self::ExtensionIterator; - - /// Clears all data that are not related to the contract state owned by - /// us in this moment — under all known contracts. Uses provided - /// `tx_resolver` to resolve validity of the related transactions (witness - /// and single-use-seal) and `ownership_resolver` for checking whether - /// specific transaction output is owned by the current user (stash data - /// holder) - fn prune( - &mut self, - tx_resolver: &mut impl ResolveTx, - ownership_resolver: impl Fn(Outpoint) -> bool, - ) -> Result; -} diff --git a/src/stash/unit.rs b/src/stash/unit.rs deleted file mode 100644 index 2655756f..00000000 --- a/src/stash/unit.rs +++ /dev/null @@ -1,125 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Definition of and operations with state transition units ([`Unit`]) - -use std::iter::Filter; - -use bitcoin::{Outpoint, Txid}; - -use crate::schema::OwnedRightType; -use crate::stash::iter::{ConsTsIter, TransitionIterator}; -use crate::{Assignments, Consignment, NodeOutput, StateTypes, Transition}; - -/// State transition units (or simply "state units", or even just "units") are -/// extracts from the RGB contract data (as they are stored in a stash) -/// representing particular step in contract state evolution. -/// -/// State units can be extracted from stash, consignment (which can be -/// represented by a set of individual state units), and, sometimes, from -/// disclosures (which may not contain even a single complete state unit) and -/// in most cases can't be represented by a set of state units. -/// -/// State units are used for data extraction only (unlike consignments and -/// disclosures) and can't be used for mutating or update the contract state or -/// stash. They also do not participate in contract validation and serve pure -/// API usability needs for creating more user-friendly schema-specific APIs. -/// -/// State units always contain fully-revealed data and can't be extracted from -/// the contract if at least some of the data are concealed (i.e. seal, state -/// or anchoring mechanism). -/// -/// State unit contract-scoped id can be defined as combination of -/// [`Unit::state_type`] and [`Unit::output`]. Global unique state unit ID may -/// be composed by adding RGB contract id to those data. -#[derive(Getters, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub struct Unit<'container, State> -where State: StateTypes -{ - /// The type of the owned rights which is being modified by the operation - state_type: OwnedRightType, - - /// State origin in the contract node graph - input: NodeOutput, - - /// State destination in the contract node graph - output: NodeOutput, - - /// The seal closed by the operation - closed_seal: Outpoint, - - /// The new seal defined by the operation - defined_seal: Outpoint, - - /// Previous state (invalidated by the operation) - prev_state: &'container State::Revealed, - - /// New state defined as a result of the operation - next_state: &'container State::Revealed, - - /// Transaction output operating as a single-use-seal closing witness - witness: Outpoint, -} - -#[derive(Eq, PartialEq, Debug)] -pub struct UnitIter<'iter, TsIter, State, Resolver> -where - State: StateTypes, - TsIter: TransitionIterator<'iter>, - Resolver: Fn(Txid) -> u16, -{ - iter: Filter, fn((Txid, &'iter Transition)) -> bool>, - item: Option<(Txid, &'iter Assignments)>, - index: usize, - resolver: Resolver, - state_type: OwnedRightType, -} - -impl<'iter, TsIter, State, Resolver> Iterator for UnitIter<'iter, TsIter, State, Resolver> -where - State: StateTypes, - TsIter: TransitionIterator<'iter>, - Resolver: Fn(Txid) -> u16, -{ - type Item = Unit<'iter, State>; - - fn next(&mut self) -> Option { - let (txid, assignments) = if let Some((txid, assignments)) = while self.item.is_none() { - let (txid, transition) = if let Some((txid, transition)) = self.iter.next() { - (txid, transition) - } else { - return None; - }; - self.item = transition - .owned_rights_by_type(self.state_type) - .map(|assignments| (txid, assignments)); - self.index = 0; - self.item - } { - (txid, assignments) - } else { - return None; - }; - - assignments - } -} diff --git a/src/stash/consignment.rs b/src/validation/consignment.rs similarity index 74% rename from src/stash/consignment.rs rename to src/validation/consignment.rs index d818fa2f..cd1fa16c 100644 --- a/src/stash/consignment.rs +++ b/src/validation/consignment.rs @@ -20,6 +20,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Data structures and APIs related to RGB data storage and data exchange +//! tasks. +//! +//! There are two main APIs which may be used to access RGB contract data (both +//! client-side-validated and data containers): [`Stash`] API and [`GraphAPI`]. +//! They differ in the fact that [`Stash`] manages long-term persistance of +//! large-volume data, while [`GraphAPI`] is used by the data structures fitting +//! into the computer memory (`Consignment`s and `Disclosure`s of the standard +//! library). +//! +//! These data structures are not part of the client-side-validation +//! commitments (like [`ConsensusCommit`] and [`CommitEncode`]), however, some +//! of them MAY participate client-side-validation process (see +//! `Consignments`) or MAY have a restricted forms of validation (see +//! `Disclosure`), while others are constantly maintained in valid state by +//! the data management procedures ([`Stash`]). + use std::collections::BTreeSet; use commit_verify::mpc; diff --git a/src/stash/graph.rs b/src/validation/graph.rs similarity index 100% rename from src/stash/graph.rs rename to src/validation/graph.rs diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 5ec19277..7c02faf9 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -25,7 +25,8 @@ use core::ops::AddAssign; use bp::Txid; -use super::schema::{self, NodeType, OccurrencesError, SchemaId}; +use crate::schema::{self, NodeType, SchemaId}; +use crate::{data, BundleId, NodeId, OccurrencesMismatch, SealEndpoint}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] #[display(Debug)] @@ -173,9 +174,9 @@ pub enum Failure { SchemaMismatchedDataType(u16), SchemaMismatchedStateType(schema::OwnedRightType), - SchemaMetaOccurrencesError(NodeId, schema::FieldType, OccurrencesError), - SchemaParentOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesError), - SchemaOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesError), + SchemaMetaOccurrencesError(NodeId, schema::FieldType, OccurrencesMismatch), + SchemaParentOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesMismatch), + SchemaOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesMismatch), SchemaScriptOverrideDenied, SchemaScriptVmChangeDenied, From c3004fab669ff55ede0ae81507cd7b2158e8dbc5 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 00:36:47 +0100 Subject: [PATCH 49/71] validation: refactor graph API --- src/contract/bundle.rs | 2 +- src/validation/consignment.rs | 82 ----------------------------------- src/validation/graph.rs | 47 +++++++++++++++----- src/validation/mod.rs | 2 + 4 files changed, 40 insertions(+), 93 deletions(-) delete mode 100644 src/validation/consignment.rs diff --git a/src/contract/bundle.rs b/src/contract/bundle.rs index 21b70a3e..54dca37e 100644 --- a/src/contract/bundle.rs +++ b/src/contract/bundle.rs @@ -30,7 +30,7 @@ use crate::LIB_NAME_RGB; /// Unique state transition bundle identifier equivalent to the bundle /// commitment hash #[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] -#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[wrapper(Deref, BorrowSlice, Display, Hex, Index, RangeOps)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr( diff --git a/src/validation/consignment.rs b/src/validation/consignment.rs deleted file mode 100644 index cd1fa16c..00000000 --- a/src/validation/consignment.rs +++ /dev/null @@ -1,82 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Data structures and APIs related to RGB data storage and data exchange -//! tasks. -//! -//! There are two main APIs which may be used to access RGB contract data (both -//! client-side-validated and data containers): [`Stash`] API and [`GraphAPI`]. -//! They differ in the fact that [`Stash`] manages long-term persistance of -//! large-volume data, while [`GraphAPI`] is used by the data structures fitting -//! into the computer memory (`Consignment`s and `Disclosure`s of the standard -//! library). -//! -//! These data structures are not part of the client-side-validation -//! commitments (like [`ConsensusCommit`] and [`CommitEncode`]), however, some -//! of them MAY participate client-side-validation process (see -//! `Consignments`) or MAY have a restricted forms of validation (see -//! `Disclosure`), while others are constantly maintained in valid state by -//! the data management procedures ([`Stash`]). - -use std::collections::BTreeSet; - -use commit_verify::mpc; - -use crate::{ - Anchor, BundleId, Extension, Genesis, GraphApi, NodeId, Schema, SealEndpoint, TransitionBundle, -}; - -pub type ConsignmentEndpoint = (BundleId, SealEndpoint); - -pub type AnchoredBundle<'me> = (&'me Anchor, &'me TransitionBundle); - -pub trait Consignment<'consignment>: 'consignment + GraphApi { - type EndpointIter: Iterator; - type BundleIter: Iterator, TransitionBundle)>; - type ExtensionsIter: Iterator; - - fn schema(&'consignment self) -> &'consignment Schema; - - fn root_schema(&'consignment self) -> Option<&'consignment Schema>; - - /// Genesis data - fn genesis(&'consignment self) -> &'consignment Genesis; - - fn node_ids(&'consignment self) -> BTreeSet; - - /// The final state ("endpoints") provided by this consignment. - /// - /// There are two reasons for having endpoints: - /// - navigation towards genesis from the final state is more - /// computationally efficient, since state transition/extension graph is - /// directed towards genesis (like bitcoin transaction graph) - /// - if the consignment contains concealed state (known by the receiver), - /// it will be computationally inefficient to understand which of the - /// state transitions represent the final state - fn endpoints(&'consignment self) -> Self::EndpointIter; - - /// Data on all anchored state transitions contained in the consignment - fn anchored_bundles(&'consignment self) -> Self::BundleIter; - - /// Data on all state extensions contained in the consignment - fn state_extensions(&'consignment self) -> Self::ExtensionsIter; -} diff --git a/src/validation/graph.rs b/src/validation/graph.rs index 1329246e..76a9975c 100644 --- a/src/validation/graph.rs +++ b/src/validation/graph.rs @@ -23,23 +23,18 @@ //! Common API for accessing RGB contract node graph, including individual state //! transitions, extensions, genesis, outputs, assignments & single-use-seal //! data. -//! -//! Implemented by all storage-managing [`rgb::stash`] structures, including: -//! - [`Consignment`] -//! - [`Disclosure`] -//! -//! [`Stash`] API is the alternative form of API used by stash implementations, -//! which may operate much larger volumes of client-side-validated data, which -//! may not fit into the memory, and thus using specially-designed iterators and -//! different storage drivers returning driver-specific error types. use std::collections::BTreeSet; use bp::dbc::AnchorId; use bp::{Outpoint, Txid}; +use commit_verify::mpc; use crate::schema::OwnedRightType; -use crate::{BundleId, Extension, Node, NodeId, NodeOutpoint, Transition, TransitionBundle}; +use crate::{ + Anchor, BundleId, Extension, Genesis, Node, NodeId, NodeOutpoint, Schema, SealEndpoint, + Transition, TransitionBundle, +}; /// Errors accessing graph data via [`GraphApi`]. /// @@ -181,3 +176,35 @@ pub trait GraphApi { witness: Txid, ) -> Result, ConsistencyError>; } + +pub trait Consignment<'consignment>: 'consignment + GraphApi { + type EndpointIter: Iterator; + type BundleIter: Iterator, TransitionBundle)>; + type ExtensionsIter: Iterator; + + fn schema(&'consignment self) -> &'consignment Schema; + + fn root_schema(&'consignment self) -> Option<&'consignment Schema>; + + /// Genesis data + fn genesis(&'consignment self) -> &'consignment Genesis; + + fn node_ids(&'consignment self) -> BTreeSet; + + /// The final state ("endpoints") provided by this consignment. + /// + /// There are two reasons for having endpoints: + /// - navigation towards genesis from the final state is more + /// computationally efficient, since state transition/extension graph is + /// directed towards genesis (like bitcoin transaction graph) + /// - if the consignment contains concealed state (known by the receiver), + /// it will be computationally inefficient to understand which of the + /// state transitions represent the final state + fn endpoints(&'consignment self) -> Self::EndpointIter; + + /// Data on all anchored state transitions contained in the consignment + fn anchored_bundles(&'consignment self) -> Self::BundleIter; + + /// Data on all state extensions contained in the consignment + fn state_extensions(&'consignment self) -> Self::ExtensionsIter; +} diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 7c02faf9..99f1becd 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -20,6 +20,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod graph; + use core::iter::FromIterator; use core::ops::AddAssign; From 04b0e0defc402dbb4ce31a6e4452fe2fa404d0ea Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 00:46:34 +0100 Subject: [PATCH 50/71] vm: refactor --- Cargo.lock | 1 + Cargo.toml | 2 +- src/validation/mod.rs | 1 + src/validation/vm.rs | 9 ++++----- src/vm/{alure.rs => isa.rs} | 11 ----------- src/vm/mod.rs | 15 ++++++++++++++- 6 files changed, 21 insertions(+), 18 deletions(-) rename src/vm/{alure.rs => isa.rs} (91%) diff --git a/Cargo.lock b/Cargo.lock index 76671ee4..17100ca1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,7 @@ dependencies = [ "paste", "secp256k1 0.26.0", "serde", + "strict_encoding", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4bdf1859..a87ae146 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ name = "rgb" amplify = "~4.0.0-beta.13" strict_encoding = "2.0.0-rc.1" strict_types = "1.0.0-beta.3" -aluvm = "0.10.0-alpha.1" +aluvm = { version = "0.10.0-alpha.1", features = ["strict_encoding"] } commit_verify = { version = "~0.10.0-beta.2", features = ["rand"] } bp-core = { version = "~0.10.0-beta.1" } secp256k1-zkp = { version = "~0.7.0", features = ["use-rand", "rand-std", "global-context"] } diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 99f1becd..9afb4104 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -21,6 +21,7 @@ // limitations under the License. mod graph; +mod vm; use core::iter::FromIterator; use core::ops::AddAssign; diff --git a/src/validation/vm.rs b/src/validation/vm.rs index 4261d092..e6c19c38 100644 --- a/src/validation/vm.rs +++ b/src/validation/vm.rs @@ -21,9 +21,8 @@ // limitations under the License. use crate::validation::Failure; -use crate::{ - validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, ValidationScript, -}; +use crate::vm::Runtime; +use crate::{validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, Scripts}; /// Trait for concrete types wrapping virtual machines to be used from inside /// RGB schema validation routines. @@ -42,7 +41,7 @@ pub trait Validate { ) -> Result<(), validation::Failure>; } -impl Validate for ValidationScript { +impl Validate for Scripts { fn validate( &self, node_id: NodeId, @@ -54,7 +53,7 @@ impl Validate for ValidationScript { current_meta: &Metadata, ) -> Result<(), validation::Failure> { match self { - ValidationScript::AluVM(script) => alure::Runtime::new(script).validate( + Scripts::AluVM(script) => Runtime::new(script).validate( node_id, node_subtype, previous_owned_rights, diff --git a/src/vm/alure.rs b/src/vm/isa.rs similarity index 91% rename from src/vm/alure.rs rename to src/vm/isa.rs index 214468ca..510d8754 100644 --- a/src/vm/alure.rs +++ b/src/vm/isa.rs @@ -83,14 +83,3 @@ impl Bytecode for RgbIsa { }) } } - -pub type AluLib = aluvm::Program; - -pub struct Runtime<'script> { - #[allow(dead_code)] - lib: &'script AluLib, -} - -impl<'script> Runtime<'script> { - pub fn new(lib: &'script AluLib) -> Self { Runtime { lib } } -} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index e3ab0707..0bc8cfa2 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -25,4 +25,17 @@ //! Concrete virtual machine implementations must be wrapped into this API // pub mod embedded; -pub mod alure; +pub mod isa; + +pub type AluLib = aluvm::Program; + +pub struct Runtime<'script> { + #[allow(dead_code)] + lib: &'script AluLib, +} + +impl<'script> Runtime<'script> { + pub fn new(_lib: &'script [u8]) -> Self { + todo!() /* Runtime { lib } */ + } +} From d33646d6e520893c03d1c24cddc962b66b5781d2 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 00:51:53 +0100 Subject: [PATCH 51/71] validation: refactor subschema validation --- src/validation/mod.rs | 1 + src/validation/schema.rs | 165 ----------------------------------- src/validation/subschema.rs | 167 ++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 165 deletions(-) create mode 100644 src/validation/subschema.rs diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 9afb4104..bc76137f 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -22,6 +22,7 @@ mod graph; mod vm; +mod subschema; use core::iter::FromIterator; use core::ops::AddAssign; diff --git a/src/validation/schema.rs b/src/validation/schema.rs index 9daafa2a..ab4513c9 100644 --- a/src/validation/schema.rs +++ b/src/validation/schema.rs @@ -20,94 +20,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// Trait used for internal schema validation against some root schema -pub trait SchemaVerify { - fn schema_verify(&self, root: &Self) -> crate::validation::Status; -} - -mod _verify { - use super::*; - use crate::schema::SchemaVerify; - use crate::validation; - - impl SchemaVerify for T - where T: NodeSchema - { - fn schema_verify(&self, root: &Self) -> validation::Status { - let mut status = validation::Status::new(); - let node_type = self.node_type(); - - for (field_type, occ) in self.metadata() { - match root.metadata().get(field_type) { - None => status.add_failure(validation::Failure::SchemaRootNoMetadataMatch( - node_type, - *field_type, - )), - Some(root_occ) if occ != root_occ => status.add_failure( - validation::Failure::SchemaRootNoMetadataMatch(node_type, *field_type), - ), - _ => &status, - }; - } - - for (assignments_type, occ) in self.closes() { - match root.closes().get(assignments_type) { - None => { - status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( - node_type, - *assignments_type, - )) - } - Some(root_occ) if occ != root_occ => { - status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( - node_type, - *assignments_type, - )) - } - _ => &status, - }; - } - - for (assignments_type, occ) in self.owned_rights() { - match root.owned_rights().get(assignments_type) { - None => status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( - node_type, - *assignments_type, - )), - Some(root_occ) if occ != root_occ => { - status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( - node_type, - *assignments_type, - )) - } - _ => &status, - }; - } - - for valencies_type in self.extends() { - if !root.extends().contains(valencies_type) { - status.add_failure(validation::Failure::SchemaRootNoParentPublicRightsMatch( - node_type, - *valencies_type, - )); - } - } - - for valencies_type in self.public_rights() { - if !root.public_rights().contains(valencies_type) { - status.add_failure(validation::Failure::SchemaRootNoPublicRightsMatch( - node_type, - *valencies_type, - )); - } - } - - status - } - } -} - -// TODO #73: Move to validation module and refactor that module into a directory mod _validation { use std::collections::BTreeSet; @@ -122,83 +34,6 @@ mod _validation { ParentOwnedRights, ParentPublicRights, PublicRights, State, TypedAssignments, }; - impl SchemaVerify for Schema { - fn schema_verify(&self, root: &Schema) -> validation::Status { - let mut status = validation::Status::new(); - - if root.root_id != SchemaId::default() { - status.add_failure(validation::Failure::SchemaRootHierarchy(root.root_id)); - } - - for (field_type, data_format) in &self.field_types { - match root.field_types.get(field_type) { - None => status - .add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)), - Some(root_data_format) if root_data_format != data_format => status - .add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)), - _ => &status, - }; - } - - for (assignments_type, state_schema) in &self.owned_right_types { - match root.owned_right_types.get(assignments_type) { - None => status.add_failure( - validation::Failure::SchemaRootNoOwnedRightTypeMatch(*assignments_type), - ), - Some(root_state_schema) if root_state_schema != state_schema => status - .add_failure(validation::Failure::SchemaRootNoOwnedRightTypeMatch( - *assignments_type, - )), - _ => &status, - }; - } - - for valencies_type in &self.public_right_types { - match root.public_right_types.contains(valencies_type) { - false => status.add_failure( - validation::Failure::SchemaRootNoPublicRightTypeMatch(*valencies_type), - ), - _ => &status, - }; - } - - status += self.genesis.schema_verify(&root.genesis); - - for (transition_type, transition_schema) in &self.transitions { - if let Some(root_transition_schema) = root.transitions.get(transition_type) { - status += transition_schema.schema_verify(root_transition_schema); - } else { - status.add_failure(validation::Failure::SchemaRootNoTransitionTypeMatch( - *transition_type, - )); - } - } - for (extension_type, extension_schema) in &self.extensions { - if let Some(root_extension_schema) = root.extensions.get(extension_type) { - status += extension_schema.schema_verify(root_extension_schema); - } else { - status.add_failure(validation::Failure::SchemaRootNoExtensionTypeMatch( - *extension_type, - )); - } - } - - match (root.override_rules, self.override_rules) { - (OverrideRules::Deny, _) if root.script != self.script => { - status.add_failure(validation::Failure::SchemaScriptOverrideDenied); - } - (OverrideRules::AllowSameVm, _) - if root.script.vm_type() != self.script.vm_type() => - { - status.add_failure(validation::Failure::SchemaScriptVmChangeDenied); - } - _ => {} // We are fine here - } - - status - } - } - impl Schema { pub fn validate( &self, diff --git a/src/validation/subschema.rs b/src/validation/subschema.rs new file mode 100644 index 00000000..de1b68ee --- /dev/null +++ b/src/validation/subschema.rs @@ -0,0 +1,167 @@ +// RGB Core Library: consensus layer for RGB smart contracts. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{validation, NodeSchema, Schema}; + +/// Trait used for internal schema validation against some root schema +pub trait SchemaVerify { + fn schema_verify(&self, root: &Self) -> crate::validation::Status; +} + +impl SchemaVerify for Schema { + fn schema_verify(&self, root: &Schema) -> validation::Status { + let mut status = validation::Status::new(); + + if let Some(other_root) = root.subset_of { + status.add_failure(validation::Failure::SchemaRootHierarchy(other_root)); + } + + for (field_type, data_format) in &self.field_types { + match root.field_types.get(field_type) { + None => { + status.add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)) + } + Some(root_data_format) if root_data_format != data_format => { + status.add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)) + } + _ => &status, + }; + } + + for (assignments_type, state_schema) in &self.owned_right_types { + match root.owned_right_types.get(assignments_type) { + None => status.add_failure(validation::Failure::SchemaRootNoOwnedRightTypeMatch( + *assignments_type, + )), + Some(root_state_schema) if root_state_schema != state_schema => status.add_failure( + validation::Failure::SchemaRootNoOwnedRightTypeMatch(*assignments_type), + ), + _ => &status, + }; + } + + for valencies_type in &self.public_right_types { + match root.public_right_types.contains(valencies_type) { + false => status.add_failure(validation::Failure::SchemaRootNoPublicRightTypeMatch( + *valencies_type, + )), + _ => &status, + }; + } + + status += self.genesis.schema_verify(&root.genesis); + + for (transition_type, transition_schema) in &self.transitions { + if let Some(root_transition_schema) = root.transitions.get(transition_type) { + status += transition_schema.schema_verify(root_transition_schema); + } else { + status.add_failure(validation::Failure::SchemaRootNoTransitionTypeMatch( + *transition_type, + )); + } + } + for (extension_type, extension_schema) in &self.extensions { + if let Some(root_extension_schema) = root.extensions.get(extension_type) { + status += extension_schema.schema_verify(root_extension_schema); + } else { + status.add_failure(validation::Failure::SchemaRootNoExtensionTypeMatch( + *extension_type, + )); + } + } + + status + } +} + +impl SchemaVerify for T +where T: NodeSchema +{ + fn schema_verify(&self, root: &Self) -> validation::Status { + let mut status = validation::Status::new(); + let node_type = self.node_type(); + + for (field_type, occ) in self.metadata() { + match root.metadata().get(field_type) { + None => status.add_failure(validation::Failure::SchemaRootNoMetadataMatch( + node_type, + *field_type, + )), + Some(root_occ) if occ != root_occ => status.add_failure( + validation::Failure::SchemaRootNoMetadataMatch(node_type, *field_type), + ), + _ => &status, + }; + } + + for (assignments_type, occ) in self.closes() { + match root.closes().get(assignments_type) { + None => { + status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( + node_type, + *assignments_type, + )) + } + Some(root_occ) if occ != root_occ => { + status.add_failure(validation::Failure::SchemaRootNoParentOwnedRightsMatch( + node_type, + *assignments_type, + )) + } + _ => &status, + }; + } + + for (assignments_type, occ) in self.owned_rights() { + match root.owned_rights().get(assignments_type) { + None => status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( + node_type, + *assignments_type, + )), + Some(root_occ) if occ != root_occ => status.add_failure( + validation::Failure::SchemaRootNoOwnedRightsMatch(node_type, *assignments_type), + ), + _ => &status, + }; + } + + for valencies_type in self.extends() { + if !root.extends().contains(valencies_type) { + status.add_failure(validation::Failure::SchemaRootNoParentPublicRightsMatch( + node_type, + *valencies_type, + )); + } + } + + for valencies_type in self.public_rights() { + if !root.public_rights().contains(valencies_type) { + status.add_failure(validation::Failure::SchemaRootNoPublicRightsMatch( + node_type, + *valencies_type, + )); + } + } + + status + } +} From 321914c4dc1b52e734f3cd74864dd42156b43c63 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 01:01:26 +0100 Subject: [PATCH 52/71] validation: refactor state validation --- src/contract/mod.rs | 2 +- src/validation/mod.rs | 1 + src/validation/schema.rs | 147 ----------------------------------- src/validation/state.rs | 162 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 148 deletions(-) create mode 100644 src/validation/state.rs diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 56a62267..c8534203 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -28,7 +28,7 @@ pub mod value; pub mod attachment; pub mod data; mod global_state; -mod owned_state; +pub mod owned_state; mod assignments; mod operations; mod bundle; diff --git a/src/validation/mod.rs b/src/validation/mod.rs index bc76137f..e342588d 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -23,6 +23,7 @@ mod graph; mod vm; mod subschema; +mod state; use core::iter::FromIterator; use core::ops::AddAssign; diff --git a/src/validation/schema.rs b/src/validation/schema.rs index ab4513c9..866dba68 100644 --- a/src/validation/schema.rs +++ b/src/validation/schema.rs @@ -508,150 +508,3 @@ mod _validation { public_rights } } - -mod _validation { - use core::any::Any; - - use amplify::AsAny; - - use super::*; - use crate::contract::AttachmentStrategy; - use crate::schema::OwnedRightType; - use crate::{ - validation, Assignment, DeclarativeStrategy, HashStrategy, NodeId, PedersenStrategy, State, - }; - - impl StateSchema { - pub fn validate( - &self, - // type_system: &TypeSystem, - node_id: &NodeId, - assignment_id: OwnedRightType, - data: &Assignment, - ) -> validation::Status - where - STATE: State, - STATE::Confidential: PartialEq + Eq, - STATE::Confidential: From<::ConcealedCommitment>, - { - let mut status = validation::Status::new(); - match data { - Assignment::Confidential { state, .. } | - Assignment::ConfidentialState { state, .. } => { - let a: &dyn Any = state.as_any(); - match self { - StateSchema::Declarative => { - if a.downcast_ref::<::Confidential>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - StateSchema::DiscreteFiniteField(_) => { - if let Some(value) = - a.downcast_ref::<::Confidential>() - { - // [SECURITY-CRITICAL]: Bulletproofs validation - if let Err(err) = value.verify_bullet_proof() { - status.add_failure(validation::Failure::InvalidBulletproofs( - *node_id, - assignment_id, - err.to_string(), - )); - } - } else { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - - // TODO: When other homomorphic formats will be - // added, - // add information to the status like with - // hashed data below - } - StateSchema::CustomData() => { - match a.downcast_ref::<::Confidential>() { - None => { - status.add_failure( - validation::Failure::SchemaMismatchedStateType( - assignment_id, - ), - ); - } - Some(_) => { - status.add_info( - validation::Info::UncheckableConfidentialStateData( - *node_id, - assignment_id, - ), - ); - } - } - } - StateSchema::DataContainer => { - if a.downcast_ref::<::Confidential>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - } - } - Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { - let a: &dyn Any = state.as_any(); - match self { - StateSchema::Declarative => { - if a.downcast_ref::<::Revealed>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - StateSchema::DiscreteFiniteField(_format) => { - if a.downcast_ref::<::Revealed>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - // TODO #15: When other homomorphic formats will be added, - // add type check like with hashed data below - } - StateSchema::CustomData(/*format*/) => { - match a.downcast_ref::<::Revealed>() { - None => { - status.add_failure( - validation::Failure::SchemaMismatchedStateType( - assignment_id, - ), - ); - } - Some(_data) => { - // TODO: run strict type validation - } - } - } - StateSchema::DataContainer => { - if a.downcast_ref::<::Revealed>() - .is_none() - { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - } - } - } - } - status - } - } -} diff --git a/src/validation/state.rs b/src/validation/state.rs new file mode 100644 index 00000000..3e86c3bf --- /dev/null +++ b/src/validation/state.rs @@ -0,0 +1,162 @@ +// RGB Core Library: consensus layer for RGB smart contracts. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::any::Any; + +use amplify::AsAny; +use commit_verify::Conceal; + +use crate::contract::owned_state::{ + AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy, +}; +use crate::schema::OwnedRightType; +use crate::{validation, Assignment, NodeId, State, StateSchema}; + +impl StateSchema { + pub fn validate( + &self, + // type_system: &TypeSystem, + node_id: &NodeId, + assignment_id: OwnedRightType, + data: &Assignment, + ) -> validation::Status + where + STATE: State, + STATE::Confidential: PartialEq + Eq, + STATE::Confidential: From<::Concealed>, + { + let mut status = validation::Status::new(); + match data { + Assignment::Confidential { state, .. } | + Assignment::ConfidentialState { state, .. } => { + let a: &dyn Any = state.as_any(); + match self { + StateSchema::Declarative => { + if a.downcast_ref::<::Confidential>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + StateSchema::Arithmetic(_) => { + if let Some(value) = + a.downcast_ref::<::Confidential>() + { + // [SECURITY-CRITICAL]: Bulletproofs validation + if let Err(err) = value.verify_range_proof() { + status.add_failure(validation::Failure::InvalidBulletproofs( + *node_id, + assignment_id, + err.to_string(), + )); + } + } else { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + + // TODO: When other homomorphic formats will be added, + // add information to the status like with hashed + // data below + } + StateSchema::Structured(_) => { + match a.downcast_ref::<::Confidential>() { + None => { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + Some(_) => { + status.add_info( + validation::Info::UncheckableConfidentialStateData( + *node_id, + assignment_id, + ), + ); + } + } + } + StateSchema::Attachment => { + if a.downcast_ref::<::Confidential>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + } + } + Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { + let a: &dyn Any = state.as_any(); + match self { + StateSchema::Declarative => { + if a.downcast_ref::<::Revealed>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + StateSchema::Arithmetic(_format) => { + if a.downcast_ref::<::Revealed>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + // TODO #15: When other homomorphic formats will be + // added, add type check + // like with hashed data below + } + StateSchema::Structured(_semid) => { + match a.downcast_ref::<::Revealed>() { + None => { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + Some(_data) => { + // TODO: #137 run strict type validation + } + } + } + StateSchema::Attachment => { + if a.downcast_ref::<::Revealed>() + .is_none() + { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); + } + } + } + } + } + status + } +} From 24c53bc030d658941a392ae777e8666045287787 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 01:28:19 +0100 Subject: [PATCH 53/71] validation: refactor schema model verification --- src/contract/assignments.rs | 46 ++-- src/validation/mod.rs | 1 + src/validation/model.rs | 512 ++++++++++++++++++++++++++++++++++++ src/validation/schema.rs | 510 ----------------------------------- src/validation/vm.rs | 10 +- src/vm/mod.rs | 4 +- 6 files changed, 546 insertions(+), 537 deletions(-) create mode 100644 src/validation/model.rs delete mode 100644 src/validation/schema.rs diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index f3ad1b4d..338c77f2 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -75,66 +75,72 @@ impl TypedAssignments { pub fn is_attachment(&self) -> bool { matches!(self, TypedAssignments::Attachment(_)) } #[inline] - pub fn to_declarative_assignments(&self) -> MediumVec> { + pub fn as_declarative_assignments(&self) -> &[Assignment] { match self { - TypedAssignments::Void(set) => set.clone(), + TypedAssignments::Void(set) => set, _ => Default::default(), } } #[inline] - pub fn to_value_assignments(&self) -> MediumVec> { + pub fn as_value_assignments(&self) -> &[Assignment] { match self { - TypedAssignments::Value(set) => set.clone(), + TypedAssignments::Value(set) => set, _ => Default::default(), } } #[inline] - pub fn to_data_assignments(&self) -> MediumVec> { + pub fn as_data_assignments(&self) -> &[Assignment] { match self { - TypedAssignments::Data(set) => set.clone(), + TypedAssignments::Data(set) => set, _ => Default::default(), } } #[inline] - pub fn to_attachment_assignments(&self) -> MediumVec> { + pub fn as_attachment_assignments(&self) -> &[Assignment] { match self { - TypedAssignments::Attachment(set) => set.clone(), + TypedAssignments::Attachment(set) => set, _ => Default::default(), } } #[inline] - pub fn into_declarative_assignments(self) -> MediumVec> { + pub fn as_declarative_assignments_mut( + &mut self, + ) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Void(set) => set, - _ => Default::default(), + TypedAssignments::Void(set) => Some(set), + _ => None, } } #[inline] - pub fn into_value_assignments(self) -> MediumVec> { + pub fn as_value_assignments_mut( + &mut self, + ) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Value(set) => set, - _ => Default::default(), + TypedAssignments::Value(set) => Some(set), + _ => None, } } #[inline] - pub fn into_data_assignments(self) -> MediumVec> { + pub fn as_data_assignments_mut(&mut self) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Data(set) => set, - _ => Default::default(), + TypedAssignments::Data(set) => Some(set), + _ => None, } } #[inline] - pub fn into_attachment_assignments(self) -> MediumVec> { + pub fn as_attachment_assignments_mut( + &mut self, + ) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Attachment(set) => set, - _ => Default::default(), + TypedAssignments::Attachment(set) => Some(set), + _ => None, } } diff --git a/src/validation/mod.rs b/src/validation/mod.rs index e342588d..7bcd45c7 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -23,6 +23,7 @@ mod graph; mod vm; mod subschema; +mod model; mod state; use core::iter::FromIterator; diff --git a/src/validation/model.rs b/src/validation/model.rs new file mode 100644 index 00000000..42f0a5cd --- /dev/null +++ b/src/validation/model.rs @@ -0,0 +1,512 @@ +// RGB Core Library: consensus layer for RGB smart contracts. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2023 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. +// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::collections::{BTreeMap, BTreeSet}; + +use amplify::confinement::Confined; +use amplify::Wrapper; +use commit_verify::Conceal; + +use crate::schema::{MetadataStructure, OwnedRightsStructure, PublicRightsStructure}; +use crate::validation::vm::VirtualMachine; +use crate::vm::AluRuntime; +use crate::{ + validation, Assignment, FieldValues, Metadata, Node, NodeId, NodeSubtype, OwnedRights, + ParentOwnedRights, ParentPublicRights, PublicRights, Schema, State, TypedAssignments, +}; + +impl Schema { + pub fn validate( + &self, + all_nodes: &BTreeMap, + node: &dyn Node, + vm: AluRuntime, + ) -> validation::Status { + let node_id = node.node_id(); + + let empty_owned_structure = OwnedRightsStructure::default(); + let empty_public_structure = PublicRightsStructure::default(); + let ( + metadata_structure, + parent_owned_structure, + parent_public_structure, + assignments_structure, + valencies_structure, + ) = match (node.transition_type(), node.extension_type()) { + (None, None) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = self.genesis.abi.get(&GenesisAction::NoOp) { + + } + */ + + ( + &self.genesis.metadata, + &empty_owned_structure, + &empty_public_structure, + &self.genesis.owned_rights, + &self.genesis.public_rights, + ) + } + (Some(transition_type), None) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = transition_type.abi.get(&TransitionAction::NoOp) { + + } + */ + + let transition_type = match self.transitions.get(&transition_type) { + None => { + return validation::Status::with_failure( + validation::Failure::SchemaUnknownTransitionType( + node_id, + transition_type, + ), + ); + } + Some(transition_type) => transition_type, + }; + + ( + &transition_type.metadata, + &transition_type.closes, + &empty_public_structure, + &transition_type.owned_rights, + &transition_type.public_rights, + ) + } + (None, Some(extension_type)) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = extension_type.abi.get(&ExtensionAction::NoOp) { + + } + */ + + let extension_type = match self.extensions.get(&extension_type) { + None => { + return validation::Status::with_failure( + validation::Failure::SchemaUnknownExtensionType( + node_id, + extension_type, + ), + ); + } + Some(extension_type) => extension_type, + }; + + ( + &extension_type.metadata, + &empty_owned_structure, + &extension_type.extends, + &extension_type.owned_rights, + &extension_type.extends, + ) + } + _ => unreachable!("Node can't be extension and state transition at the same time"), + }; + + let mut status = validation::Status::new(); + + // Validate type system + status += self.validate_type_system(); + + let parent_owned_rights = + extract_parent_owned_rights(all_nodes, node.parent_owned_rights(), &mut status); + let parent_public_rights = + extract_parent_public_rights(all_nodes, node.parent_public_rights(), &mut status); + status += self.validate_meta(node_id, node.metadata(), metadata_structure); + status += self.validate_parent_owned_rights( + node_id, + &parent_owned_rights, + parent_owned_structure, + ); + status += self.validate_parent_public_rights( + node_id, + &parent_public_rights, + parent_public_structure, + ); + status += self.validate_owned_rights(node_id, node.owned_rights(), assignments_structure); + status += self.validate_public_rights(node_id, node.public_rights(), valencies_structure); + // We need to run scripts as the very last step, since before that + // we need to make sure that the node data match the schema, so + // scripts are not required to validate the structure of the state + status += self.validate_state_evolution( + node_id, + node.subtype(), + &parent_owned_rights, + node.owned_rights(), + &parent_public_rights, + node.public_rights(), + node.metadata(), + vm, + ); + status + } + + fn validate_type_system(&self) -> validation::Status { + let status = validation::Status::new(); + // TODO: Validate type system + /*if let Err(inconsistencies) = self.type_system.validate() { + for _err in inconsistencies { + status.add_failure(validation::Failure::SchemaTypeSystem(/*err*/)); + } + }*/ + status + } + + fn validate_meta( + &self, + node_id: NodeId, + metadata: &Metadata, + metadata_structure: &MetadataStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + metadata + .keys() + .collect::>() + .difference(&metadata_structure.keys().collect()) + .for_each(|field_id| { + status + .add_failure(validation::Failure::SchemaUnknownFieldType(node_id, **field_id)); + }); + + for (field_type_id, occ) in metadata_structure { + let set = metadata + .get(field_type_id) + .cloned() + .map(FieldValues::into_inner) + .map(Confined::unbox) + .unwrap_or_default(); + + // Checking number of field occurrences + if let Err(err) = occ.check(set.len() as u16) { + status.add_failure(validation::Failure::SchemaMetaOccurrencesError( + node_id, + *field_type_id, + err, + )); + } + + let _field = self.field_types.get(field_type_id).expect( + "If the field were absent, the schema would not be able to pass the internal \ + validation and we would not reach this point", + ); + for _data in set { + // TODO: #137 Run strict type validation + /* + let schema_type = data.schema_type(); + + status.add_failure(validation::Failure::SchemaMismatchedDataType( + *field_type_id, + )); + status += field.verify(&self.type_system, node_id, *field_type_id, &data); + */ + } + } + + status + } + + fn validate_parent_owned_rights( + &self, + node_id: NodeId, + owned_rights: &OwnedRights, + owned_rights_structure: &OwnedRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + owned_rights + .keys() + .collect::>() + .difference(&owned_rights_structure.keys().collect()) + .for_each(|owned_type_id| { + status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( + node_id, + **owned_type_id, + )); + }); + + for (owned_type_id, occ) in owned_rights_structure { + let len = owned_rights + .get(owned_type_id) + .map(TypedAssignments::len) + .unwrap_or(0); + + // Checking number of ancestor's assignment occurrences + if let Err(err) = occ.check(len as u16) { + status.add_failure(validation::Failure::SchemaParentOwnedRightOccurrencesError( + node_id, + *owned_type_id, + err, + )); + } + } + + status + } + + fn validate_parent_public_rights( + &self, + node_id: NodeId, + public_rights: &PublicRights, + public_rights_structure: &PublicRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + public_rights + .difference(public_rights_structure) + .for_each(|public_type_id| { + status.add_failure(validation::Failure::SchemaUnknownPublicRightType( + node_id, + *public_type_id, + )); + }); + + status + } + + fn validate_owned_rights( + &self, + node_id: NodeId, + owned_rights: &OwnedRights, + owned_rights_structure: &OwnedRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + owned_rights + .keys() + .collect::>() + .difference(&owned_rights_structure.keys().collect()) + .for_each(|assignment_type_id| { + status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( + node_id, + **assignment_type_id, + )); + }); + + for (owned_type_id, occ) in owned_rights_structure { + let len = owned_rights + .get(owned_type_id) + .map(TypedAssignments::len) + .unwrap_or(0); + + // Checking number of assignment occurrences + if let Err(err) = occ.check(len as u16) { + status.add_failure(validation::Failure::SchemaOwnedRightOccurrencesError( + node_id, + *owned_type_id, + err, + )); + } + + let assignment = &self.owned_right_types.get(owned_type_id).expect( + "If the assignment were absent, the schema would not be able to pass the internal \ + validation and we would not reach this point", + ); + + match owned_rights.get(owned_type_id) { + None => {} + Some(TypedAssignments::Void(set)) => set + .iter() + .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + Some(TypedAssignments::Value(set)) => set + .iter() + .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + Some(TypedAssignments::Data(set)) => set + .iter() + .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + Some(TypedAssignments::Attachment(set)) => set + .iter() + .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + }; + } + + status + } + + fn validate_public_rights( + &self, + node_id: NodeId, + public_rights: &PublicRights, + public_rights_structure: &PublicRightsStructure, + ) -> validation::Status { + let mut status = validation::Status::new(); + + public_rights + .difference(public_rights_structure) + .for_each(|public_type_id| { + status.add_failure(validation::Failure::SchemaUnknownPublicRightType( + node_id, + *public_type_id, + )); + }); + + status + } + + #[allow(clippy::too_many_arguments)] + fn validate_state_evolution( + &self, + node_id: NodeId, + node_subtype: NodeSubtype, + parent_owned_rights: &OwnedRights, + owned_rights: &OwnedRights, + parent_public_rights: &PublicRights, + public_rights: &PublicRights, + metadata: &Metadata, + vm: AluRuntime, + ) -> validation::Status { + let mut status = validation::Status::new(); + + // We do not validate public rights, since they do not have an + // associated state and there is nothing to validate beyond schema + + if let Err(err) = vm.validate( + node_id, + node_subtype, + parent_owned_rights, + owned_rights, + parent_public_rights, + public_rights, + metadata, + ) { + status.add_failure(err); + } + + status + } +} + +fn extract_parent_owned_rights( + nodes: &BTreeMap, + parent_owned_rights: &ParentOwnedRights, + status: &mut validation::Status, +) -> OwnedRights { + let mut owned_rights = bmap! {}; + for (id, details) in parent_owned_rights.iter() { + let parent_node = match nodes.get(id) { + None => { + status.add_failure(validation::Failure::TransitionAbsent(*id)); + continue; + } + Some(node) => node, + }; + + fn filter(set: &[Assignment], indexes: &[u16]) -> Vec> + where + STATE: State + Clone, + STATE::Confidential: PartialEq + Eq, + STATE::Confidential: From<::Concealed>, + { + set.iter() + .enumerate() + .filter_map(|(index, item)| { + if indexes.contains(&(index as u16)) { + Some(item.clone()) + } else { + None + } + }) + .collect() + } + + for (type_id, indexes) in details { + match parent_node.owned_rights_by_type(*type_id) { + Some(TypedAssignments::Void(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Void(Default::default())) + .as_declarative_assignments_mut() + { + state.extend(set).expect("same size"); + } + } + Some(TypedAssignments::Value(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Value(Default::default())) + .as_value_assignments_mut() + { + state.extend(set).expect("same size"); + } + } + Some(TypedAssignments::Data(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Data(Default::default())) + .as_data_assignments_mut() + { + state.extend(set).expect("same size"); + } + } + Some(TypedAssignments::Attachment(set)) => { + let set = filter(set, indexes); + if let Some(state) = owned_rights + .entry(*type_id) + .or_insert_with(|| TypedAssignments::Attachment(Default::default())) + .as_attachment_assignments_mut() + { + state.extend(set).expect("same size"); + } + } + None => { + // Presence of the required owned rights type in the + // parent node was already validated; we have nothing to + // report here + } + } + } + } + Confined::try_from(owned_rights) + .expect("collections is assembled from another collection with the same size requirements") +} + +fn extract_parent_public_rights( + nodes: &BTreeMap, + parent_public_rights: &ParentPublicRights, + status: &mut validation::Status, +) -> PublicRights { + let mut public_rights = PublicRights::default(); + for (id, public_right_types) in parent_public_rights.iter() { + if nodes.get(id).is_none() { + status.add_failure(validation::Failure::TransitionAbsent(*id)); + } else { + public_rights + .extend(public_right_types.iter().copied()) + .expect("same size"); + } + } + public_rights +} diff --git a/src/validation/schema.rs b/src/validation/schema.rs deleted file mode 100644 index 866dba68..00000000 --- a/src/validation/schema.rs +++ /dev/null @@ -1,510 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -mod _validation { - use std::collections::BTreeSet; - - use super::*; - use crate::schema::{ - MetadataStructure, OwnedRightsStructure, PublicRightsStructure, SchemaVerify, - }; - use crate::script::{OverrideRules, ValidationScript}; - use crate::vm::Validate; - use crate::{ - validation, Assignment, Metadata, Node, NodeId, NodeSubtype, OwnedRights, - ParentOwnedRights, ParentPublicRights, PublicRights, State, TypedAssignments, - }; - - impl Schema { - pub fn validate( - &self, - all_nodes: &BTreeMap, - node: &dyn Node, - script: &ValidationScript, - ) -> validation::Status { - let node_id = node.node_id(); - - let empty_owned_structure = OwnedRightsStructure::default(); - let empty_public_structure = PublicRightsStructure::default(); - let ( - metadata_structure, - parent_owned_structure, - parent_public_structure, - assignments_structure, - valencies_structure, - ) = match (node.transition_type(), node.extension_type()) { - (None, None) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = self.genesis.abi.get(&GenesisAction::NoOp) { - - } - */ - - ( - &self.genesis.metadata, - &empty_owned_structure, - &empty_public_structure, - &self.genesis.owned_rights, - &self.genesis.public_rights, - ) - } - (Some(transition_type), None) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = transition_type.abi.get(&TransitionAction::NoOp) { - - } - */ - - let transition_type = match self.transitions.get(&transition_type) { - None => { - return validation::Status::with_failure( - validation::Failure::SchemaUnknownTransitionType( - node_id, - transition_type, - ), - ); - } - Some(transition_type) => transition_type, - }; - - ( - &transition_type.metadata, - &transition_type.closes, - &empty_public_structure, - &transition_type.owned_rights, - &transition_type.public_rights, - ) - } - (None, Some(extension_type)) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = extension_type.abi.get(&ExtensionAction::NoOp) { - - } - */ - - let extension_type = match self.extensions.get(&extension_type) { - None => { - return validation::Status::with_failure( - validation::Failure::SchemaUnknownExtensionType( - node_id, - extension_type, - ), - ); - } - Some(extension_type) => extension_type, - }; - - ( - &extension_type.metadata, - &empty_owned_structure, - &extension_type.extends, - &extension_type.owned_rights, - &extension_type.extends, - ) - } - _ => unreachable!("Node can't be extension and state transition at the same time"), - }; - - let mut status = validation::Status::new(); - - // Validate type system - status += self.validate_type_system(); - - let parent_owned_rights = - extract_parent_owned_rights(all_nodes, node.parent_owned_rights(), &mut status); - let parent_public_rights = - extract_parent_public_rights(all_nodes, node.parent_public_rights(), &mut status); - status += self.validate_meta(node_id, node.metadata(), metadata_structure); - status += self.validate_parent_owned_rights( - node_id, - &parent_owned_rights, - parent_owned_structure, - ); - status += self.validate_parent_public_rights( - node_id, - &parent_public_rights, - parent_public_structure, - ); - status += - self.validate_owned_rights(node_id, node.owned_rights(), assignments_structure); - status += - self.validate_public_rights(node_id, node.public_rights(), valencies_structure); - // We need to run scripts as the very last step, since before that - // we need to make sure that the node data match the schema, so - // scripts are not required to validate the structure of the state - status += self.validate_state_evolution( - node_id, - node.subtype(), - &parent_owned_rights, - node.owned_rights(), - &parent_public_rights, - node.public_rights(), - node.metadata(), - script, - ); - status - } - - fn validate_type_system(&self) -> validation::Status { - let status = validation::Status::new(); - // TODO: Validate type system - /*if let Err(inconsistencies) = self.type_system.validate() { - for _err in inconsistencies { - status.add_failure(validation::Failure::SchemaTypeSystem(/*err*/)); - } - }*/ - status - } - - fn validate_meta( - &self, - node_id: NodeId, - metadata: &Metadata, - metadata_structure: &MetadataStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - metadata - .keys() - .collect::>() - .difference(&metadata_structure.keys().collect()) - .for_each(|field_id| { - status.add_failure(validation::Failure::SchemaUnknownFieldType( - node_id, **field_id, - )); - }); - - for (field_type_id, occ) in metadata_structure { - let set = metadata.get(field_type_id).cloned().unwrap_or_default(); - - // Checking number of field occurrences - if let Err(err) = occ.check(set.len() as u16) { - status.add_failure(validation::Failure::SchemaMetaOccurrencesError( - node_id, - *field_type_id, - err, - )); - } - - let _field = self.field_types.get(field_type_id).expect( - "If the field were absent, the schema would not be able to pass the internal \ - validation and we would not reach this point", - ); - for _data in set { - // TODO: Run strict type validation - /* - let schema_type = data.schema_type(); - - status.add_failure(validation::Failure::SchemaMismatchedDataType( - *field_type_id, - )); - status += field.verify(&self.type_system, node_id, *field_type_id, &data); - */ - } - } - - status - } - - fn validate_parent_owned_rights( - &self, - node_id: NodeId, - owned_rights: &OwnedRights, - owned_rights_structure: &OwnedRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - owned_rights - .keys() - .collect::>() - .difference(&owned_rights_structure.keys().collect()) - .for_each(|owned_type_id| { - status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( - node_id, - **owned_type_id, - )); - }); - - for (owned_type_id, occ) in owned_rights_structure { - let len = owned_rights - .get(owned_type_id) - .map(TypedAssignments::len) - .unwrap_or(0); - - // Checking number of ancestor's assignment occurrences - if let Err(err) = occ.check(len as u16) { - status.add_failure( - validation::Failure::SchemaParentOwnedRightOccurrencesError( - node_id, - *owned_type_id, - err, - ), - ); - } - } - - status - } - - fn validate_parent_public_rights( - &self, - node_id: NodeId, - public_rights: &PublicRights, - public_rights_structure: &PublicRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - public_rights - .difference(public_rights_structure) - .for_each(|public_type_id| { - status.add_failure(validation::Failure::SchemaUnknownPublicRightType( - node_id, - *public_type_id, - )); - }); - - status - } - - fn validate_owned_rights( - &self, - node_id: NodeId, - owned_rights: &OwnedRights, - owned_rights_structure: &OwnedRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - owned_rights - .keys() - .collect::>() - .difference(&owned_rights_structure.keys().collect()) - .for_each(|assignment_type_id| { - status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( - node_id, - **assignment_type_id, - )); - }); - - for (owned_type_id, occ) in owned_rights_structure { - let len = owned_rights - .get(owned_type_id) - .map(TypedAssignments::len) - .unwrap_or(0); - - // Checking number of assignment occurrences - if let Err(err) = occ.check(len as u16) { - status.add_failure(validation::Failure::SchemaOwnedRightOccurrencesError( - node_id, - *owned_type_id, - err, - )); - } - - let assignment = &self.owned_right_types.get(owned_type_id).expect( - "If the assignment were absent, the schema would not be able to pass the \ - internal validation and we would not reach this point", - ); - - match owned_rights.get(owned_type_id) { - None => {} - Some(TypedAssignments::Void(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - Some(TypedAssignments::Value(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - Some(TypedAssignments::Data(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - Some(TypedAssignments::Attachment(set)) => set.iter().for_each(|data| { - status += assignment.validate(&node_id, *owned_type_id, data) - }), - }; - } - - status - } - - fn validate_public_rights( - &self, - node_id: NodeId, - public_rights: &PublicRights, - public_rights_structure: &PublicRightsStructure, - ) -> validation::Status { - let mut status = validation::Status::new(); - - public_rights - .difference(public_rights_structure) - .for_each(|public_type_id| { - status.add_failure(validation::Failure::SchemaUnknownPublicRightType( - node_id, - *public_type_id, - )); - }); - - status - } - - #[allow(clippy::too_many_arguments)] - fn validate_state_evolution( - &self, - node_id: NodeId, - node_subtype: NodeSubtype, - parent_owned_rights: &OwnedRights, - owned_rights: &OwnedRights, - parent_public_rights: &PublicRights, - public_rights: &PublicRights, - metadata: &Metadata, - script: &ValidationScript, - ) -> validation::Status { - let mut status = validation::Status::new(); - - // We do not validate public rights, since they do not have an - // associated state and there is nothing to validate beyond schema - - if let Err(err) = script.validate( - node_id, - node_subtype, - parent_owned_rights, - owned_rights, - parent_public_rights, - public_rights, - metadata, - ) { - status.add_failure(err); - } - - status - } - } - - fn extract_parent_owned_rights( - nodes: &BTreeMap, - parent_owned_rights: &ParentOwnedRights, - status: &mut validation::Status, - ) -> OwnedRights { - let mut owned_rights = OwnedRights::default(); - for (id, details) in parent_owned_rights.iter() { - let parent_node = match nodes.get(id) { - None => { - status.add_failure(validation::Failure::TransitionAbsent(*id)); - continue; - } - Some(node) => node, - }; - - fn filter(set: &[Assignment], indexes: &[u16]) -> Vec> - where - STATE: State + Clone, - STATE::Confidential: PartialEq + Eq, - STATE::Confidential: From<::ConcealedCommitment>, - { - set.iter() - .enumerate() - .filter_map(|(index, item)| { - if indexes.contains(&(index as u16)) { - Some(item.clone()) - } else { - None - } - }) - .collect() - } - - for (type_id, indexes) in details { - match parent_node.owned_rights_by_type(*type_id) { - Some(TypedAssignments::Void(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Void(Default::default())) - .declarative_assignments_mut() - { - state.extend(set); - } - } - Some(TypedAssignments::Value(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Value(Default::default())) - .value_assignments_mut() - { - state.extend(set); - } - } - Some(TypedAssignments::Data(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Data(Default::default())) - .data_assignments_mut() - { - state.extend(set); - } - } - Some(TypedAssignments::Attachment(set)) => { - let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) - .or_insert_with(|| TypedAssignments::Attachment(Default::default())) - .attachment_assignments_mut() - { - state.extend(set); - } - } - None => { - // Presence of the required owned rights type in the - // parent node was already validated; we have nothing to - // report here - } - } - } - } - owned_rights - } - - fn extract_parent_public_rights( - nodes: &BTreeMap, - parent_public_rights: &ParentPublicRights, - status: &mut validation::Status, - ) -> PublicRights { - let mut public_rights = PublicRights::default(); - for (id, public_right_types) in parent_public_rights.iter() { - if nodes.get(id).is_none() { - status.add_failure(validation::Failure::TransitionAbsent(*id)); - } else { - public_rights.extend(public_right_types); - } - } - public_rights - } -} diff --git a/src/validation/vm.rs b/src/validation/vm.rs index e6c19c38..ca90ec79 100644 --- a/src/validation/vm.rs +++ b/src/validation/vm.rs @@ -21,12 +21,12 @@ // limitations under the License. use crate::validation::Failure; -use crate::vm::Runtime; +use crate::vm::AluRuntime; use crate::{validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, Scripts}; /// Trait for concrete types wrapping virtual machines to be used from inside /// RGB schema validation routines. -pub trait Validate { +pub trait VirtualMachine { /// Validates state change in a contract node. #[allow(clippy::too_many_arguments)] fn validate( @@ -41,7 +41,7 @@ pub trait Validate { ) -> Result<(), validation::Failure>; } -impl Validate for Scripts { +impl VirtualMachine for Scripts { fn validate( &self, node_id: NodeId, @@ -53,7 +53,7 @@ impl Validate for Scripts { current_meta: &Metadata, ) -> Result<(), validation::Failure> { match self { - Scripts::AluVM(script) => Runtime::new(script).validate( + Scripts::AluVM(script) => AluRuntime::new(script).validate( node_id, node_subtype, previous_owned_rights, @@ -66,7 +66,7 @@ impl Validate for Scripts { } } -impl<'script> Validate for Runtime<'script> { +impl<'script> VirtualMachine for AluRuntime<'script> { #[allow(unused_variables)] fn validate( &self, diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 0bc8cfa2..67a6c1c5 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -29,12 +29,12 @@ pub mod isa; pub type AluLib = aluvm::Program; -pub struct Runtime<'script> { +pub struct AluRuntime<'script> { #[allow(dead_code)] lib: &'script AluLib, } -impl<'script> Runtime<'script> { +impl<'script> AluRuntime<'script> { pub fn new(_lib: &'script [u8]) -> Self { todo!() /* Runtime { lib } */ } From 2b6ec2d7ac974e5ce87d6aac81faa63d07a2fbe5 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 01:41:24 +0100 Subject: [PATCH 54/71] validation: refactor validator --- src/schema/mod.rs | 2 +- src/schema/schema.rs | 4 +-- src/schema/script.rs | 10 +++---- src/validation/mod.rs | 2 ++ src/validation/model.rs | 13 +++++--- src/validation/verify.rs | 64 +++++++++++++++++++++------------------- src/validation/vm.rs | 6 ++-- 7 files changed, 55 insertions(+), 46 deletions(-) diff --git a/src/schema/mod.rs b/src/schema/mod.rs index 94df4412..fa2b5e62 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -33,5 +33,5 @@ pub use nodes::{ }; pub use occurrences::{Occurrences, OccurrencesMismatch}; pub use schema::{ExtensionType, FieldType, Schema, SchemaId, TransitionType}; -pub use script::{Scripts, VmType}; +pub use script::{Script, VmType}; pub use state::{StateSchema, ValueType}; diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 8dd4bb34..e130498f 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -36,7 +36,7 @@ use strict_encoding::{ use strict_types::SemId; use super::{ - ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, Scripts, StateSchema, + ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, Script, StateSchema, TransitionSchema, }; use crate::LIB_NAME_RGB; @@ -104,7 +104,7 @@ pub struct Schema { /// Type system pub type_system: MediumVec, // TODO: TypeSystem, /// Validation code. - pub script: Scripts, + pub script: Script, } impl PartialEq for Schema { diff --git a/src/schema/script.rs b/src/schema/script.rs index ace7a5d3..cc1c601d 100644 --- a/src/schema/script.rs +++ b/src/schema/script.rs @@ -43,7 +43,7 @@ pub enum VmType { #[derive(StrictType, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB, tags = order)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub enum Scripts { +pub enum Script { /// AluVM: pure functional register-based virtual machine designed for RGB /// and multiparty computing. /// @@ -56,14 +56,14 @@ pub enum Scripts { AluVM(MediumVec), } -impl Default for Scripts { - fn default() -> Self { Scripts::AluVM(none!()) } +impl Default for Script { + fn default() -> Self { Script::AluVM(none!()) } } -impl Scripts { +impl Script { pub fn vm_type(&self) -> VmType { match self { - Scripts::AluVM(_) => VmType::AluVM, + Script::AluVM(_) => VmType::AluVM, } } } diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 7bcd45c7..a86ef322 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -25,11 +25,13 @@ mod vm; mod subschema; mod model; mod state; +mod verify; use core::iter::FromIterator; use core::ops::AddAssign; use bp::Txid; +pub use verify::{ResolveTx, TxResolverError, Validator}; use crate::schema::{self, NodeType, SchemaId}; use crate::{data, BundleId, NodeId, OccurrencesMismatch, SealEndpoint}; diff --git a/src/validation/model.rs b/src/validation/model.rs index 42f0a5cd..e99a1285 100644 --- a/src/validation/model.rs +++ b/src/validation/model.rs @@ -31,7 +31,7 @@ use crate::validation::vm::VirtualMachine; use crate::vm::AluRuntime; use crate::{ validation, Assignment, FieldValues, Metadata, Node, NodeId, NodeSubtype, OwnedRights, - ParentOwnedRights, ParentPublicRights, PublicRights, Schema, State, TypedAssignments, + ParentOwnedRights, ParentPublicRights, PublicRights, Schema, Script, State, TypedAssignments, }; impl Schema { @@ -39,7 +39,7 @@ impl Schema { &self, all_nodes: &BTreeMap, node: &dyn Node, - vm: AluRuntime, + script: &Script, ) -> validation::Status { let node_id = node.node_id(); @@ -155,6 +155,7 @@ impl Schema { ); status += self.validate_owned_rights(node_id, node.owned_rights(), assignments_structure); status += self.validate_public_rights(node_id, node.public_rights(), valencies_structure); + // We need to run scripts as the very last step, since before that // we need to make sure that the node data match the schema, so // scripts are not required to validate the structure of the state @@ -166,7 +167,7 @@ impl Schema { &parent_public_rights, node.public_rights(), node.metadata(), - vm, + script, ); status } @@ -383,13 +384,17 @@ impl Schema { parent_public_rights: &PublicRights, public_rights: &PublicRights, metadata: &Metadata, - vm: AluRuntime, + script: &Script, ) -> validation::Status { let mut status = validation::Status::new(); // We do not validate public rights, since they do not have an // associated state and there is nothing to validate beyond schema + let vm = match script { + Script::AluVM(lib) => Box::new(AluRuntime::new(lib)) as Box, + }; + if let Err(err) = vm.validate( node_id, node_subtype, diff --git a/src/validation/verify.rs b/src/validation/verify.rs index 2d7a812a..229f9c87 100644 --- a/src/validation/verify.rs +++ b/src/validation/verify.rs @@ -20,21 +20,30 @@ // See the License for the specific language governing permissions and // limitations under the License. -use core::iter::FromIterator; -use core::ops::AddAssign; use std::collections::{BTreeMap, BTreeSet, VecDeque}; use bp::dbc::Anchor; use bp::seals::txout::TxoSeal; use bp::{Tx, Txid}; -use commit_verify::mpc; - -use super::schema::{NodeType, OccurrencesError}; -use super::{schema, seal, ContractId, Node, NodeId, Schema, SchemaId, TypedAssignments}; -use crate::schema::SchemaVerify; -use crate::stash::Consignment; -use crate::temp::ResolveTx; -use crate::{data, outpoint, tx, txid, BundleId, Extension, SealEndpoint, TransitionBundle}; +use commit_verify::{mpc, Conceal}; + +use super::graph::Consignment; +use super::schema::NodeType; +use super::{Failure, Status, Validity, Warning}; +use crate::validation::subschema::SchemaVerify; +use crate::{ + schema, seal, BundleId, ContractId, Extension, Node, NodeId, Schema, SchemaId, + TransitionBundle, TypedAssignments, +}; + +#[derive(Debug, Display, Error)] +#[display(doc_comments)] +/// transaction {0} is not mined +pub struct TxResolverError(Txid); + +pub trait ResolveTx { + fn resolve_tx(&self, txid: Txid) -> Result; +} pub struct Validator<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> { consignment: &'consignment C, @@ -73,7 +82,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> if !TransitionBundle::validate(bundle) { status.add_failure(Failure::BundleInvalid(bundle.bundle_id())); } - for transition in bundle.known_transitions() { + for transition in bundle.revealed.keys() { let node_id = transition.node_id(); node_index.insert(node_id, transition); anchor_index.insert(node_id, anchor); @@ -103,7 +112,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Checking for endpoint definition duplicates if !transition .to_confiential_seals() - .contains(&seal_endpoint.commit_conceal()) + .contains(&seal_endpoint.conceal()) { // We generate just a warning here because it's up to a user // to decide whether to accept consignment with wrong @@ -182,9 +191,9 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Validating schema against root schema if let Some(root) = root { self.status += schema.schema_verify(root); - } else if schema.root_id != default!() { + } else if let Some(root_id) = schema.subset_of { self.status - .add_failure(Failure::SchemaRootRequired(schema.root_id)); + .add_failure(Failure::SchemaRootRequired(root_id)); } } @@ -221,16 +230,16 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> .status .failures .iter() - .position(|f| f == &Failure::WitnessTransactionMissed(txid!(anchor.txid))) + .position(|f| f == &Failure::WitnessTransactionMissed(anchor.txid)) { self.status.failures.remove(pos); self.status .unresolved_txids - .retain(|txid| *txid != txid!(anchor.txid)); - self.status.unmined_endpoint_txids.push(txid!(anchor.txid)); + .retain(|txid| *txid != anchor.txid); + self.status.unmined_endpoint_txids.push(anchor.txid); self.status .warnings - .push(Warning::EndpointTransactionMissed(txid!(anchor.txid))); + .push(Warning::EndpointTransactionMissed(anchor.txid)); } } } @@ -289,10 +298,8 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // anchor. This must be done with // deterministic bitcoin commitments & LNPBP-4 if anchor.convolve(self.contract_id, bundle_id.into()).is_err() { - self.status.add_failure(Failure::TransitionNotInAnchor( - node_id, - txid!(anchor.txid), - )); + self.status + .add_failure(Failure::TransitionNotInAnchor(node_id, anchor.txid)); } self.validate_graph_node(node, bundle_id, anchor); @@ -351,7 +358,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> bundle_id: BundleId, anchor: &'consignment Anchor, ) { - let txid = txid!(anchor.txid); + let txid = anchor.txid; let node_id = node.node_id(); // Check that the anchor is committed into a transaction spending all of @@ -384,12 +391,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // [VALIDATION]: Checking anchor deterministic bitcoin // commitment if anchor - .verify( - self.contract_id, - bundle_id.into(), - // TODO: Remove this temporary conversion fix - tx!(&witness_tx), - ) + .verify(self.contract_id, bundle_id.into(), &witness_tx) .is_err() { // TODO: Save error details @@ -494,7 +496,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> None, ) => { // We are at genesis, so the outpoint must contain tx - Some(bp::Outpoint::new(txid!(txid), vout)) + Some(bp::Outpoint::new(txid, vout)) } (Ok(Some(_)), None) => { // This can't happen, since if we have a node in the index @@ -503,7 +505,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> } /* -> ... so we can check that the bitcoin transaction * references it as one of its inputs */ - (Ok(Some(seal)), Some(anchor)) => Some(outpoint!(seal.outpoint_or(anchor.txid))), + (Ok(Some(seal)), Some(anchor)) => Some(seal.outpoint_or(anchor.txid)), } { if !witness_tx diff --git a/src/validation/vm.rs b/src/validation/vm.rs index ca90ec79..61c8cefe 100644 --- a/src/validation/vm.rs +++ b/src/validation/vm.rs @@ -22,7 +22,7 @@ use crate::validation::Failure; use crate::vm::AluRuntime; -use crate::{validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, Scripts}; +use crate::{validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, Script}; /// Trait for concrete types wrapping virtual machines to be used from inside /// RGB schema validation routines. @@ -41,7 +41,7 @@ pub trait VirtualMachine { ) -> Result<(), validation::Failure>; } -impl VirtualMachine for Scripts { +impl VirtualMachine for Script { fn validate( &self, node_id: NodeId, @@ -53,7 +53,7 @@ impl VirtualMachine for Scripts { current_meta: &Metadata, ) -> Result<(), validation::Failure> { match self { - Scripts::AluVM(script) => AluRuntime::new(script).validate( + Script::AluVM(script) => AluRuntime::new(script).validate( node_id, node_subtype, previous_owned_rights, From 283bbfabba03d0b8df7fe120690e5deafe853b59 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 01:44:28 +0100 Subject: [PATCH 55/71] test: remove legacy and invalid tests --- src/contract/owned_state.rs | 344 ------------------------------------ src/contract/seal.rs | 203 --------------------- src/contract/value.rs | 181 ------------------- 3 files changed, 728 deletions(-) diff --git a/src/contract/owned_state.rs b/src/contract/owned_state.rs index 19453fd2..7800734e 100644 --- a/src/contract/owned_state.rs +++ b/src/contract/owned_state.rs @@ -429,347 +429,3 @@ where const TAG: [u8; 32] = *b"urn:lnpbp:rgb:owned-state:v1#23A"; type Id = MerkleNode; } - -#[cfg(test)] -mod test { - #[test] - fn test_encoding_ancestor() { - let _: ParentOwnedRights = test_vec_decoding_roundtrip(PARENT_RIGHTS).unwrap(); - } - - #[test] - #[should_panic(expected = "UnexpectedEof")] - fn test_garbage_ancestor() { - let mut data = PARENT_RIGHTS.clone(); - data[0] = 0x36 as u8; - ParentOwnedRights::strict_decode(&data[..]).unwrap(); - } - - // This doesn't use the merkelize() function - // And constructs the flow by hand for a single element - // merkelization process - #[test] - fn test_parent_rights_encoding_simple() { - // Create the simplest possible ancestor structure - // Parent Rights = Map> - let mut assignment = BTreeMap::new(); - let data = 0u16; - let ty = 2 as schema::OwnedRightType; - assignment.insert(ty, vec![data]); - - let nodeid = NodeId::default(); - let mut parent_rights = ParentOwnedRights::default(); - parent_rights.as_mut().insert(nodeid, assignment); - - let mut original_commit = vec![]; - parent_rights - .to_merkle_source() - .commit_encode(&mut original_commit); // Merkelizes the structure into buf - - // Perform encoding by hand - // We only have one leaf tupple - // leaf = (NodqeId::default(), ty, 0u16); - - // Encode the leaf via strict encoding - let mut encoded_leaf = vec![]; - NodeId::default().strict_encode(&mut encoded_leaf).unwrap(); - ty.strict_encode(&mut encoded_leaf).unwrap(); - 0u16.strict_encode(&mut encoded_leaf).unwrap(); - - // take the hash of the encoded data as a MerkleNode - let merkle_node = MerkleNode::hash(&encoded_leaf[..]); - - // merkelize the node with correct tag - let (root, _) = merklize("parent_owned_right", [merkle_node]); - - // Commit encode the resulting merkle root - let handmade_commit = root.commit_serialize(); - - // This should match with original encoding - assert_eq!(original_commit, handmade_commit); - } - - /* - // Helper to create merkleroot from single merklenode - fn merkle_single(m: MerkleNode) -> MerkleNode { - let mut engine2 = MerkleNode::engine(); - let tag = format!("{}:merkle:{}", "", 0); - let tag_hash = sha256::Hash::hash(tag.as_bytes()); - engine2.input(&tag_hash[..]); - engine2.input(&tag_hash[..]); - m.strict_encode(&mut engine2).unwrap(); - 0u8.strict_encode(&mut engine2).unwrap(); - MerkleNode::from_engine(engine2) - } - */ - - // This uses merkelize() function handle multiple values - #[test] - fn test_ancestor_encoding_complex() { - // Create three random vector as assignment variants - let mut vec1 = vec![]; - let mut rng = thread_rng(); - for i in 0..6 { - vec1.insert(i, rng.next_u64() as u16); - } - - let mut vec2 = vec![]; - let mut rng = thread_rng(); - for i in 0..17 { - vec2.insert(i, rng.next_u64() as u16); - } - - let mut vec3 = vec![]; - let mut rng = thread_rng(); - for i in 0..11 { - vec3.insert(i, rng.next_u64() as u16); - } - - // Create 3 assignment type - let type1 = 1 as schema::OwnedRightType; - let type2 = 2 as schema::OwnedRightType; - let type3 = 3 as schema::OwnedRightType; - - // Create 1 NodeID - let node_id = NodeId::default(); - - // Construct assignments - let mut assignments = BTreeMap::new(); - assignments.insert(type1, vec1.clone()); - assignments.insert(type2, vec2.clone()); - assignments.insert(type3, vec3.clone()); - - // Construct ancestor - let mut parent_rights = ParentOwnedRights::default(); - parent_rights.as_mut().insert(node_id, assignments); - - // get the commit encoding - let mut original_commit = vec![]; - parent_rights - .to_merkle_source() - .commit_encode(&mut original_commit); - - // Make commitment by hand - // Create the leaf tupples - - let vec_1: Vec<(NodeId, schema::OwnedRightType, u16)> = vec1 - .iter() - .map(|i| (NodeId::default(), type1, *i)) - .collect(); - let vec_2: Vec<(NodeId, schema::OwnedRightType, u16)> = vec2 - .iter() - .map(|i| (NodeId::default(), type2, *i)) - .collect(); - let vec_3: Vec<(NodeId, schema::OwnedRightType, u16)> = vec3 - .iter() - .map(|i| (NodeId::default(), type3, *i)) - .collect(); - - // Combine all to create the final tupple list - let vec_4: Vec<(NodeId, schema::OwnedRightType, u16)> = [vec_1, vec_2, vec_3].concat(); - - // Strict encode each tupple - // hash the encoding - // convert each hash into a MerkleNode - let nodes: Vec = vec_4 - .into_iter() - .map(|item| -> MerkleNode { - let mut e = vec![]; - item.0.strict_encode(&mut e).unwrap(); - item.1.strict_encode(&mut e).unwrap(); - item.2.strict_encode(&mut e).unwrap(); - - MerkleNode::hash(&e[..]) - }) - .collect(); - - // Calculate Merkle Root for the the above nodes - let (root, _) = merklize("parent_owned_right", nodes); - - // Commit encode the root - let handmade_commit = root.commit_serialize(); - - // This should match with the original encoding - assert_eq!(original_commit, handmade_commit); - } - - #[test] - fn test_commitencode_assignments() { - //Create Declerative variant - - let mut rng = thread_rng(); - - let txid_vec: Vec = TXID_VEC - .iter() - .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) - .collect(); - - let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: data::Void(), - }; - - let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(Outpoint::new(txid_vec[1], 2)), - state: data::Void(), - }; - - let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(Outpoint::new(txid_vec[2], 3)).commit_conceal(), - state: data::Void(), - }; - - let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(Outpoint::new(txid_vec[3], 4)).commit_conceal(), - state: data::Void(), - }; - - let mut set = Vec::new(); - - set.push(assignment_1); - set.push(assignment_2); - set.push(assignment_3); - set.push(assignment_4); - - let declarative_variant = TypedAssignments::Void(set); - - // Create Pedersan Variant - - let txid_vec: Vec = TXID_VEC - .iter() - .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) - .collect(); - - let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: value::Revealed::with_amount(10u64, &mut rng), - }; - - let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), - state: value::Revealed::with_amount(20u64, &mut rng).commit_conceal(), - }; - - let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), - state: value::Revealed::with_amount(30u64, &mut rng), - }; - - let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), - state: value::Revealed::with_amount(10u64, &mut rng).commit_conceal(), - }; - - let mut set = Vec::new(); - - set.push(assignment_1); - set.push(assignment_2); - set.push(assignment_3); - set.push(assignment_4); - - let pedersen_variant = TypedAssignments::Value(set); - - // Create Hash variant - let txid_vec: Vec = TXID_VEC - .iter() - .map(|txid| bitcoin::Txid::from_hex(txid).unwrap()) - .collect(); - - let state_data_vec: Vec = STATE_DATA - .iter() - .map(|data| data::Revealed::Bytes(sha256::Hash::from_hex(data).unwrap().to_vec())) - .collect(); - - let assignment_1 = Assignment::::Revealed { - seal: Revealed::from(Outpoint::new(txid_vec[0], 1)), - state: state_data_vec[0].clone(), - }; - - let assignment_2 = Assignment::::ConfidentialState { - seal: Revealed::from(Outpoint::new(txid_vec[1], 1)), - state: state_data_vec[1].clone().commit_conceal(), - }; - - let assignment_3 = Assignment::::ConfidentialSeal { - seal: Revealed::from(Outpoint::new(txid_vec[2], 1)).commit_conceal(), - state: state_data_vec[2].clone(), - }; - - let assignment_4 = Assignment::::Confidential { - seal: Revealed::from(Outpoint::new(txid_vec[3], 1)).commit_conceal(), - state: state_data_vec[3].clone().commit_conceal(), - }; - - let mut set = Vec::new(); - - set.push(assignment_1); - set.push(assignment_2); - set.push(assignment_3); - set.push(assignment_4); - - let hash_variant = TypedAssignments::Data(set); - - // Create assignemnts - - let type1 = 1 as schema::OwnedRightType; - let type2 = 2 as schema::OwnedRightType; - let type3 = 3 as schema::OwnedRightType; - let mut owned_rights = OwnedRights::default(); - owned_rights - .as_mut() - .insert(type1, declarative_variant.clone()); - owned_rights - .as_mut() - .insert(type2, pedersen_variant.clone()); - owned_rights.as_mut().insert(type3, hash_variant.clone()); - - let mut original_encoding = vec![]; - owned_rights - .to_merkle_source() - .commit_encode(&mut original_encoding); - - // Hand calculate commitment - // create individual leaves - let declarative_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = declarative_variant - .to_declarative_assignments() - .iter() - .map(|assignment| { - (type1, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) - }) - .collect(); - - let pedersan_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = pedersen_variant - .to_value_assignments() - .iter() - .map(|assignment| { - (type2, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) - }) - .collect(); - - let hash_leaves: Vec<(schema::OwnedRightType, MerkleNode)> = hash_variant - .to_data_assignments() - .iter() - .map(|assignment| { - (type3, MerkleNode::hash(&CommitEncode::commit_serialize(assignment))) - }) - .collect(); - - // Combine all of them in a single collection - let all_leaves = [declarative_leaves, pedersan_leaves, hash_leaves].concat(); - - // create MerkleNodes from each leaf - let nodes: Vec = all_leaves - .iter() - .map(|item| MerkleNode::hash(&CommitEncode::commit_serialize(item))) - .collect(); - - // compute merkle root of all the nodes - let (root, _) = merklize("owned_right", nodes); - - // Commit encode the root - let handmade_encoding = root.commit_serialize(); - - // This should match with original encoding - assert_eq!(original_encoding, handmade_encoding); - } -} diff --git a/src/contract/seal.rs b/src/contract/seal.rs index 9fc3d0f5..959f3b2f 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -198,206 +198,3 @@ impl FromStr for SealEndpoint { .or_else(|_| RevealedSeal::from_str(s).map(SealEndpoint::from)) } } - -#[cfg(test)] -mod test { - use std::convert::TryFrom; - - use bitcoin_hashes::hex::FromHex; - use bp::seals::txout::TxoSeal; - use bp::{Outpoint, Txid}; - use commit_verify::CommitEncode; - use secp256k1_zkp::rand::{thread_rng, RngCore}; - use strict_encoding::{StrictDecode, StrictEncode}; - use strict_encoding_test::test_vec_decoding_roundtrip; - - use super::*; - - // Hard coded TxOutpoint variant of a Revealed Seal - // Constructed with following data - // txid = 201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e - // blinding = 13457965799463774082 - // vout = 6 - static REVEALED_TXOUTPOINT: [u8; 45] = [ - 0x0, 0x82, 0xe7, 0x64, 0x5c, 0x97, 0x4c, 0xc4, 0xba, 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, - 0x25, 0x89, 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, 0x1f, 0x18, 0xee, 0x18, 0x51, 0x29, - 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, 0x1f, 0x20, 0x6, 0x0, 0x0, 0x0, - ]; - - // Hard coded concealed seal of the above TxOutpoint variant - static CONCEALED_TXOUTPOINT: [u8; 32] = [ - 0x43, 0xea, 0xe3, 0x29, 0x3d, 0x22, 0xcb, 0x33, 0x37, 0x53, 0x78, 0x74, 0x8, 0xe, 0xed, - 0x5d, 0x7c, 0xff, 0xde, 0x4c, 0xee, 0x6e, 0x44, 0xc5, 0x62, 0x7d, 0x73, 0x19, 0x61, 0x6e, - 0x4, 0x87, - ]; - - // Hard coded WitnessVout variant of a Revealed Seal - // Constructred with following data - // vout = 6 - // blinding = 13457965799463774082 - static REVEALED_WITNESSVOUT: [u8; 13] = - [0x1, 0x6, 0x0, 0x0, 0x0, 0x82, 0xe7, 0x64, 0x5c, 0x97, 0x4c, 0xc4, 0xba]; - - // Hard coded concealed seal of the above WitnessVout variant - static CONCEALED_WITNESSVOUT: [u8; 32] = [ - 0x3e, 0x90, 0x1d, 0x9d, 0xef, 0xb4, 0xbb, 0x11, 0x8d, 0x69, 0x23, 0x9c, 0xe, 0x41, 0xb9, - 0x80, 0xd, 0x29, 0xdc, 0x5a, 0x7d, 0x2b, 0xa9, 0xe2, 0x39, 0xc8, 0x83, 0x90, 0x6, 0x93, - 0x74, 0xca, - ]; - - // Hard coded outpoint of the above seals - static OUTPOINT: [u8; 36] = [ - 0x8e, 0xaf, 0xd3, 0x36, 0xd, 0x65, 0x25, 0x89, 0x52, 0xf4, 0xd9, 0x57, 0x5e, 0xac, 0x1b, - 0x1f, 0x18, 0xee, 0x18, 0x51, 0x29, 0x71, 0x82, 0x93, 0xb6, 0xd7, 0x62, 0x2b, 0x1e, 0xdd, - 0x1f, 0x20, 0x6, 0x0, 0x0, 0x0, - ]; - - #[test] - #[ignore] - fn test_encode_decode() { - let _: Revealed = test_vec_decoding_roundtrip(REVEALED_TXOUTPOINT).unwrap(); - let _: Revealed = test_vec_decoding_roundtrip(REVEALED_WITNESSVOUT).unwrap(); - } - - /* - #[test] - #[ignore] - fn test_wrong_encoding() { - let err = "Revealed"; - test_garbage_exhaustive!( - 2..255; - (REVEALED_TXOUTPOINT, Revealed, err), - (REVEALED_WITNESSVOUT, Revealed, err) - ); - } - */ - - #[test] - #[ignore] - fn test_concealed() { - let revelaed = Revealed::strict_decode(&REVEALED_TXOUTPOINT[..]).unwrap(); - - let concealed = revelaed.commit_conceal(); - - // Strict encoding of Confidential data - let mut confidential_encoded = vec![]; - concealed.strict_encode(&mut confidential_encoded).unwrap(); - - assert_eq!(CONCEALED_TXOUTPOINT.to_vec(), confidential_encoded); - } - - #[test] - #[ignore] - fn test_witness_conf() { - let revelaed = Revealed::strict_decode(&REVEALED_WITNESSVOUT[..]).unwrap(); - - let concealed = revelaed.commit_conceal(); - - // Strict encoding Confidential data - let mut confidential_encoded = vec![]; - concealed.strict_encode(&mut confidential_encoded).unwrap(); - - assert_eq!(CONCEALED_WITNESSVOUT.to_vec(), confidential_encoded); - } - - #[test] - #[ignore] - fn test_into_outpoint() { - let revealed = Revealed::strict_decode(&REVEALED_TXOUTPOINT[..]).unwrap(); - - let outpoint = Outpoint::try_from(revealed.clone()).unwrap(); - - let coded = Outpoint::strict_decode(&OUTPOINT[..]).unwrap(); - - assert_eq!(coded, outpoint); - } - - #[test] - #[ignore] - #[should_panic(expected = "WitnessVoutError")] - fn test_witness_to_outpoint() { - // Conversion to Outpoint from WitnessVout variant should panic - let revealed = Revealed::strict_decode(&REVEALED_WITNESSVOUT[..]).unwrap(); - bp::Outpoint::try_from(revealed).unwrap(); - } - - #[test] - #[ignore] - fn test_outpoint_reveal() { - let revealed_txoutpoint = Revealed::strict_decode(&REVEALED_TXOUTPOINT[..]).unwrap(); - let revealed_witnessvout = Revealed::strict_decode(&REVEALED_WITNESSVOUT[..]).unwrap(); - - // Data used for constructing above seals - let txid = - Txid::from_hex("201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e") - .unwrap(); - - let blinding: u64 = 13457965799463774082; - - let vout: u32 = 6; - - // This should produce two exact same Revealed Outpoint - let outpoint_from_txoutpoint = revealed_txoutpoint.outpoint_or(txid); - let outpoint_from_witnessvout = revealed_witnessvout.outpoint_or(txid); - - // Check integrity - assert_eq!(outpoint_from_txoutpoint, outpoint_from_witnessvout); - assert_eq!(revealed_txoutpoint.blinding, blinding); - assert_eq!(outpoint_from_witnessvout.txid, txid); - assert_eq!(outpoint_from_txoutpoint.vout, vout); - } - - #[test] - #[ignore] - fn test_commitencode_seal() { - let revealed_txoutpoint = Revealed::strict_decode(&REVEALED_TXOUTPOINT[..]).unwrap(); - let revelaed_wtinessvout = Revealed::strict_decode(&REVEALED_WITNESSVOUT[..]).unwrap(); - - let mut commit1 = vec![]; - revealed_txoutpoint.commit_encode(&mut commit1); - assert_eq!(commit1, CONCEALED_TXOUTPOINT); - - let mut commit2 = vec![]; - revelaed_wtinessvout.commit_encode(&mut commit2); - assert_eq!(commit2, CONCEALED_WITNESSVOUT); - } - - #[test] - fn test_commitencoding_seals() { - let mut rng = thread_rng(); - let txid = bitcoin::Txid::from_hex( - "201fdd1e2b62d7b6938271295118ee181f1bac5e57d9f4528925650d36d3af8e", - ) - .unwrap(); - let vout = rng.next_u32(); - let revealed_txout = Revealed::from(Outpoint::new(txid, vout)); - - let revealed_witness = Revealed { - method: CloseMethod::TapretFirst, - txid: None, - vout, - blinding: rng.next_u64(), - }; - - let mut txout_orig = vec![]; - revealed_txout.clone().commit_encode(&mut txout_orig); - - let mut witness_orig = vec![]; - revealed_witness.clone().commit_encode(&mut witness_orig); - - let mut txout_new = vec![]; - revealed_txout - .commit_conceal() - .strict_encode(&mut txout_new) - .unwrap(); - - let mut witness_new = vec![]; - revealed_witness - .commit_conceal() - .strict_encode(&mut witness_new) - .unwrap(); - - assert_eq!(txout_orig, txout_new); - assert_eq!(witness_orig, witness_new); - } -} diff --git a/src/contract/value.rs b/src/contract/value.rs index f5d67c16..72049ca3 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -379,184 +379,3 @@ impl Confidential { Err(RangeProofError::BulletproofsAbsent) } } - -#[cfg(test)] -mod test { - use secp256k1_zkp::{rand, Scalar, SecretKey}; - use strict_encoding::{StrictDecode, StrictEncode}; - use strict_encoding_test::test_vec_decoding_roundtrip; - - use super::super::test::test_confidential; - use super::*; - - static AMOUNT_65: [u8; 40] = [ - 0x3, 0x41, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa6, 0x2b, 0x27, 0xae, 0x5a, 0xf, 0x8c, - 0x59, 0x5a, 0xfc, 0x8b, 0x55, 0xe5, 0x5f, 0x72, 0xd7, 0x29, 0x1, 0x55, 0xfa, 0x68, 0x25, - 0xe6, 0x3f, 0x62, 0x73, 0x54, 0xab, 0xfd, 0x11, 0x2e, - ]; - static CONFIDENTIAL_COMMITMENT: [u8; 33] = [ - 9, 28, 151, 197, 83, 49, 80, 112, 118, 251, 95, 172, 13, 248, 153, 215, 36, 80, 132, 186, - 165, 230, 100, 123, 89, 195, 155, 50, 186, 47, 189, 101, 5, - ]; - static CONFIDENTIAL_AMOUNT: [u8; 35] = [ - 9, 28, 151, 197, 83, 49, 80, 112, 118, 251, 95, 172, 13, 248, 153, 215, 36, 80, 132, 186, - 165, 230, 100, 123, 89, 195, 155, 50, 186, 47, 189, 101, 5, 0, 0, - ]; - - static AMOUNT_64: [u8; 40] = [ - 0x3, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xab, 0xe8, 0x9d, 0x73, 0xbd, 0x1c, 0x25, - 0x6d, 0x3c, 0x94, 0x94, 0xda, 0x5, 0xcc, 0x29, 0x7e, 0x34, 0xc3, 0xed, 0xfb, 0x6, 0xdb, - 0x6f, 0xe4, 0xdf, 0x6f, 0x28, 0x6e, 0x5d, 0xf6, 0xce, - ]; - - #[allow(dead_code)] - static COMMIT_SUM: [u8; 33] = [ - 0x08, 0x60, 0x23, 0x9f, 0xaa, 0x01, 0x4d, 0x24, 0x69, 0x22, 0x7f, 0x84, 0x17, 0x81, 0xe6, - 0x0a, 0x08, 0xa1, 0x42, 0xa9, 0x69, 0x89, 0x05, 0xba, 0x0e, 0x50, 0xae, 0x80, 0x88, 0x21, - 0xbf, 0xed, 0xc4, - ]; - - #[test] - #[ignore] - // We ignore the test since we do not have the correct test vectors. - // These ones are coming from the grin library and they are not compatible - // with elements project. - fn test_amount() { - // Test encoding decoding - let _: Revealed = test_vec_decoding_roundtrip(AMOUNT_65).unwrap(); - let _: Revealed = test_vec_decoding_roundtrip(AMOUNT_64).unwrap(); - let _: Confidential = test_vec_decoding_roundtrip(CONFIDENTIAL_AMOUNT).unwrap(); - - // Test commitment - test_confidential::(&AMOUNT_65, &CONFIDENTIAL_AMOUNT, &CONFIDENTIAL_COMMITMENT); - - // Test comparison - let revealed_64 = Revealed::strict_decode(&AMOUNT_64[..]).unwrap(); - let old_revealed = Revealed::strict_decode(&AMOUNT_65[..]).unwrap(); - assert_eq!(revealed_64.cmp(&old_revealed), Ordering::Less); - assert_eq!(revealed_64.partial_cmp(&old_revealed).unwrap(), Ordering::Less); - let coded_conf = Confidential::strict_decode(&CONFIDENTIAL_AMOUNT[..]).unwrap(); - let old_conf = old_revealed.commit_conceal(); - let new_conf = revealed_64.commit_conceal(); - assert_eq!(coded_conf, old_conf); - assert_ne!(old_conf, new_conf); - - // Test confidential addition - assert!(coded_conf.verify_range_proof().is_ok()); - } - - #[test] - #[ignore] - // We ignore the test since we do not have the correct test vectors. - // These ones are coming from the grin library and they are not compatible - // with elements project. - fn test_commit_sum() { - let positive = [1u64, 2u64, 3u64, 4u64, 5u64]; - let negative = [7u64, 8u64]; - - // Generate random blinding factors - let mut rng = rand::thread_rng(); - // We do not need the last one since it is auto-generated to - // zero-balance the rest - let count = positive.len() + negative.len() - 1; - let mut sum = Scalar::ZERO; - let mut blinding_factors = Vec::<_>::with_capacity(count + 1); - for _ in 0..count { - let bf = secp256k1::SecretKey::new(&mut rng); - sum = bf.add_tweak(&sum).unwrap().into(); - blinding_factors.push(bf); - } - - // let positive_factors = blinding_factors[..positive.len()].to_vec(); - // let negative_factors = blinding_factors[positive.len()..].to_vec(); - - let correction = SecretKey::from_slice(&sum.to_le_bytes()).unwrap().negate(); - blinding_factors.push(correction); - - // Create Revealed amounts with corrected blinding factors - let mut amounts = positive.to_vec(); - amounts.extend(negative.iter()); - - let commitments: Vec = amounts - .into_iter() - .zip(blinding_factors.iter()) - .map(|(amount, blinding_factor)| { - Revealed { - value: amount, - blinding: blinding_factor.clone().into(), - } - .commit_conceal() - .commitment - }) - .collect(); - - assert!(Confidential::verify_commit_sum( - commitments[..positive.len()], - commitments[positive.len()..] - )); - - // Create Revealed amounts with wrong positive values - let wrong_positive = [1u64, 5u64, 3u64, 4u64, 5u64]; - let mut amounts = wrong_positive.to_vec(); - amounts.extend(negative.iter()); - - // Create commitments with wrong positive values - let wrong_commitments: Vec = amounts - .into_iter() - .zip(blinding_factors.iter()) - .map(|(amount, blinding_factor)| { - Revealed { - value: amount, - blinding: blinding_factor.clone().into(), - } - .commit_conceal() - .commitment - }) - .collect(); - - // Ensure commit sum verification fails for wrong positive values - assert!(!Confidential::verify_commit_sum( - wrong_commitments[..positive.len()], - wrong_commitments[positive.len()..] - )); - } - - // We ignore this test for now since we are not checking blinding factor to - // be a correct scalar on Secp on read operations - for performance reason. - // It's validity will be checked during Pedersen commitment validation - // anyway - #[test] - #[ignore] - #[should_panic(expected = "DataIntegrityError")] - fn test_blinding() { - let blind = Revealed::strict_decode(&AMOUNT_64[..]).unwrap().blinding; - - let mut buff = vec![]; - blind.strict_encode(&mut buff).unwrap(); - - buff[0] = 0x10u8; - - BlindingFactor::strict_decode(&buff[..]).unwrap(); - } - - // TODO: Enable when bulletproofs will be back - /* - #[test] - #[should_panic(expected = "DataIntegrityError")] - fn test_rangeproof() { - let proof = Confidential::strict_decode(&CONFIDENTIAL_AMOUNT[..]) - .unwrap() - .bulletproof; - - let mut buff = vec![]; - proof.strict_encode(&mut buff).unwrap(); - - let mut pad = vec![0u8; 4465]; - buff.append(&mut pad); - buff[0] = 0x14u8; - buff[1] = 0x14u8; - - secp256k1zkp::pedersen::RangeProof::strict_decode(&buff[..]).unwrap(); - } - */ -} From c7b7a8c539a9b92dec021db5d22d9e134268cba8 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 01:49:30 +0100 Subject: [PATCH 56/71] ci: fix serde feature flags --- src/schema/schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema/schema.rs b/src/schema/schema.rs index e130498f..99425628 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -90,7 +90,7 @@ pub struct Schema { /// or do other backward-incompatible changes (RGB protocol versions are /// not interoperable and backward-incompatible by definitions and the /// nature of client-side-validation which does not allow upgrades). - #[serde(skip)] + #[cfg_attr(feature = "serde", serde(skip))] pub rgb_features: SchemaFlags, pub subset_of: Option, From b7f6fad2ff644d145068c21567b50c40f7324994 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 01:54:28 +0100 Subject: [PATCH 57/71] conceal: move conceal-reveal operations to standard library --- src/contract/anchor.rs | 105 -------------------------- src/contract/assignments.rs | 70 +---------------- src/contract/bundle.rs | 73 +----------------- src/contract/conceal.rs | 145 ------------------------------------ src/contract/mod.rs | 5 +- src/contract/operations.rs | 62 +-------------- src/contract/owned_state.rs | 117 +---------------------------- 7 files changed, 8 insertions(+), 569 deletions(-) delete mode 100644 src/contract/anchor.rs delete mode 100644 src/contract/conceal.rs diff --git a/src/contract/anchor.rs b/src/contract/anchor.rs deleted file mode 100644 index 2c3ce8df..00000000 --- a/src/contract/anchor.rs +++ /dev/null @@ -1,105 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use bp::dbc::Anchor; -use commit_verify::mpc; - -use crate::{reveal, ContractId, MergeReveal}; - -pub trait ConcealAnchors { - fn conceal_anchors_except( - &mut self, - contracts: impl AsRef<[ContractId]>, - ) -> Result; -} - -impl ConcealAnchors for Anchor { - fn conceal_anchors_except( - &mut self, - contracts: impl AsRef<[ContractId]>, - ) -> Result { - let protocols = contracts - .as_ref() - .iter() - .copied() - .map(mpc::ProtocolId::from) - .collect::>(); - self.conceal_except(protocols) - } -} - -impl MergeReveal for Anchor { - fn merge_reveal(self, other: Self) -> Result { - self.merge_reveal(other).map_err(reveal::Error::from) - } -} - -#[cfg(test)] -mod test { - use std::collections::BTreeMap; - - use bitcoin::consensus::deserialize; - use bitcoin::util::psbt::PartiallySignedTransaction; - use strict_encoding::StrictDecode; - - use super::*; - use crate::contract::{Genesis, Node}; - use crate::NodeId; - - static GENESIS: [u8; 2447] = include!("../../test/genesis.in"); - - static PSBT: [u8; 462] = include!("../../test/test_transaction.psbt"); - - #[test] - #[ignore] - fn test_psbt() { - // Create some dummy NodeId and ContractId for the test - let genesis = Genesis::strict_decode(&GENESIS[..]).unwrap(); - - let contract_id = genesis.contract_id(); - - let node_id = genesis.node_id(); - - // Get the test psbt - let source_psbt: PartiallySignedTransaction = deserialize(&PSBT[..]).unwrap(); - - // Copy witness psbt for future assertion - let witness_psbt = source_psbt.clone(); - - // Create the transition map for commitment - let mut map: BTreeMap = BTreeMap::new(); - map.insert(contract_id, node_id); - - // Check number of output remains same - assert_eq!(source_psbt.unsigned_tx.output.len(), witness_psbt.unsigned_tx.output.len()); - - // Check output values remains unchanged - assert_eq!( - source_psbt.unsigned_tx.output[0].value, - witness_psbt.unsigned_tx.output[0].value - ); - assert_eq!( - source_psbt.unsigned_tx.output[1].value, - witness_psbt.unsigned_tx.output[1].value - ); - } -} diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 338c77f2..005459f4 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -20,14 +20,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -use amplify::confinement::{Confined, MediumVec}; +use amplify::confinement::MediumVec; use commit_verify::merkle::MerkleNode; use commit_verify::CommitmentId; use super::owned_state::{AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy}; use super::{ - attachment, data, seal, value, Assignment, ConcealSeals, ConcealState, ConfidentialDataError, - RevealSeals, StateRetrievalError, StateType, UnknownDataError, + attachment, data, seal, value, Assignment, ConfidentialDataError, StateRetrievalError, + StateType, UnknownDataError, }; use crate::LIB_NAME_RGB; @@ -480,67 +480,3 @@ impl TypedAssignments { } } } - -impl RevealSeals for TypedAssignments { - fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize { - let mut counter = 0; - match self { - TypedAssignments::Void(_) => {} - TypedAssignments::Value(set) => { - *self = TypedAssignments::Value( - Confined::try_from_iter(set.iter().map(|assignment| { - let mut assignment = assignment.clone(); - counter += assignment.reveal_seals(known_seals); - assignment - })) - .expect("same size"), - ); - } - TypedAssignments::Data(set) => { - *self = TypedAssignments::Data( - Confined::try_from_iter(set.iter().map(|assignment| { - let mut assignment = assignment.clone(); - counter += assignment.reveal_seals(known_seals); - assignment - })) - .expect("same size"), - ); - } - TypedAssignments::Attachment(set) => { - *self = TypedAssignments::Attachment( - Confined::try_from_iter(set.iter().map(|assignment| { - let mut assignment = assignment.clone(); - counter += assignment.reveal_seals(known_seals); - assignment - })) - .expect("same size"), - ); - } - } - counter - } -} - -impl ConcealSeals for TypedAssignments { - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - match self { - TypedAssignments::Void(data) => data as &mut dyn ConcealSeals, - TypedAssignments::Value(data) => data as &mut dyn ConcealSeals, - TypedAssignments::Data(data) => data as &mut dyn ConcealSeals, - TypedAssignments::Attachment(data) => data as &mut dyn ConcealSeals, - } - .conceal_seals(seals) - } -} - -impl ConcealState for TypedAssignments { - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - match self { - TypedAssignments::Void(data) => data as &mut dyn ConcealState, - TypedAssignments::Value(data) => data as &mut dyn ConcealState, - TypedAssignments::Data(data) => data as &mut dyn ConcealState, - TypedAssignments::Attachment(data) => data as &mut dyn ConcealState, - } - .conceal_state_except(seals) - } -} diff --git a/src/contract/bundle.rs b/src/contract/bundle.rs index 54dca37e..9c49c2a0 100644 --- a/src/contract/bundle.rs +++ b/src/contract/bundle.rs @@ -20,11 +20,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use amplify::confinement::{Confined, TinyOrdMap, TinyOrdSet}; +use amplify::confinement::{TinyOrdMap, TinyOrdSet}; use amplify::{Bytes32, Wrapper}; use commit_verify::{mpc, CommitStrategy, CommitmentId}; -use super::{seal, ConcealSeals, ConcealState, Node, NodeId, RevealSeals, Transition}; +use super::{NodeId, Transition}; use crate::LIB_NAME_RGB; /// Unique state transition bundle identifier equivalent to the bundle @@ -44,11 +44,6 @@ pub struct BundleId( Bytes32, ); -pub trait ConcealTransitions { - fn conceal_transitions(&mut self) -> usize { self.conceal_transitions_except(&[]) } - fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize; -} - impl From for mpc::Message { fn from(id: BundleId) -> Self { mpc::Message::from_inner(id.into_inner()) } } @@ -67,70 +62,6 @@ pub struct TransitionBundle { pub concealed: TinyOrdMap>, } -impl ConcealTransitions for TransitionBundle { - fn conceal_transitions_except(&mut self, node_ids: &[NodeId]) -> usize { - let mut concealed = bmap! {}; - self.revealed = - Confined::try_from_iter(self.revealed.iter().filter_map(|(transition, inputs)| { - let node_id = transition.node_id(); - if !node_ids.contains(&node_id) { - concealed.insert(node_id, inputs.clone()); - None - } else { - Some((transition.clone(), inputs.clone())) - } - })) - .expect("same size"); - let count = concealed.len(); - self.concealed.extend(concealed).expect("todo: issue #141"); - count - } -} - -impl ConcealState for TransitionBundle { - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - let mut counter = 0; - self.revealed = - Confined::try_from_iter(self.revealed.iter().map(|(transition, inputs)| { - let mut transition = transition.clone(); - counter += transition.conceal_state_except(seals); - (transition, inputs.clone()) - })) - .expect("same size"); - counter - } -} - -impl ConcealSeals for TransitionBundle { - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - let mut counter = 0; - self.revealed = - Confined::try_from_iter(self.revealed.iter().map(|(transition, inputs)| { - let mut transition = transition.clone(); - counter += transition.conceal_seals(seals); - (transition, inputs.clone()) - })) - .expect("same size"); - counter - } -} - -impl RevealSeals for TransitionBundle { - fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize { - let mut counter = 0; - self.revealed = - Confined::try_from_iter(self.revealed.iter().map(|(transition, inputs)| { - let mut transition = transition.clone(); - for (_, assignment) in transition.owned_rights_mut().keyed_values_mut() { - counter += assignment.reveal_seals(known_seals); - } - (transition, inputs.clone()) - })) - .expect("same size"); - counter - } -} - impl CommitStrategy for TransitionBundle { type Strategy = commit_verify::strategies::Strict; } diff --git a/src/contract/conceal.rs b/src/contract/conceal.rs deleted file mode 100644 index 366e16da..00000000 --- a/src/contract/conceal.rs +++ /dev/null @@ -1,145 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use core::cmp::Ord; -use std::collections::{BTreeMap, BTreeSet}; -use std::hash::Hash; - -use amplify::confinement::{Collection, Confined}; - -use super::seal; - -pub trait RevealSeals { - /// Reveals previously known seal information (replacing blind UTXOs with - /// unblind ones). Function is used when a peer receives consignments - /// containing concealed seals for the outputs owned by the peer. - /// - /// # Returns - /// - /// Total number of seals revealed inside the data structure during the - /// operation. - fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize; -} - -/// Trait which must be implemented by all data structures having seals in their -/// hierarchy. -pub trait ConcealSeals { - /// Request to conceal all seals from a given subset of seals. - /// - /// # Returns - /// - /// Number of seals instances which were concealed. - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize; -} - -/// Trait which must be implemented by all data structures having state data. -pub trait ConcealState { - /// Request to conceal all state. - /// - /// # Returns - /// - /// Count of state atoms which were concealed. - fn conceal_state(&mut self) -> usize { self.conceal_state_except(&[]) } - - /// Request to conceal all of the state except given subset. - /// - /// The function doesn't requires that the state from the subset should - /// be a revealed state; if the state atom is concealed than it is just - /// ignored. - /// - /// # Returns - /// - /// Count of state atoms which were concealed. - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize; -} - -impl ConcealSeals for Confined, MIN, MAX> -where T: ConcealSeals -{ - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - self.iter_mut() - .fold(0usize, |sum, item| sum + item.conceal_seals(seals)) - } -} - -impl ConcealSeals for Confined, MIN, MAX> -where T: ConcealSeals + Ord + Clone -{ - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - let mut new_self = BTreeSet::::with_capacity(self.len()); - for item in self.iter() { - let mut new_item = item.clone(); - count += new_item.conceal_seals(seals); - new_self.insert(new_item); - } - *self = Confined::try_from(new_self).expect("same size"); - count - } -} - -impl ConcealSeals for Confined, MIN, MAX> -where - K: Ord + Hash, - V: ConcealSeals, -{ - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - self.keyed_values_mut() - .fold(0usize, |sum, item| sum + item.1.conceal_seals(seals)) - } -} - -impl ConcealState for Confined, MIN, MAX> -where T: ConcealState -{ - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - self.iter_mut() - .fold(0usize, |sum, item| sum + item.conceal_state_except(seals)) - } -} - -impl ConcealState for Confined, MIN, MAX> -where T: ConcealState + Ord + Clone -{ - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - let mut new_self = BTreeSet::::with_capacity(self.len()); - for item in self.iter() { - let mut new_item = item.clone(); - count += new_item.conceal_state_except(seals); - new_self.insert(new_item); - } - *self = Confined::try_from(new_self).expect("same size"); - count - } -} - -impl ConcealState for Confined, MIN, MAX> -where - K: Ord + Hash, - V: ConcealState, -{ - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - self.keyed_values_mut() - .fold(0usize, |sum, item| sum + item.1.conceal_state_except(seals)) - } -} diff --git a/src/contract/mod.rs b/src/contract/mod.rs index c8534203..faa24a4f 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -22,8 +22,6 @@ pub mod seal; -mod conceal; - pub mod value; pub mod attachment; pub mod data; @@ -35,8 +33,7 @@ mod bundle; pub use assignments::TypedAssignments; pub use attachment::AttachId; -pub use bundle::{BundleId, ConcealTransitions, TransitionBundle}; -pub use conceal::{ConcealSeals, ConcealState, RevealSeals}; +pub use bundle::{BundleId, TransitionBundle}; pub use global_state::{FieldValues, Metadata}; pub use operations::{ ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, OutpointParseError, OwnedRights, diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 776d6c18..4d953392 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -33,7 +33,7 @@ use bp::seals::txout::TxoSeal; use bp::{Chain, Outpoint, Txid}; use commit_verify::{mpc, CommitStrategy, CommitmentId}; -use super::{seal, ConcealSeals, ConcealState, ConfidentialDataError, Metadata, TypedAssignments}; +use super::{seal, ConfidentialDataError, Metadata, TypedAssignments}; use crate::schema::{ self, ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, PublicRightType, SchemaId, TransitionType, @@ -407,66 +407,6 @@ impl PartialOrd for Transition { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl ConcealState for Genesis { - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { - count += assignment.conceal_state_except(seals); - } - count - } -} - -impl ConcealState for Extension { - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { - count += assignment.conceal_state_except(seals); - } - count - } -} - -impl ConcealState for Transition { - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { - count += assignment.conceal_state_except(seals); - } - count - } -} - -impl ConcealSeals for Genesis { - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { - count += assignment.conceal_seals(seals); - } - count - } -} - -impl ConcealSeals for Transition { - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { - count += assignment.conceal_seals(seals); - } - count - } -} - -impl ConcealSeals for Extension { - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - let mut count = 0; - for (_, assignment) in self.owned_rights_mut().keyed_values_mut() { - count += assignment.conceal_seals(seals); - } - count - } -} - impl CommitStrategy for Genesis { // TODO: Use merklization type Strategy = commit_verify::strategies::Strict; diff --git a/src/contract/owned_state.rs b/src/contract/owned_state.rs index 7800734e..0eee317f 100644 --- a/src/contract/owned_state.rs +++ b/src/contract/owned_state.rs @@ -22,17 +22,13 @@ use core::cmp::Ordering; use core::fmt::Debug; -use std::collections::HashMap; use std::io; use commit_verify::merkle::MerkleNode; use commit_verify::{CommitEncode, CommitmentId, Conceal}; use strict_encoding::{StrictEncode, StrictWriter}; -use super::{ - attachment, data, seal, value, ConcealSeals, ConcealState, ConfidentialState, RevealSeals, - RevealedState, -}; +use super::{attachment, data, seal, value, ConfidentialState, RevealedState}; use crate::LIB_NAME_RGB; /// Categories of the state @@ -291,117 +287,6 @@ where } } -impl RevealSeals for Assignment -where - StateType: State, - StateType::Revealed: Conceal, - StateType::Confidential: PartialEq + Eq, - ::Confidential: From<::Concealed>, -{ - fn reveal_seals(&mut self, known_seals: &[seal::Revealed]) -> usize { - let known_seals: HashMap = known_seals - .iter() - .map(|rev| (rev.conceal(), *rev)) - .collect(); - - let mut counter = 0; - match self { - Assignment::Confidential { seal, state } => { - if let Some(reveal) = known_seals.get(seal) { - *self = Assignment::ConfidentialState { - seal: *reveal, - state: state.clone(), - }; - counter += 1; - }; - } - Assignment::ConfidentialSeal { seal, state } => { - if let Some(reveal) = known_seals.get(seal) { - *self = Assignment::Revealed { - seal: *reveal, - state: state.clone(), - }; - counter += 1; - }; - } - _ => {} - } - counter - } -} - -impl ConcealSeals for Assignment -where - StateType: State, - StateType::Revealed: Conceal, - StateType::Confidential: PartialEq + Eq, - ::Confidential: From<::Concealed>, -{ - fn conceal_seals(&mut self, seals: &[seal::Confidential]) -> usize { - match self { - Assignment::Confidential { .. } | Assignment::ConfidentialSeal { .. } => 0, - Assignment::ConfidentialState { seal, state } => { - if seals.contains(&seal.conceal()) { - *self = Assignment::::Confidential { - state: state.clone(), - seal: seal.conceal(), - }; - 1 - } else { - 0 - } - } - Assignment::Revealed { seal, state } => { - if seals.contains(&seal.conceal()) { - *self = Assignment::::ConfidentialSeal { - state: state.clone(), - seal: seal.conceal(), - }; - 1 - } else { - 0 - } - } - } - } -} - -impl ConcealState for Assignment -where - StateType: State, - StateType::Revealed: Conceal, - StateType::Confidential: PartialEq + Eq, - ::Confidential: From<::Concealed>, -{ - fn conceal_state_except(&mut self, seals: &[seal::Confidential]) -> usize { - match self { - Assignment::Confidential { .. } | Assignment::ConfidentialState { .. } => 0, - Assignment::ConfidentialSeal { seal, state } => { - if seals.contains(seal) { - 0 - } else { - *self = Assignment::::Confidential { - state: state.conceal().into(), - seal: *seal, - }; - 1 - } - } - Assignment::Revealed { seal, state } => { - if seals.contains(&seal.conceal()) { - 0 - } else { - *self = Assignment::::ConfidentialState { - state: state.conceal().into(), - seal: *seal, - }; - 1 - } - } - } - } -} - // We can't use `UsingConceal` strategy here since it relies on the // `commit_encode` of the concealed type, and here the concealed type is again // `OwnedState`, leading to a recurrency. So we use `strict_encode` of the From 169e77e368cfc628751cb72a2287a8482c1ce4d3 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 01:57:09 +0100 Subject: [PATCH 58/71] conceal: move IntoRevealedSeal to standard library --- src/contract/mod.rs | 2 +- src/contract/seal.rs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/contract/mod.rs b/src/contract/mod.rs index faa24a4f..037770de 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -40,7 +40,7 @@ pub use operations::{ ParentOwnedRights, ParentPublicRights, PublicRights, Transition, }; pub use owned_state::{Assignment, State, StateType}; -pub use seal::{IntoRevealedSeal, SealEndpoint}; +pub use seal::SealEndpoint; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, ValueAtom, diff --git a/src/contract/seal.rs b/src/contract/seal.rs index 959f3b2f..2c8d1d5e 100644 --- a/src/contract/seal.rs +++ b/src/contract/seal.rs @@ -35,12 +35,6 @@ use secp256k1_zkp::rand::RngCore; use crate::LIB_NAME_RGB; -/// Trait for types supporting conversion to a [`RevealedSeal`] -pub trait IntoRevealedSeal { - /// Converts seal into [`RevealedSeal`] type. - fn into_revealed_seal(self) -> RevealedSeal; -} - /// Seal definition which re-uses witness transaction id of some other seal, /// which is not known at the moment of seal construction. Thus, the definition /// has only information about output number. From a75c78d20477813afd0f3350a5d4b6a2b2220a44 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 02:02:36 +0100 Subject: [PATCH 59/71] refactor: move SealEndpoints to standard library --- doc/seals.md | 24 ----- src/contract/mod.rs | 6 +- src/contract/seal.rs | 194 --------------------------------------- src/validation/graph.rs | 6 +- src/validation/mod.rs | 6 +- src/validation/verify.rs | 7 +- 6 files changed, 11 insertions(+), 232 deletions(-) delete mode 100644 doc/seals.md delete mode 100644 src/contract/seal.rs diff --git a/doc/seals.md b/doc/seals.md deleted file mode 100644 index 2d6bcb9b..00000000 --- a/doc/seals.md +++ /dev/null @@ -1,24 +0,0 @@ -# Single-use-seal API specific for RGB implementation - -Based on LNP/BP client-side-validation single-use-seals API (see -[`lnpbp::seals`]). RGB single-use-seal implementation differs in the fact -that seals are organized into a graph; thus a seal may be defined as -pointing witness transaction closing some other seal, which is meaningless -with LNP/BP seals. - -Single-use-seals in RGB are used for holding assigned state, i.e. *state* + -*seal definition* = *assignment*. Closing of the single-use-seal invalidates -the assigned state. - -Single-use-seals in RGB can have multiple forms because of the -confidentiality options and ability to be linked to the witness transaction -closing previous seal in RGB state evolution graph. - -| **Type name** | **Lib** | **Txid** | **Blinding** | **Confidential** | **String serialization** | **Use case** | -| ----------------- | -------- | --------- | ------------ | ---------------- | --------------------------------------- | ------------- | -| [`Outpoint`] | BP Core | Required | No | No | `:` | Genesis | -| [`RevealedSeal`] | BP Core | Required | Yes | No | `:<|~>:#` | Stash | -| [`ConcealedSeal`] | BP Core | Unknown | Implicit | Yes | `txob:#` | Ext. payments | -| [`ExplicitSeal`] | BP Core | Optional | Yes | No | `:<|~>:` | Internal | -| [`VoutSeal`] | RGB Core | Absent | Yes | No | `:~:#` | SealEndpoint | -| [`SealEndpoint`] | RGB Core | Optional | Varies | Could be | `|` | Consignments | diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 037770de..74902583 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -20,8 +20,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub mod seal; - +pub mod seal { + pub use bp::seals::txout::blind::{ConcealedSeal as Confidential, RevealedSeal as Revealed}; +} pub mod value; pub mod attachment; pub mod data; @@ -40,7 +41,6 @@ pub use operations::{ ParentOwnedRights, ParentPublicRights, PublicRights, Transition, }; pub use owned_state::{Assignment, State, StateType}; -pub use seal::SealEndpoint; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, ValueAtom, diff --git a/src/contract/seal.rs b/src/contract/seal.rs deleted file mode 100644 index 2c8d1d5e..00000000 --- a/src/contract/seal.rs +++ /dev/null @@ -1,194 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![doc = include_str!("../../doc/seals.md")] - -use std::fmt::{self, Display, Formatter}; -use std::str::FromStr; - -use bp::seals::txout::blind::{ConcealedSeal, ParseError, RevealedSeal}; -pub use bp::seals::txout::blind::{ConcealedSeal as Confidential, RevealedSeal as Revealed}; -use bp::seals::txout::CloseMethod; -use bp::secp256k1::rand::thread_rng; -use bp::Vout; -use commit_verify::Conceal; -use secp256k1_zkp::rand::RngCore; - -use crate::LIB_NAME_RGB; - -/// Seal definition which re-uses witness transaction id of some other seal, -/// which is not known at the moment of seal construction. Thus, the definition -/// has only information about output number. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct VoutSeal { - /// Commitment to the specific seal close method [`CloseMethod`] which must - /// be used to close this seal. - pub method: CloseMethod, - - /// Tx output number, which should be always known. - pub vout: Vout, - - /// Blinding factor providing confidentiality of the seal definition. - /// Prevents rainbow table bruteforce attack based on the existing - /// blockchain txid set. - pub blinding: u64, -} - -impl VoutSeal { - /// Creates new seal definition for the provided output number and seal - /// closing method. Uses `thread_rng` to initialize blinding factor. - #[inline] - pub fn new(method: CloseMethod, vout: impl Into) -> Self { - VoutSeal::with(method, vout, thread_rng().next_u64()) - } - - /// Creates new opret-seal seal definition for the provided output number - /// and seal closing method. Uses `thread_rng` to initialize blinding - /// factor. - #[inline] - pub fn new_opret(vout: impl Into) -> Self { VoutSeal::new(CloseMethod::OpretFirst, vout) } - - /// Creates new tapret-seal seal definition for the provided output number - /// and seal closing method. Uses `thread_rng` to initialize blinding - /// factor. - #[inline] - pub fn new_tapret(vout: impl Into) -> Self { - VoutSeal::new(CloseMethod::TapretFirst, vout) - } - - /// Reconstructs previously defined opret seal given an output number and a - /// previously generated blinding factor. - #[inline] - pub fn with_opret(vout: impl Into, blinding: u64) -> Self { - VoutSeal::with(CloseMethod::OpretFirst, vout, blinding) - } - - /// Reconstructs previously defined tapret seal given an output number and a - /// previously generated blinding factor. - #[inline] - pub fn with_tapret(vout: impl Into, blinding: u64) -> Self { - VoutSeal::with(CloseMethod::TapretFirst, vout, blinding) - } - - /// Reconstructs previously defined seal given method, an output number and - /// a previously generated blinding factor. - #[inline] - pub fn with(method: CloseMethod, vout: impl Into, blinding: u64) -> Self { - VoutSeal { - method, - vout: vout.into(), - blinding, - } - } -} - -impl From for RevealedSeal { - fn from(seal: VoutSeal) -> Self { - RevealedSeal::with_vout(seal.method, seal.vout, seal.blinding) - } -} - -/// Seal endpoint is a confidential seal which may be linked to the witness -/// transaction, but does not contain information about its id. -/// -/// Seal endpoint can be either a pointer to the output in the witness -/// transaction, plus blinding factor value, or a confidential seal -/// [`ConcealedSeal`] value pointing some external unknown transaction -/// output -/// -/// Seal endpoint is required in situations where sender assigns state to the -/// witness transaction output on behalf of receiver -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = { Self::ConcealedUtxo(strict_dumb!()) })] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub enum SealEndpoint { - /// External transaction output in concealed form (see - /// [`seal::Confidential`]) - #[from] - #[strict_type(tag = 0)] - ConcealedUtxo(ConcealedSeal), - - /// Seal contained within the witness transaction - #[strict_type(tag = 1)] - WitnessVout(VoutSeal), -} - -impl From for SealEndpoint { - fn from(seal: RevealedSeal) -> Self { - match seal.txid { - None => { - SealEndpoint::WitnessVout(VoutSeal::with(seal.method, seal.vout, seal.blinding)) - } - Some(_) => SealEndpoint::ConcealedUtxo(seal.conceal()), - } - } -} - -impl SealEndpoint { - /// Constructs [`SealEndpoint`] for the witness transaction. Uses - /// `thread_rng` to initialize blinding factor. - pub fn new_vout(method: CloseMethod, vout: impl Into) -> SealEndpoint { - SealEndpoint::WitnessVout(VoutSeal::new(method, vout)) - } -} - -impl Conceal for SealEndpoint { - type Concealed = Confidential; - - fn conceal(&self) -> Self::Concealed { - match *self { - SealEndpoint::ConcealedUtxo(hash) => hash, - SealEndpoint::WitnessVout(seal) => RevealedSeal::from(seal).conceal(), - } - } -} - -impl Display for SealEndpoint { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match *self { - SealEndpoint::ConcealedUtxo(ref seal) => Display::fmt(seal, f), - SealEndpoint::WitnessVout(seal) => Display::fmt(&RevealedSeal::from(seal), f), - } - } -} - -impl FromStr for SealEndpoint { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - ConcealedSeal::from_str(s) - .map(SealEndpoint::from) - .or_else(|_| RevealedSeal::from_str(s).map(SealEndpoint::from)) - } -} diff --git a/src/validation/graph.rs b/src/validation/graph.rs index 76a9975c..231f5d3b 100644 --- a/src/validation/graph.rs +++ b/src/validation/graph.rs @@ -32,8 +32,8 @@ use commit_verify::mpc; use crate::schema::OwnedRightType; use crate::{ - Anchor, BundleId, Extension, Genesis, Node, NodeId, NodeOutpoint, Schema, SealEndpoint, - Transition, TransitionBundle, + seal, Anchor, BundleId, Extension, Genesis, Node, NodeId, NodeOutpoint, Schema, Transition, + TransitionBundle, }; /// Errors accessing graph data via [`GraphApi`]. @@ -178,7 +178,7 @@ pub trait GraphApi { } pub trait Consignment<'consignment>: 'consignment + GraphApi { - type EndpointIter: Iterator; + type EndpointIter: Iterator; type BundleIter: Iterator, TransitionBundle)>; type ExtensionsIter: Iterator; diff --git a/src/validation/mod.rs b/src/validation/mod.rs index a86ef322..a84dcc27 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -34,7 +34,7 @@ use bp::Txid; pub use verify::{ResolveTx, TxResolverError, Validator}; use crate::schema::{self, NodeType, SchemaId}; -use crate::{data, BundleId, NodeId, OccurrencesMismatch, SealEndpoint}; +use crate::{data, seal, BundleId, NodeId, OccurrencesMismatch}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] #[display(Debug)] @@ -248,8 +248,8 @@ pub enum Failure { // TODO #44: (v0.3) convert to detailed descriptions using doc_comments #[display(Debug)] pub enum Warning { - EndpointDuplication(NodeId, SealEndpoint), - EndpointTransitionSealNotFound(NodeId, SealEndpoint), + EndpointDuplication(NodeId, seal::Confidential), + EndpointTransitionSealNotFound(NodeId, seal::Confidential), ExcessiveNode(NodeId), EndpointTransactionMissed(Txid), } diff --git a/src/validation/verify.rs b/src/validation/verify.rs index 229f9c87..a07097ef 100644 --- a/src/validation/verify.rs +++ b/src/validation/verify.rs @@ -25,7 +25,7 @@ use std::collections::{BTreeMap, BTreeSet, VecDeque}; use bp::dbc::Anchor; use bp::seals::txout::TxoSeal; use bp::{Tx, Txid}; -use commit_verify::{mpc, Conceal}; +use commit_verify::mpc; use super::graph::Consignment; use super::schema::NodeType; @@ -110,10 +110,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> for transition in transitions { let node_id = transition.node_id(); // Checking for endpoint definition duplicates - if !transition - .to_confiential_seals() - .contains(&seal_endpoint.conceal()) - { + if !transition.to_confiential_seals().contains(&seal_endpoint) { // We generate just a warning here because it's up to a user // to decide whether to accept consignment with wrong // endpoint list From b7016f904390a388ffad6466f0af440c8c167825 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 02:23:20 +0100 Subject: [PATCH 60/71] refactor state type names - part 1 --- src/contract/assignments.rs | 272 +++++++++++----------- src/contract/global_state.rs | 56 ----- src/contract/mod.rs | 12 +- src/contract/operations.rs | 124 +++++----- src/contract/{owned_state.rs => state.rs} | 212 +++++++++-------- src/validation/model.rs | 74 +++--- src/validation/state.rs | 61 +++-- src/validation/verify.rs | 4 +- src/validation/vm.rs | 32 +-- 9 files changed, 402 insertions(+), 445 deletions(-) delete mode 100644 src/contract/global_state.rs rename src/contract/{owned_state.rs => state.rs} (50%) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 005459f4..310a5868 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -24,149 +24,143 @@ use amplify::confinement::MediumVec; use commit_verify::merkle::MerkleNode; use commit_verify::CommitmentId; -use super::owned_state::{AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy}; +use super::state::{AttachmentPair, DeclarativePair, FungiblePair, StructuredPair}; use super::{ - attachment, data, seal, value, Assignment, ConfidentialDataError, StateRetrievalError, + attachment, data, seal, value, AssignedState, ConfidentialDataError, StateRetrievalError, StateType, UnknownDataError, }; use crate::LIB_NAME_RGB; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = Self::Void(strict_dumb!()))] +#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = Self::Declarative(strict_dumb!()))] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "snake_case") )] -pub enum TypedAssignments { +pub enum TypedState { // TODO: Consider using non-empty variants #[strict_type(tag = 0x00)] - Void(MediumVec>), + Declarative(MediumVec>), #[strict_type(tag = 0x01)] - Value(MediumVec>), + Fungible(MediumVec>), #[strict_type(tag = 0x02)] - Data(MediumVec>), + Structured(MediumVec>), #[strict_type(tag = 0xFF)] - Attachment(MediumVec>), + Attachment(MediumVec>), } -impl TypedAssignments { +impl TypedState { #[inline] pub fn state_type(&self) -> StateType { match self { - TypedAssignments::Void(_) => StateType::Void, - TypedAssignments::Value(_) => StateType::Value, - TypedAssignments::Data(_) => StateType::Data, - TypedAssignments::Attachment(_) => StateType::Attachment, + TypedState::Declarative(_) => StateType::Void, + TypedState::Fungible(_) => StateType::Fungible, + TypedState::Structured(_) => StateType::Structured, + TypedState::Attachment(_) => StateType::Attachment, } } #[inline] - pub fn is_declarative(&self) -> bool { matches!(self, TypedAssignments::Void(_)) } + pub fn is_declarative(&self) -> bool { matches!(self, TypedState::Declarative(_)) } #[inline] - pub fn has_value(&self) -> bool { matches!(self, TypedAssignments::Value(_)) } + pub fn is_fungible(&self) -> bool { matches!(self, TypedState::Fungible(_)) } #[inline] - pub fn has_data(&self) -> bool { matches!(self, TypedAssignments::Data(_)) } + pub fn is_structured(&self) -> bool { matches!(self, TypedState::Structured(_)) } #[inline] - pub fn is_attachment(&self) -> bool { matches!(self, TypedAssignments::Attachment(_)) } + pub fn is_attachment(&self) -> bool { matches!(self, TypedState::Attachment(_)) } #[inline] - pub fn as_declarative_assignments(&self) -> &[Assignment] { + pub fn as_declarative(&self) -> &[AssignedState] { match self { - TypedAssignments::Void(set) => set, + TypedState::Declarative(set) => set, _ => Default::default(), } } #[inline] - pub fn as_value_assignments(&self) -> &[Assignment] { + pub fn as_fungible(&self) -> &[AssignedState] { match self { - TypedAssignments::Value(set) => set, + TypedState::Fungible(set) => set, _ => Default::default(), } } #[inline] - pub fn as_data_assignments(&self) -> &[Assignment] { + pub fn as_structured(&self) -> &[AssignedState] { match self { - TypedAssignments::Data(set) => set, + TypedState::Structured(set) => set, _ => Default::default(), } } #[inline] - pub fn as_attachment_assignments(&self) -> &[Assignment] { + pub fn as_attachment(&self) -> &[AssignedState] { match self { - TypedAssignments::Attachment(set) => set, + TypedState::Attachment(set) => set, _ => Default::default(), } } #[inline] - pub fn as_declarative_assignments_mut( - &mut self, - ) -> Option<&mut MediumVec>> { + pub fn as_declarative_mut(&mut self) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Void(set) => Some(set), + TypedState::Declarative(set) => Some(set), _ => None, } } #[inline] - pub fn as_value_assignments_mut( - &mut self, - ) -> Option<&mut MediumVec>> { + pub fn as_fungible_mut(&mut self) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Value(set) => Some(set), + TypedState::Fungible(set) => Some(set), _ => None, } } #[inline] - pub fn as_data_assignments_mut(&mut self) -> Option<&mut MediumVec>> { + pub fn as_structured_mut(&mut self) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Data(set) => Some(set), + TypedState::Structured(set) => Some(set), _ => None, } } #[inline] - pub fn as_attachment_assignments_mut( - &mut self, - ) -> Option<&mut MediumVec>> { + pub fn as_attachment_mut(&mut self) -> Option<&mut MediumVec>> { match self { - TypedAssignments::Attachment(set) => Some(set), + TypedState::Attachment(set) => Some(set), _ => None, } } pub fn revealed_seal_outputs(&self) -> Vec<(seal::Revealed, u16)> { match self { - TypedAssignments::Void(s) => s + TypedState::Declarative(s) => s .iter() - .map(Assignment::<_>::revealed_seal) + .map(AssignedState::<_>::revealed_seal) .enumerate() .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) .collect(), - TypedAssignments::Value(s) => s + TypedState::Fungible(s) => s .iter() - .map(Assignment::<_>::revealed_seal) + .map(AssignedState::<_>::revealed_seal) .enumerate() .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) .collect(), - TypedAssignments::Data(s) => s + TypedState::Structured(s) => s .iter() - .map(Assignment::<_>::revealed_seal) + .map(AssignedState::<_>::revealed_seal) .enumerate() .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) .collect(), - TypedAssignments::Attachment(s) => s + TypedState::Attachment(s) => s .iter() - .map(Assignment::<_>::revealed_seal) + .map(AssignedState::<_>::revealed_seal) .enumerate() .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) .collect(), @@ -178,19 +172,19 @@ impl TypedAssignments { /// seal data packed as `Ok(Some(`[`seal::Revealed`]`))` pub fn revealed_seal_at(&self, index: u16) -> Result, UnknownDataError> { Ok(match self { - TypedAssignments::Void(vec) => vec + TypedState::Declarative(vec) => vec .get(index as usize) .ok_or(UnknownDataError)? .revealed_seal(), - TypedAssignments::Value(vec) => vec + TypedState::Fungible(vec) => vec .get(index as usize) .ok_or(UnknownDataError)? .revealed_seal(), - TypedAssignments::Data(vec) => vec + TypedState::Structured(vec) => vec .get(index as usize) .ok_or(UnknownDataError)? .revealed_seal(), - TypedAssignments::Attachment(vec) => vec + TypedState::Attachment(vec) => vec .get(index as usize) .ok_or(UnknownDataError)? .revealed_seal(), @@ -199,12 +193,10 @@ impl TypedAssignments { pub fn revealed_seals(&self) -> Result, ConfidentialDataError> { let list: Vec<_> = match self { - TypedAssignments::Void(s) => s.iter().map(Assignment::<_>::revealed_seal).collect(), - TypedAssignments::Value(s) => s.iter().map(Assignment::<_>::revealed_seal).collect(), - TypedAssignments::Data(s) => s.iter().map(Assignment::<_>::revealed_seal).collect(), - TypedAssignments::Attachment(s) => { - s.iter().map(Assignment::<_>::revealed_seal).collect() - } + TypedState::Declarative(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), + TypedState::Fungible(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), + TypedState::Structured(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), + TypedState::Attachment(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), }; let len = list.len(); let filtered: Vec = list.into_iter().flatten().collect(); @@ -216,49 +208,51 @@ impl TypedAssignments { pub fn filter_revealed_seals(&self) -> Vec { match self { - TypedAssignments::Void(s) => s + TypedState::Declarative(s) => s .iter() - .filter_map(Assignment::<_>::revealed_seal) + .filter_map(AssignedState::<_>::revealed_seal) .collect(), - TypedAssignments::Value(s) => s + TypedState::Fungible(s) => s .iter() - .filter_map(Assignment::<_>::revealed_seal) + .filter_map(AssignedState::<_>::revealed_seal) .collect(), - TypedAssignments::Data(s) => s + TypedState::Structured(s) => s .iter() - .filter_map(Assignment::<_>::revealed_seal) + .filter_map(AssignedState::<_>::revealed_seal) .collect(), - TypedAssignments::Attachment(s) => s + TypedState::Attachment(s) => s .iter() - .filter_map(Assignment::<_>::revealed_seal) + .filter_map(AssignedState::<_>::revealed_seal) .collect(), } } pub fn to_confidential_seals(&self) -> Vec { match self { - TypedAssignments::Void(s) => s + TypedState::Declarative(s) => s .iter() - .map(Assignment::<_>::to_confidential_seal) + .map(AssignedState::<_>::to_confidential_seal) .collect(), - TypedAssignments::Value(s) => s + TypedState::Fungible(s) => s .iter() - .map(Assignment::<_>::to_confidential_seal) + .map(AssignedState::<_>::to_confidential_seal) .collect(), - TypedAssignments::Data(s) => s + TypedState::Structured(s) => s .iter() - .map(Assignment::<_>::to_confidential_seal) + .map(AssignedState::<_>::to_confidential_seal) .collect(), - TypedAssignments::Attachment(s) => s + TypedState::Attachment(s) => s .iter() - .map(Assignment::<_>::to_confidential_seal) + .map(AssignedState::<_>::to_confidential_seal) .collect(), } } - pub fn as_revealed_state_values(&self) -> Result, StateRetrievalError> { + // -------------------- + + pub fn revealed_fungible_state(&self) -> Result, StateRetrievalError> { let list = match self { - TypedAssignments::Value(s) => s.iter().map(Assignment::<_>::as_revealed_state), + TypedState::Fungible(s) => s.iter().map(AssignedState::<_>::as_revealed_state), _ => return Err(StateRetrievalError::StateTypeMismatch), }; let len = list.len(); @@ -269,9 +263,9 @@ impl TypedAssignments { Ok(filtered) } - pub fn as_revealed_state_data(&self) -> Result, StateRetrievalError> { + pub fn revealed_structured_state(&self) -> Result, StateRetrievalError> { let list = match self { - TypedAssignments::Data(s) => s.iter().map(Assignment::<_>::as_revealed_state), + TypedState::Structured(s) => s.iter().map(AssignedState::<_>::as_revealed_state), _ => return Err(StateRetrievalError::StateTypeMismatch), }; let len = list.len(); @@ -282,11 +276,9 @@ impl TypedAssignments { Ok(filtered) } - pub fn as_revealed_state_attachments( - &self, - ) -> Result, StateRetrievalError> { + pub fn revealed_attachments(&self) -> Result, StateRetrievalError> { let list = match self { - TypedAssignments::Attachment(s) => s.iter().map(Assignment::<_>::as_revealed_state), + TypedState::Attachment(s) => s.iter().map(AssignedState::<_>::as_revealed_state), _ => return Err(StateRetrievalError::StateTypeMismatch), }; let len = list.len(); @@ -297,84 +289,84 @@ impl TypedAssignments { Ok(filtered) } - pub fn filter_revealed_state_values(&self) -> Vec<&value::Revealed> { + pub fn filter_revealed_fungible_state(&self) -> Vec<&value::Revealed> { match self { - TypedAssignments::Void(_) => vec![], - TypedAssignments::Value(s) => s + TypedState::Declarative(_) => vec![], + TypedState::Fungible(s) => s .iter() - .filter_map(Assignment::<_>::as_revealed_state) + .filter_map(AssignedState::<_>::as_revealed_state) .collect(), - TypedAssignments::Data(_) => vec![], - TypedAssignments::Attachment(_) => vec![], + TypedState::Structured(_) => vec![], + TypedState::Attachment(_) => vec![], } } - pub fn filter_revealed_state_data(&self) -> Vec<&data::Revealed> { + pub fn filter_revealed_structured_state(&self) -> Vec<&data::Revealed> { match self { - TypedAssignments::Void(_) => vec![], - TypedAssignments::Value(_) => vec![], - TypedAssignments::Data(s) => s + TypedState::Declarative(_) => vec![], + TypedState::Fungible(_) => vec![], + TypedState::Structured(s) => s .iter() - .filter_map(Assignment::<_>::as_revealed_state) + .filter_map(AssignedState::<_>::as_revealed_state) .collect(), - TypedAssignments::Attachment(_) => vec![], + TypedState::Attachment(_) => vec![], } } - pub fn filter_revealed_state_attachments(&self) -> Vec<&attachment::Revealed> { + pub fn filter_revealed_attachments(&self) -> Vec<&attachment::Revealed> { match self { - TypedAssignments::Void(_) => vec![], - TypedAssignments::Value(_) => vec![], - TypedAssignments::Data(_) => vec![], - TypedAssignments::Attachment(s) => s + TypedState::Declarative(_) => vec![], + TypedState::Fungible(_) => vec![], + TypedState::Structured(_) => vec![], + TypedState::Attachment(s) => s .iter() - .filter_map(Assignment::<_>::as_revealed_state) + .filter_map(AssignedState::<_>::as_revealed_state) .collect(), } } - pub fn to_confidential_state_pedersen(&self) -> Vec { + pub fn to_confidential_fungible_state(&self) -> Vec { match self { - TypedAssignments::Void(_) => vec![], - TypedAssignments::Value(s) => s + TypedState::Declarative(_) => vec![], + TypedState::Fungible(s) => s .iter() - .map(Assignment::<_>::to_confidential_state) + .map(AssignedState::<_>::to_confidential_state) .collect(), - TypedAssignments::Data(_) => vec![], - TypedAssignments::Attachment(_) => vec![], + TypedState::Structured(_) => vec![], + TypedState::Attachment(_) => vec![], } } - pub fn to_confidential_state_hashed(&self) -> Vec { + pub fn to_confidential_structured_state(&self) -> Vec { match self { - TypedAssignments::Void(_) => vec![], - TypedAssignments::Value(_) => vec![], - TypedAssignments::Data(s) => s + TypedState::Declarative(_) => vec![], + TypedState::Fungible(_) => vec![], + TypedState::Structured(s) => s .iter() - .map(Assignment::<_>::to_confidential_state) + .map(AssignedState::<_>::to_confidential_state) .collect(), - TypedAssignments::Attachment(_) => vec![], + TypedState::Attachment(_) => vec![], } } - pub fn to_confidential_state_attachments(&self) -> Vec { + pub fn to_confidential_attachments(&self) -> Vec { match self { - TypedAssignments::Void(_) => vec![], - TypedAssignments::Value(_) => vec![], - TypedAssignments::Data(_) => vec![], - TypedAssignments::Attachment(s) => s + TypedState::Declarative(_) => vec![], + TypedState::Fungible(_) => vec![], + TypedState::Structured(_) => vec![], + TypedState::Attachment(s) => s .iter() - .map(Assignment::<_>::to_confidential_state) + .map(AssignedState::<_>::to_confidential_state) .collect(), } } #[inline] - pub fn as_revealed_owned_value( + pub fn revealed_fungible_assignments( &self, ) -> Result, StateRetrievalError> { match self { - TypedAssignments::Value(vec) => { + TypedState::Fungible(vec) => { let unfiltered: Vec<_> = vec .iter() .filter_map(|assignment| { @@ -394,11 +386,11 @@ impl TypedAssignments { } #[inline] - pub fn as_revealed_owned_data( + pub fn revealed_structured_assignments( &self, ) -> Result, StateRetrievalError> { match self { - TypedAssignments::Data(vec) => { + TypedState::Structured(vec) => { let unfiltered: Vec<_> = vec .iter() .filter_map(|assignment| { @@ -418,11 +410,11 @@ impl TypedAssignments { } #[inline] - pub fn as_revealed_owned_attachments( + pub fn revealed_attachment_assignments( &self, ) -> Result, StateRetrievalError> { match self { - TypedAssignments::Attachment(vec) => { + TypedState::Attachment(vec) => { let unfiltered: Vec<_> = vec .iter() .filter_map(|assignment| { @@ -441,41 +433,43 @@ impl TypedAssignments { } } + // --------------- + pub fn is_empty(&self) -> bool { match self { - TypedAssignments::Void(set) => set.is_empty(), - TypedAssignments::Value(set) => set.is_empty(), - TypedAssignments::Data(set) => set.is_empty(), - TypedAssignments::Attachment(set) => set.is_empty(), + TypedState::Declarative(set) => set.is_empty(), + TypedState::Fungible(set) => set.is_empty(), + TypedState::Structured(set) => set.is_empty(), + TypedState::Attachment(set) => set.is_empty(), } } pub fn len(&self) -> usize { match self { - TypedAssignments::Void(set) => set.len(), - TypedAssignments::Value(set) => set.len(), - TypedAssignments::Data(set) => set.len(), - TypedAssignments::Attachment(set) => set.len(), + TypedState::Declarative(set) => set.len(), + TypedState::Fungible(set) => set.len(), + TypedState::Structured(set) => set.len(), + TypedState::Attachment(set) => set.len(), } } pub fn commitment_leaves(&self) -> Vec { match self { - TypedAssignments::Void(vec) => vec + TypedState::Declarative(vec) => vec .iter() - .map(Assignment::::commitment_id) + .map(AssignedState::::commitment_id) .collect(), - TypedAssignments::Value(vec) => vec + TypedState::Fungible(vec) => vec .iter() - .map(Assignment::::commitment_id) + .map(AssignedState::::commitment_id) .collect(), - TypedAssignments::Data(vec) => vec + TypedState::Structured(vec) => vec .iter() - .map(Assignment::::commitment_id) + .map(AssignedState::::commitment_id) .collect(), - TypedAssignments::Attachment(vec) => vec + TypedState::Attachment(vec) => vec .iter() - .map(Assignment::::commitment_id) + .map(AssignedState::::commitment_id) .collect(), } } diff --git a/src/contract/global_state.rs b/src/contract/global_state.rs deleted file mode 100644 index e02a8bdc..00000000 --- a/src/contract/global_state.rs +++ /dev/null @@ -1,56 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Convenience metadata accessor methods for Genesis and state transitions. - -use amplify::confinement::{Confined, TinyOrdMap, U8}; -use amplify::Wrapper; -use strict_encoding::StrictDumb; - -use super::data; -use crate::{schema, LIB_NAME_RGB}; - -#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, From)] -#[wrapper(Deref)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct FieldValues(Confined, 1, U8>); - -impl StrictDumb for FieldValues { - fn strict_dumb() -> Self { Self(confined_vec!(data::Revealed::strict_dumb())) } -} - -#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, Default, From)] -#[wrapper(Deref)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct Metadata(TinyOrdMap); diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 74902583..ea400c54 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -26,21 +26,19 @@ pub mod seal { pub mod value; pub mod attachment; pub mod data; -mod global_state; -pub mod owned_state; +pub mod state; mod assignments; mod operations; mod bundle; -pub use assignments::TypedAssignments; +pub use assignments::TypedState; pub use attachment::AttachId; pub use bundle::{BundleId, TransitionBundle}; -pub use global_state::{FieldValues, Metadata}; pub use operations::{ - ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, OutpointParseError, OwnedRights, - ParentOwnedRights, ParentPublicRights, PublicRights, Transition, + ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, OutpointParseError, OwnedState, + PrevState, Redeemed, Transition, Valencies, }; -pub use owned_state::{Assignment, State, StateType}; +pub use state::{AssignedState, FieldValues, GlobalState, StatePair, StateType}; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, ValueAtom, diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 4d953392..6f252735 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -33,7 +33,7 @@ use bp::seals::txout::TxoSeal; use bp::{Chain, Outpoint, Txid}; use commit_verify::{mpc, CommitStrategy, CommitmentId}; -use super::{seal, ConfidentialDataError, Metadata, TypedAssignments}; +use super::{seal, ConfidentialDataError, GlobalState, TypedState}; use crate::schema::{ self, ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, PublicRightType, SchemaId, TransitionType, @@ -88,10 +88,10 @@ impl FromStr for NodeOutpoint { } } -pub type PublicRights = TinyOrdSet; -pub type OwnedRights = TinyOrdMap; -pub type ParentOwnedRights = TinyOrdMap>>; -pub type ParentPublicRights = TinyOrdMap>; +pub type Valencies = TinyOrdSet; +pub type OwnedState = TinyOrdMap; +pub type PrevState = TinyOrdMap>>; +pub type Redeemed = TinyOrdMap>; /// Unique node (genesis, extensions & state transition) identifier equivalent /// to the commitment hash @@ -191,30 +191,30 @@ pub trait Node: AsAny { /// [`Option::None`] for genesis and trate transitions fn extension_type(&self) -> Option; - /// Returns reference to a full set of metadata (in form of [`Metadata`] + /// Returns reference to a full set of metadata (in form of [`GlobalState`] /// wrapper structure) for the contract node. - fn metadata(&self) -> &Metadata; + fn metadata(&self) -> &GlobalState; /// Returns reference to information about the owned rights in form of - /// [`ParentOwnedRights`] wrapper structure which this node updates with + /// [`PrevState`] wrapper structure which this node updates with /// state transition ("parent owned rights"). /// /// This is always an empty `Vec` for [`Genesis`] and [`Extension`] node /// types. - fn parent_owned_rights(&self) -> &ParentOwnedRights; + fn parent_owned_rights(&self) -> &PrevState; /// Returns reference to information about the public rights (in form of - /// [`ParentPublicRights`] wrapper structure), defined with "parent" state + /// [`Redeemed`] wrapper structure), defined with "parent" state /// extensions (i.e. those finalized with the current state transition) or /// referenced by another state extension, which this node updates /// ("parent public rights"). /// /// This is always an empty `Vec` for [`Genesis`]. - fn parent_public_rights(&self) -> &ParentPublicRights; - fn owned_rights(&self) -> &OwnedRights; - fn owned_rights_mut(&mut self) -> &mut OwnedRights; - fn public_rights(&self) -> &PublicRights; - fn public_rights_mut(&mut self) -> &mut PublicRights; + fn parent_public_rights(&self) -> &Redeemed; + fn owned_rights(&self) -> &OwnedState; + fn owned_rights_mut(&mut self) -> &mut OwnedState; + fn public_rights(&self) -> &Valencies; + fn public_rights_mut(&mut self) -> &mut Valencies; #[inline] fn field_types(&self) -> Vec { self.metadata().keys().copied().collect() } @@ -286,7 +286,7 @@ pub trait Node: AsAny { } #[inline] - fn owned_rights_by_type(&self, t: OwnedRightType) -> Option<&TypedAssignments> { + fn owned_rights_by_type(&self, t: OwnedRightType) -> Option<&TypedState> { self.owned_rights() .iter() .find_map(|(t2, a)| if *t2 == t { Some(a) } else { None }) @@ -324,7 +324,7 @@ pub trait Node: AsAny { ) -> Result, ConfidentialDataError> { Ok(self .owned_rights_by_type(assignment_type) - .map(TypedAssignments::revealed_seals) + .map(TypedState::revealed_seals) .transpose()? .unwrap_or_default()) } @@ -343,7 +343,7 @@ pub trait Node: AsAny { assignment_type: OwnedRightType, ) -> Vec { self.owned_rights_by_type(assignment_type) - .map(TypedAssignments::filter_revealed_seals) + .map(TypedState::filter_revealed_seals) .unwrap_or_else(Vec::new) } @@ -368,9 +368,9 @@ pub trait Node: AsAny { pub struct Genesis { schema_id: SchemaId, chain: Chain, - metadata: Metadata, - owned_rights: OwnedRights, - public_rights: PublicRights, + metadata: GlobalState, + owned_rights: OwnedState, + public_rights: Valencies, } #[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] @@ -380,10 +380,10 @@ pub struct Genesis { pub struct Extension { extension_type: ExtensionType, contract_id: ContractId, - metadata: Metadata, - owned_rights: OwnedRights, - parent_public_rights: ParentPublicRights, - public_rights: PublicRights, + metadata: GlobalState, + owned_rights: OwnedState, + parent_public_rights: Redeemed, + public_rights: Valencies, } #[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] @@ -392,10 +392,10 @@ pub struct Extension { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Transition { transition_type: TransitionType, - metadata: Metadata, - parent_owned_rights: ParentOwnedRights, - owned_rights: OwnedRights, - public_rights: PublicRights, + metadata: GlobalState, + parent_owned_rights: PrevState, + owned_rights: OwnedState, + public_rights: Valencies, } // TODO: Remove after TransitionBundling refactoring @@ -459,29 +459,27 @@ impl Node for Genesis { fn extension_type(&self) -> Option { None } #[inline] - fn parent_owned_rights(&self) -> &ParentOwnedRights { + fn parent_owned_rights(&self) -> &PrevState { panic!("genesis can't close previous single-use-seals") } #[inline] - fn parent_public_rights(&self) -> &ParentPublicRights { - panic!("genesis can't extend previous state") - } + fn parent_public_rights(&self) -> &Redeemed { panic!("genesis can't extend previous state") } #[inline] - fn metadata(&self) -> &Metadata { &self.metadata } + fn metadata(&self) -> &GlobalState { &self.metadata } #[inline] - fn owned_rights(&self) -> &OwnedRights { &self.owned_rights } + fn owned_rights(&self) -> &OwnedState { &self.owned_rights } #[inline] - fn owned_rights_mut(&mut self) -> &mut OwnedRights { &mut self.owned_rights } + fn owned_rights_mut(&mut self) -> &mut OwnedState { &mut self.owned_rights } #[inline] - fn public_rights(&self) -> &PublicRights { &self.public_rights } + fn public_rights(&self) -> &Valencies { &self.public_rights } #[inline] - fn public_rights_mut(&mut self) -> &mut PublicRights { &mut self.public_rights } + fn public_rights_mut(&mut self) -> &mut Valencies { &mut self.public_rights } } impl Node for Extension { @@ -504,27 +502,27 @@ impl Node for Extension { fn extension_type(&self) -> Option { Some(self.extension_type) } #[inline] - fn parent_owned_rights(&self) -> &ParentOwnedRights { + fn parent_owned_rights(&self) -> &PrevState { panic!("extension can't close previous single-use-seals") } #[inline] - fn parent_public_rights(&self) -> &ParentPublicRights { &self.parent_public_rights } + fn parent_public_rights(&self) -> &Redeemed { &self.parent_public_rights } #[inline] - fn metadata(&self) -> &Metadata { &self.metadata } + fn metadata(&self) -> &GlobalState { &self.metadata } #[inline] - fn owned_rights(&self) -> &OwnedRights { &self.owned_rights } + fn owned_rights(&self) -> &OwnedState { &self.owned_rights } #[inline] - fn owned_rights_mut(&mut self) -> &mut OwnedRights { &mut self.owned_rights } + fn owned_rights_mut(&mut self) -> &mut OwnedState { &mut self.owned_rights } #[inline] - fn public_rights(&self) -> &PublicRights { &self.public_rights } + fn public_rights(&self) -> &Valencies { &self.public_rights } #[inline] - fn public_rights_mut(&mut self) -> &mut PublicRights { &mut self.public_rights } + fn public_rights_mut(&mut self) -> &mut Valencies { &mut self.public_rights } } impl Node for Transition { @@ -547,36 +545,36 @@ impl Node for Transition { fn extension_type(&self) -> Option { None } #[inline] - fn parent_owned_rights(&self) -> &ParentOwnedRights { &self.parent_owned_rights } + fn parent_owned_rights(&self) -> &PrevState { &self.parent_owned_rights } #[inline] - fn parent_public_rights(&self) -> &ParentPublicRights { + fn parent_public_rights(&self) -> &Redeemed { panic!("state transitions can't extend previous state") } #[inline] - fn metadata(&self) -> &Metadata { &self.metadata } + fn metadata(&self) -> &GlobalState { &self.metadata } #[inline] - fn owned_rights(&self) -> &OwnedRights { &self.owned_rights } + fn owned_rights(&self) -> &OwnedState { &self.owned_rights } #[inline] - fn owned_rights_mut(&mut self) -> &mut OwnedRights { &mut self.owned_rights } + fn owned_rights_mut(&mut self) -> &mut OwnedState { &mut self.owned_rights } #[inline] - fn public_rights(&self) -> &PublicRights { &self.public_rights } + fn public_rights(&self) -> &Valencies { &self.public_rights } #[inline] - fn public_rights_mut(&mut self) -> &mut PublicRights { &mut self.public_rights } + fn public_rights_mut(&mut self) -> &mut Valencies { &mut self.public_rights } } impl Genesis { pub fn with( schema_id: SchemaId, chain: Chain, - metadata: Metadata, - owned_rights: OwnedRights, - public_rights: PublicRights, + metadata: GlobalState, + owned_rights: OwnedState, + public_rights: Valencies, ) -> Self { Self { schema_id, @@ -601,10 +599,10 @@ impl Extension { pub fn with( extension_type: ExtensionType, contract_id: ContractId, - metadata: Metadata, - owned_rights: OwnedRights, - parent_public_rights: ParentPublicRights, - public_rights: PublicRights, + metadata: GlobalState, + owned_rights: OwnedState, + parent_public_rights: Redeemed, + public_rights: Valencies, ) -> Self { Self { extension_type, @@ -620,10 +618,10 @@ impl Extension { impl Transition { pub fn with( transition_type: impl Into, - metadata: Metadata, - owned_rights: OwnedRights, - public_rights: PublicRights, - parent_owned_rights: ParentOwnedRights, + metadata: GlobalState, + owned_rights: OwnedState, + public_rights: Valencies, + parent_owned_rights: PrevState, ) -> Self { Self { transition_type: transition_type.into(), diff --git a/src/contract/owned_state.rs b/src/contract/state.rs similarity index 50% rename from src/contract/owned_state.rs rename to src/contract/state.rs index 0eee317f..b9f83d80 100644 --- a/src/contract/owned_state.rs +++ b/src/contract/state.rs @@ -24,12 +24,40 @@ use core::cmp::Ordering; use core::fmt::Debug; use std::io; +use amplify::confinement::{Confined, TinyOrdMap, U8}; +use amplify::Wrapper; use commit_verify::merkle::MerkleNode; use commit_verify::{CommitEncode, CommitmentId, Conceal}; -use strict_encoding::{StrictEncode, StrictWriter}; +use strict_encoding::{StrictDumb, StrictEncode, StrictWriter}; use super::{attachment, data, seal, value, ConfidentialState, RevealedState}; -use crate::LIB_NAME_RGB; +use crate::{schema, LIB_NAME_RGB}; + +#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, From)] +#[wrapper(Deref)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct FieldValues(Confined, 1, U8>); + +impl StrictDumb for FieldValues { + fn strict_dumb() -> Self { Self(confined_vec!(data::Revealed::strict_dumb())) } +} + +#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, Default, From)] +#[wrapper(Deref)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct GlobalState(TinyOrdMap); /// Categories of the state #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] @@ -39,43 +67,44 @@ pub enum StateType { /// Value-based state, i.e. which can be committed to with a Pedersen /// commitment - Value, + Fungible, /// State defined with custom data - Data, + Structured, /// Attached data container Attachment, } -pub trait State: Debug { + +pub trait StatePair: Debug { type Confidential: ConfidentialState; type Revealed: RevealedState; } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct DeclarativeStrategy; -impl State for DeclarativeStrategy { +pub struct DeclarativePair; +impl StatePair for DeclarativePair { type Confidential = data::Void; type Revealed = data::Void; } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct PedersenStrategy; -impl State for PedersenStrategy { +pub struct FungiblePair; +impl StatePair for FungiblePair { type Confidential = value::Confidential; type Revealed = value::Revealed; } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct HashStrategy; -impl State for HashStrategy { +pub struct StructuredPair; +impl StatePair for StructuredPair { type Confidential = data::Confidential; type Revealed = data::Revealed; } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] -pub struct AttachmentStrategy; -impl State for AttachmentStrategy { +pub struct AttachmentPair; +impl StatePair for AttachmentPair { type Confidential = attachment::Confidential; type Revealed = attachment::Revealed; } @@ -95,33 +124,33 @@ impl State for AttachmentStrategy { derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "snake_case") )] -pub enum Assignment +pub enum AssignedState where - StateType: State, + Pair: StatePair, // Deterministic ordering requires Eq operation, so the confidential // state must have it - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { #[strict_type(tag = 0x00)] Confidential { seal: seal::Confidential, - state: StateType::Confidential, + state: Pair::Confidential, }, #[strict_type(tag = 0x04)] Revealed { seal: seal::Revealed, - state: StateType::Revealed, + state: Pair::Revealed, }, #[strict_type(tag = 0x02)] ConfidentialSeal { seal: seal::Confidential, - state: StateType::Revealed, + state: Pair::Revealed, }, #[strict_type(tag = 0x01)] ConfidentialState { seal: seal::Revealed, - state: StateType::Confidential, + state: Pair::Confidential, }, } @@ -129,11 +158,11 @@ where // Assignment indexes are part of the transition ancestor's commitment, so // here we use deterministic ordering based on hash values of the concealed // seal data contained within the assignment -impl PartialOrd for Assignment +impl PartialOrd for AssignedState where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { fn partial_cmp(&self, other: &Self) -> Option { self.to_confidential_seal() @@ -141,11 +170,11 @@ where } } -impl Ord for Assignment +impl Ord for AssignedState where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { fn cmp(&self, other: &Self) -> Ordering { self.to_confidential_seal() @@ -153,11 +182,11 @@ where } } -impl PartialEq for Assignment +impl PartialEq for AssignedState where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { fn eq(&self, other: &Self) -> bool { self.to_confidential_seal() == other.to_confidential_seal() && @@ -165,33 +194,35 @@ where } } -impl Eq for Assignment +impl Eq for AssignedState where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { } -impl Assignment +impl AssignedState where - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { - pub fn revealed(seal: seal::Revealed, state: StateType::Revealed) -> Self { - Assignment::Revealed { seal, state } + pub fn revealed(seal: seal::Revealed, state: Pair::Revealed) -> Self { + AssignedState::Revealed { seal, state } } pub fn with_seal_replaced(assignment: &Self, seal: seal::Revealed) -> Self { match assignment { - Assignment::Confidential { seal: _, state } | - Assignment::ConfidentialState { seal: _, state } => Assignment::ConfidentialState { - seal, - state: state.clone(), - }, - Assignment::ConfidentialSeal { seal: _, state } | - Assignment::Revealed { seal: _, state } => Assignment::Revealed { + AssignedState::Confidential { seal: _, state } | + AssignedState::ConfidentialState { seal: _, state } => { + AssignedState::ConfidentialState { + seal, + state: state.clone(), + } + } + AssignedState::ConfidentialSeal { seal: _, state } | + AssignedState::Revealed { seal: _, state } => AssignedState::Revealed { seal, state: state.clone(), }, @@ -200,86 +231,81 @@ where pub fn to_confidential_seal(&self) -> seal::Confidential { match self { - Assignment::Revealed { seal, .. } | Assignment::ConfidentialState { seal, .. } => { - seal.conceal() - } - Assignment::Confidential { seal, .. } | Assignment::ConfidentialSeal { seal, .. } => { - *seal - } + AssignedState::Revealed { seal, .. } | + AssignedState::ConfidentialState { seal, .. } => seal.conceal(), + AssignedState::Confidential { seal, .. } | + AssignedState::ConfidentialSeal { seal, .. } => *seal, } } pub fn revealed_seal(&self) -> Option { match self { - Assignment::Revealed { seal, .. } | Assignment::ConfidentialState { seal, .. } => { - Some(*seal) - } - Assignment::Confidential { .. } | Assignment::ConfidentialSeal { .. } => None, + AssignedState::Revealed { seal, .. } | + AssignedState::ConfidentialState { seal, .. } => Some(*seal), + AssignedState::Confidential { .. } | AssignedState::ConfidentialSeal { .. } => None, } } - pub fn to_confidential_state(&self) -> StateType::Confidential { + pub fn to_confidential_state(&self) -> Pair::Confidential { match self { - Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { - state.conceal().into() - } - Assignment::Confidential { state, .. } | - Assignment::ConfidentialState { state, .. } => state.clone(), + AssignedState::Revealed { state, .. } | + AssignedState::ConfidentialSeal { state, .. } => state.conceal().into(), + AssignedState::Confidential { state, .. } | + AssignedState::ConfidentialState { state, .. } => state.clone(), } } - pub fn as_revealed_state(&self) -> Option<&StateType::Revealed> { + pub fn as_revealed_state(&self) -> Option<&Pair::Revealed> { match self { - Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { - Some(state) - } - Assignment::Confidential { .. } | Assignment::ConfidentialState { .. } => None, + AssignedState::Revealed { state, .. } | + AssignedState::ConfidentialSeal { state, .. } => Some(state), + AssignedState::Confidential { .. } | AssignedState::ConfidentialState { .. } => None, } } - pub fn as_revealed(&self) -> Option<(&seal::Revealed, &StateType::Revealed)> { + pub fn as_revealed(&self) -> Option<(&seal::Revealed, &Pair::Revealed)> { match self { - Assignment::Revealed { seal, state } => Some((seal, state)), + AssignedState::Revealed { seal, state } => Some((seal, state)), _ => None, } } - pub fn to_revealed(&self) -> Option<(seal::Revealed, StateType::Revealed)> { + pub fn to_revealed(&self) -> Option<(seal::Revealed, Pair::Revealed)> { match self { - Assignment::Revealed { seal, state } => Some((*seal, state.clone())), + AssignedState::Revealed { seal, state } => Some((*seal, state.clone())), _ => None, } } - pub fn into_revealed(self) -> Option<(seal::Revealed, StateType::Revealed)> { + pub fn into_revealed(self) -> Option<(seal::Revealed, Pair::Revealed)> { match self { - Assignment::Revealed { seal, state } => Some((seal, state)), + AssignedState::Revealed { seal, state } => Some((seal, state)), _ => None, } } } -impl Conceal for Assignment +impl Conceal for AssignedState where Self: Clone, - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { type Concealed = Self; fn conceal(&self) -> Self::Concealed { match self { - Assignment::Confidential { .. } => self.clone(), - Assignment::ConfidentialState { seal, state } => Self::Confidential { + AssignedState::Confidential { .. } => self.clone(), + AssignedState::ConfidentialState { seal, state } => Self::Confidential { seal: seal.conceal(), state: state.clone(), }, - Assignment::Revealed { seal, state } => Self::Confidential { + AssignedState::Revealed { seal, state } => Self::Confidential { seal: seal.conceal(), state: state.conceal().into(), }, - Assignment::ConfidentialSeal { seal, state } => Self::Confidential { + AssignedState::ConfidentialSeal { seal, state } => Self::Confidential { seal: *seal, state: state.conceal().into(), }, @@ -291,12 +317,12 @@ where // `commit_encode` of the concealed type, and here the concealed type is again // `OwnedState`, leading to a recurrency. So we use `strict_encode` of the // concealed data. -impl CommitEncode for Assignment +impl CommitEncode for AssignedState where Self: Clone, - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { fn commit_encode(&self, e: &mut impl io::Write) { let w = StrictWriter::with(u32::MAX as usize, e); @@ -304,12 +330,12 @@ where } } -impl CommitmentId for Assignment +impl CommitmentId for AssignedState where Self: Clone, - StateType: State, - StateType::Confidential: PartialEq + Eq, - StateType::Confidential: From<::Concealed>, + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { const TAG: [u8; 32] = *b"urn:lnpbp:rgb:owned-state:v1#23A"; type Id = MerkleNode; diff --git a/src/validation/model.rs b/src/validation/model.rs index e99a1285..088edd29 100644 --- a/src/validation/model.rs +++ b/src/validation/model.rs @@ -30,8 +30,8 @@ use crate::schema::{MetadataStructure, OwnedRightsStructure, PublicRightsStructu use crate::validation::vm::VirtualMachine; use crate::vm::AluRuntime; use crate::{ - validation, Assignment, FieldValues, Metadata, Node, NodeId, NodeSubtype, OwnedRights, - ParentOwnedRights, ParentPublicRights, PublicRights, Schema, Script, State, TypedAssignments, + validation, AssignedState, FieldValues, GlobalState, Node, NodeId, NodeSubtype, OwnedState, + PrevState, Redeemed, Schema, Script, StatePair, TypedState, Valencies, }; impl Schema { @@ -186,7 +186,7 @@ impl Schema { fn validate_meta( &self, node_id: NodeId, - metadata: &Metadata, + metadata: &GlobalState, metadata_structure: &MetadataStructure, ) -> validation::Status { let mut status = validation::Status::new(); @@ -240,7 +240,7 @@ impl Schema { fn validate_parent_owned_rights( &self, node_id: NodeId, - owned_rights: &OwnedRights, + owned_rights: &OwnedState, owned_rights_structure: &OwnedRightsStructure, ) -> validation::Status { let mut status = validation::Status::new(); @@ -259,7 +259,7 @@ impl Schema { for (owned_type_id, occ) in owned_rights_structure { let len = owned_rights .get(owned_type_id) - .map(TypedAssignments::len) + .map(TypedState::len) .unwrap_or(0); // Checking number of ancestor's assignment occurrences @@ -278,7 +278,7 @@ impl Schema { fn validate_parent_public_rights( &self, node_id: NodeId, - public_rights: &PublicRights, + public_rights: &Valencies, public_rights_structure: &PublicRightsStructure, ) -> validation::Status { let mut status = validation::Status::new(); @@ -298,7 +298,7 @@ impl Schema { fn validate_owned_rights( &self, node_id: NodeId, - owned_rights: &OwnedRights, + owned_rights: &OwnedState, owned_rights_structure: &OwnedRightsStructure, ) -> validation::Status { let mut status = validation::Status::new(); @@ -317,7 +317,7 @@ impl Schema { for (owned_type_id, occ) in owned_rights_structure { let len = owned_rights .get(owned_type_id) - .map(TypedAssignments::len) + .map(TypedState::len) .unwrap_or(0); // Checking number of assignment occurrences @@ -336,16 +336,16 @@ impl Schema { match owned_rights.get(owned_type_id) { None => {} - Some(TypedAssignments::Void(set)) => set + Some(TypedState::Declarative(set)) => set .iter() .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), - Some(TypedAssignments::Value(set)) => set + Some(TypedState::Fungible(set)) => set .iter() .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), - Some(TypedAssignments::Data(set)) => set + Some(TypedState::Structured(set)) => set .iter() .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), - Some(TypedAssignments::Attachment(set)) => set + Some(TypedState::Attachment(set)) => set .iter() .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), }; @@ -357,7 +357,7 @@ impl Schema { fn validate_public_rights( &self, node_id: NodeId, - public_rights: &PublicRights, + public_rights: &Valencies, public_rights_structure: &PublicRightsStructure, ) -> validation::Status { let mut status = validation::Status::new(); @@ -379,11 +379,11 @@ impl Schema { &self, node_id: NodeId, node_subtype: NodeSubtype, - parent_owned_rights: &OwnedRights, - owned_rights: &OwnedRights, - parent_public_rights: &PublicRights, - public_rights: &PublicRights, - metadata: &Metadata, + parent_owned_rights: &OwnedState, + owned_rights: &OwnedState, + parent_public_rights: &Valencies, + public_rights: &Valencies, + metadata: &GlobalState, script: &Script, ) -> validation::Status { let mut status = validation::Status::new(); @@ -413,9 +413,9 @@ impl Schema { fn extract_parent_owned_rights( nodes: &BTreeMap, - parent_owned_rights: &ParentOwnedRights, + parent_owned_rights: &PrevState, status: &mut validation::Status, -) -> OwnedRights { +) -> OwnedState { let mut owned_rights = bmap! {}; for (id, details) in parent_owned_rights.iter() { let parent_node = match nodes.get(id) { @@ -426,9 +426,9 @@ fn extract_parent_owned_rights( Some(node) => node, }; - fn filter(set: &[Assignment], indexes: &[u16]) -> Vec> + fn filter(set: &[AssignedState], indexes: &[u16]) -> Vec> where - STATE: State + Clone, + STATE: StatePair + Clone, STATE::Confidential: PartialEq + Eq, STATE::Confidential: From<::Concealed>, { @@ -446,42 +446,42 @@ fn extract_parent_owned_rights( for (type_id, indexes) in details { match parent_node.owned_rights_by_type(*type_id) { - Some(TypedAssignments::Void(set)) => { + Some(TypedState::Declarative(set)) => { let set = filter(set, indexes); if let Some(state) = owned_rights .entry(*type_id) - .or_insert_with(|| TypedAssignments::Void(Default::default())) - .as_declarative_assignments_mut() + .or_insert_with(|| TypedState::Declarative(Default::default())) + .as_declarative_mut() { state.extend(set).expect("same size"); } } - Some(TypedAssignments::Value(set)) => { + Some(TypedState::Fungible(set)) => { let set = filter(set, indexes); if let Some(state) = owned_rights .entry(*type_id) - .or_insert_with(|| TypedAssignments::Value(Default::default())) - .as_value_assignments_mut() + .or_insert_with(|| TypedState::Fungible(Default::default())) + .as_fungible_mut() { state.extend(set).expect("same size"); } } - Some(TypedAssignments::Data(set)) => { + Some(TypedState::Structured(set)) => { let set = filter(set, indexes); if let Some(state) = owned_rights .entry(*type_id) - .or_insert_with(|| TypedAssignments::Data(Default::default())) - .as_data_assignments_mut() + .or_insert_with(|| TypedState::Structured(Default::default())) + .as_structured_mut() { state.extend(set).expect("same size"); } } - Some(TypedAssignments::Attachment(set)) => { + Some(TypedState::Attachment(set)) => { let set = filter(set, indexes); if let Some(state) = owned_rights .entry(*type_id) - .or_insert_with(|| TypedAssignments::Attachment(Default::default())) - .as_attachment_assignments_mut() + .or_insert_with(|| TypedState::Attachment(Default::default())) + .as_attachment_mut() { state.extend(set).expect("same size"); } @@ -500,10 +500,10 @@ fn extract_parent_owned_rights( fn extract_parent_public_rights( nodes: &BTreeMap, - parent_public_rights: &ParentPublicRights, + parent_public_rights: &Redeemed, status: &mut validation::Status, -) -> PublicRights { - let mut public_rights = PublicRights::default(); +) -> Valencies { + let mut public_rights = Valencies::default(); for (id, public_right_types) in parent_public_rights.iter() { if nodes.get(id).is_none() { status.add_failure(validation::Failure::TransitionAbsent(*id)); diff --git a/src/validation/state.rs b/src/validation/state.rs index 3e86c3bf..960dbe77 100644 --- a/src/validation/state.rs +++ b/src/validation/state.rs @@ -25,11 +25,9 @@ use core::any::Any; use amplify::AsAny; use commit_verify::Conceal; -use crate::contract::owned_state::{ - AttachmentStrategy, DeclarativeStrategy, HashStrategy, PedersenStrategy, -}; +use crate::contract::state::{AttachmentPair, DeclarativePair, FungiblePair, StructuredPair}; use crate::schema::OwnedRightType; -use crate::{validation, Assignment, NodeId, State, StateSchema}; +use crate::{validation, AssignedState, NodeId, StatePair, StateSchema}; impl StateSchema { pub fn validate( @@ -37,21 +35,21 @@ impl StateSchema { // type_system: &TypeSystem, node_id: &NodeId, assignment_id: OwnedRightType, - data: &Assignment, + data: &AssignedState, ) -> validation::Status where - STATE: State, + STATE: StatePair, STATE::Confidential: PartialEq + Eq, STATE::Confidential: From<::Concealed>, { let mut status = validation::Status::new(); match data { - Assignment::Confidential { state, .. } | - Assignment::ConfidentialState { state, .. } => { + AssignedState::Confidential { state, .. } | + AssignedState::ConfidentialState { state, .. } => { let a: &dyn Any = state.as_any(); match self { StateSchema::Declarative => { - if a.downcast_ref::<::Confidential>() + if a.downcast_ref::<::Confidential>() .is_none() { status.add_failure(validation::Failure::SchemaMismatchedStateType( @@ -61,7 +59,7 @@ impl StateSchema { } StateSchema::Arithmetic(_) => { if let Some(value) = - a.downcast_ref::<::Confidential>() + a.downcast_ref::<::Confidential>() { // [SECURITY-CRITICAL]: Bulletproofs validation if let Err(err) = value.verify_range_proof() { @@ -81,25 +79,23 @@ impl StateSchema { // add information to the status like with hashed // data below } - StateSchema::Structured(_) => { - match a.downcast_ref::<::Confidential>() { - None => { - status.add_failure(validation::Failure::SchemaMismatchedStateType( - assignment_id, - )); - } - Some(_) => { - status.add_info( - validation::Info::UncheckableConfidentialStateData( - *node_id, - assignment_id, - ), - ); - } + StateSchema::Structured(_) => match a + .downcast_ref::<::Confidential>() + { + None => { + status.add_failure(validation::Failure::SchemaMismatchedStateType( + assignment_id, + )); } - } + Some(_) => { + status.add_info(validation::Info::UncheckableConfidentialStateData( + *node_id, + assignment_id, + )); + } + }, StateSchema::Attachment => { - if a.downcast_ref::<::Confidential>() + if a.downcast_ref::<::Confidential>() .is_none() { status.add_failure(validation::Failure::SchemaMismatchedStateType( @@ -109,11 +105,12 @@ impl StateSchema { } } } - Assignment::Revealed { state, .. } | Assignment::ConfidentialSeal { state, .. } => { + AssignedState::Revealed { state, .. } | + AssignedState::ConfidentialSeal { state, .. } => { let a: &dyn Any = state.as_any(); match self { StateSchema::Declarative => { - if a.downcast_ref::<::Revealed>() + if a.downcast_ref::<::Revealed>() .is_none() { status.add_failure(validation::Failure::SchemaMismatchedStateType( @@ -122,7 +119,7 @@ impl StateSchema { } } StateSchema::Arithmetic(_format) => { - if a.downcast_ref::<::Revealed>() + if a.downcast_ref::<::Revealed>() .is_none() { status.add_failure(validation::Failure::SchemaMismatchedStateType( @@ -134,7 +131,7 @@ impl StateSchema { // like with hashed data below } StateSchema::Structured(_semid) => { - match a.downcast_ref::<::Revealed>() { + match a.downcast_ref::<::Revealed>() { None => { status.add_failure(validation::Failure::SchemaMismatchedStateType( assignment_id, @@ -146,7 +143,7 @@ impl StateSchema { } } StateSchema::Attachment => { - if a.downcast_ref::<::Revealed>() + if a.downcast_ref::<::Revealed>() .is_none() { status.add_failure(validation::Failure::SchemaMismatchedStateType( diff --git a/src/validation/verify.rs b/src/validation/verify.rs index a07097ef..bfbd9828 100644 --- a/src/validation/verify.rs +++ b/src/validation/verify.rs @@ -33,7 +33,7 @@ use super::{Failure, Status, Validity, Warning}; use crate::validation::subschema::SchemaVerify; use crate::{ schema, seal, BundleId, ContractId, Extension, Node, NodeId, Schema, SchemaId, - TransitionBundle, TypedAssignments, + TransitionBundle, TypedState, }; #[derive(Debug, Display, Error)] @@ -455,7 +455,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> node_id: NodeId, ancestor_id: NodeId, assignment_type: schema::OwnedRightType, - variant: &'consignment TypedAssignments, + variant: &'consignment TypedState, seal_index: u16, ) { // Getting bitcoin transaction outpoint for the current ancestor ... -> diff --git a/src/validation/vm.rs b/src/validation/vm.rs index 61c8cefe..8086f58c 100644 --- a/src/validation/vm.rs +++ b/src/validation/vm.rs @@ -22,7 +22,7 @@ use crate::validation::Failure; use crate::vm::AluRuntime; -use crate::{validation, Metadata, NodeId, NodeSubtype, OwnedRights, PublicRights, Script}; +use crate::{validation, GlobalState, NodeId, NodeSubtype, OwnedState, Script, Valencies}; /// Trait for concrete types wrapping virtual machines to be used from inside /// RGB schema validation routines. @@ -33,11 +33,11 @@ pub trait VirtualMachine { &self, node_id: NodeId, node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - previous_public_rights: &PublicRights, - current_public_rights: &PublicRights, - current_meta: &Metadata, + previous_owned_rights: &OwnedState, + current_owned_rights: &OwnedState, + previous_public_rights: &Valencies, + current_public_rights: &Valencies, + current_meta: &GlobalState, ) -> Result<(), validation::Failure>; } @@ -46,11 +46,11 @@ impl VirtualMachine for Script { &self, node_id: NodeId, node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - previous_public_rights: &PublicRights, - current_public_rights: &PublicRights, - current_meta: &Metadata, + previous_owned_rights: &OwnedState, + current_owned_rights: &OwnedState, + previous_public_rights: &Valencies, + current_public_rights: &Valencies, + current_meta: &GlobalState, ) -> Result<(), validation::Failure> { match self { Script::AluVM(script) => AluRuntime::new(script).validate( @@ -72,11 +72,11 @@ impl<'script> VirtualMachine for AluRuntime<'script> { &self, node_id: NodeId, node_subtype: NodeSubtype, - previous_owned_rights: &OwnedRights, - current_owned_rights: &OwnedRights, - previous_public_rights: &PublicRights, - current_public_rights: &PublicRights, - current_meta: &Metadata, + previous_owned_rights: &OwnedState, + current_owned_rights: &OwnedState, + previous_public_rights: &Valencies, + current_public_rights: &Valencies, + current_meta: &GlobalState, ) -> Result<(), Failure> { // TODO: Implement validation with AluVM /* From 217e67ea450d9fe1a11a01fe088629d5aa5678b8 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 02:30:12 +0100 Subject: [PATCH 61/71] state: remove unused APIs to standard library --- src/contract/assignments.rs | 311 ++++-------------------------------- src/contract/operations.rs | 67 +------- 2 files changed, 35 insertions(+), 343 deletions(-) diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs index 310a5868..7cf833b2 100644 --- a/src/contract/assignments.rs +++ b/src/contract/assignments.rs @@ -20,15 +20,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::vec; + use amplify::confinement::MediumVec; -use commit_verify::merkle::MerkleNode; +use commit_verify::merkle::{MerkleLeaves, MerkleNode}; use commit_verify::CommitmentId; use super::state::{AttachmentPair, DeclarativePair, FungiblePair, StructuredPair}; -use super::{ - attachment, data, seal, value, AssignedState, ConfidentialDataError, StateRetrievalError, - StateType, UnknownDataError, -}; +use super::{seal, AssignedState, StateType, UnknownDataError}; use crate::LIB_NAME_RGB; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -52,6 +51,24 @@ pub enum TypedState { } impl TypedState { + pub fn is_empty(&self) -> bool { + match self { + TypedState::Declarative(set) => set.is_empty(), + TypedState::Fungible(set) => set.is_empty(), + TypedState::Structured(set) => set.is_empty(), + TypedState::Attachment(set) => set.is_empty(), + } + } + + pub fn len(&self) -> usize { + match self { + TypedState::Declarative(set) => set.len(), + TypedState::Fungible(set) => set.len(), + TypedState::Structured(set) => set.len(), + TypedState::Attachment(set) => set.len(), + } + } + #[inline] pub fn state_type(&self) -> StateType { match self { @@ -138,35 +155,6 @@ impl TypedState { } } - pub fn revealed_seal_outputs(&self) -> Vec<(seal::Revealed, u16)> { - match self { - TypedState::Declarative(s) => s - .iter() - .map(AssignedState::<_>::revealed_seal) - .enumerate() - .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) - .collect(), - TypedState::Fungible(s) => s - .iter() - .map(AssignedState::<_>::revealed_seal) - .enumerate() - .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) - .collect(), - TypedState::Structured(s) => s - .iter() - .map(AssignedState::<_>::revealed_seal) - .enumerate() - .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) - .collect(), - TypedState::Attachment(s) => s - .iter() - .map(AssignedState::<_>::revealed_seal) - .enumerate() - .filter_map(|(no, seal)| seal.map(|s| (s, no as u16))) - .collect(), - } - } - /// If seal definition does not exist, returns [`UnknownDataError`]. If the /// seal is confidential, returns `Ok(None)`; otherwise returns revealed /// seal data packed as `Ok(Some(`[`seal::Revealed`]`))` @@ -191,42 +179,6 @@ impl TypedState { }) } - pub fn revealed_seals(&self) -> Result, ConfidentialDataError> { - let list: Vec<_> = match self { - TypedState::Declarative(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), - TypedState::Fungible(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), - TypedState::Structured(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), - TypedState::Attachment(s) => s.iter().map(AssignedState::<_>::revealed_seal).collect(), - }; - let len = list.len(); - let filtered: Vec = list.into_iter().flatten().collect(); - if len != filtered.len() { - return Err(ConfidentialDataError); - } - Ok(filtered) - } - - pub fn filter_revealed_seals(&self) -> Vec { - match self { - TypedState::Declarative(s) => s - .iter() - .filter_map(AssignedState::<_>::revealed_seal) - .collect(), - TypedState::Fungible(s) => s - .iter() - .filter_map(AssignedState::<_>::revealed_seal) - .collect(), - TypedState::Structured(s) => s - .iter() - .filter_map(AssignedState::<_>::revealed_seal) - .collect(), - TypedState::Attachment(s) => s - .iter() - .filter_map(AssignedState::<_>::revealed_seal) - .collect(), - } - } - pub fn to_confidential_seals(&self) -> Vec { match self { TypedState::Declarative(s) => s @@ -247,230 +199,31 @@ impl TypedState { .collect(), } } +} - // -------------------- - - pub fn revealed_fungible_state(&self) -> Result, StateRetrievalError> { - let list = match self { - TypedState::Fungible(s) => s.iter().map(AssignedState::<_>::as_revealed_state), - _ => return Err(StateRetrievalError::StateTypeMismatch), - }; - let len = list.len(); - let filtered: Vec<&value::Revealed> = list.flatten().collect(); - if len != filtered.len() { - return Err(StateRetrievalError::ConfidentialData); - } - Ok(filtered) - } - - pub fn revealed_structured_state(&self) -> Result, StateRetrievalError> { - let list = match self { - TypedState::Structured(s) => s.iter().map(AssignedState::<_>::as_revealed_state), - _ => return Err(StateRetrievalError::StateTypeMismatch), - }; - let len = list.len(); - let filtered: Vec<&data::Revealed> = list.flatten().collect(); - if len != filtered.len() { - return Err(StateRetrievalError::ConfidentialData); - } - Ok(filtered) - } - - pub fn revealed_attachments(&self) -> Result, StateRetrievalError> { - let list = match self { - TypedState::Attachment(s) => s.iter().map(AssignedState::<_>::as_revealed_state), - _ => return Err(StateRetrievalError::StateTypeMismatch), - }; - let len = list.len(); - let filtered: Vec<&attachment::Revealed> = list.flatten().collect(); - if len != filtered.len() { - return Err(StateRetrievalError::ConfidentialData); - } - Ok(filtered) - } - - pub fn filter_revealed_fungible_state(&self) -> Vec<&value::Revealed> { - match self { - TypedState::Declarative(_) => vec![], - TypedState::Fungible(s) => s - .iter() - .filter_map(AssignedState::<_>::as_revealed_state) - .collect(), - TypedState::Structured(_) => vec![], - TypedState::Attachment(_) => vec![], - } - } - - pub fn filter_revealed_structured_state(&self) -> Vec<&data::Revealed> { - match self { - TypedState::Declarative(_) => vec![], - TypedState::Fungible(_) => vec![], - TypedState::Structured(s) => s - .iter() - .filter_map(AssignedState::<_>::as_revealed_state) - .collect(), - TypedState::Attachment(_) => vec![], - } - } - - pub fn filter_revealed_attachments(&self) -> Vec<&attachment::Revealed> { - match self { - TypedState::Declarative(_) => vec![], - TypedState::Fungible(_) => vec![], - TypedState::Structured(_) => vec![], - TypedState::Attachment(s) => s - .iter() - .filter_map(AssignedState::<_>::as_revealed_state) - .collect(), - } - } - - pub fn to_confidential_fungible_state(&self) -> Vec { - match self { - TypedState::Declarative(_) => vec![], - TypedState::Fungible(s) => s - .iter() - .map(AssignedState::<_>::to_confidential_state) - .collect(), - TypedState::Structured(_) => vec![], - TypedState::Attachment(_) => vec![], - } - } - - pub fn to_confidential_structured_state(&self) -> Vec { - match self { - TypedState::Declarative(_) => vec![], - TypedState::Fungible(_) => vec![], - TypedState::Structured(s) => s - .iter() - .map(AssignedState::<_>::to_confidential_state) - .collect(), - TypedState::Attachment(_) => vec![], - } - } - - pub fn to_confidential_attachments(&self) -> Vec { - match self { - TypedState::Declarative(_) => vec![], - TypedState::Fungible(_) => vec![], - TypedState::Structured(_) => vec![], - TypedState::Attachment(s) => s - .iter() - .map(AssignedState::<_>::to_confidential_state) - .collect(), - } - } - - #[inline] - pub fn revealed_fungible_assignments( - &self, - ) -> Result, StateRetrievalError> { - match self { - TypedState::Fungible(vec) => { - let unfiltered: Vec<_> = vec - .iter() - .filter_map(|assignment| { - assignment.revealed_seal().and_then(|seal| { - assignment.as_revealed_state().map(|state| (seal, state)) - }) - }) - .collect(); - if unfiltered.len() != vec.len() { - Err(StateRetrievalError::ConfidentialData) - } else { - Ok(unfiltered) - } - } - _ => Err(StateRetrievalError::StateTypeMismatch), - } - } - - #[inline] - pub fn revealed_structured_assignments( - &self, - ) -> Result, StateRetrievalError> { - match self { - TypedState::Structured(vec) => { - let unfiltered: Vec<_> = vec - .iter() - .filter_map(|assignment| { - assignment.revealed_seal().and_then(|seal| { - assignment.as_revealed_state().map(|state| (seal, state)) - }) - }) - .collect(); - if unfiltered.len() != vec.len() { - Err(StateRetrievalError::ConfidentialData) - } else { - Ok(unfiltered) - } - } - _ => Err(StateRetrievalError::StateTypeMismatch), - } - } - - #[inline] - pub fn revealed_attachment_assignments( - &self, - ) -> Result, StateRetrievalError> { - match self { - TypedState::Attachment(vec) => { - let unfiltered: Vec<_> = vec - .iter() - .filter_map(|assignment| { - assignment.revealed_seal().and_then(|seal| { - assignment.as_revealed_state().map(|state| (seal, state)) - }) - }) - .collect(); - if unfiltered.len() != vec.len() { - Err(StateRetrievalError::ConfidentialData) - } else { - Ok(unfiltered) - } - } - _ => Err(StateRetrievalError::StateTypeMismatch), - } - } - - // --------------- - - pub fn is_empty(&self) -> bool { - match self { - TypedState::Declarative(set) => set.is_empty(), - TypedState::Fungible(set) => set.is_empty(), - TypedState::Structured(set) => set.is_empty(), - TypedState::Attachment(set) => set.is_empty(), - } - } - - pub fn len(&self) -> usize { - match self { - TypedState::Declarative(set) => set.len(), - TypedState::Fungible(set) => set.len(), - TypedState::Structured(set) => set.len(), - TypedState::Attachment(set) => set.len(), - } - } +impl MerkleLeaves for TypedState { + type Leaf = MerkleNode; + type LeafIter = vec::IntoIter; - pub fn commitment_leaves(&self) -> Vec { + fn merkle_leaves(&self) -> Self::LeafIter { match self { TypedState::Declarative(vec) => vec .iter() .map(AssignedState::::commitment_id) - .collect(), + .collect::>(), TypedState::Fungible(vec) => vec .iter() .map(AssignedState::::commitment_id) - .collect(), + .collect::>(), TypedState::Structured(vec) => vec .iter() .map(AssignedState::::commitment_id) - .collect(), + .collect::>(), TypedState::Attachment(vec) => vec .iter() .map(AssignedState::::commitment_id) - .collect(), + .collect::>(), } + .into_iter() } } diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 6f252735..37afb15a 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -21,7 +21,7 @@ // limitations under the License. use std::cmp::Ordering; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeSet; use std::num::ParseIntError; use std::str::FromStr; @@ -29,11 +29,10 @@ use amplify::confinement::{TinyOrdMap, TinyOrdSet, TinyVec}; use amplify::hex::{FromHex, ToHex}; use amplify::{hex, AsAny, Bytes32, RawArray, Wrapper}; use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; -use bp::seals::txout::TxoSeal; -use bp::{Chain, Outpoint, Txid}; +use bp::Chain; use commit_verify::{mpc, CommitStrategy, CommitmentId}; -use super::{seal, ConfidentialDataError, GlobalState, TypedState}; +use super::{seal, GlobalState, TypedState}; use crate::schema::{ self, ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, PublicRightType, SchemaId, TransitionType, @@ -299,66 +298,6 @@ pub trait Node: AsAny { .flat_map(|(_, assignment)| assignment.to_confidential_seals()) .collect() } - - #[inline] - fn revealed_seals(&self) -> Result, ConfidentialDataError> { - let unfiltered = self - .owned_rights() - .iter() - .map(|(_, assignment)| assignment.revealed_seals()) - .collect::>(); - if unfiltered.contains(&Err(ConfidentialDataError)) { - return Err(ConfidentialDataError); - } - Ok(unfiltered - .into_iter() - .filter_map(Result::ok) - .flat_map(Vec::into_iter) - .collect()) - } - - #[inline] - fn revealed_seals_by_type( - &self, - assignment_type: OwnedRightType, - ) -> Result, ConfidentialDataError> { - Ok(self - .owned_rights_by_type(assignment_type) - .map(TypedState::revealed_seals) - .transpose()? - .unwrap_or_default()) - } - - #[inline] - fn filter_revealed_seals(&self) -> Vec { - self.owned_rights() - .iter() - .flat_map(|(_, assignment)| assignment.filter_revealed_seals()) - .collect() - } - - #[inline] - fn filter_revealed_seals_by_type( - &self, - assignment_type: OwnedRightType, - ) -> Vec { - self.owned_rights_by_type(assignment_type) - .map(TypedState::filter_revealed_seals) - .unwrap_or_else(Vec::new) - } - - fn node_outputs(&self, witness_txid: Txid) -> BTreeMap { - let node_id = self.node_id(); - let mut res: BTreeMap = bmap! {}; - for (ty, assignments) in self.owned_rights() { - for (seal, node_output) in assignments.revealed_seal_outputs() { - let outpoint = seal.outpoint_or(witness_txid); - let node_outpoint = NodeOutpoint::new(node_id, *ty, node_output); - res.insert(node_outpoint, outpoint); - } - } - res - } } #[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] From e0867dd69e59beb34676fb876a469bc49c7b1d36 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 02:32:21 +0100 Subject: [PATCH 62/71] state: move TypedState to the state module --- src/contract/assignments.rs | 229 ------------------------------------ src/contract/mod.rs | 4 +- src/contract/state.rs | 206 +++++++++++++++++++++++++++++++- 3 files changed, 203 insertions(+), 236 deletions(-) delete mode 100644 src/contract/assignments.rs diff --git a/src/contract/assignments.rs b/src/contract/assignments.rs deleted file mode 100644 index 7cf833b2..00000000 --- a/src/contract/assignments.rs +++ /dev/null @@ -1,229 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2023 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2023 Dr Maxim Orlovsky. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::vec; - -use amplify::confinement::MediumVec; -use commit_verify::merkle::{MerkleLeaves, MerkleNode}; -use commit_verify::CommitmentId; - -use super::state::{AttachmentPair, DeclarativePair, FungiblePair, StructuredPair}; -use super::{seal, AssignedState, StateType, UnknownDataError}; -use crate::LIB_NAME_RGB; - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = Self::Declarative(strict_dumb!()))] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "snake_case") -)] -pub enum TypedState { - // TODO: Consider using non-empty variants - #[strict_type(tag = 0x00)] - Declarative(MediumVec>), - #[strict_type(tag = 0x01)] - Fungible(MediumVec>), - #[strict_type(tag = 0x02)] - Structured(MediumVec>), - #[strict_type(tag = 0xFF)] - Attachment(MediumVec>), -} - -impl TypedState { - pub fn is_empty(&self) -> bool { - match self { - TypedState::Declarative(set) => set.is_empty(), - TypedState::Fungible(set) => set.is_empty(), - TypedState::Structured(set) => set.is_empty(), - TypedState::Attachment(set) => set.is_empty(), - } - } - - pub fn len(&self) -> usize { - match self { - TypedState::Declarative(set) => set.len(), - TypedState::Fungible(set) => set.len(), - TypedState::Structured(set) => set.len(), - TypedState::Attachment(set) => set.len(), - } - } - - #[inline] - pub fn state_type(&self) -> StateType { - match self { - TypedState::Declarative(_) => StateType::Void, - TypedState::Fungible(_) => StateType::Fungible, - TypedState::Structured(_) => StateType::Structured, - TypedState::Attachment(_) => StateType::Attachment, - } - } - - #[inline] - pub fn is_declarative(&self) -> bool { matches!(self, TypedState::Declarative(_)) } - - #[inline] - pub fn is_fungible(&self) -> bool { matches!(self, TypedState::Fungible(_)) } - - #[inline] - pub fn is_structured(&self) -> bool { matches!(self, TypedState::Structured(_)) } - - #[inline] - pub fn is_attachment(&self) -> bool { matches!(self, TypedState::Attachment(_)) } - - #[inline] - pub fn as_declarative(&self) -> &[AssignedState] { - match self { - TypedState::Declarative(set) => set, - _ => Default::default(), - } - } - - #[inline] - pub fn as_fungible(&self) -> &[AssignedState] { - match self { - TypedState::Fungible(set) => set, - _ => Default::default(), - } - } - - #[inline] - pub fn as_structured(&self) -> &[AssignedState] { - match self { - TypedState::Structured(set) => set, - _ => Default::default(), - } - } - - #[inline] - pub fn as_attachment(&self) -> &[AssignedState] { - match self { - TypedState::Attachment(set) => set, - _ => Default::default(), - } - } - - #[inline] - pub fn as_declarative_mut(&mut self) -> Option<&mut MediumVec>> { - match self { - TypedState::Declarative(set) => Some(set), - _ => None, - } - } - - #[inline] - pub fn as_fungible_mut(&mut self) -> Option<&mut MediumVec>> { - match self { - TypedState::Fungible(set) => Some(set), - _ => None, - } - } - - #[inline] - pub fn as_structured_mut(&mut self) -> Option<&mut MediumVec>> { - match self { - TypedState::Structured(set) => Some(set), - _ => None, - } - } - - #[inline] - pub fn as_attachment_mut(&mut self) -> Option<&mut MediumVec>> { - match self { - TypedState::Attachment(set) => Some(set), - _ => None, - } - } - - /// If seal definition does not exist, returns [`UnknownDataError`]. If the - /// seal is confidential, returns `Ok(None)`; otherwise returns revealed - /// seal data packed as `Ok(Some(`[`seal::Revealed`]`))` - pub fn revealed_seal_at(&self, index: u16) -> Result, UnknownDataError> { - Ok(match self { - TypedState::Declarative(vec) => vec - .get(index as usize) - .ok_or(UnknownDataError)? - .revealed_seal(), - TypedState::Fungible(vec) => vec - .get(index as usize) - .ok_or(UnknownDataError)? - .revealed_seal(), - TypedState::Structured(vec) => vec - .get(index as usize) - .ok_or(UnknownDataError)? - .revealed_seal(), - TypedState::Attachment(vec) => vec - .get(index as usize) - .ok_or(UnknownDataError)? - .revealed_seal(), - }) - } - - pub fn to_confidential_seals(&self) -> Vec { - match self { - TypedState::Declarative(s) => s - .iter() - .map(AssignedState::<_>::to_confidential_seal) - .collect(), - TypedState::Fungible(s) => s - .iter() - .map(AssignedState::<_>::to_confidential_seal) - .collect(), - TypedState::Structured(s) => s - .iter() - .map(AssignedState::<_>::to_confidential_seal) - .collect(), - TypedState::Attachment(s) => s - .iter() - .map(AssignedState::<_>::to_confidential_seal) - .collect(), - } - } -} - -impl MerkleLeaves for TypedState { - type Leaf = MerkleNode; - type LeafIter = vec::IntoIter; - - fn merkle_leaves(&self) -> Self::LeafIter { - match self { - TypedState::Declarative(vec) => vec - .iter() - .map(AssignedState::::commitment_id) - .collect::>(), - TypedState::Fungible(vec) => vec - .iter() - .map(AssignedState::::commitment_id) - .collect::>(), - TypedState::Structured(vec) => vec - .iter() - .map(AssignedState::::commitment_id) - .collect::>(), - TypedState::Attachment(vec) => vec - .iter() - .map(AssignedState::::commitment_id) - .collect::>(), - } - .into_iter() - } -} diff --git a/src/contract/mod.rs b/src/contract/mod.rs index ea400c54..d7dd7acf 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -27,18 +27,16 @@ pub mod value; pub mod attachment; pub mod data; pub mod state; -mod assignments; mod operations; mod bundle; -pub use assignments::TypedState; pub use attachment::AttachId; pub use bundle::{BundleId, TransitionBundle}; pub use operations::{ ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, OutpointParseError, OwnedState, PrevState, Redeemed, Transition, Valencies, }; -pub use state::{AssignedState, FieldValues, GlobalState, StatePair, StateType}; +pub use state::{AssignedState, FieldValues, GlobalState, StatePair, StateType, TypedState}; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, ValueAtom, diff --git a/src/contract/state.rs b/src/contract/state.rs index b9f83d80..a9adb887 100644 --- a/src/contract/state.rs +++ b/src/contract/state.rs @@ -22,15 +22,15 @@ use core::cmp::Ordering; use core::fmt::Debug; -use std::io; +use std::{io, vec}; -use amplify::confinement::{Confined, TinyOrdMap, U8}; +use amplify::confinement::{Confined, MediumVec, TinyOrdMap, U8}; use amplify::Wrapper; -use commit_verify::merkle::MerkleNode; +use commit_verify::merkle::{MerkleLeaves, MerkleNode}; use commit_verify::{CommitEncode, CommitmentId, Conceal}; use strict_encoding::{StrictDumb, StrictEncode, StrictWriter}; -use super::{attachment, data, seal, value, ConfidentialState, RevealedState}; +use super::{attachment, data, seal, value, ConfidentialState, RevealedState, UnknownDataError}; use crate::{schema, LIB_NAME_RGB}; #[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, From)] @@ -340,3 +340,201 @@ where const TAG: [u8; 32] = *b"urn:lnpbp:rgb:owned-state:v1#23A"; type Id = MerkleNode; } + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB, tags = custom, dumb = Self::Declarative(strict_dumb!()))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "snake_case") +)] +pub enum TypedState { + // TODO: Consider using non-empty variants + #[strict_type(tag = 0x00)] + Declarative(MediumVec>), + #[strict_type(tag = 0x01)] + Fungible(MediumVec>), + #[strict_type(tag = 0x02)] + Structured(MediumVec>), + #[strict_type(tag = 0xFF)] + Attachment(MediumVec>), +} + +impl TypedState { + pub fn is_empty(&self) -> bool { + match self { + TypedState::Declarative(set) => set.is_empty(), + TypedState::Fungible(set) => set.is_empty(), + TypedState::Structured(set) => set.is_empty(), + TypedState::Attachment(set) => set.is_empty(), + } + } + + pub fn len(&self) -> usize { + match self { + TypedState::Declarative(set) => set.len(), + TypedState::Fungible(set) => set.len(), + TypedState::Structured(set) => set.len(), + TypedState::Attachment(set) => set.len(), + } + } + + #[inline] + pub fn state_type(&self) -> StateType { + match self { + TypedState::Declarative(_) => StateType::Void, + TypedState::Fungible(_) => StateType::Fungible, + TypedState::Structured(_) => StateType::Structured, + TypedState::Attachment(_) => StateType::Attachment, + } + } + + #[inline] + pub fn is_declarative(&self) -> bool { matches!(self, TypedState::Declarative(_)) } + + #[inline] + pub fn is_fungible(&self) -> bool { matches!(self, TypedState::Fungible(_)) } + + #[inline] + pub fn is_structured(&self) -> bool { matches!(self, TypedState::Structured(_)) } + + #[inline] + pub fn is_attachment(&self) -> bool { matches!(self, TypedState::Attachment(_)) } + + #[inline] + pub fn as_declarative(&self) -> &[AssignedState] { + match self { + TypedState::Declarative(set) => set, + _ => Default::default(), + } + } + + #[inline] + pub fn as_fungible(&self) -> &[AssignedState] { + match self { + TypedState::Fungible(set) => set, + _ => Default::default(), + } + } + + #[inline] + pub fn as_structured(&self) -> &[AssignedState] { + match self { + TypedState::Structured(set) => set, + _ => Default::default(), + } + } + + #[inline] + pub fn as_attachment(&self) -> &[AssignedState] { + match self { + TypedState::Attachment(set) => set, + _ => Default::default(), + } + } + + #[inline] + pub fn as_declarative_mut(&mut self) -> Option<&mut MediumVec>> { + match self { + TypedState::Declarative(set) => Some(set), + _ => None, + } + } + + #[inline] + pub fn as_fungible_mut(&mut self) -> Option<&mut MediumVec>> { + match self { + TypedState::Fungible(set) => Some(set), + _ => None, + } + } + + #[inline] + pub fn as_structured_mut(&mut self) -> Option<&mut MediumVec>> { + match self { + TypedState::Structured(set) => Some(set), + _ => None, + } + } + + #[inline] + pub fn as_attachment_mut(&mut self) -> Option<&mut MediumVec>> { + match self { + TypedState::Attachment(set) => Some(set), + _ => None, + } + } + + /// If seal definition does not exist, returns [`UnknownDataError`]. If the + /// seal is confidential, returns `Ok(None)`; otherwise returns revealed + /// seal data packed as `Ok(Some(`[`seal::Revealed`]`))` + pub fn revealed_seal_at(&self, index: u16) -> Result, UnknownDataError> { + Ok(match self { + TypedState::Declarative(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), + TypedState::Fungible(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), + TypedState::Structured(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), + TypedState::Attachment(vec) => vec + .get(index as usize) + .ok_or(UnknownDataError)? + .revealed_seal(), + }) + } + + pub fn to_confidential_seals(&self) -> Vec { + match self { + TypedState::Declarative(s) => s + .iter() + .map(AssignedState::<_>::to_confidential_seal) + .collect(), + TypedState::Fungible(s) => s + .iter() + .map(AssignedState::<_>::to_confidential_seal) + .collect(), + TypedState::Structured(s) => s + .iter() + .map(AssignedState::<_>::to_confidential_seal) + .collect(), + TypedState::Attachment(s) => s + .iter() + .map(AssignedState::<_>::to_confidential_seal) + .collect(), + } + } +} + +impl MerkleLeaves for TypedState { + type Leaf = MerkleNode; + type LeafIter = vec::IntoIter; + + fn merkle_leaves(&self) -> Self::LeafIter { + match self { + TypedState::Declarative(vec) => vec + .iter() + .map(AssignedState::::commitment_id) + .collect::>(), + TypedState::Fungible(vec) => vec + .iter() + .map(AssignedState::::commitment_id) + .collect::>(), + TypedState::Structured(vec) => vec + .iter() + .map(AssignedState::::commitment_id) + .collect::>(), + TypedState::Attachment(vec) => vec + .iter() + .map(AssignedState::::commitment_id) + .collect::>(), + } + .into_iter() + } +} From ba20835c5234d9b8df1ca568de1f1988f4ae7e4c Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 02:34:29 +0100 Subject: [PATCH 63/71] refactor: re-organize error types --- src/contract/mod.rs | 24 ------------------------ src/contract/state.rs | 7 ++++++- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/contract/mod.rs b/src/contract/mod.rs index d7dd7acf..65a3eb0c 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -65,27 +65,3 @@ pub trait RevealedState: + Clone { } - -/// Errors retrieving state data. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum StateRetrievalError { - /// the requested state has a mismatched data type. - StateTypeMismatch, - - /// some of the requested data are confidential, when they must be present - /// in revealed form. - #[from(ConfidentialDataError)] - ConfidentialData, -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error)] -#[display(doc_comments)] -/// the requested data are not present. -pub struct UnknownDataError; - -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error)] -#[display(doc_comments)] -/// some of the requested data are confidential, when they must be present in -/// revealed form. -pub struct ConfidentialDataError; diff --git a/src/contract/state.rs b/src/contract/state.rs index a9adb887..b7bf07db 100644 --- a/src/contract/state.rs +++ b/src/contract/state.rs @@ -30,9 +30,14 @@ use commit_verify::merkle::{MerkleLeaves, MerkleNode}; use commit_verify::{CommitEncode, CommitmentId, Conceal}; use strict_encoding::{StrictDumb, StrictEncode, StrictWriter}; -use super::{attachment, data, seal, value, ConfidentialState, RevealedState, UnknownDataError}; +use super::{attachment, data, seal, value, ConfidentialState, RevealedState}; use crate::{schema, LIB_NAME_RGB}; +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Display, Error)] +#[display(doc_comments)] +/// the requested data are not present. +pub struct UnknownDataError; + #[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, From)] #[wrapper(Deref)] #[derive(StrictType, StrictEncode, StrictDecode)] From cebad0e29b63d0a0aa4dd4b7325ed97de1d52f1f Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 02:52:08 +0100 Subject: [PATCH 64/71] contract: refactor naming and API in node operations --- src/contract/bundle.rs | 4 +- src/contract/mod.rs | 4 +- src/contract/operations.rs | 348 +++++++++---------------------------- src/schema/mod.rs | 2 +- src/schema/nodes.rs | 12 +- src/validation/graph.rs | 28 +-- src/validation/mod.rs | 80 ++++----- src/validation/model.rs | 46 ++--- src/validation/state.rs | 4 +- src/validation/verify.rs | 78 +++++---- src/validation/vm.rs | 14 +- 11 files changed, 222 insertions(+), 398 deletions(-) diff --git a/src/contract/bundle.rs b/src/contract/bundle.rs index 9c49c2a0..76f805af 100644 --- a/src/contract/bundle.rs +++ b/src/contract/bundle.rs @@ -24,7 +24,7 @@ use amplify::confinement::{TinyOrdMap, TinyOrdSet}; use amplify::{Bytes32, Wrapper}; use commit_verify::{mpc, CommitStrategy, CommitmentId}; -use super::{NodeId, Transition}; +use super::{OpId, Transition}; use crate::LIB_NAME_RGB; /// Unique state transition bundle identifier equivalent to the bundle @@ -59,7 +59,7 @@ impl From for BundleId { pub struct TransitionBundle { // TODO: #141 Provide type guarantees on the sum of revealed and concealed transitions pub revealed: TinyOrdMap>, - pub concealed: TinyOrdMap>, + pub concealed: TinyOrdMap>, } impl CommitStrategy for TransitionBundle { diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 65a3eb0c..446ebe26 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -33,8 +33,8 @@ mod bundle; pub use attachment::AttachId; pub use bundle::{BundleId, TransitionBundle}; pub use operations::{ - ContractId, Extension, Genesis, Node, NodeId, NodeOutpoint, OutpointParseError, OwnedState, - PrevState, Redeemed, Transition, Valencies, + ContractId, Extension, Genesis, OpId, Operation, OwnedState, PrevAssignment, PrevState, + Redeemed, Transition, Valencies, }; pub use state::{AssignedState, FieldValues, GlobalState, StatePair, StateType, TypedState}; pub use value::{ diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 37afb15a..688e07f1 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -21,8 +21,6 @@ // limitations under the License. use std::cmp::Ordering; -use std::collections::BTreeSet; -use std::num::ParseIntError; use std::str::FromStr; use amplify::confinement::{TinyOrdMap, TinyOrdSet, TinyVec}; @@ -32,10 +30,9 @@ use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; use bp::Chain; use commit_verify::{mpc, CommitStrategy, CommitmentId}; -use super::{seal, GlobalState, TypedState}; +use super::{GlobalState, TypedState}; use crate::schema::{ - self, ExtensionType, FieldType, NodeSubtype, NodeType, OwnedRightType, PublicRightType, - SchemaId, TransitionType, + self, ExtensionType, OpFullType, OpType, OwnedRightType, SchemaId, TransitionType, }; use crate::LIB_NAME_RGB; @@ -43,54 +40,21 @@ use crate::LIB_NAME_RGB; #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB)] -#[display("{node_id}/{ty}/{no}")] -pub struct NodeOutpoint { - pub node_id: NodeId, +#[display("{op}/{ty}/{no}")] +pub struct PrevAssignment { + pub op: OpId, pub ty: OwnedRightType, pub no: u16, } -impl NodeOutpoint { - pub fn new(node_id: NodeId, ty: u16, no: u16) -> NodeOutpoint { - NodeOutpoint { node_id, ty, no } - } -} - -#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] -#[display(inner)] -pub enum OutpointParseError { - #[from] - InvalidNodeId(amplify::hex::Error), - - InvalidType(ParseIntError), - - InvalidOutputNo(ParseIntError), - - /// invalid node outpoint format ('{0}') - #[display(doc_comments)] - WrongFormat(String), -} - -impl FromStr for NodeOutpoint { - type Err = OutpointParseError; - - fn from_str(s: &str) -> Result { - let mut split = s.split('/'); - match (split.next(), split.next(), split.next(), split.next()) { - (Some(node_id), Some(ty), Some(no), None) => Ok(NodeOutpoint { - node_id: node_id.parse()?, - ty: ty.parse().map_err(OutpointParseError::InvalidType)?, - no: no.parse().map_err(OutpointParseError::InvalidOutputNo)?, - }), - _ => Err(OutpointParseError::WrongFormat(s.to_owned())), - } - } +impl PrevAssignment { + pub fn new(op: OpId, ty: u16, no: u16) -> PrevAssignment { PrevAssignment { op, ty, no } } } pub type Valencies = TinyOrdSet; pub type OwnedState = TinyOrdMap; -pub type PrevState = TinyOrdMap>>; -pub type Redeemed = TinyOrdMap>; +pub type PrevState = TinyOrdMap>>; +pub type Redeemed = TinyOrdMap>; /// Unique node (genesis, extensions & state transition) identifier equivalent /// to the commitment hash @@ -104,13 +68,13 @@ pub type Redeemed = TinyOrdMap>; derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -pub struct NodeId( +pub struct OpId( #[from] #[from([u8; 32])] Bytes32, ); -impl FromStr for NodeId { +impl FromStr for OpId { type Err = hex::Error; fn from_str(s: &str) -> Result { Self::from_hex(s) } } @@ -153,27 +117,27 @@ impl From for mpc::ProtocolId { /// RGB contract node API, defined as trait /// -/// Implemented by all contract node types (see [`NodeType`]): +/// Implemented by all contract node types (see [`OpType`]): /// - Genesis ([`Genesis`]) /// - State transitions ([`Transitions`]) /// - Public state extensions ([`Extensions`]) -pub trait Node: AsAny { - /// Returns type of the node (see [`NodeType`]). Unfortunately, this can't +pub trait Operation: AsAny { + /// Returns type of the node (see [`OpType`]). Unfortunately, this can't /// be just a const, since it will break our ability to convert concrete /// `Node` types into `&dyn Node` (entities implementing traits with const /// definitions can't be made into objects) - fn node_type(&self) -> NodeType; + fn op_type(&self) -> OpType; /// Returns full contract node type information - fn subtype(&self) -> NodeSubtype; + fn full_type(&self) -> OpFullType; - /// Returns [`NodeId`], which is a hash of this node commitment + /// Returns [`OpId`], which is a hash of this node commitment /// serialization - fn node_id(&self) -> NodeId; + fn id(&self) -> OpId; /// Returns [`Option::Some`]`(`[`ContractId`]`)`, which is a hash of /// genesis. - /// - For genesis node, this hash is byte-equal to [`NodeId`] (however + /// - For genesis node, this hash is byte-equal to [`OpId`] (however /// displayed in a reverse manner, to introduce semantical distinction) /// - For extension node function returns id of the genesis, to which this /// node commits to @@ -192,7 +156,7 @@ pub trait Node: AsAny { /// Returns reference to a full set of metadata (in form of [`GlobalState`] /// wrapper structure) for the contract node. - fn metadata(&self) -> &GlobalState; + fn global_state(&self) -> &GlobalState; /// Returns reference to information about the owned rights in form of /// [`PrevState`] wrapper structure which this node updates with @@ -200,7 +164,7 @@ pub trait Node: AsAny { /// /// This is always an empty `Vec` for [`Genesis`] and [`Extension`] node /// types. - fn parent_owned_rights(&self) -> &PrevState; + fn prev_state(&self) -> &PrevState; /// Returns reference to information about the public rights (in form of /// [`Redeemed`] wrapper structure), defined with "parent" state @@ -209,95 +173,17 @@ pub trait Node: AsAny { /// ("parent public rights"). /// /// This is always an empty `Vec` for [`Genesis`]. - fn parent_public_rights(&self) -> &Redeemed; - fn owned_rights(&self) -> &OwnedState; - fn owned_rights_mut(&mut self) -> &mut OwnedState; - fn public_rights(&self) -> &Valencies; - fn public_rights_mut(&mut self) -> &mut Valencies; - - #[inline] - fn field_types(&self) -> Vec { self.metadata().keys().copied().collect() } - - #[inline] - fn parent_public_right_types(&self) -> Vec { - self.parent_public_rights() - .values() - .flat_map(|v| v.iter()) - .copied() - .collect() - } - - #[inline] - fn parent_by_public_right_type(&self, t: PublicRightType) -> Vec { - self.parent_public_rights() - .iter() - .filter(|(_, t2)| t2.contains(&t)) - .map(|(node_id, _)| *node_id) - .collect() - } - - /// For genesis and public state extensions always returns an empty list. - /// While public state extension do have parent nodes, they do not contain - /// indexed rights. - #[inline] - fn parent_outputs(&self) -> Vec { - self.parent_owned_rights() - .iter() - .flat_map(|(node_id, map)| { - let node_id = *node_id; - map.iter() - .flat_map(|(ty, vec)| vec.iter().map(|no| (*ty, *no))) - .map(move |(ty, no)| NodeOutpoint { node_id, ty, no }) - }) - .collect() - } - - #[inline] - fn parent_outputs_by_type(&self, t: OwnedRightType) -> Vec { - self.parent_outputs_by_types(&[t]) - } - - fn parent_outputs_by_types(&self, types: &[OwnedRightType]) -> Vec { - self.parent_owned_rights() - .iter() - .flat_map(|(node_id, map)| { - let node_id = *node_id; - map.iter() - .filter(|(t, _)| types.contains(*t)) - .flat_map(|(ty, vec)| vec.iter().map(|no| (*ty, *no))) - .map(move |(ty, no)| NodeOutpoint { node_id, ty, no }) - }) - .collect() - } - - #[inline] - fn parent_owned_right_types(&self) -> Vec { - self.parent_owned_rights() - .values() - .flat_map(|v| v.keys()) - .copied() - .collect() - } - - #[inline] - fn owned_right_types(&self) -> BTreeSet { - self.owned_rights().keys().cloned().collect() - } - - #[inline] - fn owned_rights_by_type(&self, t: OwnedRightType) -> Option<&TypedState> { - self.owned_rights() + fn redeemed(&self) -> &Redeemed; + fn owned_state(&self) -> &OwnedState; + fn owned_state_mut(&mut self) -> &mut OwnedState; + fn valencies(&self) -> &Valencies; + fn valencies_mut(&mut self) -> &mut Valencies; + + fn owned_state_by_type(&self, t: OwnedRightType) -> Option<&TypedState> { + self.owned_state() .iter() .find_map(|(t2, a)| if *t2 == t { Some(a) } else { None }) } - - #[inline] - fn to_confiential_seals(&self) -> Vec { - self.owned_rights() - .iter() - .flat_map(|(_, assignment)| assignment.to_confidential_seals()) - .collect() - } } #[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] @@ -305,11 +191,11 @@ pub trait Node: AsAny { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Genesis { - schema_id: SchemaId, - chain: Chain, - metadata: GlobalState, - owned_rights: OwnedState, - public_rights: Valencies, + pub schema_id: SchemaId, + pub chain: Chain, + pub global_state: GlobalState, + pub owned_state: OwnedState, + pub valencies: Valencies, } #[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] @@ -317,12 +203,12 @@ pub struct Genesis { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Extension { - extension_type: ExtensionType, - contract_id: ContractId, - metadata: GlobalState, - owned_rights: OwnedState, - parent_public_rights: Redeemed, - public_rights: Valencies, + pub extension_type: ExtensionType, + pub contract_id: ContractId, + pub global_state: GlobalState, + pub owned_state: OwnedState, + pub redeemed: Redeemed, + pub valencies: Valencies, } #[derive(Clone, PartialEq, Eq, Hash, Debug, AsAny)] @@ -330,16 +216,16 @@ pub struct Extension { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Transition { - transition_type: TransitionType, - metadata: GlobalState, - parent_owned_rights: PrevState, - owned_rights: OwnedState, - public_rights: Valencies, + pub transition_type: TransitionType, + pub global_state: GlobalState, + pub prev_state: PrevState, + pub owned_state: OwnedState, + pub valencies: Valencies, } // TODO: Remove after TransitionBundling refactoring impl Ord for Transition { - fn cmp(&self, other: &Self) -> Ordering { self.node_id().cmp(&other.node_id()) } + fn cmp(&self, other: &Self) -> Ordering { self.id().cmp(&other.id()) } } impl PartialOrd for Transition { @@ -363,7 +249,7 @@ impl CommitStrategy for Transition { impl CommitmentId for Transition { const TAG: [u8; 32] = *b"urn:lnpbp:rgb:transition:v01#32A"; - type Id = NodeId; + type Id = OpId; } impl CommitStrategy for Extension { @@ -373,22 +259,22 @@ impl CommitStrategy for Extension { impl CommitmentId for Extension { const TAG: [u8; 32] = *b"urn:lnpbp:rgb:extension:v01#2023"; - type Id = NodeId; + type Id = OpId; } -impl Node for Genesis { +impl Operation for Genesis { #[inline] - fn node_type(&self) -> NodeType { NodeType::Genesis } + fn op_type(&self) -> OpType { OpType::Genesis } #[inline] - fn subtype(&self) -> NodeSubtype { NodeSubtype::Genesis } + fn full_type(&self) -> OpFullType { OpFullType::Genesis } #[inline] - fn node_id(&self) -> NodeId { NodeId(self.commitment_id().into_inner()) } + fn id(&self) -> OpId { OpId(self.commitment_id().into_inner()) } #[inline] fn contract_id(&self) -> Option { - Some(ContractId::from_inner(self.node_id().into_inner())) + Some(ContractId::from_inner(self.id().into_inner())) } #[inline] @@ -398,38 +284,36 @@ impl Node for Genesis { fn extension_type(&self) -> Option { None } #[inline] - fn parent_owned_rights(&self) -> &PrevState { - panic!("genesis can't close previous single-use-seals") - } + fn prev_state(&self) -> &PrevState { panic!("genesis can't close previous single-use-seals") } #[inline] - fn parent_public_rights(&self) -> &Redeemed { panic!("genesis can't extend previous state") } + fn redeemed(&self) -> &Redeemed { panic!("genesis can't extend previous state") } #[inline] - fn metadata(&self) -> &GlobalState { &self.metadata } + fn global_state(&self) -> &GlobalState { &self.global_state } #[inline] - fn owned_rights(&self) -> &OwnedState { &self.owned_rights } + fn owned_state(&self) -> &OwnedState { &self.owned_state } #[inline] - fn owned_rights_mut(&mut self) -> &mut OwnedState { &mut self.owned_rights } + fn owned_state_mut(&mut self) -> &mut OwnedState { &mut self.owned_state } #[inline] - fn public_rights(&self) -> &Valencies { &self.public_rights } + fn valencies(&self) -> &Valencies { &self.valencies } #[inline] - fn public_rights_mut(&mut self) -> &mut Valencies { &mut self.public_rights } + fn valencies_mut(&mut self) -> &mut Valencies { &mut self.valencies } } -impl Node for Extension { +impl Operation for Extension { #[inline] - fn node_type(&self) -> NodeType { NodeType::StateExtension } + fn op_type(&self) -> OpType { OpType::StateExtension } #[inline] - fn subtype(&self) -> NodeSubtype { NodeSubtype::StateExtension(self.extension_type) } + fn full_type(&self) -> OpFullType { OpFullType::StateExtension(self.extension_type) } #[inline] - fn node_id(&self) -> NodeId { self.commitment_id() } + fn id(&self) -> OpId { self.commitment_id() } #[inline] fn contract_id(&self) -> Option { Some(self.contract_id) } @@ -441,38 +325,36 @@ impl Node for Extension { fn extension_type(&self) -> Option { Some(self.extension_type) } #[inline] - fn parent_owned_rights(&self) -> &PrevState { - panic!("extension can't close previous single-use-seals") - } + fn prev_state(&self) -> &PrevState { panic!("extension can't close previous single-use-seals") } #[inline] - fn parent_public_rights(&self) -> &Redeemed { &self.parent_public_rights } + fn redeemed(&self) -> &Redeemed { &self.redeemed } #[inline] - fn metadata(&self) -> &GlobalState { &self.metadata } + fn global_state(&self) -> &GlobalState { &self.global_state } #[inline] - fn owned_rights(&self) -> &OwnedState { &self.owned_rights } + fn owned_state(&self) -> &OwnedState { &self.owned_state } #[inline] - fn owned_rights_mut(&mut self) -> &mut OwnedState { &mut self.owned_rights } + fn owned_state_mut(&mut self) -> &mut OwnedState { &mut self.owned_state } #[inline] - fn public_rights(&self) -> &Valencies { &self.public_rights } + fn valencies(&self) -> &Valencies { &self.valencies } #[inline] - fn public_rights_mut(&mut self) -> &mut Valencies { &mut self.public_rights } + fn valencies_mut(&mut self) -> &mut Valencies { &mut self.valencies } } -impl Node for Transition { +impl Operation for Transition { #[inline] - fn node_type(&self) -> NodeType { NodeType::StateTransition } + fn op_type(&self) -> OpType { OpType::StateTransition } #[inline] - fn subtype(&self) -> NodeSubtype { NodeSubtype::StateTransition(self.transition_type) } + fn full_type(&self) -> OpFullType { OpFullType::StateTransition(self.transition_type) } #[inline] - fn node_id(&self) -> NodeId { self.commitment_id() } + fn id(&self) -> OpId { self.commitment_id() } #[inline] fn contract_id(&self) -> Option { None } @@ -484,92 +366,28 @@ impl Node for Transition { fn extension_type(&self) -> Option { None } #[inline] - fn parent_owned_rights(&self) -> &PrevState { &self.parent_owned_rights } + fn prev_state(&self) -> &PrevState { &self.prev_state } #[inline] - fn parent_public_rights(&self) -> &Redeemed { - panic!("state transitions can't extend previous state") - } + fn redeemed(&self) -> &Redeemed { panic!("state transitions can't extend previous state") } #[inline] - fn metadata(&self) -> &GlobalState { &self.metadata } + fn global_state(&self) -> &GlobalState { &self.global_state } #[inline] - fn owned_rights(&self) -> &OwnedState { &self.owned_rights } + fn owned_state(&self) -> &OwnedState { &self.owned_state } #[inline] - fn owned_rights_mut(&mut self) -> &mut OwnedState { &mut self.owned_rights } + fn owned_state_mut(&mut self) -> &mut OwnedState { &mut self.owned_state } #[inline] - fn public_rights(&self) -> &Valencies { &self.public_rights } + fn valencies(&self) -> &Valencies { &self.valencies } #[inline] - fn public_rights_mut(&mut self) -> &mut Valencies { &mut self.public_rights } + fn valencies_mut(&mut self) -> &mut Valencies { &mut self.valencies } } impl Genesis { - pub fn with( - schema_id: SchemaId, - chain: Chain, - metadata: GlobalState, - owned_rights: OwnedState, - public_rights: Valencies, - ) -> Self { - Self { - schema_id, - chain, - metadata, - owned_rights, - public_rights, - } - } - - #[inline] - pub fn contract_id(&self) -> ContractId { ContractId::from_inner(self.node_id().into_inner()) } - - #[inline] - pub fn schema_id(&self) -> SchemaId { self.schema_id } - #[inline] - pub fn chain(&self) -> &Chain { &self.chain } -} - -impl Extension { - pub fn with( - extension_type: ExtensionType, - contract_id: ContractId, - metadata: GlobalState, - owned_rights: OwnedState, - parent_public_rights: Redeemed, - public_rights: Valencies, - ) -> Self { - Self { - extension_type, - contract_id, - metadata, - parent_public_rights, - owned_rights, - public_rights, - } - } -} - -impl Transition { - pub fn with( - transition_type: impl Into, - metadata: GlobalState, - owned_rights: OwnedState, - public_rights: Valencies, - parent_owned_rights: PrevState, - ) -> Self { - Self { - transition_type: transition_type.into(), - metadata, - parent_owned_rights, - owned_rights, - public_rights, - } - } - - pub fn transition_type(&self) -> schema::TransitionType { self.transition_type } + pub fn contract_id(&self) -> ContractId { ContractId::from_inner(self.id().into_inner()) } } diff --git a/src/schema/mod.rs b/src/schema/mod.rs index fa2b5e62..e28940e4 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -28,7 +28,7 @@ mod state; mod occurrences; pub use nodes::{ - ExtensionSchema, GenesisSchema, MetadataStructure, NodeSchema, NodeSubtype, NodeType, + ExtensionSchema, GenesisSchema, MetadataStructure, NodeSchema, OpFullType, OpType, OwnedRightType, OwnedRightsStructure, PublicRightType, PublicRightsStructure, TransitionSchema, }; pub use occurrences::{Occurrences, OccurrencesMismatch}; diff --git a/src/schema/nodes.rs b/src/schema/nodes.rs index 54a16d95..38f6f92a 100644 --- a/src/schema/nodes.rs +++ b/src/schema/nodes.rs @@ -40,7 +40,7 @@ pub type OwnedRightsStructure = TinyOrdMap; )] #[repr(u8)] /// Node type: genesis, extensions and state transitions -pub enum NodeType { +pub enum OpType { /// Genesis node: single node per contract, defining contract and /// committing to a specific schema and underlying chain hash #[display("genesis")] @@ -63,7 +63,7 @@ pub enum NodeType { /// Aggregated type used to supply full contract node type and transition/state /// extension type information #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] -pub enum NodeSubtype { +pub enum OpFullType { /// Genesis node (no subtypes) Genesis, @@ -76,7 +76,7 @@ pub enum NodeSubtype { /// Trait defining common API for all node type schemata pub trait NodeSchema { - fn node_type(&self) -> NodeType; + fn node_type(&self) -> OpType; fn metadata(&self) -> &MetadataStructure; fn closes(&self) -> &OwnedRightsStructure; fn extends(&self) -> &PublicRightsStructure; @@ -118,7 +118,7 @@ pub struct TransitionSchema { impl NodeSchema for GenesisSchema { #[inline] - fn node_type(&self) -> NodeType { NodeType::Genesis } + fn node_type(&self) -> OpType { OpType::Genesis } #[inline] fn metadata(&self) -> &MetadataStructure { &self.metadata } #[inline] @@ -135,7 +135,7 @@ impl NodeSchema for GenesisSchema { impl NodeSchema for ExtensionSchema { #[inline] - fn node_type(&self) -> NodeType { NodeType::StateExtension } + fn node_type(&self) -> OpType { OpType::StateExtension } #[inline] fn metadata(&self) -> &MetadataStructure { &self.metadata } #[inline] @@ -152,7 +152,7 @@ impl NodeSchema for ExtensionSchema { impl NodeSchema for TransitionSchema { #[inline] - fn node_type(&self) -> NodeType { NodeType::StateTransition } + fn node_type(&self) -> OpType { OpType::StateTransition } #[inline] fn metadata(&self) -> &MetadataStructure { &self.metadata } #[inline] diff --git a/src/validation/graph.rs b/src/validation/graph.rs index 231f5d3b..950a1298 100644 --- a/src/validation/graph.rs +++ b/src/validation/graph.rs @@ -32,8 +32,8 @@ use commit_verify::mpc; use crate::schema::OwnedRightType; use crate::{ - seal, Anchor, BundleId, Extension, Genesis, Node, NodeId, NodeOutpoint, Schema, Transition, - TransitionBundle, + seal, Anchor, BundleId, Extension, Genesis, OpId, Operation, PrevAssignment, Schema, + Transition, TransitionBundle, }; /// Errors accessing graph data via [`GraphApi`]. @@ -49,26 +49,26 @@ pub enum ConsistencyError { BundleIdAbsent(BundleId), /// Transition with id {0} is not present in the storage/container - TransitionAbsent(NodeId), + TransitionAbsent(OpId), /// Extension with id {0} is not present in the storage/container - ExtensionAbsent(NodeId), + ExtensionAbsent(OpId), /// Anchor with id {0} is not present in the storage/container AnchorAbsent(AnchorId), /// No seals of the provided type {0} are closed by transition id {1} - NoSealsClosed(OwnedRightType, NodeId), + NoSealsClosed(OwnedRightType, OpId), /// Output {0} is not present in the storage - OutputNotPresent(NodeOutpoint), + OutputNotPresent(PrevAssignment), /// Seal definition for {0} is confidential while was required to be in /// revealed state - ConfidentialSeal(NodeOutpoint), + ConfidentialSeal(PrevAssignment), /// The provided node with id {0} is not an endpoint of the consignment - NotEndpoint(NodeId), + NotEndpoint(OpId), } /// Trait defining common data access API for all storage-related RGB structures @@ -84,7 +84,7 @@ pub enum ConsistencyError { pub trait GraphApi { /// Returns reference to a node (genesis, state transition or state /// extension) matching the provided id, or `None` otherwise - fn node_by_id(&self, node_id: NodeId) -> Option<&dyn Node>; + fn node_by_id(&self, node_id: OpId) -> Option<&dyn Operation>; fn bundle_by_id(&self, bundle_id: BundleId) -> Result<&TransitionBundle, ConsistencyError>; @@ -103,7 +103,7 @@ pub trait GraphApi { /// type /// - [`Error::TransitionAbsent`] when node with the given id is absent from /// the storage/container - fn transition_by_id(&self, node_id: NodeId) -> Result<&Transition, ConsistencyError>; + fn transition_by_id(&self, node_id: OpId) -> Result<&Transition, ConsistencyError>; /// Returns reference to a state extension, if known, matching the provided /// id. If id is unknown, or corresponds to other type of the node (genesis @@ -115,7 +115,7 @@ pub trait GraphApi { /// type /// - [`Error::ExtensionAbsent`] when node with the given id is absent from /// the storage/container - fn extension_by_id(&self, node_id: NodeId) -> Result<&Extension, ConsistencyError>; + fn extension_by_id(&self, node_id: OpId) -> Result<&Extension, ConsistencyError>; /// Returns reference to a state transition, like /// [`GraphApi::transition_by_id`], extended with [`Txid`] of the witness @@ -130,7 +130,7 @@ pub trait GraphApi { /// the storage/container fn transition_witness_by_id( &self, - node_id: NodeId, + node_id: OpId, ) -> Result<(&Transition, Txid), ConsistencyError>; /// Resolves seals closed by a given node with the given owned rights type @@ -171,7 +171,7 @@ pub trait GraphApi { /// closed seal, when the revealed data are required fn seals_closed_with( &self, - node_id: NodeId, + node_id: OpId, owned_right_type: impl Into, witness: Txid, ) -> Result, ConsistencyError>; @@ -189,7 +189,7 @@ pub trait Consignment<'consignment>: 'consignment + GraphApi { /// Genesis data fn genesis(&'consignment self) -> &'consignment Genesis; - fn node_ids(&'consignment self) -> BTreeSet; + fn node_ids(&'consignment self) -> BTreeSet; /// The final state ("endpoints") provided by this consignment. /// diff --git a/src/validation/mod.rs b/src/validation/mod.rs index a84dcc27..0bcc0d0e 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -33,8 +33,8 @@ use core::ops::AddAssign; use bp::Txid; pub use verify::{ResolveTx, TxResolverError, Validator}; -use crate::schema::{self, NodeType, SchemaId}; -use crate::{data, seal, BundleId, NodeId, OccurrencesMismatch}; +use crate::schema::{self, OpType, SchemaId}; +use crate::{data, seal, BundleId, OccurrencesMismatch, OpId}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Display)] #[display(Debug)] @@ -151,19 +151,19 @@ pub enum Failure { SchemaRootNoTransitionTypeMatch(schema::TransitionType), SchemaRootNoExtensionTypeMatch(schema::ExtensionType), - SchemaRootNoMetadataMatch(NodeType, schema::FieldType), - SchemaRootNoParentOwnedRightsMatch(NodeType, schema::OwnedRightType), - SchemaRootNoParentPublicRightsMatch(NodeType, schema::PublicRightType), - SchemaRootNoOwnedRightsMatch(NodeType, schema::OwnedRightType), - SchemaRootNoPublicRightsMatch(NodeType, schema::PublicRightType), + SchemaRootNoMetadataMatch(OpType, schema::FieldType), + SchemaRootNoParentOwnedRightsMatch(OpType, schema::OwnedRightType), + SchemaRootNoParentPublicRightsMatch(OpType, schema::PublicRightType), + SchemaRootNoOwnedRightsMatch(OpType, schema::OwnedRightType), + SchemaRootNoPublicRightsMatch(OpType, schema::PublicRightType), - SchemaUnknownExtensionType(NodeId, schema::ExtensionType), - SchemaUnknownTransitionType(NodeId, schema::TransitionType), - SchemaUnknownFieldType(NodeId, schema::FieldType), - SchemaUnknownOwnedRightType(NodeId, schema::OwnedRightType), - SchemaUnknownPublicRightType(NodeId, schema::PublicRightType), + SchemaUnknownExtensionType(OpId, schema::ExtensionType), + SchemaUnknownTransitionType(OpId, schema::TransitionType), + SchemaUnknownFieldType(OpId, schema::FieldType), + SchemaUnknownOwnedRightType(OpId, schema::OwnedRightType), + SchemaUnknownPublicRightType(OpId, schema::PublicRightType), - SchemaDeniedScriptExtension(NodeId), + SchemaDeniedScriptExtension(OpId), SchemaMetaValueTooSmall(schema::FieldType), SchemaMetaValueTooLarge(schema::FieldType), @@ -182,9 +182,9 @@ pub enum Failure { SchemaMismatchedDataType(u16), SchemaMismatchedStateType(schema::OwnedRightType), - SchemaMetaOccurrencesError(NodeId, schema::FieldType, OccurrencesMismatch), - SchemaParentOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesMismatch), - SchemaOwnedRightOccurrencesError(NodeId, schema::OwnedRightType, OccurrencesMismatch), + SchemaMetaOccurrencesError(OpId, schema::FieldType, OccurrencesMismatch), + SchemaParentOwnedRightOccurrencesError(OpId, schema::OwnedRightType, OccurrencesMismatch), + SchemaOwnedRightOccurrencesError(OpId, schema::OwnedRightType, OccurrencesMismatch), SchemaScriptOverrideDenied, SchemaScriptVmChangeDenied, @@ -193,53 +193,53 @@ pub enum Failure { BundleInvalid(BundleId), - TransitionAbsent(NodeId), - TransitionNotAnchored(NodeId), - TransitionNotInAnchor(NodeId, Txid), + TransitionAbsent(OpId), + TransitionNotAnchored(OpId), + TransitionNotInAnchor(OpId, Txid), TransitionParentWrongSealType { - node_id: NodeId, - ancestor_id: NodeId, + node_id: OpId, + ancestor_id: OpId, assignment_type: schema::OwnedRightType, }, TransitionParentWrongSeal { - node_id: NodeId, - ancestor_id: NodeId, + node_id: OpId, + ancestor_id: OpId, assignment_type: schema::OwnedRightType, seal_index: u16, }, TransitionParentConfidentialSeal { - node_id: NodeId, - ancestor_id: NodeId, + node_id: OpId, + ancestor_id: OpId, assignment_type: schema::OwnedRightType, seal_index: u16, }, TransitionParentIsNotWitnessInput { - node_id: NodeId, - ancestor_id: NodeId, + node_id: OpId, + ancestor_id: OpId, assignment_type: schema::OwnedRightType, seal_index: u16, outpoint: bp::Outpoint, }, - ExtensionAbsent(NodeId), + ExtensionAbsent(OpId), ExtensionParentWrongValenciesType { - node_id: NodeId, - ancestor_id: NodeId, + node_id: OpId, + ancestor_id: OpId, valencies_type: schema::PublicRightType, }, WitnessTransactionMissed(Txid), - WitnessNoCommitment(NodeId, Txid), + WitnessNoCommitment(OpId, Txid), - EndpointTransitionNotFound(NodeId), + EndpointTransitionNotFound(OpId), - InvalidStateDataType(NodeId, u16, /* TODO: Use strict type */ data::Revealed), - InvalidStateDataValue(NodeId, u16, /* TODO: Use strict type */ Vec), + InvalidStateDataType(OpId, u16, /* TODO: Use strict type */ data::Revealed), + InvalidStateDataValue(OpId, u16, /* TODO: Use strict type */ Vec), /// invalid bulletproofs in {0}:{1}: {3} - InvalidBulletproofs(NodeId, u16, String), + InvalidBulletproofs(OpId, u16, String), - ScriptFailure(NodeId), + ScriptFailure(OpId), } #[derive(Clone, PartialEq, Eq, Debug, Display, From)] @@ -248,9 +248,9 @@ pub enum Failure { // TODO #44: (v0.3) convert to detailed descriptions using doc_comments #[display(Debug)] pub enum Warning { - EndpointDuplication(NodeId, seal::Confidential), - EndpointTransitionSealNotFound(NodeId, seal::Confidential), - ExcessiveNode(NodeId), + EndpointDuplication(OpId, seal::Confidential), + EndpointTransitionSealNotFound(OpId, seal::Confidential), + ExcessiveNode(OpId), EndpointTransactionMissed(Txid), } @@ -260,5 +260,5 @@ pub enum Warning { // TODO #44: (v0.3) convert to detailed descriptions using doc_comments #[display(Debug)] pub enum Info { - UncheckableConfidentialStateData(NodeId, u16), + UncheckableConfidentialStateData(OpId, u16), } diff --git a/src/validation/model.rs b/src/validation/model.rs index 088edd29..0c014a41 100644 --- a/src/validation/model.rs +++ b/src/validation/model.rs @@ -30,18 +30,18 @@ use crate::schema::{MetadataStructure, OwnedRightsStructure, PublicRightsStructu use crate::validation::vm::VirtualMachine; use crate::vm::AluRuntime; use crate::{ - validation, AssignedState, FieldValues, GlobalState, Node, NodeId, NodeSubtype, OwnedState, + validation, AssignedState, FieldValues, GlobalState, OpFullType, OpId, Operation, OwnedState, PrevState, Redeemed, Schema, Script, StatePair, TypedState, Valencies, }; impl Schema { pub fn validate( &self, - all_nodes: &BTreeMap, - node: &dyn Node, + all_nodes: &BTreeMap, + node: &dyn Operation, script: &Script, ) -> validation::Status { - let node_id = node.node_id(); + let node_id = node.id(); let empty_owned_structure = OwnedRightsStructure::default(); let empty_public_structure = PublicRightsStructure::default(); @@ -139,10 +139,10 @@ impl Schema { status += self.validate_type_system(); let parent_owned_rights = - extract_parent_owned_rights(all_nodes, node.parent_owned_rights(), &mut status); + extract_parent_owned_rights(all_nodes, node.prev_state(), &mut status); let parent_public_rights = - extract_parent_public_rights(all_nodes, node.parent_public_rights(), &mut status); - status += self.validate_meta(node_id, node.metadata(), metadata_structure); + extract_parent_public_rights(all_nodes, node.redeemed(), &mut status); + status += self.validate_meta(node_id, node.global_state(), metadata_structure); status += self.validate_parent_owned_rights( node_id, &parent_owned_rights, @@ -153,20 +153,20 @@ impl Schema { &parent_public_rights, parent_public_structure, ); - status += self.validate_owned_rights(node_id, node.owned_rights(), assignments_structure); - status += self.validate_public_rights(node_id, node.public_rights(), valencies_structure); + status += self.validate_owned_rights(node_id, node.owned_state(), assignments_structure); + status += self.validate_public_rights(node_id, node.valencies(), valencies_structure); // We need to run scripts as the very last step, since before that // we need to make sure that the node data match the schema, so // scripts are not required to validate the structure of the state status += self.validate_state_evolution( node_id, - node.subtype(), + node.full_type(), &parent_owned_rights, - node.owned_rights(), + node.owned_state(), &parent_public_rights, - node.public_rights(), - node.metadata(), + node.valencies(), + node.global_state(), script, ); status @@ -185,7 +185,7 @@ impl Schema { fn validate_meta( &self, - node_id: NodeId, + node_id: OpId, metadata: &GlobalState, metadata_structure: &MetadataStructure, ) -> validation::Status { @@ -239,7 +239,7 @@ impl Schema { fn validate_parent_owned_rights( &self, - node_id: NodeId, + node_id: OpId, owned_rights: &OwnedState, owned_rights_structure: &OwnedRightsStructure, ) -> validation::Status { @@ -277,7 +277,7 @@ impl Schema { fn validate_parent_public_rights( &self, - node_id: NodeId, + node_id: OpId, public_rights: &Valencies, public_rights_structure: &PublicRightsStructure, ) -> validation::Status { @@ -297,7 +297,7 @@ impl Schema { fn validate_owned_rights( &self, - node_id: NodeId, + node_id: OpId, owned_rights: &OwnedState, owned_rights_structure: &OwnedRightsStructure, ) -> validation::Status { @@ -356,7 +356,7 @@ impl Schema { fn validate_public_rights( &self, - node_id: NodeId, + node_id: OpId, public_rights: &Valencies, public_rights_structure: &PublicRightsStructure, ) -> validation::Status { @@ -377,8 +377,8 @@ impl Schema { #[allow(clippy::too_many_arguments)] fn validate_state_evolution( &self, - node_id: NodeId, - node_subtype: NodeSubtype, + node_id: OpId, + node_subtype: OpFullType, parent_owned_rights: &OwnedState, owned_rights: &OwnedState, parent_public_rights: &Valencies, @@ -412,7 +412,7 @@ impl Schema { } fn extract_parent_owned_rights( - nodes: &BTreeMap, + nodes: &BTreeMap, parent_owned_rights: &PrevState, status: &mut validation::Status, ) -> OwnedState { @@ -445,7 +445,7 @@ fn extract_parent_owned_rights( } for (type_id, indexes) in details { - match parent_node.owned_rights_by_type(*type_id) { + match parent_node.owned_state_by_type(*type_id) { Some(TypedState::Declarative(set)) => { let set = filter(set, indexes); if let Some(state) = owned_rights @@ -499,7 +499,7 @@ fn extract_parent_owned_rights( } fn extract_parent_public_rights( - nodes: &BTreeMap, + nodes: &BTreeMap, parent_public_rights: &Redeemed, status: &mut validation::Status, ) -> Valencies { diff --git a/src/validation/state.rs b/src/validation/state.rs index 960dbe77..d55cb627 100644 --- a/src/validation/state.rs +++ b/src/validation/state.rs @@ -27,13 +27,13 @@ use commit_verify::Conceal; use crate::contract::state::{AttachmentPair, DeclarativePair, FungiblePair, StructuredPair}; use crate::schema::OwnedRightType; -use crate::{validation, AssignedState, NodeId, StatePair, StateSchema}; +use crate::{validation, AssignedState, OpId, StatePair, StateSchema}; impl StateSchema { pub fn validate( &self, // type_system: &TypeSystem, - node_id: &NodeId, + node_id: &OpId, assignment_id: OwnedRightType, data: &AssignedState, ) -> validation::Status diff --git a/src/validation/verify.rs b/src/validation/verify.rs index bfbd9828..27138791 100644 --- a/src/validation/verify.rs +++ b/src/validation/verify.rs @@ -28,11 +28,11 @@ use bp::{Tx, Txid}; use commit_verify::mpc; use super::graph::Consignment; -use super::schema::NodeType; +use super::schema::OpType; use super::{Failure, Status, Validity, Warning}; use crate::validation::subschema::SchemaVerify; use crate::{ - schema, seal, BundleId, ContractId, Extension, Node, NodeId, Schema, SchemaId, + schema, seal, BundleId, ContractId, Extension, OpId, Operation, Schema, SchemaId, TransitionBundle, TypedState, }; @@ -51,13 +51,13 @@ pub struct Validator<'consignment, 'resolver, C: Consignment<'consignment>, R: R status: Status, schema_id: SchemaId, - genesis_id: NodeId, + genesis_id: OpId, contract_id: ContractId, - node_index: BTreeMap, - anchor_index: BTreeMap>, - end_transitions: Vec<(&'consignment dyn Node, BundleId)>, - validation_index: BTreeSet, - anchor_validation_index: BTreeSet, + node_index: BTreeMap, + anchor_index: BTreeMap>, + end_transitions: Vec<(&'consignment dyn Operation, BundleId)>, + validation_index: BTreeSet, + anchor_validation_index: BTreeSet, resolver: &'resolver R, } @@ -71,26 +71,26 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> let mut status = Status::default(); // Frequently used computation-heavy data - let genesis_id = consignment.genesis().node_id(); + let genesis_id = consignment.genesis().id(); let contract_id = consignment.genesis().contract_id(); - let schema_id = consignment.genesis().schema_id(); + let schema_id = consignment.genesis().schema_id; // Create indexes - let mut node_index = BTreeMap::::new(); - let mut anchor_index = BTreeMap::>::new(); + let mut node_index = BTreeMap::::new(); + let mut anchor_index = BTreeMap::>::new(); for (anchor, bundle) in consignment.anchored_bundles() { if !TransitionBundle::validate(bundle) { status.add_failure(Failure::BundleInvalid(bundle.bundle_id())); } for transition in bundle.revealed.keys() { - let node_id = transition.node_id(); + let node_id = transition.id(); node_index.insert(node_id, transition); anchor_index.insert(node_id, anchor); } } node_index.insert(genesis_id, consignment.genesis()); for extension in consignment.state_extensions() { - let node_id = Extension::node_id(extension); + let node_id = Extension::id(extension); node_index.insert(node_id, extension); } @@ -98,7 +98,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // This is pretty simple operation; it takes a lot of code because // we would like to detect any potential issues with the consignment // structure and notify user about them (in form of generated warnings) - let mut end_transitions = Vec::<(&dyn Node, BundleId)>::new(); + let mut end_transitions = Vec::<(&dyn Operation, BundleId)>::new(); for (bundle_id, seal_endpoint) in consignment.endpoints() { let transitions = match consignment.known_transitions_by_bundle_id(*bundle_id) { Ok(transitions) => transitions, @@ -108,9 +108,15 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> } }; for transition in transitions { - let node_id = transition.node_id(); + let node_id = transition.id(); // Checking for endpoint definition duplicates - if !transition.to_confiential_seals().contains(&seal_endpoint) { + if !transition + .owned_state() + .values() + .map(TypedState::to_confidential_seals) + .flatten() + .any(|seal| seal == *seal_endpoint) + { // We generate just a warning here because it's up to a user // to decide whether to accept consignment with wrong // endpoint list @@ -121,7 +127,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> } if end_transitions .iter() - .filter(|(n, _)| n.node_id() == node_id) + .filter(|(n, _)| n.id() == node_id) .count() > 0 { @@ -135,11 +141,11 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Validation index is used to check that all transitions presented // in the consignment were validated. Also, we use it to avoid double // schema validations for transitions. - let validation_index = BTreeSet::::new(); + let validation_index = BTreeSet::::new(); // Index used to avoid repeated validations of the same // anchor+transition pairs - let anchor_validation_index = BTreeSet::::new(); + let anchor_validation_index = BTreeSet::::new(); Self { consignment, @@ -222,7 +228,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Replace missed (not yet mined) endpoint witness transaction failures // with a dedicated type for (node, _) in &self.end_transitions { - if let Some(anchor) = self.anchor_index.get(&node.node_id()) { + if let Some(anchor) = self.anchor_index.get(&node.id()) { if let Some(pos) = self .status .failures @@ -255,10 +261,10 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> fn validate_branch( &mut self, schema: &Schema, - node: &'consignment dyn Node, + node: &'consignment dyn Operation, bundle_id: BundleId, ) { - let mut queue: VecDeque<&dyn Node> = VecDeque::new(); + let mut queue: VecDeque<&dyn Operation> = VecDeque::new(); // Instead of constructing complex graph structures or using a // recursions we utilize queue to keep the track of the upstream @@ -272,8 +278,8 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // checking in the code below: queue.push_back(node); while let Some(node) = queue.pop_front() { - let node_id = node.node_id(); - let node_type = node.node_type(); + let node_id = node.id(); + let node_type = node.op_type(); // [VALIDATION]: Verify node against the schema. Here we check // only a single node, not state evolution (it @@ -303,7 +309,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> self.anchor_validation_index.insert(node_id); } // Ouch, we are out of that multi-level nested cycles :) - } else if node_type != NodeType::Genesis && node_type != NodeType::StateExtension { + } else if node_type != OpType::Genesis && node_type != OpType::StateExtension { // This point is actually unreachable: b/c of the // consignment structure, each state transition // has a corresponding anchor. So if we've got here there @@ -314,8 +320,8 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Now, we must collect all parent nodes and add them to the // verification queue - let parent_nodes_1: Vec<&dyn Node> = node - .parent_owned_rights() + let parent_nodes_1: Vec<&dyn Operation> = node + .prev_state() .iter() .filter_map(|(id, _)| { self.node_index.get(id).cloned().or_else(|| { @@ -329,8 +335,8 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> }) .collect(); - let parent_nodes_2: Vec<&dyn Node> = node - .parent_public_rights() + let parent_nodes_2: Vec<&dyn Operation> = node + .redeemed() .iter() .filter_map(|(id, _)| { self.node_index.get(id).cloned().or_else(|| { @@ -351,12 +357,12 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> fn validate_graph_node( &mut self, - node: &'consignment dyn Node, + node: &'consignment dyn Operation, bundle_id: BundleId, anchor: &'consignment Anchor, ) { let txid = anchor.txid; - let node_id = node.node_id(); + let node_id = node.id(); // Check that the anchor is committed into a transaction spending all of // the transition inputs. @@ -401,7 +407,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Checking that bitcoin transaction closes seals defined by // transition ancestors. - for (ancestor_id, assignments) in node.parent_owned_rights().iter() { + for (ancestor_id, assignments) in node.prev_state().iter() { let ancestor_id = *ancestor_id; let ancestor_node = if let Some(ancestor_node) = self.node_index.get(&ancestor_id) { @@ -419,7 +425,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> let assignment_type = *assignment_type; let variant = if let Some(variant) = - ancestor_node.owned_rights_by_type(assignment_type) + ancestor_node.owned_state_by_type(assignment_type) { variant } else { @@ -452,8 +458,8 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> fn validate_witness_input( &mut self, witness_tx: &Tx, - node_id: NodeId, - ancestor_id: NodeId, + node_id: OpId, + ancestor_id: OpId, assignment_type: schema::OwnedRightType, variant: &'consignment TypedState, seal_index: u16, diff --git a/src/validation/vm.rs b/src/validation/vm.rs index 8086f58c..c4566fb3 100644 --- a/src/validation/vm.rs +++ b/src/validation/vm.rs @@ -22,7 +22,7 @@ use crate::validation::Failure; use crate::vm::AluRuntime; -use crate::{validation, GlobalState, NodeId, NodeSubtype, OwnedState, Script, Valencies}; +use crate::{validation, GlobalState, OpFullType, OpId, OwnedState, Script, Valencies}; /// Trait for concrete types wrapping virtual machines to be used from inside /// RGB schema validation routines. @@ -31,8 +31,8 @@ pub trait VirtualMachine { #[allow(clippy::too_many_arguments)] fn validate( &self, - node_id: NodeId, - node_subtype: NodeSubtype, + node_id: OpId, + node_subtype: OpFullType, previous_owned_rights: &OwnedState, current_owned_rights: &OwnedState, previous_public_rights: &Valencies, @@ -44,8 +44,8 @@ pub trait VirtualMachine { impl VirtualMachine for Script { fn validate( &self, - node_id: NodeId, - node_subtype: NodeSubtype, + node_id: OpId, + node_subtype: OpFullType, previous_owned_rights: &OwnedState, current_owned_rights: &OwnedState, previous_public_rights: &Valencies, @@ -70,8 +70,8 @@ impl<'script> VirtualMachine for AluRuntime<'script> { #[allow(unused_variables)] fn validate( &self, - node_id: NodeId, - node_subtype: NodeSubtype, + node_id: OpId, + node_subtype: OpFullType, previous_owned_rights: &OwnedState, current_owned_rights: &OwnedState, previous_public_rights: &Valencies, From 16d7066827e9f12a2a21bf74fb7277576c9c14c7 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 03:00:41 +0100 Subject: [PATCH 65/71] schema: refactor naming --- src/contract/operations.rs | 18 ++--- src/contract/state.rs | 2 +- src/schema/mod.rs | 16 ++--- src/schema/{nodes.rs => operations.rs} | 92 +++++++++++++------------- src/schema/schema.rs | 12 ++-- src/schema/state.rs | 4 +- src/schema/{occurrences.rs => util.rs} | 0 src/validation/graph.rs | 6 +- src/validation/mod.rs | 48 +++++++------- src/validation/model.rs | 40 +++++------ src/validation/state.rs | 8 +-- src/validation/subschema.rs | 34 +++++----- src/validation/verify.rs | 2 +- 13 files changed, 140 insertions(+), 142 deletions(-) rename src/schema/{nodes.rs => operations.rs} (60%) rename src/schema/{occurrences.rs => util.rs} (100%) diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 688e07f1..f86d514f 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -32,7 +32,7 @@ use commit_verify::{mpc, CommitStrategy, CommitmentId}; use super::{GlobalState, TypedState}; use crate::schema::{ - self, ExtensionType, OpFullType, OpType, OwnedRightType, SchemaId, TransitionType, + self, ExtensionType, OpFullType, OpType, OwnedStateType, SchemaId, TransitionType, }; use crate::LIB_NAME_RGB; @@ -43,7 +43,7 @@ use crate::LIB_NAME_RGB; #[display("{op}/{ty}/{no}")] pub struct PrevAssignment { pub op: OpId, - pub ty: OwnedRightType, + pub ty: OwnedStateType, pub no: u16, } @@ -51,10 +51,10 @@ impl PrevAssignment { pub fn new(op: OpId, ty: u16, no: u16) -> PrevAssignment { PrevAssignment { op, ty, no } } } -pub type Valencies = TinyOrdSet; -pub type OwnedState = TinyOrdMap; -pub type PrevState = TinyOrdMap>>; -pub type Redeemed = TinyOrdMap>; +pub type Valencies = TinyOrdSet; +pub type OwnedState = TinyOrdMap; +pub type PrevState = TinyOrdMap>>; +pub type Redeemed = TinyOrdMap>; /// Unique node (genesis, extensions & state transition) identifier equivalent /// to the commitment hash @@ -179,7 +179,7 @@ pub trait Operation: AsAny { fn valencies(&self) -> &Valencies; fn valencies_mut(&mut self) -> &mut Valencies; - fn owned_state_by_type(&self, t: OwnedRightType) -> Option<&TypedState> { + fn owned_state_by_type(&self, t: OwnedStateType) -> Option<&TypedState> { self.owned_state() .iter() .find_map(|(t2, a)| if *t2 == t { Some(a) } else { None }) @@ -287,7 +287,7 @@ impl Operation for Genesis { fn prev_state(&self) -> &PrevState { panic!("genesis can't close previous single-use-seals") } #[inline] - fn redeemed(&self) -> &Redeemed { panic!("genesis can't extend previous state") } + fn redeemed(&self) -> &Redeemed { panic!("genesis can't redeem valencies") } #[inline] fn global_state(&self) -> &GlobalState { &self.global_state } @@ -369,7 +369,7 @@ impl Operation for Transition { fn prev_state(&self) -> &PrevState { &self.prev_state } #[inline] - fn redeemed(&self) -> &Redeemed { panic!("state transitions can't extend previous state") } + fn redeemed(&self) -> &Redeemed { panic!("state transitions can't redeem valencies") } #[inline] fn global_state(&self) -> &GlobalState { &self.global_state } diff --git a/src/contract/state.rs b/src/contract/state.rs index b7bf07db..cbfa55ee 100644 --- a/src/contract/state.rs +++ b/src/contract/state.rs @@ -62,7 +62,7 @@ impl StrictDumb for FieldValues { derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -pub struct GlobalState(TinyOrdMap); +pub struct GlobalState(TinyOrdMap); /// Categories of the state #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] diff --git a/src/schema/mod.rs b/src/schema/mod.rs index e28940e4..6c1bc7fd 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -20,18 +20,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod nodes; +mod operations; #[allow(clippy::module_inception)] mod schema; pub mod script; mod state; -mod occurrences; +mod util; -pub use nodes::{ - ExtensionSchema, GenesisSchema, MetadataStructure, NodeSchema, OpFullType, OpType, - OwnedRightType, OwnedRightsStructure, PublicRightType, PublicRightsStructure, TransitionSchema, +pub use operations::{ + AssignmentSchema, ExtensionSchema, GenesisSchema, GlobalSchema, OpFullType, OpSchema, OpType, + OwnedStateType, TransitionSchema, ValencySchema, ValencyType, }; -pub use occurrences::{Occurrences, OccurrencesMismatch}; -pub use schema::{ExtensionType, FieldType, Schema, SchemaId, TransitionType}; +pub use schema::{ExtensionType, GlobalStateType, Schema, SchemaId, TransitionType}; pub use script::{Script, VmType}; -pub use state::{StateSchema, ValueType}; +pub use state::{FungibleType, StateSchema}; +pub use util::{Occurrences, OccurrencesMismatch}; diff --git a/src/schema/nodes.rs b/src/schema/operations.rs similarity index 60% rename from src/schema/nodes.rs rename to src/schema/operations.rs index 38f6f92a..52f75fc4 100644 --- a/src/schema/nodes.rs +++ b/src/schema/operations.rs @@ -22,15 +22,15 @@ use amplify::confinement::{TinyOrdMap, TinyOrdSet}; -use super::{ExtensionType, FieldType, Occurrences, TransitionType}; +use super::{ExtensionType, GlobalStateType, Occurrences, TransitionType}; use crate::LIB_NAME_RGB; // Here we can use usize since encoding/decoding makes sure that it's u16 -pub type OwnedRightType = u16; -pub type PublicRightType = u16; -pub type MetadataStructure = TinyOrdMap; -pub type PublicRightsStructure = TinyOrdSet; -pub type OwnedRightsStructure = TinyOrdMap; +pub type OwnedStateType = u16; +pub type ValencyType = u16; +pub type GlobalSchema = TinyOrdMap; +pub type ValencySchema = TinyOrdSet; +pub type AssignmentSchema = TinyOrdMap; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)] #[cfg_attr( @@ -75,13 +75,13 @@ pub enum OpFullType { } /// Trait defining common API for all node type schemata -pub trait NodeSchema { - fn node_type(&self) -> OpType; - fn metadata(&self) -> &MetadataStructure; - fn closes(&self) -> &OwnedRightsStructure; - fn extends(&self) -> &PublicRightsStructure; - fn owned_rights(&self) -> &OwnedRightsStructure; - fn public_rights(&self) -> &PublicRightsStructure; +pub trait OpSchema { + fn op_type(&self) -> OpType; + fn global_state(&self) -> &GlobalSchema; + fn closes(&self) -> &AssignmentSchema; + fn redeems(&self) -> &ValencySchema; + fn owned_state(&self) -> &AssignmentSchema; + fn valencies(&self) -> &ValencySchema; } #[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] @@ -89,9 +89,9 @@ pub trait NodeSchema { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct GenesisSchema { - pub metadata: MetadataStructure, - pub owned_rights: OwnedRightsStructure, - pub public_rights: PublicRightsStructure, + pub global_state: GlobalSchema, + pub owned_state: AssignmentSchema, + pub valencies: ValencySchema, } #[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] @@ -99,10 +99,10 @@ pub struct GenesisSchema { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct ExtensionSchema { - pub metadata: MetadataStructure, - pub extends: PublicRightsStructure, - pub owned_rights: OwnedRightsStructure, - pub public_rights: PublicRightsStructure, + pub global_state: GlobalSchema, + pub redeems: ValencySchema, + pub owned_state: AssignmentSchema, + pub valencies: ValencySchema, } #[derive(Clone, PartialEq, Eq, Debug, Default, AsAny)] @@ -110,59 +110,57 @@ pub struct ExtensionSchema { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct TransitionSchema { - pub metadata: MetadataStructure, - pub closes: OwnedRightsStructure, - pub owned_rights: OwnedRightsStructure, - pub public_rights: PublicRightsStructure, + pub global_state: GlobalSchema, + pub closes: AssignmentSchema, + pub owned_state: AssignmentSchema, + pub valencies: ValencySchema, } -impl NodeSchema for GenesisSchema { +impl OpSchema for GenesisSchema { #[inline] - fn node_type(&self) -> OpType { OpType::Genesis } + fn op_type(&self) -> OpType { OpType::Genesis } #[inline] - fn metadata(&self) -> &MetadataStructure { &self.metadata } + fn global_state(&self) -> &GlobalSchema { &self.global_state } #[inline] - fn closes(&self) -> &OwnedRightsStructure { + fn closes(&self) -> &AssignmentSchema { panic!("genesis can't close previous single-use-seals") } #[inline] - fn extends(&self) -> &PublicRightsStructure { panic!("genesis can't extend previous state") } + fn redeems(&self) -> &ValencySchema { panic!("genesis can't redeem valencies") } #[inline] - fn owned_rights(&self) -> &OwnedRightsStructure { &self.owned_rights } + fn owned_state(&self) -> &AssignmentSchema { &self.owned_state } #[inline] - fn public_rights(&self) -> &PublicRightsStructure { &self.public_rights } + fn valencies(&self) -> &ValencySchema { &self.valencies } } -impl NodeSchema for ExtensionSchema { +impl OpSchema for ExtensionSchema { #[inline] - fn node_type(&self) -> OpType { OpType::StateExtension } + fn op_type(&self) -> OpType { OpType::StateExtension } #[inline] - fn metadata(&self) -> &MetadataStructure { &self.metadata } + fn global_state(&self) -> &GlobalSchema { &self.global_state } #[inline] - fn closes(&self) -> &OwnedRightsStructure { + fn closes(&self) -> &AssignmentSchema { panic!("extension can't close previous single-use-seals") } #[inline] - fn extends(&self) -> &PublicRightsStructure { &self.extends } + fn redeems(&self) -> &ValencySchema { &self.redeems } #[inline] - fn owned_rights(&self) -> &OwnedRightsStructure { &self.owned_rights } + fn owned_state(&self) -> &AssignmentSchema { &self.owned_state } #[inline] - fn public_rights(&self) -> &PublicRightsStructure { &self.public_rights } + fn valencies(&self) -> &ValencySchema { &self.valencies } } -impl NodeSchema for TransitionSchema { +impl OpSchema for TransitionSchema { #[inline] - fn node_type(&self) -> OpType { OpType::StateTransition } + fn op_type(&self) -> OpType { OpType::StateTransition } #[inline] - fn metadata(&self) -> &MetadataStructure { &self.metadata } + fn global_state(&self) -> &GlobalSchema { &self.global_state } #[inline] - fn closes(&self) -> &OwnedRightsStructure { &self.closes } + fn closes(&self) -> &AssignmentSchema { &self.closes } #[inline] - fn extends(&self) -> &PublicRightsStructure { - panic!("state transitions can't extend previous state") - } + fn redeems(&self) -> &ValencySchema { panic!("state transitions can't redeem valencies") } #[inline] - fn owned_rights(&self) -> &OwnedRightsStructure { &self.owned_rights } + fn owned_state(&self) -> &AssignmentSchema { &self.owned_state } #[inline] - fn public_rights(&self) -> &PublicRightsStructure { &self.public_rights } + fn valencies(&self) -> &ValencySchema { &self.valencies } } diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 99425628..83683f8c 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -36,12 +36,12 @@ use strict_encoding::{ use strict_types::SemId; use super::{ - ExtensionSchema, GenesisSchema, OwnedRightType, PublicRightType, Script, StateSchema, - TransitionSchema, + ExtensionSchema, GenesisSchema, OwnedStateType, Script, StateSchema, TransitionSchema, + ValencyType, }; use crate::LIB_NAME_RGB; -pub type FieldType = u16; +pub type GlobalStateType = u16; pub type ExtensionType = u16; pub type TransitionType = u16; @@ -94,9 +94,9 @@ pub struct Schema { pub rgb_features: SchemaFlags, pub subset_of: Option, - pub field_types: TinyOrdMap, - pub owned_right_types: TinyOrdMap, - pub public_right_types: TinyOrdSet, + pub global_types: TinyOrdMap, + pub owned_types: TinyOrdMap, + pub valency_types: TinyOrdSet, pub genesis: GenesisSchema, pub extensions: TinyOrdMap, pub transitions: TinyOrdMap, diff --git a/src/schema/state.rs b/src/schema/state.rs index 4b0bd53b..71c0b6ff 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -36,7 +36,7 @@ use crate::LIB_NAME_RGB; pub enum StateSchema { #[strict_type(dumb)] Declarative, - Arithmetic(ValueType), + Fungible(FungibleType), Structured(SemId), Attachment, } @@ -57,7 +57,7 @@ pub enum StateSchema { serde(crate = "serde_crate", rename_all = "camelCase") )] #[repr(u8)] -pub enum ValueType { +pub enum FungibleType { #[default] Unsigned64Bit = U64.into_code(), } diff --git a/src/schema/occurrences.rs b/src/schema/util.rs similarity index 100% rename from src/schema/occurrences.rs rename to src/schema/util.rs diff --git a/src/validation/graph.rs b/src/validation/graph.rs index 950a1298..a03db79f 100644 --- a/src/validation/graph.rs +++ b/src/validation/graph.rs @@ -30,7 +30,7 @@ use bp::dbc::AnchorId; use bp::{Outpoint, Txid}; use commit_verify::mpc; -use crate::schema::OwnedRightType; +use crate::schema::OwnedStateType; use crate::{ seal, Anchor, BundleId, Extension, Genesis, OpId, Operation, PrevAssignment, Schema, Transition, TransitionBundle, @@ -58,7 +58,7 @@ pub enum ConsistencyError { AnchorAbsent(AnchorId), /// No seals of the provided type {0} are closed by transition id {1} - NoSealsClosed(OwnedRightType, OpId), + NoSealsClosed(OwnedStateType, OpId), /// Output {0} is not present in the storage OutputNotPresent(PrevAssignment), @@ -172,7 +172,7 @@ pub trait GraphApi { fn seals_closed_with( &self, node_id: OpId, - owned_right_type: impl Into, + owned_right_type: impl Into, witness: Txid, ) -> Result, ConsistencyError>; } diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 0bcc0d0e..0b79af96 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -145,30 +145,30 @@ pub enum Failure { SchemaRootRequired(SchemaId), /// Root schema for this schema has another root, which is prohibited SchemaRootHierarchy(SchemaId), - SchemaRootNoFieldTypeMatch(schema::FieldType), - SchemaRootNoOwnedRightTypeMatch(schema::OwnedRightType), - SchemaRootNoPublicRightTypeMatch(schema::PublicRightType), + SchemaRootNoFieldTypeMatch(schema::GlobalStateType), + SchemaRootNoOwnedRightTypeMatch(schema::OwnedStateType), + SchemaRootNoPublicRightTypeMatch(schema::ValencyType), SchemaRootNoTransitionTypeMatch(schema::TransitionType), SchemaRootNoExtensionTypeMatch(schema::ExtensionType), - SchemaRootNoMetadataMatch(OpType, schema::FieldType), - SchemaRootNoParentOwnedRightsMatch(OpType, schema::OwnedRightType), - SchemaRootNoParentPublicRightsMatch(OpType, schema::PublicRightType), - SchemaRootNoOwnedRightsMatch(OpType, schema::OwnedRightType), - SchemaRootNoPublicRightsMatch(OpType, schema::PublicRightType), + SchemaRootNoMetadataMatch(OpType, schema::GlobalStateType), + SchemaRootNoParentOwnedRightsMatch(OpType, schema::OwnedStateType), + SchemaRootNoParentPublicRightsMatch(OpType, schema::ValencyType), + SchemaRootNoOwnedRightsMatch(OpType, schema::OwnedStateType), + SchemaRootNoPublicRightsMatch(OpType, schema::ValencyType), SchemaUnknownExtensionType(OpId, schema::ExtensionType), SchemaUnknownTransitionType(OpId, schema::TransitionType), - SchemaUnknownFieldType(OpId, schema::FieldType), - SchemaUnknownOwnedRightType(OpId, schema::OwnedRightType), - SchemaUnknownPublicRightType(OpId, schema::PublicRightType), + SchemaUnknownFieldType(OpId, schema::GlobalStateType), + SchemaUnknownOwnedRightType(OpId, schema::OwnedStateType), + SchemaUnknownPublicRightType(OpId, schema::ValencyType), SchemaDeniedScriptExtension(OpId), - SchemaMetaValueTooSmall(schema::FieldType), - SchemaMetaValueTooLarge(schema::FieldType), - SchemaStateValueTooSmall(schema::OwnedRightType), - SchemaStateValueTooLarge(schema::OwnedRightType), + SchemaMetaValueTooSmall(schema::GlobalStateType), + SchemaMetaValueTooLarge(schema::GlobalStateType), + SchemaStateValueTooSmall(schema::OwnedStateType), + SchemaStateValueTooLarge(schema::OwnedStateType), SchemaWrongEnumValue { field_or_state_type: u16, @@ -180,11 +180,11 @@ pub enum Failure { found: usize, }, SchemaMismatchedDataType(u16), - SchemaMismatchedStateType(schema::OwnedRightType), + SchemaMismatchedStateType(schema::OwnedStateType), - SchemaMetaOccurrencesError(OpId, schema::FieldType, OccurrencesMismatch), - SchemaParentOwnedRightOccurrencesError(OpId, schema::OwnedRightType, OccurrencesMismatch), - SchemaOwnedRightOccurrencesError(OpId, schema::OwnedRightType, OccurrencesMismatch), + SchemaMetaOccurrencesError(OpId, schema::GlobalStateType, OccurrencesMismatch), + SchemaParentOwnedRightOccurrencesError(OpId, schema::OwnedStateType, OccurrencesMismatch), + SchemaOwnedRightOccurrencesError(OpId, schema::OwnedStateType, OccurrencesMismatch), SchemaScriptOverrideDenied, SchemaScriptVmChangeDenied, @@ -199,24 +199,24 @@ pub enum Failure { TransitionParentWrongSealType { node_id: OpId, ancestor_id: OpId, - assignment_type: schema::OwnedRightType, + assignment_type: schema::OwnedStateType, }, TransitionParentWrongSeal { node_id: OpId, ancestor_id: OpId, - assignment_type: schema::OwnedRightType, + assignment_type: schema::OwnedStateType, seal_index: u16, }, TransitionParentConfidentialSeal { node_id: OpId, ancestor_id: OpId, - assignment_type: schema::OwnedRightType, + assignment_type: schema::OwnedStateType, seal_index: u16, }, TransitionParentIsNotWitnessInput { node_id: OpId, ancestor_id: OpId, - assignment_type: schema::OwnedRightType, + assignment_type: schema::OwnedStateType, seal_index: u16, outpoint: bp::Outpoint, }, @@ -225,7 +225,7 @@ pub enum Failure { ExtensionParentWrongValenciesType { node_id: OpId, ancestor_id: OpId, - valencies_type: schema::PublicRightType, + valencies_type: schema::ValencyType, }, WitnessTransactionMissed(Txid), diff --git a/src/validation/model.rs b/src/validation/model.rs index 0c014a41..6e5adf95 100644 --- a/src/validation/model.rs +++ b/src/validation/model.rs @@ -26,7 +26,7 @@ use amplify::confinement::Confined; use amplify::Wrapper; use commit_verify::Conceal; -use crate::schema::{MetadataStructure, OwnedRightsStructure, PublicRightsStructure}; +use crate::schema::{AssignmentSchema, GlobalSchema, ValencySchema}; use crate::validation::vm::VirtualMachine; use crate::vm::AluRuntime; use crate::{ @@ -43,8 +43,8 @@ impl Schema { ) -> validation::Status { let node_id = node.id(); - let empty_owned_structure = OwnedRightsStructure::default(); - let empty_public_structure = PublicRightsStructure::default(); + let empty_owned_structure = AssignmentSchema::default(); + let empty_public_structure = ValencySchema::default(); let ( metadata_structure, parent_owned_structure, @@ -63,11 +63,11 @@ impl Schema { */ ( - &self.genesis.metadata, + &self.genesis.global_state, &empty_owned_structure, &empty_public_structure, - &self.genesis.owned_rights, - &self.genesis.public_rights, + &self.genesis.owned_state, + &self.genesis.valencies, ) } (Some(transition_type), None) => { @@ -93,11 +93,11 @@ impl Schema { }; ( - &transition_type.metadata, + &transition_type.global_state, &transition_type.closes, &empty_public_structure, - &transition_type.owned_rights, - &transition_type.public_rights, + &transition_type.owned_state, + &transition_type.valencies, ) } (None, Some(extension_type)) => { @@ -123,11 +123,11 @@ impl Schema { }; ( - &extension_type.metadata, + &extension_type.global_state, &empty_owned_structure, - &extension_type.extends, - &extension_type.owned_rights, - &extension_type.extends, + &extension_type.redeems, + &extension_type.owned_state, + &extension_type.redeems, ) } _ => unreachable!("Node can't be extension and state transition at the same time"), @@ -187,7 +187,7 @@ impl Schema { &self, node_id: OpId, metadata: &GlobalState, - metadata_structure: &MetadataStructure, + metadata_structure: &GlobalSchema, ) -> validation::Status { let mut status = validation::Status::new(); @@ -217,7 +217,7 @@ impl Schema { )); } - let _field = self.field_types.get(field_type_id).expect( + let _field = self.global_types.get(field_type_id).expect( "If the field were absent, the schema would not be able to pass the internal \ validation and we would not reach this point", ); @@ -241,7 +241,7 @@ impl Schema { &self, node_id: OpId, owned_rights: &OwnedState, - owned_rights_structure: &OwnedRightsStructure, + owned_rights_structure: &AssignmentSchema, ) -> validation::Status { let mut status = validation::Status::new(); @@ -279,7 +279,7 @@ impl Schema { &self, node_id: OpId, public_rights: &Valencies, - public_rights_structure: &PublicRightsStructure, + public_rights_structure: &ValencySchema, ) -> validation::Status { let mut status = validation::Status::new(); @@ -299,7 +299,7 @@ impl Schema { &self, node_id: OpId, owned_rights: &OwnedState, - owned_rights_structure: &OwnedRightsStructure, + owned_rights_structure: &AssignmentSchema, ) -> validation::Status { let mut status = validation::Status::new(); @@ -329,7 +329,7 @@ impl Schema { )); } - let assignment = &self.owned_right_types.get(owned_type_id).expect( + let assignment = &self.owned_types.get(owned_type_id).expect( "If the assignment were absent, the schema would not be able to pass the internal \ validation and we would not reach this point", ); @@ -358,7 +358,7 @@ impl Schema { &self, node_id: OpId, public_rights: &Valencies, - public_rights_structure: &PublicRightsStructure, + public_rights_structure: &ValencySchema, ) -> validation::Status { let mut status = validation::Status::new(); diff --git a/src/validation/state.rs b/src/validation/state.rs index d55cb627..f86f6920 100644 --- a/src/validation/state.rs +++ b/src/validation/state.rs @@ -26,7 +26,7 @@ use amplify::AsAny; use commit_verify::Conceal; use crate::contract::state::{AttachmentPair, DeclarativePair, FungiblePair, StructuredPair}; -use crate::schema::OwnedRightType; +use crate::schema::OwnedStateType; use crate::{validation, AssignedState, OpId, StatePair, StateSchema}; impl StateSchema { @@ -34,7 +34,7 @@ impl StateSchema { &self, // type_system: &TypeSystem, node_id: &OpId, - assignment_id: OwnedRightType, + assignment_id: OwnedStateType, data: &AssignedState, ) -> validation::Status where @@ -57,7 +57,7 @@ impl StateSchema { )); } } - StateSchema::Arithmetic(_) => { + StateSchema::Fungible(_) => { if let Some(value) = a.downcast_ref::<::Confidential>() { @@ -118,7 +118,7 @@ impl StateSchema { )); } } - StateSchema::Arithmetic(_format) => { + StateSchema::Fungible(_format) => { if a.downcast_ref::<::Revealed>() .is_none() { diff --git a/src/validation/subschema.rs b/src/validation/subschema.rs index de1b68ee..db32f13c 100644 --- a/src/validation/subschema.rs +++ b/src/validation/subschema.rs @@ -20,7 +20,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{validation, NodeSchema, Schema}; +use crate::{validation, OpSchema, Schema}; /// Trait used for internal schema validation against some root schema pub trait SchemaVerify { @@ -35,8 +35,8 @@ impl SchemaVerify for Schema { status.add_failure(validation::Failure::SchemaRootHierarchy(other_root)); } - for (field_type, data_format) in &self.field_types { - match root.field_types.get(field_type) { + for (field_type, data_format) in &self.global_types { + match root.global_types.get(field_type) { None => { status.add_failure(validation::Failure::SchemaRootNoFieldTypeMatch(*field_type)) } @@ -47,8 +47,8 @@ impl SchemaVerify for Schema { }; } - for (assignments_type, state_schema) in &self.owned_right_types { - match root.owned_right_types.get(assignments_type) { + for (assignments_type, state_schema) in &self.owned_types { + match root.owned_types.get(assignments_type) { None => status.add_failure(validation::Failure::SchemaRootNoOwnedRightTypeMatch( *assignments_type, )), @@ -59,8 +59,8 @@ impl SchemaVerify for Schema { }; } - for valencies_type in &self.public_right_types { - match root.public_right_types.contains(valencies_type) { + for valencies_type in &self.valency_types { + match root.valency_types.contains(valencies_type) { false => status.add_failure(validation::Failure::SchemaRootNoPublicRightTypeMatch( *valencies_type, )), @@ -94,14 +94,14 @@ impl SchemaVerify for Schema { } impl SchemaVerify for T -where T: NodeSchema +where T: OpSchema { fn schema_verify(&self, root: &Self) -> validation::Status { let mut status = validation::Status::new(); - let node_type = self.node_type(); + let node_type = self.op_type(); - for (field_type, occ) in self.metadata() { - match root.metadata().get(field_type) { + for (field_type, occ) in self.global_state() { + match root.global_state().get(field_type) { None => status.add_failure(validation::Failure::SchemaRootNoMetadataMatch( node_type, *field_type, @@ -131,8 +131,8 @@ where T: NodeSchema }; } - for (assignments_type, occ) in self.owned_rights() { - match root.owned_rights().get(assignments_type) { + for (assignments_type, occ) in self.owned_state() { + match root.owned_state().get(assignments_type) { None => status.add_failure(validation::Failure::SchemaRootNoOwnedRightsMatch( node_type, *assignments_type, @@ -144,8 +144,8 @@ where T: NodeSchema }; } - for valencies_type in self.extends() { - if !root.extends().contains(valencies_type) { + for valencies_type in self.redeems() { + if !root.redeems().contains(valencies_type) { status.add_failure(validation::Failure::SchemaRootNoParentPublicRightsMatch( node_type, *valencies_type, @@ -153,8 +153,8 @@ where T: NodeSchema } } - for valencies_type in self.public_rights() { - if !root.public_rights().contains(valencies_type) { + for valencies_type in self.valencies() { + if !root.valencies().contains(valencies_type) { status.add_failure(validation::Failure::SchemaRootNoPublicRightsMatch( node_type, *valencies_type, diff --git a/src/validation/verify.rs b/src/validation/verify.rs index 27138791..f92de489 100644 --- a/src/validation/verify.rs +++ b/src/validation/verify.rs @@ -460,7 +460,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> witness_tx: &Tx, node_id: OpId, ancestor_id: OpId, - assignment_type: schema::OwnedRightType, + assignment_type: schema::OwnedStateType, variant: &'consignment TypedState, seal_index: u16, ) { From baa309fb4ebbe2e7a0f00c2e4a92db943f475ce6 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 03:13:02 +0100 Subject: [PATCH 66/71] schema: refactor variable names --- src/contract/mod.rs | 2 +- src/contract/state.rs | 6 +- src/validation/model.rs | 397 ++++++++++++++++++---------------------- 3 files changed, 186 insertions(+), 219 deletions(-) diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 446ebe26..17f94cc6 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -36,7 +36,7 @@ pub use operations::{ ContractId, Extension, Genesis, OpId, Operation, OwnedState, PrevAssignment, PrevState, Redeemed, Transition, Valencies, }; -pub use state::{AssignedState, FieldValues, GlobalState, StatePair, StateType, TypedState}; +pub use state::{AssignedState, GlobalState, GlobalValues, StatePair, StateType, TypedState}; pub use value::{ BlindingFactor, FieldOrderOverflow, NoiseDumb, PedersenCommitment, RangeProof, RangeProofError, ValueAtom, diff --git a/src/contract/state.rs b/src/contract/state.rs index cbfa55ee..875f4099 100644 --- a/src/contract/state.rs +++ b/src/contract/state.rs @@ -47,9 +47,9 @@ pub struct UnknownDataError; derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -pub struct FieldValues(Confined, 1, U8>); +pub struct GlobalValues(Confined, 1, U8>); -impl StrictDumb for FieldValues { +impl StrictDumb for GlobalValues { fn strict_dumb() -> Self { Self(confined_vec!(data::Revealed::strict_dumb())) } } @@ -62,7 +62,7 @@ impl StrictDumb for FieldValues { derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -pub struct GlobalState(TinyOrdMap); +pub struct GlobalState(TinyOrdMap); /// Categories of the state #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] diff --git a/src/validation/model.rs b/src/validation/model.rs index 6e5adf95..32009788 100644 --- a/src/validation/model.rs +++ b/src/validation/model.rs @@ -30,143 +30,125 @@ use crate::schema::{AssignmentSchema, GlobalSchema, ValencySchema}; use crate::validation::vm::VirtualMachine; use crate::vm::AluRuntime; use crate::{ - validation, AssignedState, FieldValues, GlobalState, OpFullType, OpId, Operation, OwnedState, + validation, AssignedState, GlobalState, GlobalValues, OpFullType, OpId, Operation, OwnedState, PrevState, Redeemed, Schema, Script, StatePair, TypedState, Valencies, }; impl Schema { pub fn validate( &self, - all_nodes: &BTreeMap, - node: &dyn Operation, + all_ops: &BTreeMap, + op: &dyn Operation, script: &Script, ) -> validation::Status { - let node_id = node.id(); - - let empty_owned_structure = AssignmentSchema::default(); - let empty_public_structure = ValencySchema::default(); - let ( - metadata_structure, - parent_owned_structure, - parent_public_structure, - assignments_structure, - valencies_structure, - ) = match (node.transition_type(), node.extension_type()) { - (None, None) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = self.genesis.abi.get(&GenesisAction::NoOp) { - - } - */ - - ( - &self.genesis.global_state, - &empty_owned_structure, - &empty_public_structure, - &self.genesis.owned_state, - &self.genesis.valencies, - ) - } - (Some(transition_type), None) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = transition_type.abi.get(&TransitionAction::NoOp) { + let id = op.id(); + + let empty_assign_schema = AssignmentSchema::default(); + let empty_valency_schema = ValencySchema::default(); + let (global_schema, owned_schema, redeem_schema, assign_schema, valency_schema) = + match (op.transition_type(), op.extension_type()) { + (None, None) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = self.genesis.abi.get(&GenesisAction::NoOp) { + } + */ + + ( + &self.genesis.global_state, + &empty_assign_schema, + &empty_valency_schema, + &self.genesis.owned_state, + &self.genesis.valencies, + ) } - */ + (Some(transition_type), None) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = transition_type.abi.get(&TransitionAction::NoOp) { - let transition_type = match self.transitions.get(&transition_type) { - None => { - return validation::Status::with_failure( - validation::Failure::SchemaUnknownTransitionType( - node_id, - transition_type, - ), - ); } - Some(transition_type) => transition_type, - }; - - ( - &transition_type.global_state, - &transition_type.closes, - &empty_public_structure, - &transition_type.owned_state, - &transition_type.valencies, - ) - } - (None, Some(extension_type)) => { - // Right now we do not have actions to implement; but later - // we may have embedded procedures which must be verified - // here - /* - if let Some(procedure) = extension_type.abi.get(&ExtensionAction::NoOp) { - + */ + + let transition_type = match self.transitions.get(&transition_type) { + None => { + return validation::Status::with_failure( + validation::Failure::SchemaUnknownTransitionType( + id, + transition_type, + ), + ); + } + Some(transition_type) => transition_type, + }; + + ( + &transition_type.global_state, + &transition_type.closes, + &empty_valency_schema, + &transition_type.owned_state, + &transition_type.valencies, + ) } - */ + (None, Some(extension_type)) => { + // Right now we do not have actions to implement; but later + // we may have embedded procedures which must be verified + // here + /* + if let Some(procedure) = extension_type.abi.get(&ExtensionAction::NoOp) { - let extension_type = match self.extensions.get(&extension_type) { - None => { - return validation::Status::with_failure( - validation::Failure::SchemaUnknownExtensionType( - node_id, - extension_type, - ), - ); } - Some(extension_type) => extension_type, - }; - - ( - &extension_type.global_state, - &empty_owned_structure, - &extension_type.redeems, - &extension_type.owned_state, - &extension_type.redeems, - ) - } - _ => unreachable!("Node can't be extension and state transition at the same time"), - }; + */ + + let extension_type = match self.extensions.get(&extension_type) { + None => { + return validation::Status::with_failure( + validation::Failure::SchemaUnknownExtensionType(id, extension_type), + ); + } + Some(extension_type) => extension_type, + }; + + ( + &extension_type.global_state, + &empty_assign_schema, + &extension_type.redeems, + &extension_type.owned_state, + &extension_type.redeems, + ) + } + _ => unreachable!("Node can't be extension and state transition at the same time"), + }; let mut status = validation::Status::new(); // Validate type system status += self.validate_type_system(); - let parent_owned_rights = - extract_parent_owned_rights(all_nodes, node.prev_state(), &mut status); - let parent_public_rights = - extract_parent_public_rights(all_nodes, node.redeemed(), &mut status); - status += self.validate_meta(node_id, node.global_state(), metadata_structure); - status += self.validate_parent_owned_rights( - node_id, - &parent_owned_rights, - parent_owned_structure, - ); - status += self.validate_parent_public_rights( - node_id, - &parent_public_rights, - parent_public_structure, - ); - status += self.validate_owned_rights(node_id, node.owned_state(), assignments_structure); - status += self.validate_public_rights(node_id, node.valencies(), valencies_structure); + let prev_state = extract_prev_state(all_ops, op.prev_state(), &mut status); + let redeemed = extract_redeemed_valencies(all_ops, op.redeemed(), &mut status); + status += self.validate_global_state(id, op.global_state(), global_schema); + status += self.validate_prev_state(id, &prev_state, owned_schema); + status += self.validate_redeemed(id, &redeemed, redeem_schema); + status += self.validate_owned_state(id, op.owned_state(), assign_schema); + status += self.validate_valencies(id, op.valencies(), valency_schema); // We need to run scripts as the very last step, since before that // we need to make sure that the node data match the schema, so // scripts are not required to validate the structure of the state status += self.validate_state_evolution( - node_id, - node.full_type(), - &parent_owned_rights, - node.owned_state(), - &parent_public_rights, - node.valencies(), - node.global_state(), + id, + op.full_type(), + &prev_state, + op.owned_state(), + &redeemed, + op.valencies(), + op.global_state(), script, ); status @@ -183,41 +165,38 @@ impl Schema { status } - fn validate_meta( + fn validate_global_state( &self, - node_id: OpId, - metadata: &GlobalState, - metadata_structure: &GlobalSchema, + op_id: OpId, + global: &GlobalState, + global_schema: &GlobalSchema, ) -> validation::Status { let mut status = validation::Status::new(); - metadata + global .keys() .collect::>() - .difference(&metadata_structure.keys().collect()) + .difference(&global_schema.keys().collect()) .for_each(|field_id| { - status - .add_failure(validation::Failure::SchemaUnknownFieldType(node_id, **field_id)); + status.add_failure(validation::Failure::SchemaUnknownFieldType(op_id, **field_id)); }); - for (field_type_id, occ) in metadata_structure { - let set = metadata - .get(field_type_id) + for (global_id, occ) in global_schema { + let set = global + .get(global_id) .cloned() - .map(FieldValues::into_inner) + .map(GlobalValues::into_inner) .map(Confined::unbox) .unwrap_or_default(); // Checking number of field occurrences if let Err(err) = occ.check(set.len() as u16) { status.add_failure(validation::Failure::SchemaMetaOccurrencesError( - node_id, - *field_type_id, - err, + op_id, *global_id, err, )); } - let _field = self.global_types.get(field_type_id).expect( + let _field = self.global_types.get(global_id).expect( "If the field were absent, the schema would not be able to pass the internal \ validation and we would not reach this point", ); @@ -237,27 +216,27 @@ impl Schema { status } - fn validate_parent_owned_rights( + fn validate_prev_state( &self, - node_id: OpId, - owned_rights: &OwnedState, - owned_rights_structure: &AssignmentSchema, + id: OpId, + owned_state: &OwnedState, + assign_schema: &AssignmentSchema, ) -> validation::Status { let mut status = validation::Status::new(); - owned_rights + owned_state .keys() .collect::>() - .difference(&owned_rights_structure.keys().collect()) + .difference(&assign_schema.keys().collect()) .for_each(|owned_type_id| { status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( - node_id, + id, **owned_type_id, )); }); - for (owned_type_id, occ) in owned_rights_structure { - let len = owned_rights + for (owned_type_id, occ) in assign_schema { + let len = owned_state .get(owned_type_id) .map(TypedState::len) .unwrap_or(0); @@ -265,7 +244,7 @@ impl Schema { // Checking number of ancestor's assignment occurrences if let Err(err) = occ.check(len as u16) { status.add_failure(validation::Failure::SchemaParentOwnedRightOccurrencesError( - node_id, + id, *owned_type_id, err, )); @@ -275,19 +254,19 @@ impl Schema { status } - fn validate_parent_public_rights( + fn validate_redeemed( &self, - node_id: OpId, - public_rights: &Valencies, - public_rights_structure: &ValencySchema, + id: OpId, + valencies: &Valencies, + valency_schema: &ValencySchema, ) -> validation::Status { let mut status = validation::Status::new(); - public_rights - .difference(public_rights_structure) + valencies + .difference(valency_schema) .for_each(|public_type_id| { status.add_failure(validation::Failure::SchemaUnknownPublicRightType( - node_id, + id, *public_type_id, )); }); @@ -295,78 +274,73 @@ impl Schema { status } - fn validate_owned_rights( + fn validate_owned_state( &self, - node_id: OpId, - owned_rights: &OwnedState, - owned_rights_structure: &AssignmentSchema, + id: OpId, + owned_state: &OwnedState, + assign_schema: &AssignmentSchema, ) -> validation::Status { let mut status = validation::Status::new(); - owned_rights + owned_state .keys() .collect::>() - .difference(&owned_rights_structure.keys().collect()) + .difference(&assign_schema.keys().collect()) .for_each(|assignment_type_id| { status.add_failure(validation::Failure::SchemaUnknownOwnedRightType( - node_id, + id, **assignment_type_id, )); }); - for (owned_type_id, occ) in owned_rights_structure { - let len = owned_rights - .get(owned_type_id) - .map(TypedState::len) - .unwrap_or(0); + for (state_id, occ) in assign_schema { + let len = owned_state.get(state_id).map(TypedState::len).unwrap_or(0); // Checking number of assignment occurrences if let Err(err) = occ.check(len as u16) { status.add_failure(validation::Failure::SchemaOwnedRightOccurrencesError( - node_id, - *owned_type_id, - err, + id, *state_id, err, )); } - let assignment = &self.owned_types.get(owned_type_id).expect( + let assignment = &self.owned_types.get(state_id).expect( "If the assignment were absent, the schema would not be able to pass the internal \ validation and we would not reach this point", ); - match owned_rights.get(owned_type_id) { + match owned_state.get(state_id) { None => {} Some(TypedState::Declarative(set)) => set .iter() - .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + .for_each(|data| status += assignment.validate(&id, *state_id, data)), Some(TypedState::Fungible(set)) => set .iter() - .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + .for_each(|data| status += assignment.validate(&id, *state_id, data)), Some(TypedState::Structured(set)) => set .iter() - .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + .for_each(|data| status += assignment.validate(&id, *state_id, data)), Some(TypedState::Attachment(set)) => set .iter() - .for_each(|data| status += assignment.validate(&node_id, *owned_type_id, data)), + .for_each(|data| status += assignment.validate(&id, *state_id, data)), }; } status } - fn validate_public_rights( + fn validate_valencies( &self, - node_id: OpId, - public_rights: &Valencies, - public_rights_structure: &ValencySchema, + id: OpId, + valencies: &Valencies, + valency_schema: &ValencySchema, ) -> validation::Status { let mut status = validation::Status::new(); - public_rights - .difference(public_rights_structure) + valencies + .difference(valency_schema) .for_each(|public_type_id| { status.add_failure(validation::Failure::SchemaUnknownPublicRightType( - node_id, + id, *public_type_id, )); }); @@ -377,13 +351,13 @@ impl Schema { #[allow(clippy::too_many_arguments)] fn validate_state_evolution( &self, - node_id: OpId, - node_subtype: OpFullType, - parent_owned_rights: &OwnedState, - owned_rights: &OwnedState, - parent_public_rights: &Valencies, - public_rights: &Valencies, - metadata: &GlobalState, + id: OpId, + ty: OpFullType, + prev_state: &OwnedState, + owned_state: &OwnedState, + redeemed: &Valencies, + valencies: &Valencies, + global: &GlobalState, script: &Script, ) -> validation::Status { let mut status = validation::Status::new(); @@ -395,15 +369,8 @@ impl Schema { Script::AluVM(lib) => Box::new(AluRuntime::new(lib)) as Box, }; - if let Err(err) = vm.validate( - node_id, - node_subtype, - parent_owned_rights, - owned_rights, - parent_public_rights, - public_rights, - metadata, - ) { + if let Err(err) = vm.validate(id, ty, prev_state, owned_state, redeemed, valencies, global) + { status.add_failure(err); } @@ -411,14 +378,14 @@ impl Schema { } } -fn extract_parent_owned_rights( - nodes: &BTreeMap, - parent_owned_rights: &PrevState, +fn extract_prev_state( + ops: &BTreeMap, + prev_state: &PrevState, status: &mut validation::Status, ) -> OwnedState { - let mut owned_rights = bmap! {}; - for (id, details) in parent_owned_rights.iter() { - let parent_node = match nodes.get(id) { + let mut owned_state = bmap! {}; + for (id, details) in prev_state.iter() { + let prev_op = match ops.get(id) { None => { status.add_failure(validation::Failure::TransitionAbsent(*id)); continue; @@ -426,11 +393,11 @@ fn extract_parent_owned_rights( Some(node) => node, }; - fn filter(set: &[AssignedState], indexes: &[u16]) -> Vec> + fn filter(set: &[AssignedState], indexes: &[u16]) -> Vec> where - STATE: StatePair + Clone, - STATE::Confidential: PartialEq + Eq, - STATE::Confidential: From<::Concealed>, + Pair: StatePair + Clone, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, { set.iter() .enumerate() @@ -444,12 +411,12 @@ fn extract_parent_owned_rights( .collect() } - for (type_id, indexes) in details { - match parent_node.owned_state_by_type(*type_id) { + for (state_id, indexes) in details { + match prev_op.owned_state_by_type(*state_id) { Some(TypedState::Declarative(set)) => { let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) + if let Some(state) = owned_state + .entry(*state_id) .or_insert_with(|| TypedState::Declarative(Default::default())) .as_declarative_mut() { @@ -458,8 +425,8 @@ fn extract_parent_owned_rights( } Some(TypedState::Fungible(set)) => { let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) + if let Some(state) = owned_state + .entry(*state_id) .or_insert_with(|| TypedState::Fungible(Default::default())) .as_fungible_mut() { @@ -468,8 +435,8 @@ fn extract_parent_owned_rights( } Some(TypedState::Structured(set)) => { let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) + if let Some(state) = owned_state + .entry(*state_id) .or_insert_with(|| TypedState::Structured(Default::default())) .as_structured_mut() { @@ -478,8 +445,8 @@ fn extract_parent_owned_rights( } Some(TypedState::Attachment(set)) => { let set = filter(set, indexes); - if let Some(state) = owned_rights - .entry(*type_id) + if let Some(state) = owned_state + .entry(*state_id) .or_insert_with(|| TypedState::Attachment(Default::default())) .as_attachment_mut() { @@ -494,22 +461,22 @@ fn extract_parent_owned_rights( } } } - Confined::try_from(owned_rights) + Confined::try_from(owned_state) .expect("collections is assembled from another collection with the same size requirements") } -fn extract_parent_public_rights( - nodes: &BTreeMap, - parent_public_rights: &Redeemed, +fn extract_redeemed_valencies( + operations: &BTreeMap, + redeemed: &Redeemed, status: &mut validation::Status, ) -> Valencies { let mut public_rights = Valencies::default(); - for (id, public_right_types) in parent_public_rights.iter() { - if nodes.get(id).is_none() { + for (id, valencies) in redeemed.iter() { + if operations.get(id).is_none() { status.add_failure(validation::Failure::TransitionAbsent(*id)); } else { public_rights - .extend(public_right_types.iter().copied()) + .extend(valencies.iter().copied()) .expect("same size"); } } From 207905d10cb6d91dd6504b4590b64a5f66a1b963 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 03:26:38 +0100 Subject: [PATCH 67/71] contract: merklize owned state data. Closes #138 --- src/contract/operations.rs | 31 ++++++++++++++++++++++++++----- src/contract/state.rs | 7 ++++++- src/validation/model.rs | 1 + 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/contract/operations.rs b/src/contract/operations.rs index f86d514f..3a522adc 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -21,6 +21,7 @@ // limitations under the License. use std::cmp::Ordering; +use std::io::Write; use std::str::FromStr; use amplify::confinement::{TinyOrdMap, TinyOrdSet, TinyVec}; @@ -28,7 +29,8 @@ use amplify::hex::{FromHex, ToHex}; use amplify::{hex, AsAny, Bytes32, RawArray, Wrapper}; use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; use bp::Chain; -use commit_verify::{mpc, CommitStrategy, CommitmentId}; +use commit_verify::{mpc, CommitEncode, CommitStrategy, CommitmentId}; +use strict_encoding::{StrictEncode, StrictWriter}; use super::{GlobalState, TypedState}; use crate::schema::{ @@ -52,10 +54,32 @@ impl PrevAssignment { } pub type Valencies = TinyOrdSet; -pub type OwnedState = TinyOrdMap; pub type PrevState = TinyOrdMap>>; pub type Redeemed = TinyOrdMap>; +#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, Default, From)] +#[wrapper(Deref)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", transparent) +)] +pub struct OwnedState(TinyOrdMap); + +impl CommitEncode for OwnedState { + fn commit_encode(&self, mut e: &mut impl Write) { + let w = StrictWriter::with(u32::MAX as usize, &mut e); + self.0.len_u8().strict_encode(w).ok(); + for (ty, state) in &self.0 { + let w = StrictWriter::with(u32::MAX as usize, &mut e); + ty.strict_encode(w).ok(); + state.commit_encode(e); + } + } +} + /// Unique node (genesis, extensions & state transition) identifier equivalent /// to the commitment hash #[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] @@ -233,7 +257,6 @@ impl PartialOrd for Transition { } impl CommitStrategy for Genesis { - // TODO: Use merklization type Strategy = commit_verify::strategies::Strict; } @@ -243,7 +266,6 @@ impl CommitmentId for Genesis { } impl CommitStrategy for Transition { - // TODO: Use merklization type Strategy = commit_verify::strategies::Strict; } @@ -253,7 +275,6 @@ impl CommitmentId for Transition { } impl CommitStrategy for Extension { - // TODO: Use merklization type Strategy = commit_verify::strategies::Strict; } diff --git a/src/contract/state.rs b/src/contract/state.rs index 875f4099..0af62a7f 100644 --- a/src/contract/state.rs +++ b/src/contract/state.rs @@ -27,7 +27,7 @@ use std::{io, vec}; use amplify::confinement::{Confined, MediumVec, TinyOrdMap, U8}; use amplify::Wrapper; use commit_verify::merkle::{MerkleLeaves, MerkleNode}; -use commit_verify::{CommitEncode, CommitmentId, Conceal}; +use commit_verify::{CommitEncode, CommitStrategy, CommitmentId, Conceal}; use strict_encoding::{StrictDumb, StrictEncode, StrictWriter}; use super::{attachment, data, seal, value, ConfidentialState, RevealedState}; @@ -517,6 +517,11 @@ impl TypedState { } } +impl CommitStrategy for TypedState { + type Strategy = + commit_verify::strategies::Merklize<{ u128::from_be_bytes(*b"rgb:state:owned*") }>; +} + impl MerkleLeaves for TypedState { type Leaf = MerkleNode; type LeafIter = vec::IntoIter; diff --git a/src/validation/model.rs b/src/validation/model.rs index 32009788..7d53b99b 100644 --- a/src/validation/model.rs +++ b/src/validation/model.rs @@ -463,6 +463,7 @@ fn extract_prev_state( } Confined::try_from(owned_state) .expect("collections is assembled from another collection with the same size requirements") + .into() } fn extract_redeemed_valencies( From b42a20e0327e98d53629a7c3653edbcd028d1cd2 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 03:34:27 +0100 Subject: [PATCH 68/71] add operation metadata. Closes #139 --- src/contract/operations.rs | 33 ++++++++++++++++++++++++--------- src/schema/operations.rs | 11 +++++++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/contract/operations.rs b/src/contract/operations.rs index 3a522adc..ccb449bd 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -178,6 +178,9 @@ pub trait Operation: AsAny { /// [`Option::None`] for genesis and trate transitions fn extension_type(&self) -> Option; + /// Returns metadata associated with the operation, if any. + fn metadata(&self) -> Option<&[u8]>; + /// Returns reference to a full set of metadata (in form of [`GlobalState`] /// wrapper structure) for the contract node. fn global_state(&self) -> &GlobalState; @@ -217,6 +220,7 @@ pub trait Operation: AsAny { pub struct Genesis { pub schema_id: SchemaId, pub chain: Chain, + pub metadata: Option>, pub global_state: GlobalState, pub owned_state: OwnedState, pub valencies: Valencies, @@ -229,6 +233,7 @@ pub struct Genesis { pub struct Extension { pub extension_type: ExtensionType, pub contract_id: ContractId, + pub metadata: Option>, pub global_state: GlobalState, pub owned_state: OwnedState, pub redeemed: Redeemed, @@ -241,6 +246,7 @@ pub struct Extension { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Transition { pub transition_type: TransitionType, + pub metadata: Option>, pub global_state: GlobalState, pub prev_state: PrevState, pub owned_state: OwnedState, @@ -305,13 +311,16 @@ impl Operation for Genesis { fn extension_type(&self) -> Option { None } #[inline] - fn prev_state(&self) -> &PrevState { panic!("genesis can't close previous single-use-seals") } + fn metadata(&self) -> Option<&[u8]> { self.metadata.as_ref().map(TinyVec::as_ref) } #[inline] - fn redeemed(&self) -> &Redeemed { panic!("genesis can't redeem valencies") } + fn global_state(&self) -> &GlobalState { &self.global_state } #[inline] - fn global_state(&self) -> &GlobalState { &self.global_state } + fn prev_state(&self) -> &PrevState { panic!("genesis can't close previous single-use-seals") } + + #[inline] + fn redeemed(&self) -> &Redeemed { panic!("genesis can't redeem valencies") } #[inline] fn owned_state(&self) -> &OwnedState { &self.owned_state } @@ -346,13 +355,16 @@ impl Operation for Extension { fn extension_type(&self) -> Option { Some(self.extension_type) } #[inline] - fn prev_state(&self) -> &PrevState { panic!("extension can't close previous single-use-seals") } + fn metadata(&self) -> Option<&[u8]> { self.metadata.as_ref().map(TinyVec::as_ref) } #[inline] - fn redeemed(&self) -> &Redeemed { &self.redeemed } + fn global_state(&self) -> &GlobalState { &self.global_state } #[inline] - fn global_state(&self) -> &GlobalState { &self.global_state } + fn prev_state(&self) -> &PrevState { panic!("extension can't close previous single-use-seals") } + + #[inline] + fn redeemed(&self) -> &Redeemed { &self.redeemed } #[inline] fn owned_state(&self) -> &OwnedState { &self.owned_state } @@ -387,13 +399,16 @@ impl Operation for Transition { fn extension_type(&self) -> Option { None } #[inline] - fn prev_state(&self) -> &PrevState { &self.prev_state } + fn metadata(&self) -> Option<&[u8]> { self.metadata.as_ref().map(TinyVec::as_ref) } #[inline] - fn redeemed(&self) -> &Redeemed { panic!("state transitions can't redeem valencies") } + fn global_state(&self) -> &GlobalState { &self.global_state } #[inline] - fn global_state(&self) -> &GlobalState { &self.global_state } + fn prev_state(&self) -> &PrevState { &self.prev_state } + + #[inline] + fn redeemed(&self) -> &Redeemed { panic!("state transitions can't redeem valencies") } #[inline] fn owned_state(&self) -> &OwnedState { &self.owned_state } diff --git a/src/schema/operations.rs b/src/schema/operations.rs index 52f75fc4..806de9c5 100644 --- a/src/schema/operations.rs +++ b/src/schema/operations.rs @@ -21,6 +21,7 @@ // limitations under the License. use amplify::confinement::{TinyOrdMap, TinyOrdSet}; +use strict_types::SemId; use super::{ExtensionType, GlobalStateType, Occurrences, TransitionType}; use crate::LIB_NAME_RGB; @@ -77,6 +78,7 @@ pub enum OpFullType { /// Trait defining common API for all node type schemata pub trait OpSchema { fn op_type(&self) -> OpType; + fn metadata(&self) -> Option; fn global_state(&self) -> &GlobalSchema; fn closes(&self) -> &AssignmentSchema; fn redeems(&self) -> &ValencySchema; @@ -89,6 +91,7 @@ pub trait OpSchema { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct GenesisSchema { + pub metadata: Option, pub global_state: GlobalSchema, pub owned_state: AssignmentSchema, pub valencies: ValencySchema, @@ -99,6 +102,7 @@ pub struct GenesisSchema { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct ExtensionSchema { + pub metadata: Option, pub global_state: GlobalSchema, pub redeems: ValencySchema, pub owned_state: AssignmentSchema, @@ -110,6 +114,7 @@ pub struct ExtensionSchema { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct TransitionSchema { + pub metadata: Option, pub global_state: GlobalSchema, pub closes: AssignmentSchema, pub owned_state: AssignmentSchema, @@ -120,6 +125,8 @@ impl OpSchema for GenesisSchema { #[inline] fn op_type(&self) -> OpType { OpType::Genesis } #[inline] + fn metadata(&self) -> Option { self.metadata } + #[inline] fn global_state(&self) -> &GlobalSchema { &self.global_state } #[inline] fn closes(&self) -> &AssignmentSchema { @@ -137,6 +144,8 @@ impl OpSchema for ExtensionSchema { #[inline] fn op_type(&self) -> OpType { OpType::StateExtension } #[inline] + fn metadata(&self) -> Option { self.metadata } + #[inline] fn global_state(&self) -> &GlobalSchema { &self.global_state } #[inline] fn closes(&self) -> &AssignmentSchema { @@ -154,6 +163,8 @@ impl OpSchema for TransitionSchema { #[inline] fn op_type(&self) -> OpType { OpType::StateTransition } #[inline] + fn metadata(&self) -> Option { self.metadata } + #[inline] fn global_state(&self) -> &GlobalSchema { &self.global_state } #[inline] fn closes(&self) -> &AssignmentSchema { &self.closes } From 9cd15ff579c2a25b606f35ce31153c438382e529 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 03:42:51 +0100 Subject: [PATCH 69/71] style: fix clippy lints --- src/contract/mod.rs | 3 +++ src/contract/state.rs | 15 ++++++++++++++- src/contract/value.rs | 6 ++---- src/validation/mod.rs | 8 +++----- src/validation/model.rs | 3 +-- src/validation/verify.rs | 4 +--- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 17f94cc6..32692c72 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -30,6 +30,8 @@ pub mod state; mod operations; mod bundle; +use std::hash::Hash; + pub use attachment::AttachId; pub use bundle::{BundleId, TransitionBundle}; pub use operations::{ @@ -50,6 +52,7 @@ pub trait ConfidentialState: + strict_encoding::StrictEncode + strict_encoding::StrictDecode + amplify::AsAny + + Hash + Clone { } diff --git a/src/contract/state.rs b/src/contract/state.rs index 0af62a7f..73923110 100644 --- a/src/contract/state.rs +++ b/src/contract/state.rs @@ -22,6 +22,7 @@ use core::cmp::Ordering; use core::fmt::Debug; +use std::hash::{Hash, Hasher}; use std::{io, vec}; use amplify::confinement::{Confined, MediumVec, TinyOrdMap, U8}; @@ -117,7 +118,7 @@ impl StatePair for AttachmentPair { /// 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, Hash, Debug)] +#[derive(Clone, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type( lib = LIB_NAME_RGB, @@ -207,6 +208,18 @@ where { } +impl Hash for AssignedState +where + Pair: StatePair, + Pair::Confidential: PartialEq + Eq, + Pair::Confidential: From<::Concealed>, +{ + fn hash(&self, state: &mut H) { + self.to_confidential_seal().hash(state); + self.to_confidential_state().hash(state); + } +} + impl AssignedState where Pair: StatePair, diff --git a/src/contract/value.rs b/src/contract/value.rs index 72049ca3..510a3b90 100644 --- a/src/contract/value.rs +++ b/src/contract/value.rs @@ -271,9 +271,7 @@ impl CommitVerify for PedersenCommitment { let blinding = Tweak::from_inner(revealed.blinding.0.into_inner()) .expect("type guarantees of BlindingFactor are broken"); - let value = match revealed.value { - ValueAtom::Bits64(value) => value, - }; + let ValueAtom::Bits64(value) = revealed.value; // TODO: Check that we create correct generator value. let g = secp256k1_zkp::PublicKey::from_secret_key(SECP256K1, &secp256k1_zkp::ONE_KEY); @@ -281,7 +279,7 @@ impl CommitVerify for PedersenCommitment { let tag = Tag::from(h); let generator = Generator::new_unblinded(SECP256K1, tag); - secp256k1_zkp::PedersenCommitment::new(&SECP256K1, value, blinding, generator).into() + secp256k1_zkp::PedersenCommitment::new(SECP256K1, value, blinding, generator).into() } } diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 0b79af96..84f2bfff 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -123,12 +123,10 @@ impl Status { } else { Validity::ValidExceptEndpoints } + } else if self.unresolved_txids.is_empty() { + Validity::Invalid } else { - if self.unresolved_txids.is_empty() { - Validity::Invalid - } else { - Validity::UnresolvedTransactions - } + Validity::UnresolvedTransactions } } } diff --git a/src/validation/model.rs b/src/validation/model.rs index 7d53b99b..902e9715 100644 --- a/src/validation/model.rs +++ b/src/validation/model.rs @@ -155,14 +155,13 @@ impl Schema { } fn validate_type_system(&self) -> validation::Status { - let status = validation::Status::new(); + validation::Status::new() // TODO: Validate type system /*if let Err(inconsistencies) = self.type_system.validate() { for _err in inconsistencies { status.add_failure(validation::Failure::SchemaTypeSystem(/*err*/)); } }*/ - status } fn validate_global_state( diff --git a/src/validation/verify.rs b/src/validation/verify.rs index f92de489..c5edf032 100644 --- a/src/validation/verify.rs +++ b/src/validation/verify.rs @@ -113,8 +113,7 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> if !transition .owned_state() .values() - .map(TypedState::to_confidential_seals) - .flatten() + .flat_map(TypedState::to_confidential_seals) .any(|seal| seal == *seal_endpoint) { // We generate just a warning here because it's up to a user @@ -480,7 +479,6 @@ impl<'consignment, 'resolver, C: Consignment<'consignment>, R: ResolveTx> // Everything is ok, but we have incomplete data (confidential), // thus can't do a full verification and have to report the // failure - eprintln!("{:#?}", variant); self.status .add_failure(Failure::TransitionParentConfidentialSeal { node_id, From 79e93074854ab43a3ef121789207a66d8dcae19b Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 03:52:54 +0100 Subject: [PATCH 70/71] add fast-forward version codes. Closes #140 --- src/contract/operations.rs | 5 +++- src/lib.rs | 29 ++++++++++++++++++++ src/schema/schema.rs | 55 +++----------------------------------- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/src/contract/operations.rs b/src/contract/operations.rs index ccb449bd..71999d49 100644 --- a/src/contract/operations.rs +++ b/src/contract/operations.rs @@ -36,7 +36,7 @@ use super::{GlobalState, TypedState}; use crate::schema::{ self, ExtensionType, OpFullType, OpType, OwnedStateType, SchemaId, TransitionType, }; -use crate::LIB_NAME_RGB; +use crate::{Ffv, LIB_NAME_RGB}; /// RGB contract node output pointer, defined by the node ID and output number. #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] @@ -218,6 +218,7 @@ pub trait Operation: AsAny { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Genesis { + pub ffv: Ffv, pub schema_id: SchemaId, pub chain: Chain, pub metadata: Option>, @@ -231,6 +232,7 @@ pub struct Genesis { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Extension { + pub ffv: Ffv, pub extension_type: ExtensionType, pub contract_id: ContractId, pub metadata: Option>, @@ -245,6 +247,7 @@ pub struct Extension { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Transition { + pub ffv: Ffv, pub transition_type: TransitionType, pub metadata: Option>, pub global_state: GlobalState, diff --git a/src/lib.rs b/src/lib.rs index b68a0e34..12a08ad5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,3 +66,32 @@ pub mod prelude { } pub use prelude::*; + +/// Fast-forward version code +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default, Debug, Display)] +#[display("v0.10.0+{0}")] +#[derive(StrictType, StrictEncode)] +#[strict_type(lib = LIB_NAME_RGB)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] +pub struct Ffv(u16); + +mod _ffv { + use strict_encoding::{DecodeError, ReadTuple, StrictDecode, TypedRead}; + + use crate::Ffv; + + impl StrictDecode for Ffv { + fn strict_decode(reader: &mut impl TypedRead) -> Result { + let ffv = reader.read_tuple(|r| r.read_field().map(Self))?; + if ffv != Ffv::default() { + Err(DecodeError::DataIntegrityError(format!( + "unsupported fast-forward version code belonging to a future RGB version. \ + Please update your software, or, if the problem persists, contact your \ + vendor providing the following version information: {ffv}" + ))) + } else { + Ok(ffv) + } + } + } +} diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 83683f8c..93632458 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -21,25 +21,20 @@ // limitations under the License. use std::cmp::Ordering; -use std::io; use std::str::FromStr; use amplify::confinement::{MediumVec, TinyOrdMap, TinyOrdSet}; -use amplify::flags::FlagVec; use amplify::{Bytes32, RawArray}; use baid58::{Baid58ParseError, FromBaid58, ToBaid58}; use commit_verify::{CommitStrategy, CommitmentId}; -use strict_encoding::{ - DecodeError, ReadTuple, StrictDecode, StrictEncode, StrictProduct, StrictTuple, StrictType, - TypeName, TypedRead, TypedWrite, WriteTuple, -}; +use strict_encoding::{StrictDecode, StrictEncode, StrictType}; use strict_types::SemId; use super::{ ExtensionSchema, GenesisSchema, OwnedStateType, Script, StateSchema, TransitionSchema, ValencyType, }; -use crate::LIB_NAME_RGB; +use crate::{Ffv, LIB_NAME_RGB}; pub type GlobalStateType = u16; pub type ExtensionType = u16; @@ -80,18 +75,7 @@ impl FromStr for SchemaId { #[strict_type(lib = LIB_NAME_RGB)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct Schema { - /// Feature flags control which of the available RGB features are allowed - /// for smart contracts created under this schema. - /// - /// NB: This is not the same as RGB protocol versioning: feature flag set - /// is specific to a particular RGB protocol version. The only currently - /// defined RGB version is RGBv1; future versions may change the whole - /// structure of Schema data, use of feature flags, re-define their meaning - /// or do other backward-incompatible changes (RGB protocol versions are - /// not interoperable and backward-incompatible by definitions and the - /// nature of client-side-validation which does not allow upgrades). - #[cfg_attr(feature = "serde", serde(skip))] - pub rgb_features: SchemaFlags, + pub ffv: Ffv, pub subset_of: Option, pub global_types: TinyOrdMap, @@ -133,39 +117,6 @@ impl Schema { pub fn schema_id(&self) -> SchemaId { self.commitment_id() } } -#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Default)] -#[display(inner)] -pub struct SchemaFlags(FlagVec); - -impl StrictType for SchemaFlags { - const STRICT_LIB_NAME: &'static str = LIB_NAME_RGB; - fn strict_name() -> Option { Some(tn!("SchemaFlags")) } -} -impl StrictProduct for SchemaFlags {} -impl StrictTuple for SchemaFlags { - const FIELD_COUNT: u8 = 1; -} -impl StrictEncode for SchemaFlags { - fn strict_encode(&self, writer: W) -> io::Result { - writer.write_tuple::(|w| Ok(w.write_field(&self.0.shrunk().into_inner())?.complete())) - } -} -impl StrictDecode for SchemaFlags { - fn strict_decode(reader: &mut impl TypedRead) -> Result { - let flags = - reader.read_tuple(|r| r.read_field().map(|vec| Self(FlagVec::from_inner(vec))))?; - if !flags.0.is_empty() { - Err(DecodeError::DataIntegrityError(format!( - "unsupported schema flags potentially belonging to a future RGB version. Please \ - update your software, or, if the problem persists, contact your vendor providing \ - the following flag information: {flags}" - ))) - } else { - Ok(flags) - } - } -} - #[cfg(test)] mod test { use strict_encoding::StrictDumb; From 3aa71b30748da7ac31b6c29e802f5aa09c7b56e1 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 Feb 2023 04:12:39 +0100 Subject: [PATCH 71/71] release v0.10.0-beta.1 --- Cargo.lock | 29 +++++++++++++++++------------ Cargo.toml | 8 ++------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17100ca1..09bf5c6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,8 +207,9 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" +version = "0.10.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df303019e413ee932020d096590ff65329842a89b08b30ad073d2091ce2fcb45" dependencies = [ "amplify", "bp-dbc", @@ -222,8 +223,9 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" +version = "0.10.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa49d853e43fafe58f8157669e28f92d1920a9cbf2a416fab2300a7ff074fe8" dependencies = [ "amplify", "bp-primitives", @@ -235,8 +237,9 @@ dependencies = [ [[package]] name = "bp-primitives" -version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" +version = "0.10.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e8c5a805cc58b0f6fb9ba81b20632bde1ee2844ee5513ad35aad2371a83b45" dependencies = [ "amplify", "commit_verify", @@ -247,11 +250,12 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.10.0-beta.1" -source = "git+https://github.com/BP-WG/bp-core#2dcbb11d34ab87dfbd04f2a2c56fd427279e5cee" +version = "0.10.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfeddf854d81ba9f5e7cfe68987e3eac976674b041b9f877b04d88f97268b851" dependencies = [ "amplify", - "baid58 0.1.0", + "baid58 0.2.0", "bp-dbc", "bp-primitives", "commit_verify", @@ -310,8 +314,9 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.10.0-beta.2" -source = "git+https://github.com/LNP-BP/client_side_validation#4e0d5b3e89055b7ce2d7013d82a97f9d0eae58bd" +version = "0.10.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "072e9eeca63f7e23387f17f7b897042a66399f4e6965525c69559acace91b2b0" dependencies = [ "amplify", "rand", @@ -723,7 +728,7 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.10.0-alpha.1" +version = "0.10.0-beta.1" dependencies = [ "aluvm", "amplify", diff --git a/Cargo.toml b/Cargo.toml index a87ae146..1d2bf2ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rgb-core" -version = "0.10.0-alpha.1" +version = "0.10.0-beta.1" authors = ["Dr Maxim Orlovsky "] description = "RGB Core Library: confidential & scalable smart contracts on Bitcoin & Lightning (consensus layer)" repository = "https://github.com/RGB-WG/rgb-core" @@ -17,7 +17,7 @@ exclude = [".github"] name = "rgb" [dependencies] -amplify = "~4.0.0-beta.13" +amplify = "~4.0.0-beta.15" strict_encoding = "2.0.0-rc.1" strict_types = "1.0.0-beta.3" aluvm = { version = "0.10.0-alpha.1", features = ["strict_encoding"] } @@ -44,7 +44,3 @@ serde = [ [package.metadata.docs.rs] features = [ "all" ] - -[patch.crates-io] -bp-core = { git = "https://github.com/BP-WG/bp-core" } -commit_verify = { git = "https://github.com/LNP-BP/client_side_validation" }