From bfe0d9f5e785a34cba69f3702e5fa02357c3481b Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 08:58:02 +0200 Subject: [PATCH 01/23] chore: remove unused dependency --- Cargo.lock | 7 ------- Cargo.toml | 1 - 2 files changed, 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1af4d602..cb105e09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -532,12 +532,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - [[package]] name = "minicov" version = "0.3.7" @@ -678,7 +672,6 @@ dependencies = [ "chrono", "commit_verify", "getrandom 0.3.2", - "mime", "rand 0.9.1", "secp256k1", "serde", diff --git a/Cargo.toml b/Cargo.toml index 1128950c..caf7f009 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ commit_verify = { version = "0.11.1-alpha.2", features = ["rand", "derive"] } single_use_seals = "~0.11.1-alpha.2" bp-core = { version = "~0.11.1-alpha.2" } secp256k1 = { version = "0.30.0", features = ["global-context"] } -mime = "~0.3.17" serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } chrono = "0.4.38" From b47df61fbd6443e0eab39e1f9045cfa698ffde2a Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 09:00:37 +0200 Subject: [PATCH 02/23] chore: remove chrono dependency --- Cargo.lock | 1 - Cargo.toml | 1 - src/vm/contract.rs | 7 +------ 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb105e09..1ffe468d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -669,7 +669,6 @@ dependencies = [ "amplify", "baid64", "bp-core", - "chrono", "commit_verify", "getrandom 0.3.2", "rand 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index caf7f009..aeca4ca4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,6 @@ single_use_seals = "~0.11.1-alpha.2" bp-core = { version = "~0.11.1-alpha.2" } secp256k1 = { version = "0.30.0", features = ["global-context"] } serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } -chrono = "0.4.38" [features] default = [] diff --git a/src/vm/contract.rs b/src/vm/contract.rs index ce51c6cc..e4e1d1c8 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -29,7 +29,6 @@ use std::rc::Rc; use amplify::num::u24; use bp::{BlockHeight, Outpoint, Txid}; -use chrono::{MappedLocalTime, TimeZone, Utc}; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use crate::{ @@ -242,11 +241,7 @@ impl Ord for WitnessPos { impl Display for WitnessPos { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}:{}, ", self.layer1, self.height)?; - match Utc.timestamp_opt(self.timestamp, 0) { - MappedLocalTime::Single(time) => write!(f, "{}", time.format("%Y-%m-%d %H:%M:%S")), - _ => f.write_str("invalid timestamp"), - } + write!(f, "{}:{}@{}", self.layer1, self.height, self.timestamp) } } From e260deada988508edda903116d069a40dfd4d5c2 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 09:15:53 +0200 Subject: [PATCH 03/23] remove unnecessary wrapping of fungible state into `revealed` --- src/operation/assignments.rs | 8 ++-- src/operation/commit.rs | 6 +-- src/operation/fungible.rs | 79 ++++++------------------------------ src/operation/mod.rs | 2 +- src/operation/operations.rs | 6 +-- src/operation/state.rs | 4 +- src/schema/mod.rs | 2 +- src/schema/state.rs | 20 +-------- src/validation/logic.rs | 12 +----- src/validation/status.rs | 8 ---- src/vm/op_contract.rs | 10 ++--- 11 files changed, 34 insertions(+), 123 deletions(-) diff --git a/src/operation/assignments.rs b/src/operation/assignments.rs index b7e55034..052a9463 100644 --- a/src/operation/assignments.rs +++ b/src/operation/assignments.rs @@ -32,7 +32,7 @@ use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use super::ExposedState; use crate::operation::seal::GenesisSeal; use crate::{ - AssignmentType, ExposedSeal, GraphSeal, RevealedData, RevealedValue, SecretSeal, StateType, + AssignmentType, ExposedSeal, FungibleState, GraphSeal, RevealedData, SecretSeal, StateType, VoidState, LIB_NAME_RGB_COMMIT, }; @@ -70,7 +70,7 @@ impl IntoIterator for AssignVec pub struct UnknownDataError; pub type AssignRights = Assign; -pub type AssignFungible = Assign; +pub type AssignFungible = Assign; pub type AssignData = Assign; /// State data are assigned to a seal definition, which means that they are @@ -410,7 +410,7 @@ impl TypedAssigns { } } - pub fn as_fungible_state_at(&self, index: u16) -> Result<&RevealedValue, UnknownDataError> { + pub fn as_fungible_state_at(&self, index: u16) -> Result<&FungibleState, UnknownDataError> { match self { TypedAssigns::Fungible(vec) => Ok(vec .get(index as usize) @@ -432,7 +432,7 @@ impl TypedAssigns { } } - pub fn into_fungible_state_at(self, index: u16) -> Result { + pub fn into_fungible_state_at(self, index: u16) -> Result { match self { TypedAssigns::Fungible(vec) => { if index as usize >= vec.len() { diff --git a/src/operation/commit.rs b/src/operation/commit.rs index 6ee4f484..5631ebfc 100644 --- a/src/operation/commit.rs +++ b/src/operation/commit.rs @@ -38,8 +38,8 @@ use strict_encoding::StrictDumb; use crate::{ impl_serde_baid64, Assign, AssignmentType, Assignments, BundleId, ChainNet, ExposedSeal, - ExposedState, Ffv, Genesis, GlobalState, GlobalStateType, Operation, RevealedData, - RevealedState, RevealedValue, SchemaId, SealClosingStrategy, SecretSeal, Transition, + ExposedState, Ffv, FungibleState, Genesis, GlobalState, GlobalStateType, Operation, + RevealedData, RevealedState, SchemaId, SealClosingStrategy, SecretSeal, Transition, TransitionBundle, TransitionType, TypedAssigns, LIB_NAME_RGB_COMMIT, }; @@ -188,7 +188,7 @@ impl AssignmentIndex { pub struct OpDisclose { pub id: OpId, pub seals: MediumOrdMap, - pub fungible: MediumOrdMap, + pub fungible: MediumOrdMap, pub data: MediumOrdMap, } diff --git a/src/operation/fungible.rs b/src/operation/fungible.rs index c28b55b4..38a3d0dd 100644 --- a/src/operation/fungible.rs +++ b/src/operation/fungible.rs @@ -26,86 +26,31 @@ //! some coins of fungible tokens, where each coin or token consists of an //! integer number of atomic subdivisions of the total supply (like satoshis in //! bitcoin represent just a portion, i.e. fixed-precision rational number, of -//! the total possible bitcoin supply). Such numbers demonstrate constant -//! properties regarding their total sum and, thus, can be made confidential -//! using elliptic curve homomorphic cryptography such as Pedesen commitments. +//! the total possible bitcoin supply). use core::fmt::Debug; -use core::num::ParseIntError; -use core::str::FromStr; use std::hash::Hash; -use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; +use strict_encoding::{StrictDecode, StrictEncode}; -use super::ExposedState; -use crate::{schema, RevealedState, StateType, LIB_NAME_RGB_COMMIT}; +use crate::{ExposedState, RevealedState, StateType, LIB_NAME_RGB_COMMIT}; /// 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( + Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From +)] +#[wrapper(Deref, Display, UpperHex, LowerHex, Octal, FromStr)] +#[wrapper_mut(DerefMut)] #[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT, tags = custom)] +#[strict_type(lib = LIB_NAME_RGB_COMMIT)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase", untagged) + serde(crate = "serde_crate", transparent) )] -pub enum FungibleState { - /// 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 Default for FungibleState { - fn default() -> Self { FungibleState::Bits64(0) } -} - -impl FromStr for FungibleState { - type Err = ParseIntError; - fn from_str(s: &str) -> Result { s.parse().map(FungibleState::Bits64) } -} - -impl From for u64 { - fn from(value: FungibleState) -> Self { - match value { - FungibleState::Bits64(val) => val, - } - } -} +pub struct FungibleState(pub u64); -impl FungibleState { - pub fn fungible_type(&self) -> schema::FungibleType { - match self { - FungibleState::Bits64(_) => schema::FungibleType::Unsigned64Bit, - } - } - - pub fn as_u64(&self) -> u64 { (*self).into() } -} - -/// State item for a homomorphically-encryptable state. -/// -/// Consists of the 64-bit value and -#[derive(Wrapper, Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, From, Display)] -#[display(inner)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[wrapper(Deref)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct RevealedValue(FungibleState); - -impl RevealedValue { - /// Convenience constructor. - pub fn new(value: impl Into) -> Self { Self(value.into()) } -} - -impl ExposedState for RevealedValue { +impl ExposedState for FungibleState { fn state_type(&self) -> StateType { StateType::Fungible } fn state_data(&self) -> RevealedState { RevealedState::Fungible(*self) } } - -impl From for RevealedValue { - fn from(value: u64) -> Self { Self(FungibleState::Bits64(value)) } -} diff --git a/src/operation/mod.rs b/src/operation/mod.rs index 795b7dc7..d424c56c 100644 --- a/src/operation/mod.rs +++ b/src/operation/mod.rs @@ -41,7 +41,7 @@ pub use commit::{ DiscloseHash, GlobalCommitment, OpCommitment, OpDisclose, OpId, TypeCommitment, }; pub use data::{RevealedData, VoidState}; -pub use fungible::{FungibleState, RevealedValue}; +pub use fungible::FungibleState; pub use global::{GlobalState, GlobalValues}; pub use layer1::{ChainNet, Layer1}; pub use meta::{MetaValue, Metadata, MetadataError}; diff --git a/src/operation/operations.rs b/src/operation/operations.rs index eca418f9..e6232124 100644 --- a/src/operation/operations.rs +++ b/src/operation/operations.rs @@ -33,8 +33,8 @@ use strict_encoding::{RString, StrictDeserialize, StrictEncode, StrictSerialize} use crate::schema::{OpFullType, SchemaId, TransitionType}; use crate::{ Assign, AssignmentIndex, AssignmentType, Assignments, AssignmentsRef, ChainNet, ContractId, - DiscloseHash, ExposedState, Ffv, GenesisSeal, GlobalState, GraphSeal, Metadata, OpDisclose, - OpId, RevealedData, RevealedValue, SecretSeal, TypedAssigns, VoidState, LIB_NAME_RGB_COMMIT, + DiscloseHash, ExposedState, Ffv, FungibleState, GenesisSeal, GlobalState, GraphSeal, Metadata, + OpDisclose, OpId, RevealedData, SecretSeal, TypedAssigns, VoidState, LIB_NAME_RGB_COMMIT, }; #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] @@ -152,7 +152,7 @@ pub trait Operation { let mut seals: BTreeMap = bmap!(); let mut void: BTreeMap = bmap!(); - let mut fungible: BTreeMap = bmap!(); + let mut fungible: BTreeMap = bmap!(); let mut data: BTreeMap = bmap!(); for (ty, assigns) in self.assignments().flat() { match assigns { diff --git a/src/operation/state.rs b/src/operation/state.rs index a0e92e80..9a329c1e 100644 --- a/src/operation/state.rs +++ b/src/operation/state.rs @@ -25,7 +25,7 @@ use core::hash::Hash; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; -use crate::{RevealedData, RevealedValue}; +use crate::{FungibleState, RevealedData}; /// Marker trait for types of state holding explicit state data. pub trait ExposedState: @@ -63,7 +63,7 @@ pub enum StateType { )] pub enum RevealedState { Void, - Fungible(RevealedValue), + Fungible(FungibleState), Structured(RevealedData), } diff --git a/src/schema/mod.rs b/src/schema/mod.rs index f6b436d0..7dfcab60 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -35,4 +35,4 @@ pub use schema::{ AssignmentDetails, GlobalDetails, GlobalStateType, MetaDetails, MetaType, Schema, SchemaId, TransitionDetails, TransitionType, }; -pub use state::{FungibleType, GlobalStateSchema, OwnedStateSchema}; +pub use state::{GlobalStateSchema, OwnedStateSchema}; diff --git a/src/schema/state.rs b/src/schema/state.rs index 7b9072d8..84fcfebd 100644 --- a/src/schema/state.rs +++ b/src/schema/state.rs @@ -21,7 +21,6 @@ // limitations under the License. use amplify::num::u24; -use strict_encoding::Primitive; use strict_types::SemId; use crate::{StateType, LIB_NAME_RGB_COMMIT}; @@ -37,7 +36,7 @@ use crate::{StateType, LIB_NAME_RGB_COMMIT}; pub enum OwnedStateSchema { #[strict_type(dumb)] Declarative, - Fungible(FungibleType), + Fungible, Structured(SemId), } @@ -45,7 +44,7 @@ impl OwnedStateSchema { pub fn state_type(&self) -> StateType { match self { OwnedStateSchema::Declarative => StateType::Void, - OwnedStateSchema::Fungible(_) => StateType::Fungible, + OwnedStateSchema::Fungible => StateType::Fungible, OwnedStateSchema::Structured(_) => StateType::Structured, } } @@ -59,21 +58,6 @@ impl OwnedStateSchema { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Display)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT, 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 FungibleType { - #[default] - #[display("64bit")] - Unsigned64Bit = Primitive::U64.into_code(), -} - #[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_COMMIT)] diff --git a/src/validation/logic.rs b/src/validation/logic.rs index 0e69d806..756a01cc 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -479,17 +479,7 @@ impl OwnedStateSchema { Assign::Revealed { state, .. } | Assign::ConfidentialSeal { state, .. } => { match (self, state.state_data()) { (OwnedStateSchema::Declarative, RevealedState::Void) => {} - (OwnedStateSchema::Fungible(schema), RevealedState::Fungible(v)) - if v.as_inner().fungible_type() != *schema => - { - status.add_failure(validation::Failure::FungibleTypeMismatch { - opid, - state_type, - expected: *schema, - found: v.as_inner().fungible_type(), - }); - } - (OwnedStateSchema::Fungible(_), RevealedState::Fungible(_)) => {} + (OwnedStateSchema::Fungible, RevealedState::Fungible(_)) => {} (OwnedStateSchema::Structured(sem_id), RevealedState::Structured(data)) => { if type_system .strict_deserialize_type(*sem_id, data.as_ref()) diff --git a/src/validation/status.rs b/src/validation/status.rs index ec4a7e7d..46e1cdd1 100644 --- a/src/validation/status.rs +++ b/src/validation/status.rs @@ -309,14 +309,6 @@ pub enum Failure { expected: StateType, found: StateType, }, - /// state in {opid}/{state_type} is of {found} type, while schema requires - /// it to be {expected}. - FungibleTypeMismatch { - opid: OpId, - state_type: schema::AssignmentType, - expected: schema::FungibleType, - found: schema::FungibleType, - }, /// evaluation of AluVM script for operation {0} has failed with the code /// {1:?} and message {2:?}. ScriptFailure(OpId, Option, Option), diff --git a/src/vm/op_contract.rs b/src/vm/op_contract.rs index a1c58b0d..18f022c8 100644 --- a/src/vm/op_contract.rs +++ b/src/vm/op_contract.rs @@ -269,8 +269,8 @@ impl InstructionSet for ContractOp { match context.op_info.prev_state.get($state_type) { Some(TypedAssigns::Fungible(state)) => { let mut values = vec![]; - for assign in state.iter().map(Assign::as_revealed_state) { - values.push(assign.as_inner().as_u64()) + for val in state.iter().map(Assign::as_revealed_state) { + values.push(val.into_inner()) } values } @@ -284,8 +284,8 @@ impl InstructionSet for ContractOp { match context.op_info.owned_state().get(*$state_type) { Some(TypedAssigns::Fungible(state)) => { let mut values = vec![]; - for assign in state.iter().map(Assign::as_revealed_state) { - values.push(assign.as_inner().as_u64()) + for val in state.iter().map(Assign::as_revealed_state) { + values.push(val.into_inner()) } values } @@ -385,7 +385,7 @@ impl InstructionSet for ContractOp { else { fail!() }; - regs.set_n(RegA::A64, *reg, state.as_inner().as_u64()); + regs.set_n(RegA::A64, *reg, state.as_inner()); } ContractOp::LdG(state_type, reg_8, reg_s) => { let Some(reg_32) = *regs.get_n(RegA::A8, *reg_8) else { From ccbd07967be85bc1cf2e2601ec085a0b93a74850 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 09:17:13 +0200 Subject: [PATCH 04/23] chore: remove names for state using "revealed" --- src/operation/assignments.rs | 8 ++++---- src/operation/commit.rs | 14 +++++++------- src/operation/data.rs | 16 ++++++++-------- src/operation/fungible.rs | 4 ++-- src/operation/global.rs | 16 ++++++++-------- src/operation/mod.rs | 4 ++-- src/operation/operations.rs | 4 ++-- src/operation/state.rs | 16 ++++++++-------- src/validation/logic.rs | 12 ++++++------ src/vm/contract.rs | 8 ++++---- 10 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/operation/assignments.rs b/src/operation/assignments.rs index 052a9463..e2633be3 100644 --- a/src/operation/assignments.rs +++ b/src/operation/assignments.rs @@ -32,7 +32,7 @@ use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use super::ExposedState; use crate::operation::seal::GenesisSeal; use crate::{ - AssignmentType, ExposedSeal, FungibleState, GraphSeal, RevealedData, SecretSeal, StateType, + AssignmentType, ExposedSeal, FungibleState, GraphSeal, SecretSeal, StateType, StructureddData, VoidState, LIB_NAME_RGB_COMMIT, }; @@ -71,7 +71,7 @@ pub struct UnknownDataError; pub type AssignRights = Assign; pub type AssignFungible = Assign; -pub type AssignData = Assign; +pub type AssignData = Assign; /// 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 @@ -400,7 +400,7 @@ impl TypedAssigns { } } - pub fn as_structured_state_at(&self, index: u16) -> Result<&RevealedData, UnknownDataError> { + pub fn as_structured_state_at(&self, index: u16) -> Result<&StructureddData, UnknownDataError> { match self { TypedAssigns::Structured(vec) => Ok(vec .get(index as usize) @@ -420,7 +420,7 @@ impl TypedAssigns { } } - pub fn into_structured_state_at(self, index: u16) -> Result { + pub fn into_structured_state_at(self, index: u16) -> Result { match self { TypedAssigns::Structured(vec) => { if index as usize >= vec.len() { diff --git a/src/operation/commit.rs b/src/operation/commit.rs index 5631ebfc..47fa38a8 100644 --- a/src/operation/commit.rs +++ b/src/operation/commit.rs @@ -37,9 +37,9 @@ use commit_verify::{ use strict_encoding::StrictDumb; use crate::{ - impl_serde_baid64, Assign, AssignmentType, Assignments, BundleId, ChainNet, ExposedSeal, - ExposedState, Ffv, FungibleState, Genesis, GlobalState, GlobalStateType, Operation, - RevealedData, RevealedState, SchemaId, SealClosingStrategy, SecretSeal, Transition, + impl_serde_baid64, AnyState, Assign, AssignmentType, Assignments, BundleId, ChainNet, + ExposedSeal, ExposedState, Ffv, FungibleState, Genesis, GlobalState, GlobalStateType, + Operation, SchemaId, SealClosingStrategy, SecretSeal, StructureddData, Transition, TransitionBundle, TransitionType, TypedAssigns, LIB_NAME_RGB_COMMIT, }; @@ -189,7 +189,7 @@ pub struct OpDisclose { pub id: OpId, pub seals: MediumOrdMap, pub fungible: MediumOrdMap, - pub data: MediumOrdMap, + pub data: MediumOrdMap, } #[derive(Clone, Eq, PartialEq, Hash, Debug)] @@ -300,7 +300,7 @@ impl Transition { } } -impl RevealedState { +impl AnyState { fn commit_encode(&self, e: &mut CommitEngine) { match self { Self::Void => {} @@ -313,7 +313,7 @@ impl RevealedState { #[derive(Clone, Eq, PartialEq, Debug)] pub struct AssignmentCommitment { pub ty: AssignmentType, - pub state: RevealedState, + pub state: AnyState, pub seal: SecretSeal, } @@ -371,7 +371,7 @@ impl MerkleLeaves for Assignments { #[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct GlobalCommitment { pub ty: GlobalStateType, - pub state: RevealedData, + pub state: StructureddData, } impl CommitEncode for GlobalCommitment { diff --git a/src/operation/data.rs b/src/operation/data.rs index d4129a45..70de0b1c 100644 --- a/src/operation/data.rs +++ b/src/operation/data.rs @@ -25,7 +25,7 @@ use amplify::Wrapper; use strict_encoding::StrictType; use super::ExposedState; -use crate::{RevealedState, StateType, LIB_NAME_RGB_COMMIT}; +use crate::{AnyState, StateType, LIB_NAME_RGB_COMMIT}; /// Struct using for storing Void (i.e. absent) state #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Display, Default)] @@ -37,7 +37,7 @@ pub struct VoidState(()); impl ExposedState for VoidState { fn state_type(&self) -> StateType { StateType::Void } - fn state_data(&self) -> RevealedState { RevealedState::Void } + fn state_data(&self) -> AnyState { AnyState::Void } } #[derive(Wrapper, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, From, Display, Default)] @@ -45,16 +45,16 @@ impl ExposedState for VoidState { #[wrapper(Deref, AsSlice, BorrowSlice, Hex)] #[derive(StrictType, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_COMMIT)] -pub struct RevealedData(SmallBlob); +pub struct StructureddData(SmallBlob); -impl RevealedData { +impl StructureddData { /// Convenience constructor. pub fn new(value: impl Into) -> Self { Self(value.into()) } } -impl ExposedState for RevealedData { +impl ExposedState for StructureddData { fn state_type(&self) -> StateType { StateType::Structured } - fn state_data(&self) -> RevealedState { RevealedState::Structured(self.clone()) } + fn state_data(&self) -> AnyState { AnyState::Structured(self.clone()) } } #[cfg(feature = "serde")] @@ -65,14 +65,14 @@ mod _serde { use super::*; - impl Serialize for RevealedData { + impl Serialize for StructureddData { fn serialize(&self, serializer: S) -> Result where S: Serializer { serializer.serialize_str(&self.to_string()) } } - impl<'de> Deserialize<'de> for RevealedData { + impl<'de> Deserialize<'de> for StructureddData { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { let s = String::deserialize(deserializer)?; diff --git a/src/operation/fungible.rs b/src/operation/fungible.rs index 38a3d0dd..40d33d45 100644 --- a/src/operation/fungible.rs +++ b/src/operation/fungible.rs @@ -33,7 +33,7 @@ use std::hash::Hash; use strict_encoding::{StrictDecode, StrictEncode}; -use crate::{ExposedState, RevealedState, StateType, LIB_NAME_RGB_COMMIT}; +use crate::{AnyState, ExposedState, StateType, LIB_NAME_RGB_COMMIT}; /// An atom of an additive state, which thus can be monomorphically encrypted. #[derive( @@ -52,5 +52,5 @@ pub struct FungibleState(pub u64); impl ExposedState for FungibleState { fn state_type(&self) -> StateType { StateType::Fungible } - fn state_data(&self) -> RevealedState { RevealedState::Fungible(*self) } + fn state_data(&self) -> AnyState { AnyState::Fungible(*self) } } diff --git a/src/operation/global.rs b/src/operation/global.rs index a59c8f8c..f556f04f 100644 --- a/src/operation/global.rs +++ b/src/operation/global.rs @@ -27,7 +27,7 @@ use amplify::confinement::{Confined, TinyOrdMap, U16}; use amplify::{confinement, Wrapper}; use strict_encoding::StrictDumb; -use crate::{schema, RevealedData, LIB_NAME_RGB_COMMIT}; +use crate::{schema, StructureddData, LIB_NAME_RGB_COMMIT}; #[derive(Wrapper, WrapperMut, Clone, PartialEq, Eq, Hash, Debug, From)] #[wrapper(Deref)] @@ -39,19 +39,19 @@ use crate::{schema, RevealedData, LIB_NAME_RGB_COMMIT}; derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -pub struct GlobalValues(Confined, 1, U16>); +pub struct GlobalValues(Confined, 1, U16>); impl StrictDumb for GlobalValues { - fn strict_dumb() -> Self { Self(Confined::with(RevealedData::strict_dumb())) } + fn strict_dumb() -> Self { Self(Confined::with(StructureddData::strict_dumb())) } } impl GlobalValues { - pub fn with(state: RevealedData) -> Self { GlobalValues(Confined::with(state)) } + pub fn with(state: StructureddData) -> Self { GlobalValues(Confined::with(state)) } } impl IntoIterator for GlobalValues { - type Item = RevealedData; - type IntoIter = vec::IntoIter; + type Item = StructureddData; + type IntoIter = vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } @@ -72,7 +72,7 @@ impl GlobalState { pub fn add_state( &mut self, ty: schema::GlobalStateType, - state: RevealedData, + state: StructureddData, ) -> Result<(), confinement::Error> { match self.0.get_mut(&ty) { Some(vec) => vec.push(state), @@ -83,7 +83,7 @@ impl GlobalState { pub fn extend_state( &mut self, ty: schema::GlobalStateType, - iter: impl IntoIterator, + iter: impl IntoIterator, ) -> Result<(), confinement::Error> { match self.0.get_mut(&ty) { Some(vec) => vec.extend(iter), diff --git a/src/operation/mod.rs b/src/operation/mod.rs index d424c56c..1ffa82b5 100644 --- a/src/operation/mod.rs +++ b/src/operation/mod.rs @@ -40,7 +40,7 @@ pub use commit::{ AssignmentCommitment, AssignmentIndex, BaseCommitment, BundleDisclosure, ContractId, DiscloseHash, GlobalCommitment, OpCommitment, OpDisclose, OpId, TypeCommitment, }; -pub use data::{RevealedData, VoidState}; +pub use data::{StructureddData, VoidState}; pub use fungible::FungibleState; pub use global::{GlobalState, GlobalValues}; pub use layer1::{ChainNet, Layer1}; @@ -50,4 +50,4 @@ pub use operations::{ Transition, }; pub use seal::{ExposedSeal, GenesisSeal, GraphSeal, OutputSeal, SecretSeal, TxoSeal}; -pub use state::{ExposedState, RevealedState, StateType}; +pub use state::{AnyState, ExposedState, StateType}; diff --git a/src/operation/operations.rs b/src/operation/operations.rs index e6232124..2482fe82 100644 --- a/src/operation/operations.rs +++ b/src/operation/operations.rs @@ -34,7 +34,7 @@ use crate::schema::{OpFullType, SchemaId, TransitionType}; use crate::{ Assign, AssignmentIndex, AssignmentType, Assignments, AssignmentsRef, ChainNet, ContractId, DiscloseHash, ExposedState, Ffv, FungibleState, GenesisSeal, GlobalState, GraphSeal, Metadata, - OpDisclose, OpId, RevealedData, SecretSeal, TypedAssigns, VoidState, LIB_NAME_RGB_COMMIT, + OpDisclose, OpId, SecretSeal, StructureddData, TypedAssigns, VoidState, LIB_NAME_RGB_COMMIT, }; #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] @@ -153,7 +153,7 @@ pub trait Operation { let mut seals: BTreeMap = bmap!(); let mut void: BTreeMap = bmap!(); let mut fungible: BTreeMap = bmap!(); - let mut data: BTreeMap = bmap!(); + let mut data: BTreeMap = bmap!(); for (ty, assigns) in self.assignments().flat() { match assigns { TypedAssigns::Declarative(a) => { diff --git a/src/operation/state.rs b/src/operation/state.rs index 9a329c1e..06e09740 100644 --- a/src/operation/state.rs +++ b/src/operation/state.rs @@ -25,14 +25,14 @@ use core::hash::Hash; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; -use crate::{FungibleState, RevealedData}; +use crate::{FungibleState, StructureddData}; /// Marker trait for types of state holding explicit state data. pub trait ExposedState: Debug + StrictDumb + StrictEncode + StrictDecode + Eq + Ord + Clone { fn state_type(&self) -> StateType; - fn state_data(&self) -> RevealedState; + fn state_data(&self) -> AnyState; } /// Categories of the state @@ -61,18 +61,18 @@ pub enum StateType { derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "camelCase", tag = "type") )] -pub enum RevealedState { +pub enum AnyState { Void, Fungible(FungibleState), - Structured(RevealedData), + Structured(StructureddData), } -impl RevealedState { +impl AnyState { pub fn state_type(&self) -> StateType { match self { - RevealedState::Void => StateType::Void, - RevealedState::Fungible(_) => StateType::Fungible, - RevealedState::Structured(_) => StateType::Structured, + AnyState::Void => StateType::Void, + AnyState::Fungible(_) => StateType::Fungible, + AnyState::Structured(_) => StateType::Structured, } } } diff --git a/src/validation/logic.rs b/src/validation/logic.rs index 756a01cc..8f44f590 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -38,9 +38,9 @@ use crate::schema::{AssignmentsSchema, GlobalSchema}; use crate::validation::{CheckedConsignment, ConsignmentApi}; use crate::vm::{ContractStateAccess, ContractStateEvolve, OpInfo, OrdOpRef, RgbIsa, VmContext}; use crate::{ - validation, Assign, AssignmentType, Assignments, AssignmentsRef, ExposedSeal, ExposedState, - GlobalState, GlobalStateSchema, GlobalValues, GraphSeal, Inputs, MetaSchema, Metadata, OpId, - Operation, Opout, OwnedStateSchema, RevealedState, Schema, SealClosingStrategy, Transition, + validation, AnyState, Assign, AssignmentType, Assignments, AssignmentsRef, ExposedSeal, + ExposedState, GlobalState, GlobalStateSchema, GlobalValues, GraphSeal, Inputs, MetaSchema, + Metadata, OpId, Operation, Opout, OwnedStateSchema, Schema, SealClosingStrategy, Transition, TypedAssigns, }; @@ -478,9 +478,9 @@ impl OwnedStateSchema { match data { Assign::Revealed { state, .. } | Assign::ConfidentialSeal { state, .. } => { match (self, state.state_data()) { - (OwnedStateSchema::Declarative, RevealedState::Void) => {} - (OwnedStateSchema::Fungible, RevealedState::Fungible(_)) => {} - (OwnedStateSchema::Structured(sem_id), RevealedState::Structured(data)) => { + (OwnedStateSchema::Declarative, AnyState::Void) => {} + (OwnedStateSchema::Fungible, AnyState::Fungible(_)) => {} + (OwnedStateSchema::Structured(sem_id), AnyState::Structured(data)) => { if type_system .strict_deserialize_type(*sem_id, data.as_ref()) .is_err() diff --git a/src/vm/contract.rs b/src/vm/contract.rs index e4e1d1c8..621df2cf 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -34,7 +34,7 @@ use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use crate::{ AssignmentType, Assignments, AssignmentsRef, BundleId, ContractId, FungibleState, Genesis, GlobalState, GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, - RevealedData, Transition, TransitionType, TypedAssigns, LIB_NAME_RGB_LOGIC, + StructureddData, Transition, TransitionType, TypedAssigns, LIB_NAME_RGB_LOGIC, }; /// The type is used during validation and computing a contract state. It @@ -387,7 +387,7 @@ impl GlobalOrd { } pub trait GlobalStateIter { - type Data: Borrow; + type Data: Borrow; fn size(&mut self) -> u24; fn prev(&mut self) -> Option<(GlobalOrd, Self::Data)>; fn last(&mut self) -> Option<(GlobalOrd, Self::Data)>; @@ -439,7 +439,7 @@ impl GlobalContractState { /// Retrieves global state data located `depth` items back from the most /// recent global state value. Ensures that the global state ordering is /// consensus-based. - pub fn nth(&mut self, depth: u24) -> Option + '_> { + pub fn nth(&mut self, depth: u24) -> Option + '_> { if depth > self.iter.size() { return None; } @@ -492,7 +492,7 @@ pub trait ContractStateAccess: Debug { &self, outpoint: Outpoint, ty: AssignmentType, - ) -> impl DoubleEndedIterator>; + ) -> impl DoubleEndedIterator>; } pub trait ContractStateEvolve { From 4620d57189b2bad6ad1cfdfb1962fc83379cc978 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 09:21:39 +0200 Subject: [PATCH 05/23] chore: remove `revealed` from state-related method names in assignments --- src/operation/assignments.rs | 46 +++++++++++++++++------------------- src/operation/commit.rs | 2 +- src/operation/operations.rs | 5 +--- src/validation/logic.rs | 2 +- src/vm/op_contract.rs | 4 ++-- 5 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/operation/assignments.rs b/src/operation/assignments.rs index e2633be3..9e55b849 100644 --- a/src/operation/assignments.rs +++ b/src/operation/assignments.rs @@ -92,7 +92,7 @@ pub enum Assign { #[strict_type(tag = 0x00)] Revealed { seal: Seal, state: State }, #[strict_type(tag = 0x01)] - ConfidentialSeal { seal: SecretSeal, state: State }, + SecretSeal { seal: SecretSeal, state: State }, } // Consensus-critical! @@ -115,7 +115,7 @@ impl Assign { pub fn with_seal_replaced(assignment: &Self, seal: Seal) -> Self { match assignment { - Assign::ConfidentialSeal { seal: _, state } | Assign::Revealed { seal: _, state } => { + Assign::SecretSeal { seal: _, state } | Assign::Revealed { seal: _, state } => { Assign::Revealed { seal, state: state.clone(), @@ -127,32 +127,32 @@ impl Assign { pub fn to_confidential_seal(&self) -> SecretSeal { match self { Assign::Revealed { seal, .. } => seal.conceal(), - Assign::ConfidentialSeal { seal, .. } => *seal, + Assign::SecretSeal { seal, .. } => *seal, } } pub fn revealed_seal(&self) -> Option { match self { Assign::Revealed { seal, .. } => Some(*seal), - Assign::ConfidentialSeal { .. } => None, + Assign::SecretSeal { .. } => None, } } - pub fn as_revealed_state(&self) -> &State { + pub fn as_state(&self) -> &State { match self { - Assign::Revealed { state, .. } | Assign::ConfidentialSeal { state, .. } => state, + Assign::Revealed { state, .. } | Assign::SecretSeal { state, .. } => state, } } - pub fn as_revealed_state_mut(&mut self) -> &mut State { + pub fn as_state_mut(&mut self) -> &mut State { match self { - Assign::Revealed { state, .. } | Assign::ConfidentialSeal { state, .. } => state, + Assign::Revealed { state, .. } | Assign::SecretSeal { state, .. } => state, } } - pub fn into_revealed_state(self) -> State { + pub fn into_state(self) -> State { match self { - Assign::Revealed { state, .. } | Assign::ConfidentialSeal { state, .. } => state, + Assign::Revealed { state, .. } | Assign::SecretSeal { state, .. } => state, } } @@ -185,11 +185,11 @@ where Self: Clone fn conceal(&self) -> Self::Concealed { match self { - Assign::Revealed { seal, state } => Self::ConfidentialSeal { + Assign::Revealed { seal, state } => Self::SecretSeal { seal: seal.conceal(), state: state.clone(), }, - Assign::ConfidentialSeal { .. } => self.clone(), + Assign::SecretSeal { .. } => self.clone(), } } } @@ -197,7 +197,7 @@ where Self: Clone impl Assign { pub fn transmutate_seals(&self) -> Assign { match self { - Assign::ConfidentialSeal { seal, state } => Assign::ConfidentialSeal { + Assign::SecretSeal { seal, state } => Assign::SecretSeal { seal: *seal, state: state.clone(), }, @@ -365,7 +365,7 @@ impl TypedAssigns { ) { for assign in vec.iter_mut() { match assign { - Assign::ConfidentialSeal { seal, state } if *seal == revealed.conceal() => { + Assign::SecretSeal { seal, state } if *seal == revealed.conceal() => { *assign = Assign::Revealed { seal: revealed, state: state.clone(), @@ -402,20 +402,18 @@ impl TypedAssigns { pub fn as_structured_state_at(&self, index: u16) -> Result<&StructureddData, UnknownDataError> { match self { - TypedAssigns::Structured(vec) => Ok(vec - .get(index as usize) - .ok_or(UnknownDataError)? - .as_revealed_state()), + TypedAssigns::Structured(vec) => { + Ok(vec.get(index as usize).ok_or(UnknownDataError)?.as_state()) + } _ => Err(UnknownDataError), } } pub fn as_fungible_state_at(&self, index: u16) -> Result<&FungibleState, UnknownDataError> { match self { - TypedAssigns::Fungible(vec) => Ok(vec - .get(index as usize) - .ok_or(UnknownDataError)? - .as_revealed_state()), + TypedAssigns::Fungible(vec) => { + Ok(vec.get(index as usize).ok_or(UnknownDataError)?.as_state()) + } _ => Err(UnknownDataError), } } @@ -426,7 +424,7 @@ impl TypedAssigns { if index as usize >= vec.len() { return Err(UnknownDataError); } - Ok(vec.0.release().remove(index as usize).into_revealed_state()) + Ok(vec.0.release().remove(index as usize).into_state()) } _ => Err(UnknownDataError), } @@ -438,7 +436,7 @@ impl TypedAssigns { if index as usize >= vec.len() { return Err(UnknownDataError); } - Ok(vec.0.release().remove(index as usize).into_revealed_state()) + Ok(vec.0.release().remove(index as usize).into_state()) } _ => Err(UnknownDataError), } diff --git a/src/operation/commit.rs b/src/operation/commit.rs index 47fa38a8..6ff0b17a 100644 --- a/src/operation/commit.rs +++ b/src/operation/commit.rs @@ -330,7 +330,7 @@ impl CommitEncode for AssignmentCommitment { impl Assign { pub fn commitment(&self, ty: AssignmentType) -> AssignmentCommitment { - let Self::ConfidentialSeal { seal, state } = self.conceal() else { + let Self::SecretSeal { seal, state } = self.conceal() else { unreachable!(); }; AssignmentCommitment { diff --git a/src/operation/operations.rs b/src/operation/operations.rs index 2482fe82..9090754c 100644 --- a/src/operation/operations.rs +++ b/src/operation/operations.rs @@ -143,10 +143,7 @@ pub trait Operation { if let Some(seal) = assignment.revealed_seal() { seals.insert(AssignmentIndex::new(ty, index as u16), seal.to_secret_seal()); } - state.insert( - AssignmentIndex::new(ty, index as u16), - assignment.as_revealed_state().clone(), - ); + state.insert(AssignmentIndex::new(ty, index as u16), assignment.as_state().clone()); } } diff --git a/src/validation/logic.rs b/src/validation/logic.rs index 8f44f590..ae3e2042 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -476,7 +476,7 @@ impl OwnedStateSchema { ) -> validation::Status { let mut status = validation::Status::new(); match data { - Assign::Revealed { state, .. } | Assign::ConfidentialSeal { state, .. } => { + Assign::Revealed { state, .. } | Assign::SecretSeal { state, .. } => { match (self, state.state_data()) { (OwnedStateSchema::Declarative, AnyState::Void) => {} (OwnedStateSchema::Fungible, AnyState::Fungible(_)) => {} diff --git a/src/vm/op_contract.rs b/src/vm/op_contract.rs index 18f022c8..73b43686 100644 --- a/src/vm/op_contract.rs +++ b/src/vm/op_contract.rs @@ -269,7 +269,7 @@ impl InstructionSet for ContractOp { match context.op_info.prev_state.get($state_type) { Some(TypedAssigns::Fungible(state)) => { let mut values = vec![]; - for val in state.iter().map(Assign::as_revealed_state) { + for val in state.iter().map(Assign::as_state) { values.push(val.into_inner()) } values @@ -284,7 +284,7 @@ impl InstructionSet for ContractOp { match context.op_info.owned_state().get(*$state_type) { Some(TypedAssigns::Fungible(state)) => { let mut values = vec![]; - for val in state.iter().map(Assign::as_revealed_state) { + for val in state.iter().map(Assign::as_state) { values.push(val.into_inner()) } values From 9c2aa52b693f80d33f2194221f729969f9014615 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 09:51:36 +0200 Subject: [PATCH 06/23] epic: remove transition bundles --- src/bin/rgbcore-stl.rs | 12 +- src/operation/bundle.rs | 153 --------------------- src/operation/commit.rs | 53 ++----- src/operation/mod.rs | 6 +- src/stl.rs | 7 +- src/validation/consignment.rs | 23 +--- src/validation/status.rs | 39 ++---- src/validation/validator.rs | 251 +++++++++++++--------------------- src/vm/contract.rs | 13 +- stl/TransitionBundle.vesper | 99 -------------- 10 files changed, 141 insertions(+), 515 deletions(-) delete mode 100644 src/operation/bundle.rs delete mode 100644 stl/TransitionBundle.vesper diff --git a/src/bin/rgbcore-stl.rs b/src/bin/rgbcore-stl.rs index 9aac2db0..5a1bc3b3 100644 --- a/src/bin/rgbcore-stl.rs +++ b/src/bin/rgbcore-stl.rs @@ -28,7 +28,7 @@ use bp::stl::bp_core_stl; use commit_verify::stl::commit_verify_stl; use commit_verify::CommitmentLayout; use rgbcore::stl::{bp_consensus_stl, bp_tx_stl}; -use rgbcore::{Schema, Transition, TransitionBundle}; +use rgbcore::{Genesis, Schema, Transition}; use strict_types::stl::{std_stl, strict_types_stl}; use strict_types::typelib::parse_args; use strict_types::SystemBuilder; @@ -138,10 +138,12 @@ Transition vesper lexicon=types+commitments writeln!(file, "{layout}").unwrap(); let tt = sys.type_tree("RGBCommit.OpCommitment").unwrap(); writeln!(file, "{tt}").unwrap(); + let tt = sys.type_tree("RGBLogic.DbcProof").unwrap(); + writeln!(file, "{tt}").unwrap(); let tt = sys.type_tree("RGBCommit.Transition").unwrap(); writeln!(file, "{tt}").unwrap(); - let mut file = fs::File::create(format!("{dir}/TransitionBundle.vesper")).unwrap(); + let mut file = fs::File::create(format!("{dir}/Genesis.vesper")).unwrap(); writeln!( file, "{{- @@ -155,10 +157,8 @@ Bundles vesper lexicon=types+commitments " ) .unwrap(); - let layout = TransitionBundle::commitment_layout(); + let layout = Genesis::commitment_layout(); writeln!(file, "{layout}").unwrap(); - let tt = sys.type_tree("RGBLogic.DbcProof").unwrap(); - writeln!(file, "{tt}").unwrap(); - let tt = sys.type_tree("RGBCommit.TransitionBundle").unwrap(); + let tt = sys.type_tree("RGBCommit.Genesis").unwrap(); writeln!(file, "{tt}").unwrap(); } diff --git a/src/operation/bundle.rs b/src/operation/bundle.rs deleted file mode 100644 index 10412bc7..00000000 --- a/src/operation/bundle.rs +++ /dev/null @@ -1,153 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2024 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_set; -use std::iter; - -use amplify::confinement::{NonEmptyOrdMap, NonEmptyOrdSet, U16 as U16MAX}; -use amplify::{Bytes32, Wrapper}; -use bp::Vout; -use commit_verify::{mpc, CommitEncode, CommitEngine, CommitId, CommitmentId, DigestExt, Sha256}; -use strict_encoding::{StrictDumb, StrictEncode}; - -use super::GraphSeal; -use crate::operation::operations::Operation; -use crate::{OpId, Transition, LIB_NAME_RGB_COMMIT}; - -pub type Vin = Vout; - -/// 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, Display, Hex, Index, RangeOps)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct BundleId( - #[from] - #[from([u8; 32])] - Bytes32, -); - -impl From for BundleId { - fn from(hasher: Sha256) -> Self { hasher.finish().into() } -} - -impl CommitmentId for BundleId { - const TAG: &'static str = "urn:lnp-bp:rgb:bundle#2024-02-03"; -} - -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(Wrapper, WrapperMut, Clone, PartialEq, Eq, Hash, Debug, From)] -#[wrapper(Deref)] -#[wrapper_mut(DerefMut)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT, dumb = Self(NonEmptyOrdSet::with(OpId::strict_dumb())))] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct InputOpids(NonEmptyOrdSet); - -impl<'a> IntoIterator for &'a InputOpids { - type Item = OpId; - type IntoIter = iter::Copied>; - - fn into_iter(self) -> Self::IntoIter { self.0.iter().copied() } -} - -#[derive(Clone, Eq, PartialEq, Debug, Display, Error)] -#[display("state transition {0} is not a part of the bundle.")] -pub struct UnrelatedTransition(OpId); - -#[derive(Clone, PartialEq, Eq, Debug, From)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct TransitionBundle { - pub input_map: NonEmptyOrdMap, - pub known_transitions: NonEmptyOrdMap, -} - -impl CommitEncode for TransitionBundle { - type CommitmentId = BundleId; - - fn commit_encode(&self, e: &mut CommitEngine) { e.commit_to_map(&self.input_map); } -} - -impl StrictDumb for TransitionBundle { - fn strict_dumb() -> Self { - Self { - input_map: NonEmptyOrdMap::with_key_value(strict_dumb!(), strict_dumb!()), - known_transitions: NonEmptyOrdMap::with_key_value(strict_dumb!(), strict_dumb!()), - } - } -} - -impl TransitionBundle { - pub fn bundle_id(&self) -> BundleId { self.commit_id() } - - pub fn reveal_seal(&mut self, bundle_id: BundleId, seal: GraphSeal) -> bool { - if self.bundle_id() != bundle_id { - return false; - } - self.known_transitions - .values_mut() - .flat_map(|t| t.assignments.values_mut()) - .for_each(|a| a.reveal_seal(seal)); - - true - } - - pub fn reveal_transition( - &mut self, - transition: Transition, - ) -> Result { - let opid = transition.id(); - if self.input_map.values().all(|ids| !ids.contains(&opid)) { - return Err(UnrelatedTransition(opid)); - } - if self.known_transitions.contains_key(&opid) { - return Ok(false); - } - self.known_transitions - .insert(opid, transition) - .expect("same size as input map"); - Ok(true) - } -} diff --git a/src/operation/commit.rs b/src/operation/commit.rs index 6ff0b17a..bf51ca0a 100644 --- a/src/operation/commit.rs +++ b/src/operation/commit.rs @@ -20,12 +20,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::collections::BTreeSet; use std::fmt::{Display, Formatter}; use std::str::FromStr; use std::{fmt, vec}; -use amplify::confinement::{Confined, MediumOrdMap, U16 as U16MAX}; +use amplify::confinement::MediumOrdMap; use amplify::hex::{FromHex, ToHex}; use amplify::num::u256; use amplify::{hex, ByteArray, Bytes32, FromSliceError, Wrapper}; @@ -37,10 +36,10 @@ use commit_verify::{ use strict_encoding::StrictDumb; use crate::{ - impl_serde_baid64, AnyState, Assign, AssignmentType, Assignments, BundleId, ChainNet, - ExposedSeal, ExposedState, Ffv, FungibleState, Genesis, GlobalState, GlobalStateType, - Operation, SchemaId, SealClosingStrategy, SecretSeal, StructureddData, Transition, - TransitionBundle, TransitionType, TypedAssigns, LIB_NAME_RGB_COMMIT, + impl_serde_baid64, AnyState, Assign, AssignmentType, Assignments, ChainNet, ExposedSeal, + ExposedState, Ffv, FungibleState, Genesis, GlobalState, GlobalStateType, Operation, SchemaId, + SealClosingStrategy, SecretSeal, StructureddData, Transition, TransitionType, TypedAssigns, + LIB_NAME_RGB_COMMIT, }; /// Unique contract identifier equivalent to the contract genesis commitment @@ -120,6 +119,14 @@ impl CommitmentId for OpId { const TAG: &'static str = "urn:lnp-bp:rgb:operation#2024-02-03"; } +impl From for mpc::Message { + fn from(id: OpId) -> Self { mpc::Message::from_inner(id.into_inner()) } +} + +impl From for OpId { + fn from(id: mpc::Message) -> Self { OpId(id.into_inner()) } +} + impl FromStr for OpId { type Err = hex::Error; fn from_str(s: &str) -> Result { Self::from_hex(s) } @@ -192,40 +199,6 @@ pub struct OpDisclose { pub data: MediumOrdMap, } -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -#[derive(CommitEncode)] -#[commit_encode(strategy = strict, id = DiscloseHash)] -pub struct BundleDisclosure { - pub id: BundleId, - pub known_transitions: Confined, 1, U16MAX>, -} - -impl StrictDumb for BundleDisclosure { - fn strict_dumb() -> Self { - Self { - id: strict_dumb!(), - known_transitions: Confined::with(strict_dumb!()), - } - } -} - -impl TransitionBundle { - /// Provides summary about parts of the bundle which are revealed. - pub fn disclose(&self) -> BundleDisclosure { - BundleDisclosure { - id: self.bundle_id(), - known_transitions: Confined::from_iter_checked( - self.known_transitions.values().map(|t| t.disclose_hash()), - ), - } - } - - /// Returns commitment to the bundle plus revealed data within it. - pub fn disclose_hash(&self) -> DiscloseHash { self.disclose().commit_id() } -} - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_COMMIT)] diff --git a/src/operation/mod.rs b/src/operation/mod.rs index 1ffa82b5..87a910cc 100644 --- a/src/operation/mod.rs +++ b/src/operation/mod.rs @@ -28,17 +28,15 @@ mod state; pub mod seal; pub mod assignments; mod operations; -mod bundle; mod layer1; mod commit; pub use assignments::{ Assign, AssignData, AssignFungible, AssignRights, Assignments, AssignmentsRef, TypedAssigns, }; -pub use bundle::{BundleId, InputOpids, TransitionBundle, UnrelatedTransition, Vin}; pub use commit::{ - AssignmentCommitment, AssignmentIndex, BaseCommitment, BundleDisclosure, ContractId, - DiscloseHash, GlobalCommitment, OpCommitment, OpDisclose, OpId, TypeCommitment, + AssignmentCommitment, AssignmentIndex, BaseCommitment, ContractId, DiscloseHash, + GlobalCommitment, OpCommitment, OpDisclose, OpId, TypeCommitment, }; pub use data::{StructureddData, VoidState}; pub use fungible::FungibleState; diff --git a/src/stl.rs b/src/stl.rs index c8ba2a06..02bc9b3d 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -31,10 +31,7 @@ use strict_types::{CompileError, TypeLib}; use crate::validation::DbcProof; use crate::vm::GlobalOrd; -use crate::{ - BundleId, Genesis, OpCommitment, Schema, TransitionBundle, LIB_NAME_RGB_COMMIT, - LIB_NAME_RGB_LOGIC, -}; +use crate::{Genesis, OpCommitment, Schema, LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_COMMIT: &str = @@ -56,8 +53,6 @@ fn _rgb_commit_stl() -> Result> { .transpile::() .transpile::() .transpile::() - .transpile::() - .transpile::() .transpile::() .compile()?) } diff --git a/src/validation/consignment.rs b/src/validation/consignment.rs index 1f5cc8ce..b7abcbf7 100644 --- a/src/validation/consignment.rs +++ b/src/validation/consignment.rs @@ -30,8 +30,8 @@ use strict_types::TypeSystem; use super::EAnchor; use crate::{ - AssignmentType, AssignmentsRef, BundleId, ContractId, Genesis, GlobalState, GraphSeal, - Metadata, OpFullType, OpId, Operation, Schema, Transition, TransitionBundle, TypedAssigns, + AssignmentType, AssignmentsRef, ContractId, Genesis, GlobalState, GraphSeal, Metadata, + OpFullType, OpId, Operation, Schema, Transition, TypedAssigns, }; pub const CONSIGNMENT_MAX_LIBS: usize = 1024; @@ -123,15 +123,9 @@ impl ConsignmentApi for CheckedConsignment<'_, C> { fn genesis(&self) -> &Genesis { self.0.genesis() } - fn bundle_ids<'iter>(&self) -> impl Iterator + 'iter { self.0.bundle_ids() } + fn transitions(&self) -> impl Iterator { self.0.transitions() } - fn bundle(&self, bundle_id: BundleId) -> Option<&TransitionBundle> { - self.0 - .bundle(bundle_id) - .filter(|b| b.bundle_id() == bundle_id) - } - - fn anchor(&self, bundle_id: BundleId) -> Option<(Txid, &EAnchor)> { self.0.anchor(bundle_id) } + fn anchor(&self, opid: OpId) -> Option<(Txid, &EAnchor)> { self.0.anchor(opid) } fn op_witness_id(&self, opid: OpId) -> Option { self.0.op_witness_id(opid) } } @@ -161,14 +155,11 @@ pub trait ConsignmentApi { /// Contract genesis. fn genesis(&self) -> &Genesis; - /// Returns iterator over all bundle ids present in the consignment. - fn bundle_ids<'iter>(&self) -> impl Iterator + 'iter; - - /// Returns reference to a bundle given a bundle id. - fn bundle(&self, bundle_id: BundleId) -> Option<&TransitionBundle>; + /// Returns iterator over all transition ids present in the consignment. + fn transitions(&self) -> impl Iterator; /// Returns a grip given a bundle id. - fn anchor(&self, bundle_id: BundleId) -> Option<(Txid, &EAnchor)>; + fn anchor(&self, opid: OpId) -> Option<(Txid, &EAnchor)>; /// Returns witness id for a given operation. fn op_witness_id(&self, opid: OpId) -> Option; diff --git a/src/validation/status.rs b/src/validation/status.rs index 46e1cdd1..9e620e92 100644 --- a/src/validation/status.rs +++ b/src/validation/status.rs @@ -33,8 +33,8 @@ use strict_types::SemId; use crate::schema::{self, SchemaId}; use crate::validation::WitnessResolverError; use crate::{ - BundleId, ChainNet, ContractId, OccurrencesMismatch, OpFullType, OpId, Opout, - SealClosingStrategy, StateType, Vin, + ChainNet, ContractId, OccurrencesMismatch, OpFullType, OpId, Opout, SealClosingStrategy, + StateType, }; pub type UnsafeHistoryMap = HashMap>; @@ -243,32 +243,19 @@ pub enum Failure { CyclicGraph(OpId), /// operation {0} is absent from the consignment. OperationAbsent(OpId), - /// transition bundle {0} is absent in the consignment. - BundleAbsent(BundleId), - /// anchor for transitio bundle {0} is absent in the consignment. - AnchorAbsent(BundleId), - /// witness id for transition bundle {0} is absent in the consignment. - WitnessIdAbsent(BundleId), + /// anchor for transitio {0} is absent in the consignment. + AnchorAbsent(OpId), + /// witness id for transition {0} is absent in the consignment. + WitnessIdAbsent(OpId), /// bundle {0} public witness {1} is not known to the resolver; validation /// stopped since operations can't be consensus-ordered. The resolver /// responded with error {2} - WitnessUnresolved(BundleId, Txid, WitnessResolverError), + WitnessUnresolved(OpId, Txid, WitnessResolverError), /// operation {0} is under a different contract {1}. ContractMismatch(OpId, ContractId), /// opout {0} appears more than once as input DoubleSpend(Opout), - // Errors checking bundle commitments - /// transition bundle {0} references state transition {1} which is not - /// included into the bundle input map. - BundleExtraTransition(BundleId, OpId), - /// transition bundle {0} references non-existing input in witness {2} for - /// the state transition {1}. - BundleInvalidInput(BundleId, OpId, Txid), - /// transition bundle {0} doesn't commit to the input {1} in the witness {2} - /// which is an input of the state transition {3}. - BundleInvalidCommitment(BundleId, Vin, Txid, OpId), - // Errors checking seal closing /// transition {opid} references state type {state_type} absent in the /// outputs of previous state transition {prev_id}. @@ -282,18 +269,18 @@ pub enum Failure { /// seal defined in the history as a part of operation output {0} is /// confidential and can't be validated. ConfidentialSeal(Opout), - /// bundle {0} public witness {1} is not known to the resolver. Resolver + /// transition {0} public witness {1} is not known to the resolver. Resolver /// reported error {2} - SealNoPubWitness(BundleId, Txid, WitnessResolverError), - /// transition bundle {0} doesn't close seal with the witness {1}. Details: + SealNoPubWitness(OpId, Txid, WitnessResolverError), + /// transition {0} doesn't close seal with the witness {1}. Details: /// {2} - SealsInvalid(BundleId, Txid, String), + SealsInvalid(OpId, Txid, String), /// single-use seals for the operation {0} were not validated, which /// probably indicates unanchored state transition. SealsUnvalidated(OpId), - /// transition bundle {0} is not properly anchored to the witness {1}. + /// transition {0} is not properly anchored to the witness {1}. /// Details: {2} - MpcInvalid(BundleId, Txid, InvalidProof), + MpcInvalid(OpId, Txid, InvalidProof), /// witness transaction {0} has no taproot or OP_RETURN output. NoDbcOutput(Txid), /// first DBC-compatible output of witness transaction {0} doesn't match the provided proof diff --git a/src/validation/validator.rs b/src/validation/validator.rs index 4f4a5dfb..24a454ca 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -21,13 +21,13 @@ // limitations under the License. use std::cell::RefCell; -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::num::NonZeroU32; use std::rc::Rc; use bp::dbc::Anchor; use bp::seals::txout::{CloseMethod, Witness}; -use bp::{dbc, Outpoint, Tx, Txid}; +use bp::{dbc, Tx, Txid}; use commit_verify::mpc; use single_use_seals::SealWitness; @@ -36,8 +36,8 @@ use super::{CheckedConsignment, ConsignmentApi, EAnchor, Status, Validity}; use crate::operation::seal::ExposedSeal; use crate::vm::{ContractStateAccess, ContractStateEvolve, OrdOpRef, WitnessOrd}; use crate::{ - validation, BundleId, ChainNet, ContractId, OpFullType, OpId, Operation, Opout, OutputSeal, - Schema, SchemaId, TransitionBundle, + validation, ChainNet, ContractId, OpFullType, OpId, Operation, Opout, OutputSeal, Schema, + SchemaId, Transition, }; #[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] @@ -275,30 +275,27 @@ impl< // consensus ordering rules. let mut ops = BTreeSet::::new(); let mut unsafe_history_map: HashMap> = HashMap::new(); - for bundle_id in self.consignment.bundle_ids() { - let bundle = self - .consignment - .bundle(bundle_id) - .expect("invalid checked consignment"); + for transition in self.consignment.transitions() { + let opid = transition.id(); let (witness_id, _) = self .consignment - .anchor(bundle_id) + .anchor(opid) .expect("invalid checked consignment"); - let witness_ord = - match self.resolver.resolve_pub_witness_ord(witness_id) { - Ok(ord) => ord, - Err(err) => { - self.status.borrow_mut().add_failure( - validation::Failure::WitnessUnresolved(bundle_id, witness_id, err), - ); - // We need to stop validation there since we can't order operations - return; - } - }; + let witness_ord = match self.resolver.resolve_pub_witness_ord(witness_id) { + Ok(ord) => ord, + Err(err) => { + self.status + .borrow_mut() + .add_failure(validation::Failure::WitnessUnresolved(opid, witness_id, err)); + // We need to stop validation there since we can't order operations + return; + } + }; if let Some(safe_height) = self.safe_height { match witness_ord { WitnessOrd::Mined(witness_pos) => { let witness_height = witness_pos.height(); + // TODO: Safe height can't be "injected" into the consensus! if witness_height > safe_height { unsafe_history_map .entry(witness_height.into()) @@ -311,9 +308,7 @@ impl< } } } - for op in bundle.known_transitions.values() { - ops.insert(OrdOpRef::Transition(op, witness_id, witness_ord, bundle_id)); - } + ops.insert(OrdOpRef::Transition(transition, witness_id, witness_ord, opid)); } if self.safe_height.is_some() && !unsafe_history_map.is_empty() { self.status @@ -370,72 +365,20 @@ impl< // *** PART III: Validating single-use-seals fn validate_commitments(&mut self) { - for bundle_id in self.consignment.bundle_ids() { - let Some(bundle) = self.consignment.bundle(bundle_id) else { - self.status - .borrow_mut() - .add_failure(Failure::BundleAbsent(bundle_id)); - continue; - }; - let Some((witness_id, anchor)) = self.consignment.anchor(bundle_id) else { + for transition in self.consignment.transitions() { + let opid = transition.id(); + let Some((witness_id, anchor)) = self.consignment.anchor(opid) else { self.status .borrow_mut() - .add_failure(Failure::AnchorAbsent(bundle_id)); + .add_failure(Failure::AnchorAbsent(opid)); continue; }; // [VALIDATION]: We validate that the seals were properly defined on BP-type layer - let (seals, input_map) = self.validate_seal_definitions(bundle); + let seals = self.validate_seal_definitions(transition); // [VALIDATION]: We validate that the seals were properly closed on BP-type layer - let Some(witness_tx) = - self.validate_seal_commitments(&seals, bundle_id, witness_id, anchor) - else { - continue; - }; - - // [VALIDATION]: We validate bundle commitments to the input map - self.validate_bundle_commitments(bundle_id, bundle, witness_tx, input_map); - } - } - - /// Validates that the transition bundle is internally consistent: inputs of - /// its state transitions correspond to the way how they are committed - /// in the input map of the bundle; and these inputs are real inputs of - /// the transaction. - fn validate_bundle_commitments( - &self, - bundle_id: BundleId, - bundle: &TransitionBundle, - pub_witness: Tx, - input_map: BTreeMap>, - ) { - let witness_id = pub_witness.txid(); - for (vin, opids) in &bundle.input_map { - for opid in opids { - if self.trusted_op_seals.contains(&opid) { - continue; - } - let Some(outpoints) = input_map.get(&opid) else { - self.status - .borrow_mut() - .add_failure(Failure::BundleExtraTransition(bundle_id, opid)); - continue; - }; - let Some(input) = pub_witness.inputs.get(vin.to_usize()) else { - self.status - .borrow_mut() - .add_failure(Failure::BundleInvalidInput(bundle_id, opid, witness_id)); - continue; - }; - if !outpoints.contains(&input.prev_output) { - self.status - .borrow_mut() - .add_failure(Failure::BundleInvalidCommitment( - bundle_id, *vin, witness_id, opid, - )); - } - } + self.validate_seal_commitments(&seals, opid, witness_id, anchor); } } @@ -444,10 +387,10 @@ impl< fn validate_seal_commitments( &self, seals: impl AsRef<[OutputSeal]>, - bundle_id: BundleId, + opid: OpId, witness_id: Txid, anchor: &EAnchor, - ) -> Option { + ) { // Check that the anchor is committed into a transaction spending all the // transition inputs. // Here the method can do SPV proof instead of querying the indexer. The SPV @@ -465,14 +408,12 @@ impl< // failure!) self.status .borrow_mut() - .add_failure(Failure::SealNoPubWitness(bundle_id, witness_id, err)); - None + .add_failure(Failure::SealNoPubWitness(opid, witness_id, err)); } Ok(pub_witness) => { let seals = seals.as_ref(); let witness = Witness::with(pub_witness.clone(), anchor.dbc_proof.clone()); - self.validate_seal_closing(seals, bundle_id, witness, anchor.mpc_proof.clone()); - Some(pub_witness) + self.validate_seal_closing(seals, opid, witness, anchor.mpc_proof.clone()); } } } @@ -480,88 +421,80 @@ impl< /// Single-use-seal definition validation. /// /// Takes state transition, extracts all seals from its inputs and validates them. - fn validate_seal_definitions( - &self, - bundle: &TransitionBundle, - ) -> (Vec, BTreeMap>) { - let mut input_map: BTreeMap> = bmap!(); + fn validate_seal_definitions(&self, transition: &Transition) -> Vec { let mut seals = vec![]; - for (opid, transition) in &bundle.known_transitions { - if self.trusted_op_seals.contains(opid) { - continue; - } - let opid = *opid; - if !self.status.borrow_mut().validated_opids.insert(opid) { + let opid = transition.id(); + if self.trusted_op_seals.contains(&opid) { + panic!("remove trusted op seals injection!"); + } + + if !self.status.borrow_mut().validated_opids.insert(opid) { + self.status + .borrow_mut() + .add_failure(Failure::CyclicGraph(opid)); + } + + // Checking that witness transaction closes seals defined by transition previous + // outputs. + for input in &transition.inputs { + let Opout { op, ty, no } = input; + if !self.input_assignments.borrow_mut().insert(input) { self.status .borrow_mut() - .add_failure(Failure::CyclicGraph(opid)); + .add_failure(Failure::DoubleSpend(input)); } - // Checking that witness transaction closes seals defined by transition previous - // outputs. - for input in &transition.inputs { - let Opout { op, ty, no } = input; - if !self.input_assignments.borrow_mut().insert(input) { - self.status - .borrow_mut() - .add_failure(Failure::DoubleSpend(input)); - } + let Some(prev_op) = self.consignment.operation(op) else { + // Node, referenced as the ancestor, was not found in the consignment. + // Usually this means that the consignment data are broken + self.status + .borrow_mut() + .add_failure(Failure::OperationAbsent(op)); + continue; + }; - let Some(prev_op) = self.consignment.operation(op) else { - // Node, referenced as the ancestor, was not found in the consignment. - // Usually this means that the consignment data are broken - self.status - .borrow_mut() - .add_failure(Failure::OperationAbsent(op)); - continue; - }; + let Some(variant) = prev_op.assignments_by_type(ty) else { + self.status.borrow_mut().add_failure(Failure::NoPrevState { + opid, + prev_id: op, + state_type: ty, + }); + continue; + }; - let Some(variant) = prev_op.assignments_by_type(ty) else { - self.status.borrow_mut().add_failure(Failure::NoPrevState { - opid, - prev_id: op, - state_type: ty, - }); - continue; - }; + let Ok(seal) = variant.revealed_seal_at(no) else { + self.status + .borrow_mut() + .add_failure(Failure::NoPrevOut(opid, input)); + continue; + }; + let Some(seal) = seal else { + // Everything is ok, but we have incomplete data (confidential), thus can't do a + // full verification and have to report the failure + self.status + .borrow_mut() + .add_failure(Failure::ConfidentialSeal(input)); + continue; + }; - let Ok(seal) = variant.revealed_seal_at(no) else { + let seal = if matches!(prev_op.full_type(), OpFullType::StateTransition(_)) { + let Some(witness_id) = self.consignment.op_witness_id(op) else { self.status .borrow_mut() - .add_failure(Failure::NoPrevOut(opid, input)); - continue; - }; - let Some(seal) = seal else { - // Everything is ok, but we have incomplete data (confidential), thus can't do a - // full verification and have to report the failure - self.status - .borrow_mut() - .add_failure(Failure::ConfidentialSeal(input)); + .add_failure(Failure::OperationAbsent(op)); continue; }; + seal.to_output_seal_or_default(witness_id) + } else { + seal.to_output_seal() + .expect("genesis must have explicit seals") + }; - let seal = if matches!(prev_op.full_type(), OpFullType::StateTransition(_)) { - let Some(witness_id) = self.consignment.op_witness_id(op) else { - self.status - .borrow_mut() - .add_failure(Failure::OperationAbsent(op)); - continue; - }; - seal.to_output_seal_or_default(witness_id) - } else { - seal.to_output_seal() - .expect("genesis must have explicit seals") - }; - - seals.push(seal); - input_map - .entry(opid) - .or_default() - .insert(Outpoint::new(seal.txid, seal.vout)); - } + seals.push(seal); } - (seals, input_map) + + seals } /// Single-use-seal closing validation. @@ -577,13 +510,13 @@ impl< fn validate_seal_closing<'seal, Seal: 'seal, Dbc: dbc::Proof>( &self, seals: impl IntoIterator, - bundle_id: BundleId, + opid: OpId, witness: Witness, mpc_proof: mpc::MerkleProof, ) where Witness: SealWitness, { - let message = mpc::Message::from(bundle_id); + let message = mpc::Message::from(opid); let witness_id = witness.txid; let anchor = Anchor::new(mpc_proof, witness.proof.clone()); // [VALIDATION]: Checking anchor MPC commitment @@ -593,7 +526,7 @@ impl< // Ultimate failure. But continuing to detect the rest (after reporting it). self.status .borrow_mut() - .add_failure(Failure::MpcInvalid(bundle_id, witness_id, err)); + .add_failure(Failure::MpcInvalid(opid, witness_id, err)); } Ok(commitment) => { // [VALIDATION]: Verify commitment @@ -623,7 +556,7 @@ impl< .verify_many_seals(seals, &commitment) .map_err(|err| { self.status.borrow_mut().add_failure(Failure::SealsInvalid( - bundle_id, + opid, witness_id, err.to_string(), )); diff --git a/src/vm/contract.rs b/src/vm/contract.rs index 621df2cf..d31218cb 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -32,9 +32,9 @@ use bp::{BlockHeight, Outpoint, Txid}; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use crate::{ - AssignmentType, Assignments, AssignmentsRef, BundleId, ContractId, FungibleState, Genesis, - GlobalState, GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, - StructureddData, Transition, TransitionType, TypedAssigns, LIB_NAME_RGB_LOGIC, + AssignmentType, Assignments, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, + GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, StructureddData, + Transition, TransitionType, TypedAssigns, LIB_NAME_RGB_LOGIC, }; /// The type is used during validation and computing a contract state. It @@ -45,7 +45,7 @@ use crate::{ pub enum OrdOpRef<'op> { #[from] Genesis(&'op Genesis), - Transition(&'op Transition, Txid, WitnessOrd, BundleId), + Transition(&'op Transition, Txid, WitnessOrd, OpId), } impl PartialOrd for OrdOpRef<'_> { @@ -64,10 +64,10 @@ impl OrdOpRef<'_> { } } - pub fn bundle_id(&self) -> Option { + pub fn opid(&self) -> Option { match self { OrdOpRef::Genesis(_) => None, - OrdOpRef::Transition(_, _, _, bundle_id) => Some(*bundle_id), + OrdOpRef::Transition(_, _, _, opid) => Some(*opid), } } @@ -157,6 +157,7 @@ pub struct WitnessPos { #[getter(as_copy)] height: BlockHeight, + // TODO: Remove #[getter(as_copy)] timestamp: i64, } diff --git a/stl/TransitionBundle.vesper b/stl/TransitionBundle.vesper deleted file mode 100644 index 3e5c2384..00000000 --- a/stl/TransitionBundle.vesper +++ /dev/null @@ -1,99 +0,0 @@ -{- - Description: RGB Transition Bundles - Author: Dr Maxim Orlovsky - Copyright (C) 2024 LNP/BP Standards Association. All rights reserved. - License: Apache-2.0 --} - -Bundles vesper lexicon=types+commitments - -commitment BundleId, hasher SHA256, tagged urn:lnp-bp:rgb:bundle#2024-02-03 - map InputOpids, len 1..MAX16 - mapKey Vout - mapValue InputOpids - -union DbcProof - rec tapret, TapretProof, wrapped, tag 0 - rec pathProof, TapretPathProof - union some, TapretNodePartner, option, wrapped, tag 1 - bytes leftNode, len 32, wrapped, aka TapNodeHash, tag 0 - rec rightLeaf, LeafScript, wrapped, tag 1 - is version, U8, aka LeafVer - bytes script, len 0..MAX32, aka ScriptBytes - rec rightBranch, TapretRightBranch, wrapped, tag 2 - bytes leftNodeHash, len 32, aka TapNodeHash - bytes rightNodeHash, len 32, aka TapNodeHash - is nonce, U8 - bytes internalPk, len 32, aka InternalPk, aka XOnlyPk - is opret, Unit, wrapped, aka OpretProof, tag 1 - -rec TransitionBundle - map inputMap, len 1..MAX16 - is key, U32, aka Vout - set value, len 1..MAX16, aka InputOpids - bytes element, len 32, aka OpId - map knownTransitions, len 1..MAX16 - bytes key, len 32, aka OpId - rec value, Transition - is ffv, U16, aka Ffv - bytes contractId, len 32, aka ContractId - is nonce, U64 - is transitionType, U16, aka TransitionType - map metadata, len 0..MAX8, aka Metadata - is key, U16, aka MetaType - bytes value, len 0..MAX16, aka MetaValue - map globals, len 0..MAX8, aka GlobalState - is key, U16, aka GlobalStateType - list value, len 1..MAX16, aka GlobalValues - bytes element, len 0..MAX16, aka RevealedData - set inputs, len 1..MAX16, aka Inputs - rec Opout - bytes op, len 32, aka OpId - is ty, U16, aka AssignmentType - is no, U16 - map assignments, len 0..MAX16, aka AssignmentsBlindSealTxPtr - is key, U16, aka AssignmentType - union value, TypedAssignsBlindSealTxPtr - list declarative, len 1..MAX16, wrapped, aka AssignVecAssignVoidStateBlindSealTxPtr, tag 0 - union AssignVoidStateBlindSealTxPtr - rec revealed, tag 0 - rec seal, BlindSealTxPtr - union txid, TxPtr - is witnessTx, Unit, tag 0 - bytes txid, len 32, wrapped, aka Txid, tag 1 - is vout, U32, aka Vout - is blinding, U64 - is state, Unit, aka VoidState - rec confidentialSeal, tag 1 - bytes seal, len 32, aka SecretSeal - is state, Unit, aka VoidState - list fungible, len 1..MAX16, wrapped, aka AssignVecAssignRevealedValueBlindSealTxPtr, tag 1 - union AssignRevealedValueBlindSealTxPtr - rec revealed, tag 0 - rec seal, BlindSealTxPtr - union txid, TxPtr - is witnessTx, Unit, tag 0 - bytes txid, len 32, wrapped, aka Txid, tag 1 - is vout, U32, aka Vout - is blinding, U64 - union state, FungibleState, aka RevealedValue - is bits64, U64, wrapped, tag 0 - rec confidentialSeal, tag 1 - bytes seal, len 32, aka SecretSeal - union state, FungibleState, aka RevealedValue - is bits64, U64, wrapped, tag 0 - list structured, len 1..MAX16, wrapped, aka AssignVecAssignRevealedDataBlindSealTxPtr, tag 2 - union AssignRevealedDataBlindSealTxPtr - rec revealed, tag 0 - rec seal, BlindSealTxPtr - union txid, TxPtr - is witnessTx, Unit, tag 0 - bytes txid, len 32, wrapped, aka Txid, tag 1 - is vout, U32, aka Vout - is blinding, U64 - bytes state, len 0..MAX16, aka RevealedData - rec confidentialSeal, tag 1 - bytes seal, len 32, aka SecretSeal - bytes state, len 0..MAX16, aka RevealedData - bytes some, len 64, option, wrapped, aka Signature, tag 1 - From dc771d19f2d37167af8b26bbca7e7a83a56196b7 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 09:57:36 +0200 Subject: [PATCH 07/23] stl: regenerate --- src/stl.rs | 8 +- stl/Genesis.vesper | 63 ++++++++++ stl/RGBCommit@0.1.0.sta | 252 +++++++++++++++++++--------------------- stl/RGBCommit@0.1.0.stl | Bin 9158 -> 8687 bytes stl/RGBCommit@0.1.0.sty | 96 +++++++-------- stl/RGBLogic@0.1.0.sta | 20 ++-- stl/RGBLogic@0.1.0.stl | Bin 1378 -> 1378 bytes stl/RGBLogic@0.1.0.sty | 10 +- stl/Schema.vesper | 2 +- stl/Transition.vesper | 41 ++++--- 10 files changed, 272 insertions(+), 220 deletions(-) create mode 100644 stl/Genesis.vesper diff --git a/src/stl.rs b/src/stl.rs index 02bc9b3d..a5c8cbb6 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -31,14 +31,14 @@ use strict_types::{CompileError, TypeLib}; use crate::validation::DbcProof; use crate::vm::GlobalOrd; -use crate::{Genesis, OpCommitment, Schema, LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; +use crate::{Genesis, OpCommitment, Schema, Transition, LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_COMMIT: &str = - "stl:XbiECcs9-xlyofco-wkXoupT-gJ61JJf-XWL0DWf-INKzIp0#support-iris-depend"; + "stl:4j4rCC1R-6vHqghw-KSKgmbD-Ec9DPDA-IRqa6~L-aZ_1GRM#susan-olympic-minute"; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_LOGIC: &str = - "stl:qolQpjNB-4ZkpJIo-U1tktjI-mwAYyEg-kOGQttY-ZoK3Loo#colombo-famous-erosion"; + "stl:iCs0AShc-KXU0vsu-te5lPow-NY7LYgX-i~LFvvl-1hVcbRw#jump-heaven-binary"; fn _rgb_commit_stl() -> Result> { Ok(LibBuilder::with(libname!(LIB_NAME_RGB_COMMIT), [ @@ -50,8 +50,8 @@ fn _rgb_commit_stl() -> Result> { aluvm_stl().to_dependency_types(), ]) .transpile::() - .transpile::() .transpile::() + .transpile::() .transpile::() .transpile::() .compile()?) diff --git a/stl/Genesis.vesper b/stl/Genesis.vesper new file mode 100644 index 00000000..e3ef95cf --- /dev/null +++ b/stl/Genesis.vesper @@ -0,0 +1,63 @@ +{- + Description: RGB Transition Bundles + Author: Dr Maxim Orlovsky + Copyright (C) 2024 LNP/BP Standards Association. All rights reserved. + License: Apache-2.0 +-} + +Bundles vesper lexicon=types+commitments + +commitment OpId, hasher SHA256, tagged urn:lnp-bp:rgb:operation#2024-02-03 + serialized OpCommitment + +rec Genesis + is ffv, U16, aka Ffv + bytes schemaId, len 32, aka SchemaId + is timestamp, I64 + ascii issuer, aka Identity, first AsciiPrintable, rest AsciiPrintable, len 1..4096 + enum chainNet, ChainNet, bitcoinMainnet 0, bitcoinTestnet3 1, bitcoinTestnet4 2, bitcoinSignet 3, bitcoinRegtest 4, liquidMainnet 5, liquidTestnet 6 + enum sealClosingStrategy, SealClosingStrategy, firstOpretOrTapret 0 + map metadata, len 0..MAX8, aka Metadata + is key, U16, aka MetaType + bytes value, len 0..MAX16, aka MetaValue + map globals, len 0..MAX8, aka GlobalState + is key, U16, aka GlobalStateType + list value, len 1..MAX16, aka GlobalValues + bytes element, len 0..MAX16, aka StructureddData + map assignments, len 0..MAX16, aka AssignmentsBlindSealTxid + is key, U16, aka AssignmentType + union value, TypedAssignsBlindSealTxid + list declarative, len 1..MAX16, wrapped, aka AssignVecAssignVoidStateBlindSealTxid, tag 0 + union AssignVoidStateBlindSealTxid + rec revealed, tag 0 + rec seal, BlindSealTxid + bytes txid, len 32, aka Txid + is vout, U32, aka Vout + is blinding, U64 + is state, Unit, aka VoidState + rec secretSeal, tag 1 + bytes seal, len 32, aka SecretSeal + is state, Unit, aka VoidState + list fungible, len 1..MAX16, wrapped, aka AssignVecAssignFungibleStateBlindSealTxid, tag 1 + union AssignFungibleStateBlindSealTxid + rec revealed, tag 0 + rec seal, BlindSealTxid + bytes txid, len 32, aka Txid + is vout, U32, aka Vout + is blinding, U64 + is state, U64, aka FungibleState + rec secretSeal, tag 1 + bytes seal, len 32, aka SecretSeal + is state, U64, aka FungibleState + list structured, len 1..MAX16, wrapped, aka AssignVecAssignStructureddDataBlindSealTxid, tag 2 + union AssignStructureddDataBlindSealTxid + rec revealed, tag 0 + rec seal, BlindSealTxid + bytes txid, len 32, aka Txid + is vout, U32, aka Vout + is blinding, U64 + bytes state, len 0..MAX16, aka StructureddData + rec secretSeal, tag 1 + bytes seal, len 32, aka SecretSeal + bytes state, len 0..MAX16, aka StructureddData + diff --git a/stl/RGBCommit@0.1.0.sta b/stl/RGBCommit@0.1.0.sta index 44614e51..2c2ffcf2 100644 --- a/stl/RGBCommit@0.1.0.sta +++ b/stl/RGBCommit@0.1.0.sta @@ -1,5 +1,5 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:XbiECcs9-xlyofco-wkXoupT-gJ61JJf-XWL0DWf-INKzIp0#support-iris-depend +Id: stl:4j4rCC1R-6vHqghw-KSKgmbD-Ec9DPDA-IRqa6~L-aZ_1GRM#susan-olympic-minute Name: RGBCommit Dependencies: BPCore#juliet-super-dominic, @@ -8,7 +8,7 @@ Dependencies: AluVM#jargon-gorilla-poetic, StrictTypes#henry-heart-survive, Bitcoin#signal-color-cipher -Check-SHA256: d929bd2f8100135aeea673c5949e0a762b52943dd8ebe2c0156e02c453d4294f +Check-SHA256: ceef12091bb2a30ef26c112e446f801c2f402f33c0609fb38ae43804c1b59e3c 2~tNwLvL+uX>pKz(VCaX%3mIP&XB&sB3y@ML2MxM-cip;h4&;#rLQq3*a%D_q7H}ii_tAk8EiIL^ F;WduOYhK!;vHZzZO$@xxWWuWZ*6U9bXH|@X=ZtXiR(=d3vg7gbV~*3!PlK51EySK%g?1}nECovJTYnm @@ -26,134 +26,126 @@ NMUnm15ioJpYH;+t0eX2w~A!Q -+0eaZ{MVycPK^aqWo=1hIRGF*b8~5DZc=4-WnpY(WJFcz4~pa1P{=r>OF|0}@Y#k~NrxRcQq+F$P2q2)nlU -E64L7%3W7R1#@&^bY%e`@=#VHk7myNk^1UqykExfX%7&o7^|1Fn59cLW!>7R25;!; -BSw%P#_(xeJx6(SSwF1NH_CEIWgkIvb7^O8Qe}2!VQgh& -L}7GcLTqVnWK(5fY*ct@WCQ{L2y$h1WnpY(WB>*N1aoC!Yyv&&I}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D --MVlN`(=BbYXO50U+{FRw9pP&is-3>Sw%P#_(xe -Jx6(SSwF1NH_CEIWdRUlZ*FF3WMyu2X<=+rWnpXp1_A_gWnpXrJ?lFX3Sj7m#S0l<6lWWUs|%1)CkG9> -cz4~pa1P{=Xc_Cg)w39@m$R6qOEzWQ+NTC@=;*N -1aoC!Yyv&&I}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlNcz4~pa1P{=Xc_Cg)w39@m$R6qOEzWQ+NTC@=;hpP*aQYQxux_Ecp -x^NEUkt_p^NJ~fc1UzTDb_LBRjrSXj?;k=^zm6d~Uh7!wPz7^zVRU5y;>Mp{wIfQLx1JC|lRtv}2|vJ# -Rj;5&YI0c6F%?4p0T5$vZf0p@Wo~q7VQf=nVQc^f0t9nqVQd0D>pKz(VCaX%3mIP&XB&sB3y@ML2MxM- -cip;h4&;$&8SA{&vly$FvzVnzHf7z~rv`86=_Ka^V5yX|y#`JNb97;JWdY*GpIx;hN}RWz5J8hag8d0U -z>8I{phs$QSkN&QLjNg2b8~5DZdPSuL349yXKqquc4c8~Wn@HQbYVhlX>MdwWnpYocu;h51pxpE0SrRj -skq)xpV`Gw<@$3$0NV?f{JPT8u3(v#XUGyU%mDxZ000000RR600000004PCob7^O8R%K&Bb8~5DZc=4- -WnpY(WJFIGsVJuTN&(i?_00000 -0096000000001UIb8~5DZdPSuL349yXKq$+X=GD$VRU6eY-w&}Q)OXnRCrKyas>eZ2muyOO0=mQ@c;WkPIeZe&wsVQf@*P;_zx0sshdWp-s@Y-MBs1_A_gWnpXrJ?lFX3Sj7m#S0l< -6lWWUs|%1)CkG9>cz4~pa1P{=r>OF|0}@Y#k~NrxRcQq+F$P2q2)nlUE64L7%3W7R1#@&^bY%f9vZekP -z%WEGnBZKS8(M7E9_@AwVcyGtCevi|7U8=A5Mys{W@%()Zggp3Y*S@nYybuV1aoC!Yyv&&I}!?D=!eA% -8DA7<8;7e4kWwcH4Z3)D-MVlN%7&o7^|1Fn59cLW!>7R25;!;BwOY}Ov_b`4?P%YY`+Wb+o`yBtAtb7^O8R&Qx!Q*>c;WkPIeZe&wsVQf@*X=DTf00?qr -c4c8~Wn=&b0t9nqVQd0D>pKz(VCaX%3mIP&XB&sB3y@ML2MxM-cip;h4&;$61C2;aNA(0eXS#L;%_oib -8;tKCLQ=nuAv#{`SnN;*b97;JWdSa-rT!PdFhnqz;9Q#hpP*aQYQxux_Ecpx^NEUk!Ts~yw$T9tCzEwrAszt --P)%HZ|LbH=L2A=l(W4CP6cyxVRU5yF0!Tm7r-z?Fqq(6n;Tke)*kJ44PoBPfF{#q^A_Q|5kYfvX=iS2 -Wo~ptWprU_Y;y(!5N~&GWn@!yVRU6vV`yb7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj065I6*X)C9iYp+?yjr7~y^L349yXKrm} -Zgf<6aAgGn0006RL349yXKrm}Zgg`(Y-w&}Q)OXnRCrKyas>eZ3IT`y;$>KfZ0H=mhJ>?uV_ -ZDC1d0hChH+XJhss8OG%_CC-Q>(otsF+cqN0Qy}ddQ=3E5D9c?ZDn(GVQp{#07wRDb8~fNaso_c7H}ii -_tAk8EiIL^F;WduOYhK!;vHZzZO$@xxWa9(t;O}HAO^^zqT0%g+nC0;-MWK<)&Ge4`aq}l(*_7*Xklq? -PGxiftsXy=AYX8dDQEQRO5D(yMKm~r|3!X*hx(?lDDx}U6LV!@Y(s2sb7^j8Q*?4+bY*9G0h%q;z`x)s -Sf3Z(2eI_JHZ((SFcY?<6X>Ltn -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 -JXK)_7bXT%V`yb -mw%Cdg|0Y-zbj2Rx3qrTq9O+2!s^Lf^?|9I@Xg>Oi(W05|TJ%PM*ricn_PmXk-a(WprUw -d2nTO015$ht0000000000{{R30000003ukO^Vqt7ld2nTO015%s?vf5kh_h+&YE#h%O8d1V_{UOl9{V;u -R#^q%lDklY(DVQRZ2_xNXm|`iS|~;BRWrW0000000000{{R30000003U7CAWn@%& -aAk7<3IT`y;$>KfZ0H=mhJ>?uVb7^w{PHf7Wpb~G=Pm~XxYI*`6rJj{160lxOxY(3#7BW?i -3v_Z}ZgXjLX>V?G015##QV*^ZmKt8YDf|&5KZQ>65I6*X)C9iYp+?yjr7~y%r?zUHR4te2+NwrBxfixd_%u|$Wt2vcKdWo=D+0ot2U6Id2jc94hrndMfLayEe1ISdA&%p{mB1!VWk)e2*8Zgg^CV{}Pm0iOsgNjk^^qPoT1 -+zTRnAg`3vXv9d*8d@RXy~6c6G6imLZewKt00<6ra$#@6CZd7@2WdSr&53UoI8eY9A{1GERg--Gi -I0S#x1is&)M%fmnGH3{GWprU=VRT^u^?FS>S$_F2)vN@Mb6UJ-F(lri_dqerx4lR4>iBsz2WM<=Vqt7^ -0irX>=qOIib(s7HIp;Lc%L0r`EZl^VKAG97Mm{9gQU+;maCLNZ0X7CplUE@k+(@AMA;**Avw@PI9YE8Q -DR*w0ca`xfVhdq&b7^O8ZDnqBa{-I4R4RNCFj+|XM1C+DXk-poZ)C_D*YlJ+82MQED-Q{CX=iR>bairN -00aU61a5C`WdHyG0R(ezZDjxj0Rcq9?S_9%zBIrmKs6QQX?psHjFs5t#D;?!SMk=|KFbhPa$#@6C -ZbEf#WNc*y0tjhtaCLM|VQ>Hn0`+VYVk7oBr%DNv+($;q`HHK!gIHa)*%m(-e#9sm3L)b@L&d6G@+l`% -qd385?K@+fP1(-9sgE>i7rMzqbpe9wZFzp>JB4@xD;^wu&SY_r(E19cP`Q -rta`4SL+aF4>h_8B*ZM$_{DUqzm~P&L)y{-0000000030{{R300000HRB~Z%b7^#GZ*D|obYW?1a|Qws -baG*Cb7^#GZ*Eg#Xk~3-0jz(i9yuZQ_f<_~3)9CPP+$;5D=2dnwEKV#qFOR4as+N+ZDj)Ko|5M~K$m}! -eub_$g}*CJIJdNZ+@c}}C`8q6D?Csev{(W1V6JV*{3!yZ{M3XW@z+pxis%K -u=2wF+7z(Wqt=tdZk`V^s(Ana000000093000000000JQZg6#Ua{vkfhyLPaScq)s9KMExvw34D6J>+N -wrBxfixd_%u|$Wt0XD%jq57bK6Q|uUfIMEX^1}Vv6tLB!)|10-o)0prc>n+a000000RI300000001IJr -b7^O8ZDnqBa{vkfhyLPaScq)s9KMExvw34D6J>+NwrBxfixd_%u|$Wt0XD%jq57bK6Q|uUfIMEX^1}Vv -6tLB!)|10-o)0prc>n+a000000RI3000000010+sY-wa+bZ>G11OfmAZf|a7000011aog~WdH>M0-Gv5 -(&k{eX@5SIR>|w{s%)+}o6^~`ha@$PehdAwF>UXmCgHqw;r~cW`-Qb7^w`1pxuGATjcBM0KUs3yuTaBu#bt -AlTMkBr_I*#EX^1JzD<(3UqQ|ZgXjLX>V=-1p)z|2rNlD$O59e#ogQsB77jPl+h5j^*S;E -G*S<)6P6lYy(#<=BR_>s@(?%#f7ArN-=Rj?7Ns(18dQ03Wn@8fb7^O8b3$xsZe&wsVQf@*P;_zx0{{zT -Wn*k%a$$67c4Yts0Rfg5{EB0fg;c|RERyKwyc?S`-(k#Jc79Ua6d|cNYh3{dW_507X<}?;00jX7t)le6 -tF1w|qkKKoQ8@+ft}Og`cxWD32N9OlJRp>80t$0Lb#i5700jX7w}_%X+LPM83Yle?T&{7IutOmr -M0ry;ESwv+3 -lBrcu^)moMuzDTL*_JDxK=Xf+&45B--vJ0_b#7;AVr*pq1pxt*I?dmD_aL)Lb)L?ZrQ2W!68hCK)<9B4 -o`z7Y8iKY03UhRFbz^jOa%E%y1pxs#vU_4@XKMa?TsAlK-}9~&K4&!}B_Q_~{-JMMpvoBuR&Qx!Q*>c; -Wd#8M000 ++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 +c{K-TY;R&=Y;yr~1*%39vO>-_DBy8`Vb0 +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 delta 2017 zcmaFwe9V1=0E>VngMwpmab|j6P-g--!tO8sf){!IM!Dt%AO`ROgmZkUT*!k)BZqr==ufjSw#^S3`L#(WAPRt zEvSK)0@fTzET9T{$OPye&)(xr6?GpD7W5HdW&$N&NV|3m0{4dTqtOaU7|EyeebXZtl{ z)-$j6Uij}=#KZE))?PM@>*D=#_24JFQ_zjq!eKf%c0kV8M|1!8v-gj`DlEI)?lpJz z?u%V(rL2^DRb@o>7*_Q_M`9GD|jV2`Do9E;2s( zLc{M&>5M;Ymd{NtoM!6r*16L%(Qf9=Rc>}F*Mhhc!KF$ru!tyTJY%g;$hrDBhlPux zQ&-lTLvIx;;?+0${+*l=r{d3KIbrh*L1iWdHa&I$u;(q7rFFTU|^5)^7_nm#3 zo2Ixe>piw0ZrSA9!t)deW&X)CMK)P+dFB8*hgE zfBv* zRAfG@@zmAdY(f*+#nm?3N+vQYtWK?{*~6yMvb!l~x!&zd6JM(y*>9KiWu0ltC4OC> zfTqp+qzo7*i^`l*AQa@2|I3(ab*~H2su47Z^!VvgXCRf4!WW*Oazgt0=PA|_KO=r< z^K*h?GO?tzD0T7#dC|$mvWoHoAw`M62rkLY&x0fnHYSctPyqTS7BFxzO}wfwS(Hhk zp0VlImN3h2bLMn}DoqGZ2nt?d-p*j{Ix(Dzv(Vcl_NS=e;h4YExv!+)(6hFE}`49d5WwubNw{&KV8X_ zTSE@l>P&j^e2?^Oqx*?xqRQ%m?uaO^w8)NSEvz)$p1_kn6m*fHhK0+tA%$v8g&KJw5ARb&Q$$ om;0aBiQ1)`Dyu4d7yq{~KYGC_Nlw17{LGZ#lEji!P#$Ig05!c%x&QzG diff --git a/stl/RGBCommit@0.1.0.sty b/stl/RGBCommit@0.1.0.sty index cf7d043d..b9c05303 100644 --- a/stl/RGBCommit@0.1.0.sty +++ b/stl/RGBCommit@0.1.0.sty @@ -1,5 +1,5 @@ {- - Id: stl:XbiECcs9-xlyofco-wkXoupT-gJ61JJf-XWL0DWf-INKzIp0#support-iris-depend + Id: stl:4j4rCC1R-6vHqghw-KSKgmbD-Ec9DPDA-IRqa6~L-aZ_1GRM#susan-olympic-minute Name: RGBCommit Version: 0.1.0 Description: Consensus commitment layer for RGB smart contracts @@ -41,33 +41,33 @@ import Bitcoin#signal-color-cipher use Txid#shallow-light-reverse -@mnemonic(control-basic-labor) -data AssignRevealedDataBlindSealTxPtr : revealed (seal BPCore.BlindSealTxPtr, state RevealedData) - | confidentialSeal (seal BPCore.SecretSeal, state RevealedData) +@mnemonic(alert-segment-canoe) +data AssignFungibleStateBlindSealTxPtr : revealed (seal BPCore.BlindSealTxPtr, state FungibleState) + | secretSeal (seal BPCore.SecretSeal, state FungibleState) -@mnemonic(passage-circus-compact) -data AssignRevealedDataBlindSealTxid : revealed (seal BPCore.BlindSealTxid, state RevealedData) - | confidentialSeal (seal BPCore.SecretSeal, state RevealedData) +@mnemonic(sushi-herman-gamma) +data AssignFungibleStateBlindSealTxid : revealed (seal BPCore.BlindSealTxid, state FungibleState) + | secretSeal (seal BPCore.SecretSeal, state FungibleState) -@mnemonic(beatles-service-husband) -data AssignRevealedValueBlindSealTxPtr : revealed (seal BPCore.BlindSealTxPtr, state RevealedValue) - | confidentialSeal (seal BPCore.SecretSeal, state RevealedValue) +@mnemonic(aloha-urban-factor) +data AssignStructureddDataBlindSealTxPtr : revealed (seal BPCore.BlindSealTxPtr, state StructureddData) + | secretSeal (seal BPCore.SecretSeal, state StructureddData) -@mnemonic(address-natural-neptune) -data AssignRevealedValueBlindSealTxid : revealed (seal BPCore.BlindSealTxid, state RevealedValue) - | confidentialSeal (seal BPCore.SecretSeal, state RevealedValue) +@mnemonic(diploma-declare-domain) +data AssignStructureddDataBlindSealTxid : revealed (seal BPCore.BlindSealTxid, state StructureddData) + | secretSeal (seal BPCore.SecretSeal, state StructureddData) -@mnemonic(critic-alcohol-actor) -data AssignVecAssignRevealedDataBlindSealTxPtr : [AssignRevealedDataBlindSealTxPtr ^ 1..] +@mnemonic(gong-bronze-critic) +data AssignVecAssignFungibleStateBlindSealTxPtr : [AssignFungibleStateBlindSealTxPtr ^ 1..] -@mnemonic(sonata-food-tina) -data AssignVecAssignRevealedDataBlindSealTxid : [AssignRevealedDataBlindSealTxid ^ 1..] +@mnemonic(detect-orchid-finish) +data AssignVecAssignFungibleStateBlindSealTxid : [AssignFungibleStateBlindSealTxid ^ 1..] -@mnemonic(magic-pupil-model) -data AssignVecAssignRevealedValueBlindSealTxPtr : [AssignRevealedValueBlindSealTxPtr ^ 1..] +@mnemonic(citizen-telecom-albert) +data AssignVecAssignStructureddDataBlindSealTxPtr : [AssignStructureddDataBlindSealTxPtr ^ 1..] -@mnemonic(equator-sector-regard) -data AssignVecAssignRevealedValueBlindSealTxid : [AssignRevealedValueBlindSealTxid ^ 1..] +@mnemonic(avatar-boris-felix) +data AssignVecAssignStructureddDataBlindSealTxid : [AssignStructureddDataBlindSealTxid ^ 1..] @mnemonic(begin-process-outside) data AssignVecAssignVoidStateBlindSealTxPtr : [AssignVoidStateBlindSealTxPtr ^ 1..] @@ -75,13 +75,13 @@ data AssignVecAssignVoidStateBlindSealTxPtr : [AssignVoidStateBlindSealTxPtr ^ 1 @mnemonic(arena-neuron-cantina) data AssignVecAssignVoidStateBlindSealTxid : [AssignVoidStateBlindSealTxid ^ 1..] -@mnemonic(magnum-tango-bronze) +@mnemonic(amazon-loyal-jazz) data AssignVoidStateBlindSealTxPtr : revealed (seal BPCore.BlindSealTxPtr, state VoidState) - | confidentialSeal (seal BPCore.SecretSeal, state VoidState) + | secretSeal (seal BPCore.SecretSeal, state VoidState) -@mnemonic(shelf-korea-begin) +@mnemonic(labor-package-normal) data AssignVoidStateBlindSealTxid : revealed (seal BPCore.BlindSealTxid, state VoidState) - | confidentialSeal (seal BPCore.SecretSeal, state VoidState) + | secretSeal (seal BPCore.SecretSeal, state VoidState) @mnemonic(sabine-magic-deal) data AssignmentDetails : ownedStateSchema OwnedStateSchema @@ -104,9 +104,6 @@ data BaseCommitment : schemaId SchemaId , chainNet ChainNet , sealClosingStrategy SealClosingStrategy -@mnemonic(carmen-farmer-diesel) -data BundleId : [Byte ^ 32] - @mnemonic(ringo-fashion-enrico) data ChainNet : bitcoinMainnet | bitcoinTestnet3 | bitcoinTestnet4 | bitcoinSignet | bitcoinRegtest | liquidMainnet | liquidTestnet @@ -118,12 +115,8 @@ data ContractId : [Byte ^ 32] @mnemonic(pigment-career-hippie) data Ffv : U16 -@mnemonic(guide-poker-coconut) -data FungibleState : bits64#8 U64 | (|) - -@mnemonic(matrix-optimal-sinatra) -data FungibleType : unsigned64Bit#8 | (|) - +@mnemonic(citrus-miami-geneva) +data FungibleState : U64 @mnemonic(salami-water-climax) data Genesis : ffv Ffv @@ -154,15 +147,12 @@ data GlobalStateSchema : semId StrictTypes.SemId, maxItems U24 @mnemonic(yoga-quick-jasmine) data GlobalStateType : U16 -@mnemonic(henry-kevin-carrot) -data GlobalValues : [RevealedData ^ 1..] +@mnemonic(single-rodent-appear) +data GlobalValues : [StructureddData ^ 1..] @mnemonic(smart-pioneer-nominal) data Identity : Std.AsciiPrintable, [Std.AsciiPrintable ^ ..0xfff] -@mnemonic(legal-milk-gold) -data InputOpids : {OpId ^ 1..} - @mnemonic(judo-invest-thermos) data Inputs : {Opout ^ 1..} @@ -198,17 +188,11 @@ data Opout : op OpId , ty AssignmentType , no U16 -@mnemonic(sincere-teacher-stella) +@mnemonic(river-neon-user) data OwnedStateSchema : declarative () - | fungible FungibleType + | fungible () | structured StrictTypes.SemId -@mnemonic(salon-clarion-factor) -data RevealedData : [Byte] - -@mnemonic(chance-stage-kermit) -data RevealedValue : FungibleState - @mnemonic(burma-bambino-nobody) data Schema : ffv Ffv , name StrictTypes.TypeName @@ -229,6 +213,9 @@ data SealClosingStrategy : firstOpretOrTapret | (|) @mnemonic(ferrari-zebra-tempo) data Signature : [Byte ^ 64] +@mnemonic(jerome-format-saga) +data StructureddData : [Byte] + @mnemonic(remark-gravity-vitamin) data Transition : ffv Ffv , contractId ContractId @@ -240,9 +227,6 @@ data Transition : ffv Ffv , assignments AssignmentsBlindSealTxPtr , signature Signature? -@mnemonic(isabel-duet-cover) -data TransitionBundle : inputMap {Bitcoin.Vout -> ^ 1.. InputOpids}, knownTransitions {OpId -> ^ 1.. Transition} - @mnemonic(orbit-pattern-goblin) data TransitionDetails : transitionSchema TransitionSchema, name StrictTypes.FieldName @@ -260,15 +244,15 @@ data TransitionType : U16 data TypeCommitment : genesis BaseCommitment | transition (ContractId, TransitionType) -@mnemonic(ship-trilogy-clara) +@mnemonic(civil-flex-palma) data TypedAssignsBlindSealTxPtr : declarative AssignVecAssignVoidStateBlindSealTxPtr - | fungible AssignVecAssignRevealedValueBlindSealTxPtr - | structured AssignVecAssignRevealedDataBlindSealTxPtr + | fungible AssignVecAssignFungibleStateBlindSealTxPtr + | structured AssignVecAssignStructureddDataBlindSealTxPtr -@mnemonic(felix-compare-history) +@mnemonic(switch-orchid-kevin) data TypedAssignsBlindSealTxid : declarative AssignVecAssignVoidStateBlindSealTxid - | fungible AssignVecAssignRevealedValueBlindSealTxid - | structured AssignVecAssignRevealedDataBlindSealTxid + | fungible AssignVecAssignFungibleStateBlindSealTxid + | structured AssignVecAssignStructureddDataBlindSealTxid @mnemonic(email-snow-safari) data VoidState : () diff --git a/stl/RGBLogic@0.1.0.sta b/stl/RGBLogic@0.1.0.sta index 3b3e1751..c108e4d4 100644 --- a/stl/RGBLogic@0.1.0.sta +++ b/stl/RGBLogic@0.1.0.sta @@ -1,15 +1,15 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:qolQpjNB-4ZkpJIo-U1tktjI-mwAYyEg-kOGQttY-ZoK3Loo#colombo-famous-erosion +Id: stl:iCs0AShc-KXU0vsu-te5lPow-NY7LYgX-i~LFvvl-1hVcbRw#jump-heaven-binary Name: RGBLogic Dependencies: BPCore#juliet-super-dominic, - RGBCommit#support-iris-depend, - Bitcoin#quiz-patent-exit -Check-SHA256: b5ace1d4b22b65bde7b4ed6e0d76575244f48e7bbe5873cce25832abcf618ac1 + Bitcoin#quiz-patent-exit, + RGBCommit#susan-olympic-minute +Check-SHA256: e5c834dbd5b7f95b65c0d1ba858710cac39e592a05fded12cde7517d1f2443c0 -2vSEvOmAmtV*@?wI}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlNwB!7L}MA7sFvK#<=RP4S#T1Vv-hhTICs&5fM~jaB^jIPH$voP+@X(Ze?;0 +2vSEvOmAmtV*@?wI}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlNNgzlT_m +3wFmfDB@ZlUF_{Gi(YuS4F^JLbYpL6ZsI;G2rW_S@#=yc3P`9XY%v`4Gs6IcYHP2{X`i(j6A4mBLPKwD +ZE17^20~CnZ*pY?00DdlT>wB!7L}MA7sFvK#<=RP4S#T1Vv-hhTICs&5fM~jaB^jIPH$voP+@X(Ze?;0 wjY>38tto&d&=eG4cRAF#( Wpq+$XJ~Xna$#;`Xh%-ZT+rxDK6vW;JU&?LxLM72H?wDC1Zo}=N}D)4mkLjCa%FT-a&K>D2SRCdV{d70 @@ -23,9 +23,9 @@ hs6sSUleB>hpP*aQYQxux_Ecpx^NEUkq@>Xm_HirtB!lh<{Yi-S-!KI0_27BH<@sVme~^s3<3pjaB^jI 00jX8J?lFX3Sj7m#S0l<6lWWUs|%1)CkG9>cz4~pa1P{=M^4XN(CAD)cag{2}f*iVqt7ga%2Vq1#fUqa%2Inp_$2edG9dLzy*OG4Oq4bRCJgzb0?22v{-Vn;AC_IX=Hc+00IU~ VR>b8F#`ezVrg_^Z)t7-25f0@b!lV)1y68Ka%2Po00(DfZe??6a{vGU{|a<+VQzD2bZKvH00smHcWHEP -Wpi@@kLzIp{8F`MCJ5#v8Msl{)Y>tRJ&yoJw@!EgNsxtt0(5x-UATk^%RRs@(?%#f7ArN-=Rj?7Ns(11#WL{V`TsU2n26%X=DOjxP%GIJ;q$9 -eabMAdM>3n3F}fxeRYe_HJ>2Tvm%|9$mV(;bz)!CmQ_M(k?Vd!kfCo{nDM?)_qK{868FUlS7~%^Wpi^+ +Wpi@@kLzIp{8F`MCJ5#v8Msl{)Y>tRJ&yoJw@!EgNsxtt0(5x-;yx<~Em7+6>Vg~!NT?=kF&y+W!vKV8 +Yp=^`pS2kiG*S<)6P6lYy(#<=BR_>s@(?%#f7ArN-=Rj?7Ns(11#WL{V`TsU2n26%X=DQ8J}U?@L7b8}E{a|QzjY+-q2axnpU#Mns)Y&M6LqDeqU-jv95KHlTh h+c{38p;h*Y8ns*Xk}? Date: Mon, 2 Jun 2025 09:59:13 +0200 Subject: [PATCH 08/23] validation: remove `trusted_op_seals` injection --- src/validation/validator.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/validation/validator.rs b/src/validation/validator.rs index 24a454ca..46f6f6a6 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -136,8 +136,6 @@ pub struct Validator< contract_state: Rc>, input_assignments: RefCell>, - // Operations in this set will not be validated - trusted_op_seals: BTreeSet, resolver: CheckedWitnessResolver<&'resolver R>, safe_height: Option, } @@ -155,7 +153,6 @@ impl< resolver: &'resolver R, context: S::Context<'_>, safe_height: Option, - trusted_op_seals: BTreeSet, ) -> Self { // We use validation status object to store all detected failures and // warnings @@ -176,7 +173,6 @@ impl< schema_id, contract_id, chain_net, - trusted_op_seals, input_assignments: input_transitions, resolver: CheckedWitnessResolver::from(resolver), contract_state: Rc::new(RefCell::new(S::init(context))), @@ -199,10 +195,8 @@ impl< chain_net: ChainNet, context: S::Context<'_>, safe_height: Option, - trusted_op_seals: BTreeSet, ) -> Status { - let mut validator = - Self::init(consignment, resolver, context, safe_height, trusted_op_seals); + let mut validator = Self::init(consignment, resolver, context, safe_height); // If the chain-network pair doesn't match there is no point in validating the contract // since all witness transactions will be missed. if validator.chain_net != chain_net { @@ -326,9 +320,6 @@ impl< fn validate_operation(&self, operation: OrdOpRef<'consignment>) { let schema = self.consignment.schema(); let opid = operation.id(); - if self.trusted_op_seals.contains(&opid) { - return; - } if operation.contract_id() != self.contract_id { self.status @@ -425,9 +416,6 @@ impl< let mut seals = vec![]; let opid = transition.id(); - if self.trusted_op_seals.contains(&opid) { - panic!("remove trusted op seals injection!"); - } if !self.status.borrow_mut().validated_opids.insert(opid) { self.status From df9de368f50bb0bfe0da589b0b3e0994f5ed1801 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 10:26:26 +0200 Subject: [PATCH 09/23] epic: exterpate AluVM --- Cargo.lock | 63 -------- Cargo.toml | 4 +- src/bin/rgbcore-stl.rs | 4 - src/schema/mod.rs | 2 +- src/schema/operations.rs | 19 ++- src/schema/schema.rs | 14 -- src/stl.rs | 7 +- src/validation/consignment.rs | 10 -- src/validation/logic.rs | 54 ++----- src/validation/mod.rs | 2 +- src/validation/status.rs | 4 +- src/vm/contract.rs | 28 +--- src/vm/isa.rs | 113 -------------- src/vm/macroasm.rs | 72 --------- src/vm/mod.rs | 9 -- src/vm/opcodes.rs | 53 ------- stl/RGBCommit@0.1.0.sta | 271 +++++++++++++++++----------------- stl/RGBCommit@0.1.0.stl | Bin 8687 -> 8430 bytes stl/RGBCommit@0.1.0.sty | 17 +-- stl/RGBLogic@0.1.0.sta | 14 +- stl/RGBLogic@0.1.0.stl | Bin 1378 -> 1378 bytes stl/RGBLogic@0.1.0.sty | 4 +- stl/Schema.vesper | 7 +- 23 files changed, 186 insertions(+), 585 deletions(-) delete mode 100644 src/vm/isa.rs delete mode 100644 src/vm/macroasm.rs delete mode 100644 src/vm/opcodes.rs diff --git a/Cargo.lock b/Cargo.lock index 1ffe468d..3fb82cf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,27 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "aluvm" -version = "0.11.1-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6035110db4d2f0a0e6df87e7b61f1c397828ed127ed97d46896371a258888403" -dependencies = [ - "amplify", - "ascii-armor", - "baid64", - "blake3", - "getrandom 0.3.2", - "half", - "paste", - "ripemd", - "serde", - "sha2", - "strict_encoding", - "strict_types", - "wasm-bindgen", -] - [[package]] name = "amplify" version = "4.8.1" @@ -99,12 +78,6 @@ dependencies = [ "libc", ] -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.6" @@ -188,19 +161,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" -[[package]] -name = "blake3" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -342,12 +302,6 @@ dependencies = [ "vesper-lang", ] -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -363,12 +317,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - [[package]] name = "crypto-common" version = "0.1.6" @@ -432,16 +380,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "half" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.15.3" @@ -665,7 +603,6 @@ dependencies = [ name = "rgb-core" version = "0.11.1-alpha.3+unreviewed" dependencies = [ - "aluvm", "amplify", "baid64", "bp-core", diff --git a/Cargo.toml b/Cargo.toml index aeca4ca4..388273f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ amplify = { version = "~4.8.0", features = ["rand"] } baid64 = "~0.4.1" strict_encoding = "~2.8.2" strict_types = { version = "~2.8.3", features = ["armor"] } -aluvm = { version = "~0.11.1-alpha.2", features = ["std", "ascii-armor"] } commit_verify = { version = "0.11.1-alpha.2", features = ["rand", "derive"] } single_use_seals = "~0.11.1-alpha.2" bp-core = { version = "~0.11.1-alpha.2" } @@ -36,7 +35,7 @@ serde_crate = { package = "serde", version = "1", features = ["derive"], optiona [features] default = [] all = ["stl", "serde"] -stl = ["commit_verify/stl", "bp-core/stl", "aluvm/stl"] +stl = ["commit_verify/stl", "bp-core/stl"] serde = [ "serde_crate", "amplify/serde", @@ -44,7 +43,6 @@ serde = [ "strict_types/serde", "commit_verify/serde", "bp-core/serde", - "aluvm/serde", "secp256k1/serde" ] diff --git a/src/bin/rgbcore-stl.rs b/src/bin/rgbcore-stl.rs index 5a1bc3b3..3a1ec0a4 100644 --- a/src/bin/rgbcore-stl.rs +++ b/src/bin/rgbcore-stl.rs @@ -23,7 +23,6 @@ use std::fs; use std::io::Write; -use aluvm::stl::aluvm_stl; use bp::stl::bp_core_stl; use commit_verify::stl::commit_verify_stl; use commit_verify::CommitmentLayout; @@ -75,15 +74,12 @@ fn main() { let bp = bp_core_stl(); let cv = commit_verify_stl(); let st = strict_types_stl(); - let vm = aluvm_stl(); let sys = SystemBuilder::new() .import(rgb_logic) .unwrap() .import(rgb_commit) .unwrap() - .import(vm) - .unwrap() .import(bp) .unwrap() .import(consensus) diff --git a/src/schema/mod.rs b/src/schema/mod.rs index 7dfcab60..be67e4e9 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -29,7 +29,7 @@ mod occurrences; pub use occurrences::{Occurrences, OccurrencesMismatch}; pub use operations::{ AssignmentType, AssignmentsSchema, GenesisSchema, GlobalSchema, MetaSchema, OpFullType, - OpSchema, TransitionSchema, + OpSchema, TransitionSchema, Verifier, }; pub use schema::{ AssignmentDetails, GlobalDetails, GlobalStateType, MetaDetails, MetaType, Schema, SchemaId, diff --git a/src/schema/operations.rs b/src/schema/operations.rs index d9c7e312..587a3369 100644 --- a/src/schema/operations.rs +++ b/src/schema/operations.rs @@ -20,7 +20,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use aluvm::library::LibSite; use amplify::confinement::{TinyOrdMap, TinyOrdSet}; use amplify::Wrapper; @@ -108,8 +107,6 @@ pub struct GenesisSchema { pub metadata: MetaSchema, pub globals: GlobalSchema, pub assignments: AssignmentsSchema, - // NB: it is possible to transform option into enum covering other virtual machines - pub validator: Option, } #[derive(Clone, PartialEq, Eq, Debug, Default)] @@ -125,7 +122,7 @@ pub struct TransitionSchema { pub globals: GlobalSchema, pub inputs: InputsSchema, pub assignments: AssignmentsSchema, - pub validator: Option, + pub verifier: Verifier, } impl OpSchema for GenesisSchema { @@ -149,3 +146,17 @@ impl OpSchema for TransitionSchema { #[inline] fn assignments(&self) -> &AssignmentsSchema { &self.assignments } } + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)] +#[derive(StrictType, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB_COMMIT, tags = repr, try_from_u8, into_u8)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "camelCase") +)] +#[repr(u8)] +pub enum Verifier { + #[default] + None = 0, +} diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 69cf6796..1a1e8ffd 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -24,7 +24,6 @@ use std::cmp::Ordering; use std::fmt::{self, Display, Formatter}; use std::str::FromStr; -use aluvm::library::LibId; use amplify::confinement::TinyOrdMap; use amplify::{ByteArray, Bytes32}; use baid64::{Baid64ParseError, DisplayBaid64, FromBaid64Str}; @@ -260,19 +259,6 @@ impl Schema { ) } - pub fn libs(&self) -> impl Iterator + '_ { - self.genesis - .validator - .iter() - .copied() - .chain( - self.transitions - .values() - .filter_map(|i| i.transition_schema.validator), - ) - .map(|site| site.lib) - } - pub fn default_transition_for_assignment( &self, assignment_type: &AssignmentType, diff --git a/src/stl.rs b/src/stl.rs index a5c8cbb6..e9e8d80a 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -20,7 +20,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use aluvm::stl::aluvm_stl; pub use bp::bc::stl::{bp_consensus_stl, bp_tx_stl}; pub use bp::stl::bp_core_stl; use bp::Txid; @@ -35,10 +34,10 @@ use crate::{Genesis, OpCommitment, Schema, Transition, LIB_NAME_RGB_COMMIT, LIB_ /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_COMMIT: &str = - "stl:4j4rCC1R-6vHqghw-KSKgmbD-Ec9DPDA-IRqa6~L-aZ_1GRM#susan-olympic-minute"; + "stl:2cchW1ud-aDIF0xy-igHwZpu-9QOBMjc-aiO_rs7-ph0Dua0#ralph-chris-hotel"; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_LOGIC: &str = - "stl:iCs0AShc-KXU0vsu-te5lPow-NY7LYgX-i~LFvvl-1hVcbRw#jump-heaven-binary"; + "stl:NsWww4jr-kCiM8Nn-cCkVgU4-d2BYla2-S0e7r9D-1B8AzBE#malta-dispute-trapeze"; fn _rgb_commit_stl() -> Result> { Ok(LibBuilder::with(libname!(LIB_NAME_RGB_COMMIT), [ @@ -47,7 +46,6 @@ fn _rgb_commit_stl() -> Result> { commit_verify_stl().to_dependency_types(), bp_tx_stl().to_dependency_types(), bp_core_stl().to_dependency_types(), - aluvm_stl().to_dependency_types(), ]) .transpile::() .transpile::() @@ -64,7 +62,6 @@ fn _rgb_logic_stl() -> Result> { commit_verify_stl().to_dependency_types(), bp_consensus_stl().to_dependency_types(), bp_core_stl().to_dependency_types(), - aluvm_stl().to_dependency_types(), rgb_commit_stl().to_dependency_types(), ]) .transpile::() diff --git a/src/validation/consignment.rs b/src/validation/consignment.rs index b7abcbf7..6f0c267a 100644 --- a/src/validation/consignment.rs +++ b/src/validation/consignment.rs @@ -23,8 +23,6 @@ //! Common API for accessing RGB contract operation graph, including individual //! state transitions, genesis, outputs, assignments & single-use-seal data. -use aluvm::library::{Lib, LibId}; -use amplify::confinement::ConfinedOrdMap; use bp::Txid; use strict_types::TypeSystem; @@ -36,8 +34,6 @@ use crate::{ pub const CONSIGNMENT_MAX_LIBS: usize = 1024; -pub type Scripts = ConfinedOrdMap; - #[derive(Copy, Clone, PartialEq, Eq, Debug, From)] pub enum OpRef<'op> { #[from] @@ -115,8 +111,6 @@ impl ConsignmentApi for CheckedConsignment<'_, C> { fn types(&self) -> &TypeSystem { self.0.types() } - fn scripts(&self) -> &Scripts { self.0.scripts() } - fn operation(&self, opid: OpId) -> Option { self.0.operation(opid).filter(|op| op.id() == opid) } @@ -144,10 +138,6 @@ pub trait ConsignmentApi { /// Returns reference to the type system. fn types(&self) -> &TypeSystem; - /// Returns reference to a collection of AluVM libraries used for the - /// validation. - fn scripts(&self) -> &Scripts; - /// Retrieves reference to an operation (genesis or state transition) matching the provided id, /// or `None` otherwise fn operation(&self, opid: OpId) -> Option; diff --git a/src/validation/logic.rs b/src/validation/logic.rs index ae3e2042..cd23a189 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -25,10 +25,6 @@ use std::collections::btree_map::Entry; use std::collections::{BTreeMap, BTreeSet}; use std::rc::Rc; -use aluvm::data::Number; -use aluvm::isa::Instr; -use aluvm::reg::{Reg32, RegA}; -use aluvm::Vm; use amplify::confinement::{Confined, NonEmptyVec}; use amplify::Wrapper; use strict_types::TypeSystem; @@ -36,12 +32,12 @@ use strict_types::TypeSystem; use crate::assignments::AssignVec; use crate::schema::{AssignmentsSchema, GlobalSchema}; use crate::validation::{CheckedConsignment, ConsignmentApi}; -use crate::vm::{ContractStateAccess, ContractStateEvolve, OpInfo, OrdOpRef, RgbIsa, VmContext}; +use crate::vm::{ContractStateAccess, ContractStateEvolve, OrdOpRef}; use crate::{ validation, AnyState, Assign, AssignmentType, Assignments, AssignmentsRef, ExposedSeal, ExposedState, GlobalState, GlobalStateSchema, GlobalValues, GraphSeal, Inputs, MetaSchema, Metadata, OpId, Operation, Opout, OwnedStateSchema, Schema, SealClosingStrategy, Transition, - TypedAssigns, + TypedAssigns, Verifier, }; impl Schema { @@ -75,7 +71,7 @@ impl Schema { &self.genesis.globals, &empty_assign_schema, &self.genesis.assignments, - self.genesis.validator, + Verifier::None, None::, ) } @@ -111,7 +107,7 @@ impl Schema { &transition_schema.globals, &transition_schema.inputs, &transition_schema.assignments, - transition_schema.validator, + transition_schema.verifier, Some(transition_type.into_inner()), ) } @@ -136,40 +132,16 @@ impl Schema { } }; - let genesis = consignment.genesis(); - let op_info = OpInfo::with(opid, &op, &prev_state); - let context = VmContext { - contract_id: genesis.contract_id(), - op_info, - contract_state, - }; - - // We need to run scripts as the very last step, since before that - // we need to make sure that the operation data match the schema, so - // scripts are not required to validate the structure of the state - if let Some(validator) = validator { - let scripts = consignment.scripts(); - let mut vm = Vm::>>::new(); - if let Some(ty) = ty { - vm.registers.set_n(RegA::A16, Reg32::Reg0, ty); - } - if !vm.exec(validator, |id| scripts.get(&id), &context) { - let error_code: Option = vm.registers.get_n(RegA::A8, Reg32::Reg0).into(); - status.add_failure(validation::Failure::ScriptFailure( - opid, - error_code.map(u8::from), - None, - )); - // We return here since all other validations will have no valid state to access - return status; - } - let contract_state = context.contract_state; - if contract_state.borrow_mut().evolve_state(op).is_err() { - status.add_failure(validation::Failure::ContractStateFilled(opid)); - // We return here since all other validations will have no valid state to access - return status; - } + // Run the validation logic + match validator { + Verifier::None => {} } + if contract_state.borrow_mut().evolve_state(op).is_err() { + status.add_failure(validation::Failure::ContractStateFilled(opid)); + // We return here since all other validations will have no valid state to access + return status; + } + status } diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 18d96cd8..36e540bd 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -28,6 +28,6 @@ mod status; mod commitments; pub use commitments::{DbcError, DbcProof, EAnchor}; -pub use consignment::{CheckedConsignment, ConsignmentApi, OpRef, Scripts, CONSIGNMENT_MAX_LIBS}; +pub use consignment::{CheckedConsignment, ConsignmentApi, OpRef, CONSIGNMENT_MAX_LIBS}; pub use status::{Failure, Info, Status, UnsafeHistoryMap, Validity, Warning}; pub use validator::{ResolveWitness, Validator, WitnessResolverError}; diff --git a/src/validation/status.rs b/src/validation/status.rs index 9e620e92..cc36c28c 100644 --- a/src/validation/status.rs +++ b/src/validation/status.rs @@ -296,9 +296,7 @@ pub enum Failure { expected: StateType, found: StateType, }, - /// evaluation of AluVM script for operation {0} has failed with the code - /// {1:?} and message {2:?}. - ScriptFailure(OpId, Option, Option), + /// contract state can't fit more data (at operation id {0}). ContractStateFilled(OpId), diff --git a/src/vm/contract.rs b/src/vm/contract.rs index d31218cb..606033fc 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -21,18 +21,16 @@ // limitations under the License. use std::borrow::Borrow; -use std::cell::RefCell; use std::cmp::Ordering; use std::fmt::{self, Debug, Display, Formatter}; use std::num::NonZeroU32; -use std::rc::Rc; use amplify::num::u24; use bp::{BlockHeight, Outpoint, Txid}; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use crate::{ - AssignmentType, Assignments, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, + AssignmentType, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, StructureddData, Transition, TransitionType, TypedAssigns, LIB_NAME_RGB_LOGIC, }; @@ -503,30 +501,6 @@ pub trait ContractStateEvolve { fn evolve_state(&mut self, op: OrdOpRef) -> Result<(), Self::Error>; } -pub struct VmContext<'op, S: ContractStateAccess> { - pub contract_id: ContractId, - pub op_info: OpInfo<'op>, - pub contract_state: Rc>, -} - -pub struct OpInfo<'op> { - pub id: OpId, - pub prev_state: &'op Assignments, - pub op: &'op OrdOpRef<'op>, -} - -impl<'op> OpInfo<'op> { - pub fn with(id: OpId, op: &'op OrdOpRef<'op>, prev_state: &'op Assignments) -> Self { - OpInfo { id, prev_state, op } - } - - pub fn global(&self) -> &'op GlobalState { self.op.globals() } - - pub fn metadata(&self) -> &'op Metadata { self.op.metadata() } - - pub fn owned_state(&self) -> AssignmentsRef<'op> { self.op.assignments() } -} - #[cfg(test)] mod test { use super::*; diff --git a/src/vm/isa.rs b/src/vm/isa.rs deleted file mode 100644 index b78b4869..00000000 --- a/src/vm/isa.rs +++ /dev/null @@ -1,113 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2024 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; -use std::ops::RangeInclusive; - -use aluvm::isa; -use aluvm::isa::{Bytecode, BytecodeError, ExecStep, InstructionSet}; -use aluvm::library::{CodeEofError, IsaSeg, LibSite, Read, Write}; -use aluvm::reg::{CoreRegs, Reg}; - -use super::opcodes::{INSTR_RGBISA_FROM, INSTR_RGBISA_TO}; -use super::{ContractOp, ContractStateAccess, VmContext}; - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -#[display(inner)] -#[non_exhaustive] -pub enum RgbIsa { - Contract(ContractOp), - - /// All other future unsupported operations, which must set `st0` to - /// `false`. - Fail(u8), -} - -impl InstructionSet for RgbIsa { - type Context<'ctx> = VmContext<'ctx, S>; - - fn isa_ids() -> IsaSeg { IsaSeg::with("RGB") } - - fn src_regs(&self) -> BTreeSet { - match self { - RgbIsa::Contract(op) => op.src_regs(), - RgbIsa::Fail(_) => bset![], - } - } - - fn dst_regs(&self) -> BTreeSet { - match self { - RgbIsa::Contract(op) => op.dst_regs(), - RgbIsa::Fail(_) => bset![], - } - } - - fn complexity(&self) -> u64 { - match self { - RgbIsa::Contract(op) => op.complexity(), - RgbIsa::Fail(_) => u64::MAX, - } - } - - fn exec(&self, regs: &mut CoreRegs, site: LibSite, context: &Self::Context<'_>) -> ExecStep { - match self { - RgbIsa::Contract(op) => op.exec(regs, site, context), - RgbIsa::Fail(_) => { - isa::ControlFlowOp::Fail.exec(regs, site, &()); - ExecStep::Stop - } - } - } -} - -impl Bytecode for RgbIsa { - fn instr_range() -> RangeInclusive { INSTR_RGBISA_FROM..=INSTR_RGBISA_TO } - - fn instr_byte(&self) -> u8 { - match self { - RgbIsa::Contract(op) => op.instr_byte(), - RgbIsa::Fail(code) => *code, - } - } - - fn encode_args(&self, writer: &mut W) -> Result<(), BytecodeError> - where W: Write { - match self { - RgbIsa::Contract(op) => op.encode_args(writer), - RgbIsa::Fail(_) => Ok(()), - } - } - - fn decode(reader: &mut R) -> Result - where - Self: Sized, - R: Read, - { - let instr = reader.peek_u8()?; - Ok(match instr { - instr if ContractOp::::instr_range().contains(&instr) => { - RgbIsa::Contract(ContractOp::decode(reader)?) - } - x => RgbIsa::Fail(x), - }) - } -} diff --git a/src/vm/macroasm.rs b/src/vm/macroasm.rs deleted file mode 100644 index d702e1ed..00000000 --- a/src/vm/macroasm.rs +++ /dev/null @@ -1,72 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2024 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. - -#[macro_export] -macro_rules! rgbasm { - ($( $tt:tt )+) => {{ #[allow(unused_imports)] { - use amplify::num::{u4, u5}; - use $crate::vm::{RgbIsa, ContractOp}; - use $crate::vm::aluasm_isa; - use $crate::isa_instr; - aluasm_isa! { RgbIsa<_> => $( $tt )+ } - } }}; -} - -#[macro_export] -macro_rules! isa_instr { - (svs $no:ident) => {{ - RgbIsa::Contract(ContractOp::Svs($no)) - }}; - (sas $no:ident) => {{ - RgbIsa::Contract(ContractOp::Sas($no)) - }}; - (sps $no:ident) => {{ - RgbIsa::Contract(ContractOp::Sps($no)) - }}; - (cng $t:ident,a8[$a_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::CnG($t, Reg32::from(u5::with($a_idx)))) - }}; - (cnc $t:ident,a16[$a_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::CnC($t, Reg32::from(u5::with($a_idx)))) - }}; - (ldc $t:ident,a32[$a_idx:literal],s16[$s_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::LdC($t, Reg16::from(u4::with($a_idx)), RegS::from($s_idx))) - }}; - (ldm $t:ident,s16[$s_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::LdM($t, RegS::from($s_idx))) - }}; - (ldg $t:ident,a8[$a_idx:literal],s16[$s_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::LdG($t, Reg16::from(u4::with($a_idx)), RegS::from($s_idx))) - }}; - (ldp $t:ident,a16[$a_idx:literal],s16[$s_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::LdP($t, Reg16::from(u4::with($a_idx)), RegS::from($s_idx))) - }}; - (lds $t:ident,a16[$a_idx:literal],s16[$s_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::LdS($t, Reg16::from(u4::with($a_idx)), RegS::from($s_idx))) - }}; - (vts s16[$s_idx:literal]) => {{ - RgbIsa::Contract(ContractOp::Vts(RegS::from($s_idx))) - }}; - ($op:ident $($tt:tt)+) => {{ - compile_error!(concat!("unknown RGB assembly opcode `", stringify!($op), "`")) - }}; -} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 5a3b4bed..592b419f 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -24,18 +24,9 @@ //! //! Concrete virtual machine implementations must be wrapped into this API -pub mod opcodes; -mod isa; -mod op_contract; -#[macro_use] -mod macroasm; mod contract; -pub use aluvm::aluasm_isa; pub use contract::{ ContractStateAccess, ContractStateEvolve, GlobalContractState, GlobalOrd, GlobalStateIter, OpOrd, OrdOpRef, UnknownGlobalStateType, WitnessOrd, WitnessPos, }; -pub(crate) use contract::{OpInfo, VmContext}; -pub use isa::RgbIsa; -pub use op_contract::ContractOp; diff --git a/src/vm/opcodes.rs b/src/vm/opcodes.rs deleted file mode 100644 index 8b189a23..00000000 --- a/src/vm/opcodes.rs +++ /dev/null @@ -1,53 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2024 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)] - -use aluvm::isa::opcodes::INSTR_ISAE_TO; - -pub const INSTR_RGBISA_FROM: u8 = 0b10_010_000; -pub const INSTR_RGBISA_TO: u8 = INSTR_ISAE_TO; - -// CONTRACTS: -pub const INSTR_CNP: u8 = 0b11_000_000; -pub const INSTR_CNS: u8 = 0b11_000_001; -pub const INSTR_CNG: u8 = 0b11_000_010; -pub const INSTR_CNC: u8 = 0b11_000_011; - -pub const INSTR_LDP: u8 = 0b11_000_100; -pub const INSTR_LDS: u8 = 0b11_000_101; -pub const INSTR_LDF: u8 = 0b11_000_110; -// Reserved 0b11_000_111 - -pub const INSTR_LDG: u8 = 0b11_001_000; -pub const INSTR_LDC: u8 = 0b11_001_001; -pub const INSTR_LDM: u8 = 0b11_001_010; -// Reserved 0b11_001_111 - -pub const INSTR_SVS: u8 = 0b11_010_000; -pub const INSTR_SAS: u8 = 0b11_010_001; -pub const INSTR_SPS: u8 = 0b11_010_010; -pub const INSTR_VTS: u8 = 0b11_010_011; -// Reserved 0b11_010_100 - -pub const INSTR_CONTRACT_FROM: u8 = 0b11_000_000; -pub const INSTR_CONTRACT_TO: u8 = 0b11_010_100; diff --git a/stl/RGBCommit@0.1.0.sta b/stl/RGBCommit@0.1.0.sta index 2c2ffcf2..044c5c64 100644 --- a/stl/RGBCommit@0.1.0.sta +++ b/stl/RGBCommit@0.1.0.sta @@ -1,151 +1,146 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:4j4rCC1R-6vHqghw-KSKgmbD-Ec9DPDA-IRqa6~L-aZ_1GRM#susan-olympic-minute +Id: stl:2cchW1ud-aDIF0xy-igHwZpu-9QOBMjc-aiO_rs7-ph0Dua0#ralph-chris-hotel Name: RGBCommit Dependencies: BPCore#juliet-super-dominic, CommitVerify#violet-panther-herbert, Std#delete-roman-hair, - AluVM#jargon-gorilla-poetic, StrictTypes#henry-heart-survive, Bitcoin#signal-color-cipher -Check-SHA256: ceef12091bb2a30ef26c112e446f801c2f402f33c0609fb38ae43804c1b59e3c +Check-SHA256: 6f8d32a4a997f8ae3c8afc9be7621039597686d1729e4805f3fd99bff682c31a -2~tNwLvL+uX>pKz(VCaX%3mIP&XB&sB3y@ML2MxM-cip;h4&;#rLQq3*a%D_q7H}ii_tAk8EiIL^ +2~tNwLvL+uX>pKz(VCaX%3mIP&XB&sB3y@ML2MxM-cip;h4&;#rLQq3*a%D_q7H}ii_tAk8EiIL^ F;WduOYhK!;vHZzZO$@xxWWuWZ*6U9bXH|@X=ZtXiR(=d3vg7gbV~*3!PlK51EySK%g?1}nECovJTYnm -Q*>mTDm~KXV7O_2K9yF<>+h;;t~i_0*|LWuHI04?{jxCyL2PwaP3fMJ=Q}``f02HLt~iCiD@{1Jw0_*8 -A_pi$)ov?1PzzIZa%p39RC#b^bMaU=OZ$bvG|>z)+>9PT;Au-7)~D;-++hbyX<}1pbY-V7RRS&fT*&Z=qeY@Wmfle* -z!SF)@h8|JkU^FEQwjx4X<|ua20~CnZ*pY>04xKINJ~fc1UzTDb_LBRjrSXj?;k=^zm6d~Uh7!wPz^$C -X>MdwWnpYocxhy48SA{&vly$FvzVnzHf7z~rv`86=_Ka^V5yX|y#`JSQ)OdvWpqi7rMzqbp%##b#$YGLi5Yl -(a@n1+Ku60FILp}Zw|!7cE!MGSxid=WmW`Kcxhw|LvL+uX>?X)a%pCH0suIkLxv|61vo|1ioJpYH;+t0eX2w~A!Q -+0eaZ{MVycPK^aqWo=1hGyow%b8~5DZbo%(XK7+=Wm9xvbY((pX>MdwWnpYocu;h51OfmEa%Fa9VQgh& -00sgCb7f&{0zKhpP*aQYQxux_Ecpx^NEUk*BEgxdReUg_1Rxg;i+hpP*aQYQxux_Ecpx^NEUk!Ts~yw$T9tCzEwrAszt-P)%HZ|LbH=L2A= -l(W4CP6cyxVRU5ya8s&1i~(KPc+oy|5YcifETK|4Gx3F{F4yC1Gh5PkAVG6;X=iRmb#7;AVr*qobYXO5 -LTqVnWK(5fY*ct@WCQ{L2y$h1WnpY(WB>*N1aoC!Yyv&&I}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlN -`(=BbYXO50dP~QJ&XZe*m%)CbP&;UDlDN=IWzHv -rY_gxY%^QZcL54>Wn*$>bW>$vYybuV1aoC!Yyv&&I}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlN%7&o7^|1Fn59cLW!>7R25;!;B*N1aoC!Yyv&& -I}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlNheK_vfJDKdRfkLPI75mFCjkm`Wn*$>bW>$vYybuV1aoC!Yyv&&I}!?D -=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlN%7&o7^|1Fn59cLW!>7R25;!;BheK_vfJDKdRfkLPI75mFCn7;}b7^O8Q*?55V{~hpP*aQYQxux_Ecpx^NEUkt_p^NJ~fc -1UzTDb_LBRjrSXj?;k=^zm6d~Uh7!wPz7^zVRU5yR}KZ&QZP3~KTfDRB(ge(Lv5>oM8Tj{hfDA{Ly8F} -0Sa?vV{&D5Q)OXn00sgCb7f&{0zKhpP*aQYQxux_Ecpx^NEUk!Ts~yw$T9tCzEw -rAszt-P)%HZ|LbH=L2A=l(W4CP6cyxVRU5yR}KZ&QZP3~KTfDRB(ge(Lv5>oM8Tj{hfDA{Ly8F}DnWB| -X=iR$Wn)2eb7^O8Ms;pyX<}?;Q*>c;WkPIeZe&wsVQf@*P;_zy0RRXAhHIF*Z;JjWTihv!&{)qMok5KO -=G{w$2x#urkqJDM0RR9100000|Nj6000000DM52{X=iR$Wn)2eb7^O8Ms;pyX<}?;Q*>c;WkPIeZe&ws -VQf@*X=DWf00;p%4)_d`T&OlmrtrSSk`4ApQi3>fDkH7ALZ#J3$S)BA0000000030{{R300000iL349y -XKq$yV?lFsX=iRzbaHiLbairNWMo8PbYVhlX>MdwWnpYocu;h51pxpE0S;~BWVXR;V$G05L}7GcLTqVn -WK(5fY*ct@WCZ~L2m!LukNp4WGEk%9O+Zr#RlCJbQEVfI=a8Y^FX0L8X)*x-000000096000000001UI -b8~5DZdPSuL349yXKq$+X=GD$VRU6eY-w&}Q)OXnRCrKyas>eZ2mu)@`bp7b7}p@jt$c1>Y&)x;l{?fg -Ty9Yg2OLfE+l&DK000000096000000001RHb8~5DZdPSuL349yXKq$+X=GD$VRU6eY-w&}Q)OXnRCsA* -1pxpE0iaSbQa$WiQLrw+HljZgruH)j!GWP=tMpo04c;WkPIeZe&wsVQf@*P;_zx0sshdWp-s@Y-MBs1_A_gWnpXrJ?lFX3Sj7m#S0l<6lWWUs|%1)CkG9> -cz4~pa1P{=r>OF|0}@Y#k~NrxRcQq+F$P2q2)nlUE64L7%3W7R1#@&^bY%f9vZekPz%WEGnBZKS8(M7E -9_@AwVcyGtCevi|7U8=A3Ug&+a%FT=WnpXp1_A_gWnpXrJ?lFX3Sj7m#S0l<6lWWUs|%1)CkG9>cz4~p -a1P{=Xc_Cg)w39@m$R6qOEzWQ+NTC@=;hpP*aQYQxux_Ecpx^NEUkt_p^NJ~fc1UzTDb_LBRjrSXj?;k=^zm6d~Uh7!wPz7^z -VRU5yF0!Tm7r-z?Fqq(6n;Tke)*kJ44PoBPfF{#q^A_Q|0Sa?vV{&D5Q)OXn00sgCb7f&{0zKhpP*aQYQxux_Ecpx^NEUk!Ts~yw$T9tCzEwrAszt-P)%HZ|LbH=L2A=l(W4CP6cyxVRU5y -F0!Tm7r-z?Fqq(6n;Tke)*kJ44PoBPfF{#q^A_Q|5kYfvX=iS2Wo~ptWprU_Y;y(!5N~&GWn@!yVRU6v -V`yb>SKenA+;cP=FifXbr)e?kOqVQpms>7J73J3yCzk$#1)IEB9}O*pr- -e%zuW2Pj065I6*X)C9iYp+?yjr7~y^L349yXKrm}Zgf<6aAgGn0006RL349yXKrm}Zgg`( -Y-w&}Q)OXnRCrKyas>eZ3IT`y;$>KfZ0H=mhJ>?uVWN4zL!h;nL -l?ng=000000096000000000g`VRL0eZ*6U9bZupBbOr?ob7N>_ZDC1d0hChH+XJhss8OG%_CC-Q>(ots -F+cqN0Qy}ddQ=3E5D9c?ZDn(GVQp{#07wRDb8~fNaso_c7H}ii_tAk8EiIL^F;WduOYhK!;vHZzZO$@x -xWa9(t;O}HAO^^zqT0%g+nC0;-MWK<)&Ge4`aq}l(*_7*Xklq?PGxiftsXy=AYX8dDQEQRO5D(yMKm~r -|3!X*hx(?lDDx}U6LV!@Y(s2sb7^j8Q*?4+bY*9G0h%q;z`x)sSf3Z(2eI_JHZ((SFcY?<6X>L<#XKrP50}f(obYpL6Zc=4ubY*jN1PyFyadl~AO<`$nZe?@@4Qy#~b!lW&Wpi|HWpoA#LvL<$ -a$#e1Nn`~900#g7Kp+4EMrL*e0RR934MuftXK7+=Wm9xvbY%qr000OFM`dnhb7^x12?J(kb^+R(Q4?4e -R(6nw`~Wpi|4ZEyepNCs(hb9H5M0k-IXh8!q$B6|*YuiTY;OURW8#d%1{rxIXtTaY^?oCsrRVQFqo -Wpn|p9zT>IUvP{mXY}ey+|ZdtG&qC*MSg*Y`lhfb^DEX9b7f&{Lu_wzX>MmzbaG*IWoLN-nl048zu+oZ -pBLT-vGlq&G(&DM6SaUd5X-W&Oj60I2yJC_VPs)+VFC4eO*mP8`7qV21dnrCyk{{a-lF$FG0V5TNAc?T -c{K-TY;R&=Y;yr~1*%39vO>-_DBy8`Vb0 -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 +%7&o7^|1Fn59cLW!>7R25;!;B*N1aoC! +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 +NAc?Tc{K-TY;R&=Y;yr~1*%39vO>-_DBy +8`Vb0jGrW9$=2qSMXvL3HGEG0000000000{{R30 +000003t@9}X=iS2Wo~qH015$z{^Dg=h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQnHo-KZ`k;Xmr`<4s +JYKN!!u{G5u+^j1lf!PF4>GEG0000000000{{R30000004M%KmVqt7VWprU_Y;y(z5oc^~Vqt7kbYXO5 +Q)6glZD9d+nB!jSlPQjTl%(2ntadXH-EO|kM)2Sug?ZeeX@0_mQT=Q}``f02HLt~iCiD@{1J +w0_*8A_pi$)ov?1P#d&Z0rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~atlXnZ(?C=Q*>c;Wd#8M3IWyb +k`76TvuW{aQ_%-X`?VwZ$5L?~`!+pRSq0(b70Uqz4Mioice*JsNExZXTBqWc!?;yX>tAhmw6GC?2vq<8 +0000000030000000000HM{I9mVQf=$VRU6vV`ybmw%Cdg|0Y-zbj2Rx3qrT +q9O+ioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^j{VR%V&Wo>f+00R$4Y;R&=Y*Tb$ +bY)a|aAgGn0006EM{I9mVQf}mY;|RG1pxpE0ap$M*HSPyML$lcIwZ0>heK_vfJDKdRfkLPI75mFCjkHe +000000RR600000000>EBWo~q7ba@2<00ja9f{E)*4-0TquXIZV=)u>WBLk*fW6RH_XPEi=Ry;9kNWLQ% +D(Hkon&*Qwpawq)`VKLB>Wd>h=Ype%b?27200;ttiR(=d3vg7gbV~*3!PlK51EySK%g?1}nECovJTYoW +z9SbZ=!8X@=Yuq$20sb<4l#S`iz7Vef}@Ca=a#qt00000000304*&oF00006Np5g;baMp(00{w;5WIk~ +G+K)5%bR49t5yk`^qQ9e0000000030{{R300000BO=WapL}hegX>4-_0tItrZAoMT +>7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0mw%Cdg|0Y-zbj2Rx3qrTq9O+QGbYWy+bYTSn +015$h4P{pQ?3(@m6s4{*=wy-PiS_k>Wl|t&* +Fr0fZ0000000000{{R30000003r}NXb#iiLZewM01_A?ZX>I@j0t0PfcmMzb3{P-FZ*6U9bZupBbOr|l +W@dH)+M7`mSQb`xkca!3ceuiB +udT)PryvH%qoUf%jN6#Tx81sfg4O?s`uaep_R|IjXKZg`VQg~(Ol1~uBiHxQff6k(m9sHY4N^<*(1+q3 +U@~paGIzMbIG#g>Clv)aMjKgwAH@`bu1x<7g|G$};xvA~n-$_S25D|^b#!wAOl1~uBiHxQff6k(m9sHY +4N^<*(1+q3U@~paGIzMbIG#g>Clv)aMjKgwAH@`bu1x<7g|G$};xvA~n-$_S3t@9}X=iS2Wo~qH0!(EV +a3k0E(SZ^zEtRt|QVmi|@6dsZfv!yd427@;7veO2zMB=|GXzg? +Nn`~900#g7Kp+4GPjGK_bOr+gZ*T#X$mV(;bz)!CmQ_M(k?Vd!kfCo{nDM?)_qK{868FUdba?@X{^Dg= +h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQoZf^hp0uWDkZe?UsbYXO5Q)6glZD9lh01ISgV{Bn^VRUJB +WdHyG0SIPwZf9v?Y-Iod00IhgbaHiLbairNWB>&L0_mQT=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1 +P-_IE6rQG)02XJT?*g=|B=zREie$*y(7k2+*P~cYjRsR=Xk~3-1_%RYW_AJEn^6;37FKqUhx?i3R+Mr! +fY&(;2BFL(m@EZk_srDU3Qf4cdUdGS4#Tk(yYN*ff#-&-~S0000000030000000000BXKZg`VQf@+aAk7< +3IWybk`76TvuW{aQ_%-X`?VwZ$5L?~`!+pRSq0(b70Uq+w#z7JBTYQ(6wA15KJe33N=y1k%8ssy_EyFt +I!|)|0000000030000000000AZ+C8GWK?-@Wpe-u0f+wLWmt%8=p4R=gtK{LClh6Z#kObxUW*hKHnBv9 +xdFK%KKY6{y^9(U*_!W#CeCf%@U$Ra$QlHXZNo +_Yhhx0Be79xh+o&58gBLg%$F9MUi-9%UHGxbaG*Cb7^#GZ*Fq{3IQ}y53UoI8eY9A{1GERg--GiI0S#x +1is&)M%fmnGH3x@!%VR!boT!l0ce6}iE2`s>&2w5gKr7m?oSuHf_Z2F0000000030000000000HWMyVy +b!>D&b8~5DZf#|5bN~bb00eGtZe;)f009JZZ*64&1pxtv{^Dg=h-~N_zJ`Red1EINWrM}GXaQb}6c#qI +M2EQuQ)6glZDC1d1pxpD002NB025PXVQfQeZ*ysGXH#@?VRU6@c>@6wW@&PBbWd<{Wpqz+RAF#(Wpn@u +Q)y>zVRUtJWd#8M2LJ#-KmZR@baHiLbairNWMo8PbYTSn00;m8KmY&$000000RR6000000018xcVQzD2 +bZKvH1_=XZW_AJEn^6;37FKqUhx?i3R+Mr!fY&(;2BFL(m@EZk_srD_V{dMBa$#e1Nn`<^2rNlD$O59e +#ogQsB77jPl+h5j^*S;IZf|a5WdHyO4s>#1ZgXjLX>V>+d2nR`G*S<)6P6lYy(#<=BR_>s +@(?%#f7ArN-=Rj?7Ns(12yJC_VPs)+VFC4eO*mP8`7qV21dnrCyk{{a-lF$FG0V5TNAc?Tc{K-TY;R&= +Y;yr~1*%39M?JbaMeV21}DyAtKyJp!y-llj5_1lAj$w +(~~K8Zku=D-c1t133F*@ZeetF +a%BJn0ssVVZ*FA(00035b8l^B00jX7M8fTce@(tLz$ZX87367p`iG2_*yhBBgBn-y*4#eJ5ma(vZgXjL +X>V>sWprU_Y;y(z5Oi{3ZgXjLX>V>*V`yb7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0V>*V`ybVZDn*}WMOn+00{wgM?JbaMa-0f+wLWmt%8 +=p4R=gtK{LClh6Z#kObxUW*hKHnBv9xdAr8G@<&SffJ|QFn~N>u=2wF+7z(Wqt=tdZk`V^s(Ana00000 +0093000000000YNb8~5DZf#|5baMa-0f+wLWmt%8=p4R=gtK{LClh6Z#kObxUW*hKHnBv9xdAr8G@<&S +ffJ|QFn~N>u=2wF+7z(Wqt=tdZk`V^s(Ana000000093000000000PfWpZg|X=QQ&S&9Jdz!fD%xD>w# +lyWiUB+!(H@tHM=pRv_mVsOaX4peesZgXjLX>V>+d2nR~0RR934pez?WkYXmZE19EWo~o?0sseRWo~72 +X>$Mt0RgihG4gRlb*0t|jsx5zO?CPp*w$VoGZuoxi65I6*X)C9iYp+?yjr7~z5RC#b^WI=Ot +X=iS8LTqVnWK(5fY*ctqbaDg(01ISgV{Bn^VRUJBWdH>M0jXmSzQi_Bob4h>{BE>m*T@oo-6oh0SIPwZf9v?Y-Ioi0RaQ+ +LUU)9P1F3fk)PC*KgHh%%41=0N|UI$lu$Tz`bPo^b98cbV{~SEP-*{> +tZNSyepJg@gxtasDgX#pWpZg|X=QQ)0R(PuZe;)oR&Qx!Q*>c;Wd#8M000 -----END STRICT TYPE LIB----- diff --git a/stl/RGBCommit@0.1.0.stl b/stl/RGBCommit@0.1.0.stl index 86582652d8f684ee033ac9c0008b67b2438867bf..ae09b6d0653bcb26ed66abd7fe82e49458e3da05 100644 GIT binary patch delta 252 zcmV49q;b<5Lzw(YkzaOEl&&&-ZS%s74myUk$7awShkb*8ZaPS!%VR! zboT!l0ce6}iE2`s>&2w5gKr7m?oSuHf_Z4OM;mhjAg0VfR$RNi*+MKxNl&Cl_Pw)d zUO;)deRDuKpc&epyOZ1%MzbIuW&tV)c4cyDW@%+|0a=Ow?Z6c!Mz|Ee2$XU$_+Oy^#`T-yaR%LQ&W@%+|0|5kXZ*FA(307}uWK(oubY%qr0002$ CCuZ;f delta 520 zcmaFo_}-bDGsxY^IX^cyvxIGOBe%jt?FhBmTDF&-CG5zox0@Pv^7Z>wIqNKDU%I)e zUB$Gwj{EN>LsrL}(lFo2iV_MF7n_8$LAXo|x$hUMJ=|0J@V|%m@79AR7kP~C^vF3p z$n=)Ew*2*-JBjQ*nMuK!C8^5|LYZ`b#+>-jx!84){j__5ng@ip^LD>hEAK zR-ii1l#Ms`Ffp4jC{EtUA~*RJYy4&r7I9uimdQGTKN2|05_2+B5=-)n7+9DXSn~4o zQW+Q+7+H$*b5j{u8JP%qfRIZ!s|a0ZSMbX@HEV%T{w4n@{ByIanB-ZH;2lEx#N17DX9p6-^R#+w3Bn#z=dgU6K36$j=#; QpP3R|l30?;$_NZN0Qf1~nE(I) diff --git a/stl/RGBCommit@0.1.0.sty b/stl/RGBCommit@0.1.0.sty index b9c05303..6c16a6c6 100644 --- a/stl/RGBCommit@0.1.0.sty +++ b/stl/RGBCommit@0.1.0.sty @@ -1,5 +1,5 @@ {- - Id: stl:4j4rCC1R-6vHqghw-KSKgmbD-Ec9DPDA-IRqa6~L-aZ_1GRM#susan-olympic-minute + Id: stl:2cchW1ud-aDIF0xy-igHwZpu-9QOBMjc-aiO_rs7-ph0Dua0#ralph-chris-hotel Name: RGBCommit Version: 0.1.0 Description: Consensus commitment layer for RGB smart contracts @@ -27,10 +27,6 @@ import Std#delete-roman-hair use AlphaCapsLodash#duet-hammer-labor use AlphaSmallLodash#pioneer-eagle-spell -import AluVM#jargon-gorilla-poetic - use LibSite#ultra-grace-message - use LibId#germany-culture-olivia - import StrictTypes#henry-heart-survive use FieldName#present-flute-herman use TypeName#edgar-carol-mystery @@ -129,11 +125,10 @@ data Genesis : ffv Ffv , globals GlobalState , assignments AssignmentsBlindSealTxid -@mnemonic(strong-mister-version) +@mnemonic(organic-tahiti-career) data GenesisSchema : metadata {MetaType ^ ..0xff} , globals {GlobalStateType -> ^ ..0xff Occurrences} , assignments {AssignmentType -> ^ ..0xff Occurrences} - , validator AluVM.LibSite? @mnemonic(eddie-super-cartoon) data GlobalDetails : globalStateSchema GlobalStateSchema, name StrictTypes.FieldName @@ -230,12 +225,12 @@ data Transition : ffv Ffv @mnemonic(orbit-pattern-goblin) data TransitionDetails : transitionSchema TransitionSchema, name StrictTypes.FieldName -@mnemonic(scratch-magnum-polaris) +@mnemonic(binary-square-basket) data TransitionSchema : metadata {MetaType ^ ..0xff} , globals {GlobalStateType -> ^ ..0xff Occurrences} , inputs {AssignmentType -> ^ ..0xff Occurrences} , assignments {AssignmentType -> ^ ..0xff Occurrences} - , validator AluVM.LibSite? + , verifier Verifier @mnemonic(picture-reflex-brigade) data TransitionType : U16 @@ -254,6 +249,10 @@ data TypedAssignsBlindSealTxid : declarative AssignVecAssignVoidStateBlindSealTx | fungible AssignVecAssignFungibleStateBlindSealTxid | structured AssignVecAssignStructureddDataBlindSealTxid +@mnemonic(escort-pretend-comedy) +data Verifier : none | (|) + + @mnemonic(email-snow-safari) data VoidState : () diff --git a/stl/RGBLogic@0.1.0.sta b/stl/RGBLogic@0.1.0.sta index c108e4d4..389d51d4 100644 --- a/stl/RGBLogic@0.1.0.sta +++ b/stl/RGBLogic@0.1.0.sta @@ -1,14 +1,14 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:iCs0AShc-KXU0vsu-te5lPow-NY7LYgX-i~LFvvl-1hVcbRw#jump-heaven-binary +Id: stl:NsWww4jr-kCiM8Nn-cCkVgU4-d2BYla2-S0e7r9D-1B8AzBE#malta-dispute-trapeze Name: RGBLogic Dependencies: BPCore#juliet-super-dominic, Bitcoin#quiz-patent-exit, - RGBCommit#susan-olympic-minute -Check-SHA256: e5c834dbd5b7f95b65c0d1ba858710cac39e592a05fded12cde7517d1f2443c0 + RGBCommit#ralph-chris-hotel +Check-SHA256: adaaa59106db98a7b028564d10f545cd88f9fd3cdd86f892cb53051786e9a8fc 2vSEvOmAmtV*@?wI}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlNNgzlT_m -3wFmfDB@ZlUF_{Gi(YuS4F^JLbYpL6ZsI;G2rW_S@#=yc3P`9XY%v`4Gs6IcYHP2{X`i(j6A4mBLPKwD +3wFmfDB@ZlUF_{Gi(YuS4F^JLbYpL6ZrR5nTU(uIG6mBdqJVrErteTV6C-h`j{3VhrX2&htqD>`LPKwD ZE17^20~CnZ*pY?00DdlT>wB!7L}MA7sFvK#<=RP4S#T1Vv-hhTICs&5fM~jaB^jIPH$voP+@X(Ze?;0 wjY>38tto&d&=eG4cRAF#( @@ -23,9 +23,9 @@ hs6sSUleB>hpP*aQYQxux_Ecpx^NEUkq@>Xm_HirtB!lh<{Yi-S-!KI0_27BH<@sVme~^s3<3pjaB^jI 00jX8J?lFX3Sj7m#S0l<6lWWUs|%1)CkG9>cz4~pa1P{=M^4XN(CAD)cag{2}f*iVqt7ga%2Vq1#fUqa%2Inp_$2edG9dLzy*OG4Oq4bRCJgzb0?22v{-Vn;AC_IX=Hc+00IU~ VR>b8F#`ezVrg_^Z)t7-25f0@b!lV)1y68Ka%2Po00(DfZe??6a{vGU{|a<+VQzD2bZKvH00smHcWHEP -Wpi@@kLzIp{8F`MCJ5#v8Msl{)Y>tRJ&yoJw@!EgNsxtt0(5x-;yx<~Em7+6>Vg~!NT?=kF&y+W!vKV8 -Yp=^`pS2kiG*S<)6P6lYy(#<=BR_>s@(?%#f7ArN-=Rj?7Ns(11#WL{V`TsU2n26%X=DQ8J}U?tRJ&yoJw@!EgNsxtt0(5x-*~cMUTb*b!1=Ad&fP5LI?@%}sBXOvX +`nx-(9Rss@(?%#f7ArN-=Rj?7Ns(11#WL{V`TsU2n26%X=DP~$01u=ooF%z +(;T9Jd>N+iP&gAKaj1^^yE~>G1G%l0$mV(;bz)!CmQ_M(k?Vd!kfCo{nDM?)_qK{868FUlS7~%^Wpi^+ a%2Pq00nJnZe?Tu1pxtE+zulZFL@%{hr{`tLyD)K8_+CBIb!yB_q58$0Duw!33O#{bYXO9c4Ytn00IYT XKrtDWn=&V00RhNa${&|c4cG$000VCX>@L7b8}E{a|QzjY+-q2axnpU#Mns)Y&M6LqDeqU-jv95KHlTh h+c{38p;h*Y8ns*Xk}?i4 diff --git a/stl/RGBLogic@0.1.0.sty b/stl/RGBLogic@0.1.0.sty index 685b04ad..8afef6a6 100644 --- a/stl/RGBLogic@0.1.0.sty +++ b/stl/RGBLogic@0.1.0.sty @@ -1,5 +1,5 @@ {- - Id: stl:iCs0AShc-KXU0vsu-te5lPow-NY7LYgX-i~LFvvl-1hVcbRw#jump-heaven-binary + Id: stl:NsWww4jr-kCiM8Nn-cCkVgU4-d2BYla2-S0e7r9D-1B8AzBE#malta-dispute-trapeze Name: RGBLogic Version: 0.1.0 Description: Consensus logic layer for RGB smart contracts @@ -26,7 +26,7 @@ import Bitcoin#quiz-patent-exit use LeafVer#benefit-carbon-africa use XOnlyPk#clever-swim-carpet -import RGBCommit#susan-olympic-minute +import RGBCommit#ralph-chris-hotel use TransitionType#picture-reflex-brigade use OpId#picnic-single-gloria diff --git a/stl/Schema.vesper b/stl/Schema.vesper index d6174694..75e5b011 100644 --- a/stl/Schema.vesper +++ b/stl/Schema.vesper @@ -62,9 +62,6 @@ rec Schema rec value, Occurrences is min, U16 is max, U16 - rec some, LibSite, option, wrapped, tag 1 - bytes lib, len 32, aka LibId - is pos, U16 map transitions, len 0..MAX8 is key, U16, aka TransitionType rec value, TransitionDetails @@ -86,9 +83,7 @@ rec Schema rec value, Occurrences is min, U16 is max, U16 - rec some, LibSite, option, wrapped, tag 1 - bytes lib, len 32, aka LibId - is pos, U16 + enum verifier, Verifier, none 0 ascii name, aka FieldName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 is some, U16, option, wrapped, aka AssignmentType, tag 1 From c038bfd9d79f7279501a19d19b0946583a004975 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 10:42:54 +0200 Subject: [PATCH 10/23] validation: remove tapret seals --- src/validation/status.rs | 6 ------ src/validation/validator.rs | 39 +++++++++++++------------------------ 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/src/validation/status.rs b/src/validation/status.rs index cc36c28c..542783e0 100644 --- a/src/validation/status.rs +++ b/src/validation/status.rs @@ -25,7 +25,6 @@ use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt::{self, Display, Formatter}; use amplify::num::u24; -use bp::seals::txout::CloseMethod; use bp::Txid; use commit_verify::mpc::InvalidProof; use strict_types::SemId; @@ -281,11 +280,6 @@ pub enum Failure { /// transition {0} is not properly anchored to the witness {1}. /// Details: {2} MpcInvalid(OpId, Txid, InvalidProof), - /// witness transaction {0} has no taproot or OP_RETURN output. - NoDbcOutput(Txid), - /// first DBC-compatible output of witness transaction {0} doesn't match the provided proof - /// type ({1}) - InvalidProofType(Txid, CloseMethod), // State check errors /// state in {opid}/{state_type} is of {found} type, while schema requires diff --git a/src/validation/validator.rs b/src/validation/validator.rs index 46f6f6a6..a11d88b0 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -25,7 +25,6 @@ use std::collections::{BTreeSet, HashMap, HashSet}; use std::num::NonZeroU32; use std::rc::Rc; -use bp::dbc::Anchor; use bp::seals::txout::{CloseMethod, Witness}; use bp::{dbc, Tx, Txid}; use commit_verify::mpc; @@ -505,10 +504,22 @@ impl< Witness: SealWitness, { let message = mpc::Message::from(opid); + let protocol = mpc::ProtocolId::from(self.contract_id); let witness_id = witness.txid; - let anchor = Anchor::new(mpc_proof, witness.proof.clone()); + + // TODO: Remove these two temporary checks once getting rid of bp-core and bp-dbc + assert_eq!(witness.proof.method(), CloseMethod::OpretFirst); + for out in witness.tx.outputs() { + if out.script_pubkey.is_p2tr() { + panic!("Not an Opret commitment!"); + } + if out.script_pubkey.is_op_return() { + break; + } + } + // [VALIDATION]: Checking anchor MPC commitment - match anchor.convolve(self.contract_id, message) { + match mpc_proof.convolve(protocol, message) { Err(err) => { // The operation is not committed to bitcoin transaction graph! // Ultimate failure. But continuing to detect the rest (after reporting it). @@ -517,28 +528,6 @@ impl< .add_failure(Failure::MpcInvalid(opid, witness_id, err)); } Ok(commitment) => { - // [VALIDATION]: Verify commitment - let Some(output) = witness - .tx - .outputs() - .find(|out| out.script_pubkey.is_op_return() || out.script_pubkey.is_p2tr()) - else { - self.status - .borrow_mut() - .add_failure(Failure::NoDbcOutput(witness_id)); - return; - }; - let output_method = if output.script_pubkey.is_op_return() { - CloseMethod::OpretFirst - } else { - CloseMethod::TapretFirst - }; - let proof_method = witness.proof.method(); - if proof_method != output_method { - self.status - .borrow_mut() - .add_failure(Failure::InvalidProofType(witness_id, proof_method)); - } // [VALIDATION]: CHECKING SINGLE-USE-SEALS witness .verify_many_seals(seals, &commitment) From 957ef7fc8436c5d71f06d26444f9bdb914cca22c Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:07:33 +0200 Subject: [PATCH 11/23] epic: remove a lot of unnecessary stuff. Upgrade to simplified bp-seals and v0.12 underlying stack --- .github/workflows/build.yml | 2 +- Cargo.lock | 148 +++++++------------- Cargo.toml | 29 ++-- scripts/typelib.sh | 6 +- src/bin/rgbcore-stl.rs | 4 +- src/lib.rs | 2 +- src/operation/assignments.rs | 8 +- src/operation/commit.rs | 252 +--------------------------------- src/operation/data.rs | 10 +- src/operation/global.rs | 16 +-- src/operation/layer1.rs | 2 +- src/operation/mod.rs | 7 +- src/operation/operations.rs | 72 ++-------- src/operation/seal.rs | 13 +- src/operation/state.rs | 4 +- src/schema/schema.rs | 8 +- src/stl.rs | 19 ++- src/validation/commitments.rs | 120 ---------------- src/validation/consignment.rs | 11 +- src/validation/mod.rs | 2 - src/validation/status.rs | 2 +- src/validation/validator.rs | 61 +++----- src/vm/contract.rs | 47 +++---- 23 files changed, 177 insertions(+), 668 deletions(-) delete mode 100644 src/validation/commitments.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d4f59b61..5dec94d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: strategy: fail-fast: false matrix: - feature: [ stl, serde ] + feature: [ stl, vesper, serde ] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable diff --git a/Cargo.lock b/Cargo.lock index 3fb82cf1..e0c17c22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,32 +4,22 @@ version = 3 [[package]] name = "amplify" -version = "4.8.1" +version = "4.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9d7cb29f1d4c6ec8650abbee35948b8bdefb7f0750a26445ff593eb9bf7fcf" +checksum = "3f7fb4ac7c881e54a8e7015e399b6112a2a5bc958b6c89ac510840ff20273b31" dependencies = [ - "amplify_apfloat", "amplify_derive", "amplify_num", "amplify_syn", "ascii", - "rand 0.8.5", + "getrandom 0.2.16", + "getrandom 0.3.3", + "rand 0.9.1", "serde", "stringly_conversions", "wasm-bindgen", ] -[[package]] -name = "amplify_apfloat" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695e433882668b55b3d7fb0ba22bf9be66a91abe30d7ca1f1a774f8b90b4db4c" -dependencies = [ - "amplify_num", - "bitflags", - "wasm-bindgen", -] - [[package]] name = "amplify_derive" version = "4.0.1" @@ -114,9 +104,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "baid64" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb4a8b2f1afee4ef00a190b260ad871842b93206177b59631fecd325d48d538" +checksum = "61eced31ae690ea39ffe808ed970bd11ebbb3ccc6861d2ab787d848b03a0d049" dependencies = [ "amplify", "base64", @@ -157,9 +147,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" @@ -172,69 +162,37 @@ dependencies = [ [[package]] name = "bp-consensus" -version = "0.11.1-alpha.2+unreviewed" +version = "0.12.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d473a0cea358746ab5ef820b62f2530ce6516cb59226c9a3736a8e60c4943d9" +checksum = "810f5e6361430adfcd6be36151c84409e9c05f3fb8a7455c8d4aa583fd89f043" dependencies = [ "amplify", "chrono", "commit_verify", - "secp256k1", - "serde", - "strict_encoding", - "strict_types", -] - -[[package]] -name = "bp-core" -version = "0.11.1-alpha.2+unreviewed" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d248df4e1ab41de97556bb092891c8c5208604f471a20c4129dc357fd9eade39" -dependencies = [ - "amplify", - "bp-consensus", - "bp-dbc", - "bp-seals", - "commit_verify", "getrandom 0.2.16", - "getrandom 0.3.2", + "getrandom 0.3.3", + "secp256k1", "serde", - "single_use_seals", "strict_encoding", "strict_types", "wasm-bindgen", ] -[[package]] -name = "bp-dbc" -version = "0.11.1-alpha.2+unreviewed" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2670bd384743ba75ca6d8cf821bcdcb74bfd5715e8798e545331dc00652f612c" -dependencies = [ - "amplify", - "base85", - "bp-consensus", - "commit_verify", - "secp256k1", - "serde", - "strict_encoding", -] - [[package]] name = "bp-seals" -version = "0.11.1-alpha.2+unreviewed" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aab0c94862b08721f7a60eb0d13502605147ebc2fc3cfe0ceacdb6d58aeb43c" +version = "0.11.1-beta.1" dependencies = [ "amplify", "baid64", "bp-consensus", - "bp-dbc", "commit_verify", + "getrandom 0.2.16", + "getrandom 0.3.3", "rand 0.9.1", "serde", - "single_use_seals", "strict_encoding", + "strict_types", + "wasm-bindgen", ] [[package]] @@ -245,9 +203,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "cc" -version = "1.2.20" +version = "1.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" +checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" dependencies = [ "shlex", ] @@ -274,9 +232,9 @@ dependencies = [ [[package]] name = "commit_encoding_derive" -version = "0.11.1-alpha.2" +version = "0.12.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d12f2e05ae7d81bc49d9f0856ff97968da750bf09f145043155e9c7f13ce4ace" +checksum = "783e42e09ad9dbc48d01532fc59fd1f1c64c98c09f523abeb6a069756651c9c3" dependencies = [ "amplify", "amplify_syn", @@ -287,12 +245,14 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.11.1-alpha.2" +version = "0.12.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171940b95b456f7c8906c78cd548c1dcf30310c4dc2e2a5ba352ac183bf163b3" +checksum = "2c91d4e2c820279c133f8cb1c7c7544caba346c8049d6a7749dca1031d7acb68" dependencies = [ "amplify", "commit_encoding_derive", + "getrandom 0.2.16", + "getrandom 0.3.3", "rand 0.9.1", "ripemd", "serde", @@ -300,6 +260,7 @@ dependencies = [ "strict_encoding", "strict_types", "vesper-lang", + "wasm-bindgen", ] [[package]] @@ -368,9 +329,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "js-sys", @@ -596,22 +557,22 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] name = "rgb-core" -version = "0.11.1-alpha.3+unreviewed" +version = "0.11.1-beta.1" dependencies = [ "amplify", "baid64", - "bp-core", + "bp-consensus", + "bp-seals", "commit_verify", - "getrandom 0.3.2", + "getrandom 0.3.3", "rand 0.9.1", "secp256k1", "serde", - "single_use_seals", "strict_encoding", "strict_types", "wasm-bindgen", @@ -629,9 +590,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -750,22 +711,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "single_use_seals" -version = "0.11.1-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36139c6f642d05f2d74501a8f84ccfb5833caeb7c8cde1e6b811261cd526bd" -dependencies = [ - "amplify_derive", -] - [[package]] name = "strict_encoding" -version = "2.8.2" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8553c0321466c11aa1e33f082c9190194f380efd8824bf5ce4fa56b64b875be9" +checksum = "5b8d9721d221d797767f8d5ad72b3a34dcdb5b9d646fe76248ee0f5e6fa6ca89" dependencies = [ "amplify", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "strict_encoding_derive", "wasm-bindgen", @@ -786,13 +740,15 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.8.3" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dd1bdf4bfce0a1ff3eec041e7d4d20b06d22ca2aaf71338726dd9609e57a5e" +checksum = "493821521630a023d79a210033fe1f5135ae3d3f8fccd8dbf1a98b7dfe56b144" dependencies = [ "amplify", "ascii-armor", "baid64", + "getrandom 0.2.16", + "getrandom 0.3.3", "indexmap", "serde", "serde_json", @@ -1072,9 +1028,9 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", @@ -1113,18 +1069,18 @@ checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -1204,9 +1160,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e27d6ad3dac991091e4d35de9ba2d2d00647c5d0fc26c5496dee55984ae111b" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 388273f1..eb9974b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rgb-core" -version = "0.11.1-alpha.3+unreviewed" +version = "0.11.1-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" @@ -19,30 +19,32 @@ crate-type = ["cdylib", "rlib"] # We need this for WASM [[bin]] name = "rgbcore-stl" -required-features = ["stl"] +required-features = ["stl", "vesper"] [dependencies] -amplify = { version = "~4.8.0", features = ["rand"] } -baid64 = "~0.4.1" -strict_encoding = "~2.8.2" -strict_types = { version = "~2.8.3", features = ["armor"] } -commit_verify = { version = "0.11.1-alpha.2", features = ["rand", "derive"] } -single_use_seals = "~0.11.1-alpha.2" -bp-core = { version = "~0.11.1-alpha.2" } +amplify = { version = "~4.9.0", features = ["rand"] } +baid64 = "~0.4.2" +strict_encoding = "~2.9.1" +strict_types = { version = "~2.9.0", features = ["armor"] } +commit_verify = { version = "0.12.0-rc.1", features = ["rand", "derive"] } +bp-consensus = { version = "~0.12.0-rc.2" } +bp-seals = { version = "~0.11.1-beta.1" } secp256k1 = { version = "0.30.0", features = ["global-context"] } serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true } [features] default = [] -all = ["stl", "serde"] -stl = ["commit_verify/stl", "bp-core/stl"] +all = ["stl", "vesper", "serde"] +stl = ["commit_verify/stl", "bp-consensus/stl", "bp-seals/stl"] +vesper = ["bp-seals/vesper"] serde = [ "serde_crate", "amplify/serde", "strict_encoding/serde", "strict_types/serde", "commit_verify/serde", - "bp-core/serde", + "bp-consensus/serde", + "bp-seals/serde", "secp256k1/serde" ] @@ -56,3 +58,6 @@ wasm-bindgen-test = "0.3" [package.metadata.docs.rs] features = ["all"] + +[patch.crates-io] +bp-seals = { path = "../bp-core" } diff --git a/scripts/typelib.sh b/scripts/typelib.sh index cb53b98e..4e8f5d1f 100755 --- a/scripts/typelib.sh +++ b/scripts/typelib.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -cargo run --features stl --bin rgbcore-stl -- --sty -cargo run --features stl --bin rgbcore-stl -- --stl -cargo run --features stl --bin rgbcore-stl -- --sta +cargo run --features stl,vesper --bin rgbcore-stl -- --sty +cargo run --features stl,vesper --bin rgbcore-stl -- --stl +cargo run --features stl,vesper --bin rgbcore-stl -- --sta diff --git a/src/bin/rgbcore-stl.rs b/src/bin/rgbcore-stl.rs index 3a1ec0a4..2edd5211 100644 --- a/src/bin/rgbcore-stl.rs +++ b/src/bin/rgbcore-stl.rs @@ -23,11 +23,11 @@ use std::fs; use std::io::Write; -use bp::stl::bp_core_stl; use commit_verify::stl::commit_verify_stl; use commit_verify::CommitmentLayout; use rgbcore::stl::{bp_consensus_stl, bp_tx_stl}; use rgbcore::{Genesis, Schema, Transition}; +use seals::stl::bp_seals_stl; use strict_types::stl::{std_stl, strict_types_stl}; use strict_types::typelib::parse_args; use strict_types::SystemBuilder; @@ -71,7 +71,7 @@ fn main() { let std = std_stl(); let consensus = bp_consensus_stl(); let tx = bp_tx_stl(); - let bp = bp_core_stl(); + let bp = bp_seals_stl(); let cv = commit_verify_stl(); let st = strict_types_stl(); diff --git a/src/lib.rs b/src/lib.rs index 1945cdf0..5bcf3294 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,7 @@ pub mod vm; pub mod stl; pub mod prelude { - pub use bp::Txid; + pub use bc::Txid; pub use operation::*; pub use schema::*; diff --git a/src/operation/assignments.rs b/src/operation/assignments.rs index 9e55b849..c52c90d0 100644 --- a/src/operation/assignments.rs +++ b/src/operation/assignments.rs @@ -32,7 +32,7 @@ use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use super::ExposedState; use crate::operation::seal::GenesisSeal; use crate::{ - AssignmentType, ExposedSeal, FungibleState, GraphSeal, SecretSeal, StateType, StructureddData, + AssignmentType, ExposedSeal, FungibleState, GraphSeal, SecretSeal, StateType, StructuredData, VoidState, LIB_NAME_RGB_COMMIT, }; @@ -71,7 +71,7 @@ pub struct UnknownDataError; pub type AssignRights = Assign; pub type AssignFungible = Assign; -pub type AssignData = Assign; +pub type AssignData = Assign; /// 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 @@ -400,7 +400,7 @@ impl TypedAssigns { } } - pub fn as_structured_state_at(&self, index: u16) -> Result<&StructureddData, UnknownDataError> { + pub fn as_structured_state_at(&self, index: u16) -> Result<&StructuredData, UnknownDataError> { match self { TypedAssigns::Structured(vec) => { Ok(vec.get(index as usize).ok_or(UnknownDataError)?.as_state()) @@ -418,7 +418,7 @@ impl TypedAssigns { } } - pub fn into_structured_state_at(self, index: u16) -> Result { + pub fn into_structured_state_at(self, index: u16) -> Result { match self { TypedAssigns::Structured(vec) => { if index as usize >= vec.len() { diff --git a/src/operation/commit.rs b/src/operation/commit.rs index bf51ca0a..429ff6d4 100644 --- a/src/operation/commit.rs +++ b/src/operation/commit.rs @@ -20,27 +20,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::fmt; use std::fmt::{Display, Formatter}; use std::str::FromStr; -use std::{fmt, vec}; -use amplify::confinement::MediumOrdMap; use amplify::hex::{FromHex, ToHex}; -use amplify::num::u256; use amplify::{hex, ByteArray, Bytes32, FromSliceError, Wrapper}; use baid64::{Baid64ParseError, DisplayBaid64, FromBaid64Str}; -use commit_verify::{ - mpc, CommitEncode, CommitEngine, CommitId, CommitmentId, Conceal, DigestExt, MerkleHash, - MerkleLeaves, Sha256, StrictHash, -}; +use commit_verify::{mpc, CommitmentId, DigestExt, Sha256}; use strict_encoding::StrictDumb; -use crate::{ - impl_serde_baid64, AnyState, Assign, AssignmentType, Assignments, ChainNet, ExposedSeal, - ExposedState, Ffv, FungibleState, Genesis, GlobalState, GlobalStateType, Operation, SchemaId, - SealClosingStrategy, SecretSeal, StructureddData, Transition, TransitionType, TypedAssigns, - LIB_NAME_RGB_COMMIT, -}; +use crate::{impl_serde_baid64, LIB_NAME_RGB_COMMIT}; /// Unique contract identifier equivalent to the contract genesis commitment #[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] @@ -137,239 +127,3 @@ impl OpId { Bytes32::copy_from_slice(slice).map(Self) } } - -/// Hash committing to all data which are disclosed by a contract or some part -/// of it (operation, bundle, consignment, disclosure). -#[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_COMMIT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct DiscloseHash( - #[from] - #[from([u8; 32])] - Bytes32, -); - -impl From for DiscloseHash { - fn from(hasher: Sha256) -> Self { hasher.finish().into() } -} - -impl CommitmentId for DiscloseHash { - const TAG: &'static str = "urn:lnp-bp:rgb:disclose#2024-02-16"; -} - -impl FromStr for DiscloseHash { - type Err = hex::Error; - fn from_str(s: &str) -> Result { Self::from_hex(s) } -} - -impl DiscloseHash { - pub fn copy_from_slice(slice: impl AsRef<[u8]>) -> Result { - Bytes32::copy_from_slice(slice).map(Self) - } -} - -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -pub struct AssignmentIndex { - pub ty: AssignmentType, - pub pos: u16, -} - -impl AssignmentIndex { - pub fn new(ty: AssignmentType, pos: u16) -> Self { AssignmentIndex { ty, pos } } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -#[derive(CommitEncode)] -#[commit_encode(strategy = strict, id = DiscloseHash)] -pub struct OpDisclose { - pub id: OpId, - pub seals: MediumOrdMap, - pub fungible: MediumOrdMap, - pub data: MediumOrdMap, -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -pub struct BaseCommitment { - pub schema_id: SchemaId, - pub timestamp: i64, - pub issuer: StrictHash, - pub chain_net: ChainNet, - pub seal_closing_strategy: SealClosingStrategy, -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT, tags = custom, dumb = Self::Transition(strict_dumb!(), strict_dumb!()))] -pub enum TypeCommitment { - #[strict_type(tag = 0)] - Genesis(BaseCommitment), - - #[strict_type(tag = 1)] - Transition(ContractId, TransitionType), -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT)] -#[derive(CommitEncode)] -#[commit_encode(strategy = strict, id = OpId)] -pub struct OpCommitment { - pub ffv: Ffv, - pub nonce: u64, - pub op_type: TypeCommitment, - pub metadata: StrictHash, - pub globals: MerkleHash, - pub inputs: MerkleHash, - pub assignments: MerkleHash, -} - -impl Genesis { - pub fn commit(&self) -> OpCommitment { - let base = BaseCommitment { - schema_id: self.schema_id, - timestamp: self.timestamp, - chain_net: self.chain_net, - seal_closing_strategy: self.seal_closing_strategy, - issuer: self.issuer.commit_id(), - }; - OpCommitment { - ffv: self.ffv, - nonce: u64::MAX, - op_type: TypeCommitment::Genesis(base), - metadata: self.metadata.commit_id(), - globals: MerkleHash::merklize(&self.globals), - inputs: MerkleHash::void(0, u256::ZERO), - assignments: MerkleHash::merklize(&self.assignments), - } - } - - pub fn disclose_hash(&self) -> DiscloseHash { self.disclose().commit_id() } -} - -impl Transition { - pub fn commit(&self) -> OpCommitment { - OpCommitment { - ffv: self.ffv, - nonce: self.nonce, - op_type: TypeCommitment::Transition(self.contract_id, self.transition_type), - metadata: self.metadata.commit_id(), - globals: MerkleHash::merklize(&self.globals), - inputs: MerkleHash::merklize(&self.inputs), - assignments: MerkleHash::merklize(&self.assignments), - } - } -} - -impl AnyState { - fn commit_encode(&self, e: &mut CommitEngine) { - match self { - Self::Void => {} - Self::Fungible(val) => e.commit_to_serialized(&val), - Self::Structured(dat) => e.commit_to_serialized(dat), - } - } -} - -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct AssignmentCommitment { - pub ty: AssignmentType, - pub state: AnyState, - pub seal: SecretSeal, -} - -impl CommitEncode for AssignmentCommitment { - type CommitmentId = MerkleHash; - - fn commit_encode(&self, e: &mut CommitEngine) { - e.commit_to_serialized(&self.ty); - self.state.commit_encode(e); - e.commit_to_serialized(&self.seal); - e.set_finished(); - } -} - -impl Assign { - pub fn commitment(&self, ty: AssignmentType) -> AssignmentCommitment { - let Self::SecretSeal { seal, state } = self.conceal() else { - unreachable!(); - }; - AssignmentCommitment { - ty, - state: state.state_data(), - seal, - } - } -} - -impl MerkleLeaves for Assignments { - type Leaf = AssignmentCommitment; - type LeafIter<'tmp> - = vec::IntoIter - where Seal: 'tmp; - - fn merkle_leaves(&self) -> Self::LeafIter<'_> { - self.iter() - .flat_map(|(ty, a)| { - match a { - TypedAssigns::Declarative(list) => { - list.iter().map(|a| a.commitment(*ty)).collect::>() - } - TypedAssigns::Fungible(list) => { - list.iter().map(|a| a.commitment(*ty)).collect() - } - TypedAssigns::Structured(list) => { - list.iter().map(|a| a.commitment(*ty)).collect() - } - } - .into_iter() - }) - .collect::>() - .into_iter() - } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -pub struct GlobalCommitment { - pub ty: GlobalStateType, - pub state: StructureddData, -} - -impl CommitEncode for GlobalCommitment { - type CommitmentId = MerkleHash; - - fn commit_encode(&self, e: &mut CommitEngine) { - e.commit_to_serialized(&self.ty); - e.commit_to_serialized(&self.state); - e.set_finished(); - } -} - -impl MerkleLeaves for GlobalState { - type Leaf = GlobalCommitment; - type LeafIter<'tmp> = vec::IntoIter; - - fn merkle_leaves(&self) -> Self::LeafIter<'_> { - self.iter() - .flat_map(|(ty, list)| { - list.iter().map(|val| GlobalCommitment { - ty: *ty, - state: val.clone(), - }) - }) - .collect::>() - .into_iter() - } -} diff --git a/src/operation/data.rs b/src/operation/data.rs index 70de0b1c..0e6449fb 100644 --- a/src/operation/data.rs +++ b/src/operation/data.rs @@ -45,14 +45,14 @@ impl ExposedState for VoidState { #[wrapper(Deref, AsSlice, BorrowSlice, Hex)] #[derive(StrictType, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_COMMIT)] -pub struct StructureddData(SmallBlob); +pub struct StructuredData(SmallBlob); -impl StructureddData { +impl StructuredData { /// Convenience constructor. pub fn new(value: impl Into) -> Self { Self(value.into()) } } -impl ExposedState for StructureddData { +impl ExposedState for StructuredData { fn state_type(&self) -> StateType { StateType::Structured } fn state_data(&self) -> AnyState { AnyState::Structured(self.clone()) } } @@ -65,14 +65,14 @@ mod _serde { use super::*; - impl Serialize for StructureddData { + impl Serialize for StructuredData { fn serialize(&self, serializer: S) -> Result where S: Serializer { serializer.serialize_str(&self.to_string()) } } - impl<'de> Deserialize<'de> for StructureddData { + impl<'de> Deserialize<'de> for StructuredData { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { let s = String::deserialize(deserializer)?; diff --git a/src/operation/global.rs b/src/operation/global.rs index f556f04f..ba037150 100644 --- a/src/operation/global.rs +++ b/src/operation/global.rs @@ -27,7 +27,7 @@ use amplify::confinement::{Confined, TinyOrdMap, U16}; use amplify::{confinement, Wrapper}; use strict_encoding::StrictDumb; -use crate::{schema, StructureddData, LIB_NAME_RGB_COMMIT}; +use crate::{schema, StructuredData, LIB_NAME_RGB_COMMIT}; #[derive(Wrapper, WrapperMut, Clone, PartialEq, Eq, Hash, Debug, From)] #[wrapper(Deref)] @@ -39,19 +39,19 @@ use crate::{schema, StructureddData, LIB_NAME_RGB_COMMIT}; derive(Serialize, Deserialize), serde(crate = "serde_crate", transparent) )] -pub struct GlobalValues(Confined, 1, U16>); +pub struct GlobalValues(Confined, 1, U16>); impl StrictDumb for GlobalValues { - fn strict_dumb() -> Self { Self(Confined::with(StructureddData::strict_dumb())) } + fn strict_dumb() -> Self { Self(Confined::with(StructuredData::strict_dumb())) } } impl GlobalValues { - pub fn with(state: StructureddData) -> Self { GlobalValues(Confined::with(state)) } + pub fn with(state: StructuredData) -> Self { GlobalValues(Confined::with(state)) } } impl IntoIterator for GlobalValues { - type Item = StructureddData; - type IntoIter = vec::IntoIter; + type Item = StructuredData; + type IntoIter = vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } @@ -72,7 +72,7 @@ impl GlobalState { pub fn add_state( &mut self, ty: schema::GlobalStateType, - state: StructureddData, + state: StructuredData, ) -> Result<(), confinement::Error> { match self.0.get_mut(&ty) { Some(vec) => vec.push(state), @@ -83,7 +83,7 @@ impl GlobalState { pub fn extend_state( &mut self, ty: schema::GlobalStateType, - iter: impl IntoIterator, + iter: impl IntoIterator, ) -> Result<(), confinement::Error> { match self.0.get_mut(&ty) { Some(vec) => vec.extend(iter), diff --git a/src/operation/layer1.rs b/src/operation/layer1.rs index 209207bc..2eb42569 100644 --- a/src/operation/layer1.rs +++ b/src/operation/layer1.rs @@ -22,7 +22,7 @@ use std::str::FromStr; -use bp::BlockHash; +use bc::BlockHash; use strict_encoding::{StrictDecode, StrictEncode, StrictType}; use crate::{LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; diff --git a/src/operation/mod.rs b/src/operation/mod.rs index 87a910cc..955c4d0d 100644 --- a/src/operation/mod.rs +++ b/src/operation/mod.rs @@ -34,11 +34,8 @@ mod commit; pub use assignments::{ Assign, AssignData, AssignFungible, AssignRights, Assignments, AssignmentsRef, TypedAssigns, }; -pub use commit::{ - AssignmentCommitment, AssignmentIndex, BaseCommitment, ContractId, DiscloseHash, - GlobalCommitment, OpCommitment, OpDisclose, OpId, TypeCommitment, -}; -pub use data::{StructureddData, VoidState}; +pub use commit::{ContractId, OpId}; +pub use data::{StructuredData, VoidState}; pub use fungible::FungibleState; pub use global::{GlobalState, GlobalValues}; pub use layer1::{ChainNet, Layer1}; diff --git a/src/operation/operations.rs b/src/operation/operations.rs index 9090754c..e7466624 100644 --- a/src/operation/operations.rs +++ b/src/operation/operations.rs @@ -20,21 +20,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::collections::{btree_set, BTreeMap}; +use std::collections::btree_set; use std::iter; use std::num::ParseIntError; -use amplify::confinement::{Confined, NonEmptyOrdSet, TinyOrdSet, U16}; +use amplify::confinement::{NonEmptyOrdSet, U16}; use amplify::{hex, Bytes64, Wrapper}; -use commit_verify::{CommitEncode, CommitEngine, CommitId, MerkleHash, MerkleLeaves, StrictHash}; +use commit_verify::{CommitEncode, CommitId, MerkleHash, MerkleLeaves, StrictHash}; use strict_encoding::stl::AsciiPrintable; use strict_encoding::{RString, StrictDeserialize, StrictEncode, StrictSerialize}; use crate::schema::{OpFullType, SchemaId, TransitionType}; use crate::{ - Assign, AssignmentIndex, AssignmentType, Assignments, AssignmentsRef, ChainNet, ContractId, - DiscloseHash, ExposedState, Ffv, FungibleState, GenesisSeal, GlobalState, GraphSeal, Metadata, - OpDisclose, OpId, SecretSeal, StructureddData, TypedAssigns, VoidState, LIB_NAME_RGB_COMMIT, + AssignmentType, Assignments, AssignmentsRef, ChainNet, ContractId, Ffv, GenesisSeal, + GlobalState, GraphSeal, Metadata, OpId, TypedAssigns, LIB_NAME_RGB_COMMIT, }; #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] @@ -96,9 +95,8 @@ impl<'a> IntoIterator for &'a Inputs { impl MerkleLeaves for Inputs { type Leaf = Opout; - type LeafIter<'tmp> = as MerkleLeaves>::LeafIter<'tmp>; - fn merkle_leaves(&self) -> Self::LeafIter<'_> { self.0.merkle_leaves() } + fn merkle_leaves(&self) -> impl ExactSizeIterator { self.0.merkle_leaves() } } /// RGB contract operation API, defined as trait @@ -130,50 +128,6 @@ pub trait Operation { fn assignments(&self) -> AssignmentsRef; fn assignments_by_type(&self, t: AssignmentType) -> Option>; - - /// Provides summary about parts of the operation which are revealed. - fn disclose(&self) -> OpDisclose { - fn proc_seals( - ty: AssignmentType, - a: &[Assign], - seals: &mut BTreeMap, - state: &mut BTreeMap, - ) { - for (index, assignment) in a.iter().enumerate() { - if let Some(seal) = assignment.revealed_seal() { - seals.insert(AssignmentIndex::new(ty, index as u16), seal.to_secret_seal()); - } - state.insert(AssignmentIndex::new(ty, index as u16), assignment.as_state().clone()); - } - } - - let mut seals: BTreeMap = bmap!(); - let mut void: BTreeMap = bmap!(); - let mut fungible: BTreeMap = bmap!(); - let mut data: BTreeMap = bmap!(); - for (ty, assigns) in self.assignments().flat() { - match assigns { - TypedAssigns::Declarative(a) => { - proc_seals(ty, &a, &mut seals, &mut void); - } - TypedAssigns::Fungible(a) => { - proc_seals(ty, &a, &mut seals, &mut fungible); - } - TypedAssigns::Structured(a) => { - proc_seals(ty, &a, &mut seals, &mut data); - } - } - } - - OpDisclose { - id: self.id(), - seals: Confined::from_checked(seals), - fungible: Confined::from_iter_checked(fungible), - data: Confined::from_checked(data), - } - } - - fn disclose_hash(&self) -> DiscloseHash { self.disclose().commit_id() } } /// An ASCII printable string up to 4096 chars representing identity of the @@ -226,6 +180,8 @@ pub enum SealClosingStrategy { #[derive(Clone, PartialEq, Eq, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_COMMIT)] +#[derive(CommitEncode)] +#[commit_encode(id = OpId, strategy = strict)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -261,6 +217,8 @@ pub struct Signature(Bytes64); #[derive(Clone, PartialEq, Eq, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_COMMIT)] +#[derive(CommitEncode)] +#[commit_encode(id = OpId, strategy = strict)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -281,16 +239,6 @@ pub struct Transition { impl StrictSerialize for Transition {} impl StrictDeserialize for Transition {} -impl CommitEncode for Genesis { - type CommitmentId = OpId; - fn commit_encode(&self, e: &mut CommitEngine) { e.commit_to_serialized(&self.commit()) } -} - -impl CommitEncode for Transition { - type CommitmentId = OpId; - fn commit_encode(&self, e: &mut CommitEngine) { e.commit_to_serialized(&self.commit()) } -} - impl Transition { /// Returns reference to information about the owned rights in form of /// [`Inputs`] wrapper structure which this operation updates with diff --git a/src/operation/seal.rs b/src/operation/seal.rs index 94dab24e..fb0b8fa8 100644 --- a/src/operation/seal.rs +++ b/src/operation/seal.rs @@ -23,12 +23,11 @@ use core::fmt::Debug; use std::hash::Hash; -pub use bp::seals::txout::blind::{ChainBlindSeal, ParseError, SingleBlindSeal}; -use bp::seals::txout::ExplicitSeal; -pub use bp::seals::txout::TxoSeal; -pub use bp::seals::SecretSeal; -use bp::Txid; +use bc::Txid; use commit_verify::Conceal; +pub use seals::txout::TxoSeal; +use seals::txout::{ChainBlindSeal, ExplicitSeal, SingleBlindSeal}; +pub use seals::SecretSeal; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; pub type GenesisSeal = SingleBlindSeal; @@ -67,8 +66,8 @@ impl ExposedSeal for GenesisSeal {} #[cfg(test)] mod test { use amplify::hex::FromHex; - use bp::seals::txout::{BlindSeal, TxPtr}; - use bp::Vout; + use bc::Vout; + use seals::txout::{BlindSeal, TxPtr}; use super::*; diff --git a/src/operation/state.rs b/src/operation/state.rs index 06e09740..51ffc440 100644 --- a/src/operation/state.rs +++ b/src/operation/state.rs @@ -25,7 +25,7 @@ use core::hash::Hash; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; -use crate::{FungibleState, StructureddData}; +use crate::{FungibleState, StructuredData}; /// Marker trait for types of state holding explicit state data. pub trait ExposedState: @@ -64,7 +64,7 @@ pub enum StateType { pub enum AnyState { Void, Fungible(FungibleState), - Structured(StructureddData), + Structured(StructuredData), } impl AnyState { diff --git a/src/schema/schema.rs b/src/schema/schema.rs index 1a1e8ffd..5c26840f 100644 --- a/src/schema/schema.rs +++ b/src/schema/schema.rs @@ -213,11 +213,11 @@ impl CommitEncode for Schema { e.commit_to_serialized(&self.name); - e.commit_to_map(&self.meta_types); - e.commit_to_map(&self.global_types); - e.commit_to_map(&self.owned_types); + e.commit_to_linear_map(&self.meta_types); + e.commit_to_linear_map(&self.global_types); + e.commit_to_linear_map(&self.owned_types); e.commit_to_serialized(&self.genesis); - e.commit_to_map(&self.transitions); + e.commit_to_linear_map(&self.transitions); e.commit_to_option(&self.default_assignment); } diff --git a/src/stl.rs b/src/stl.rs index e9e8d80a..d4e58869 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -20,24 +20,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use bp::bc::stl::{bp_consensus_stl, bp_tx_stl}; -pub use bp::stl::bp_core_stl; -use bp::Txid; +pub use bc::stl::{bp_consensus_stl, bp_tx_stl}; +use bc::Txid; use commit_verify::stl::commit_verify_stl; +pub use seals::stl::bp_seals_stl; use strict_types::stl::{std_stl, strict_types_stl}; use strict_types::typelib::LibBuilder; use strict_types::{CompileError, TypeLib}; -use crate::validation::DbcProof; use crate::vm::GlobalOrd; -use crate::{Genesis, OpCommitment, Schema, Transition, LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; +use crate::{Genesis, Schema, Transition, LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_COMMIT: &str = - "stl:2cchW1ud-aDIF0xy-igHwZpu-9QOBMjc-aiO_rs7-ph0Dua0#ralph-chris-hotel"; + "stl:eBR7hVUY-AAhMZQS-BxMGUdt-D5VCa4l-gvFPe4s-hXYkthg#enrico-ohio-maxwell"; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_LOGIC: &str = - "stl:NsWww4jr-kCiM8Nn-cCkVgU4-d2BYla2-S0e7r9D-1B8AzBE#malta-dispute-trapeze"; + "stl:u28Zbwug-pBA9hRj-v_2ofr6-hz9QvYb-_rU0Luy-tBs2YUg#dynamic-first-middle"; fn _rgb_commit_stl() -> Result> { Ok(LibBuilder::with(libname!(LIB_NAME_RGB_COMMIT), [ @@ -45,13 +44,12 @@ fn _rgb_commit_stl() -> Result> { strict_types_stl().to_dependency_types(), commit_verify_stl().to_dependency_types(), bp_tx_stl().to_dependency_types(), - bp_core_stl().to_dependency_types(), + bp_seals_stl().to_dependency_types(), ]) .transpile::() .transpile::() .transpile::() .transpile::() - .transpile::() .compile()?) } @@ -61,11 +59,10 @@ fn _rgb_logic_stl() -> Result> { strict_types_stl().to_dependency_types(), commit_verify_stl().to_dependency_types(), bp_consensus_stl().to_dependency_types(), - bp_core_stl().to_dependency_types(), + bp_seals_stl().to_dependency_types(), rgb_commit_stl().to_dependency_types(), ]) .transpile::() - .transpile::() .compile()?) } diff --git a/src/validation/commitments.rs b/src/validation/commitments.rs deleted file mode 100644 index c59b412e..00000000 --- a/src/validation/commitments.rs +++ /dev/null @@ -1,120 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2024 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::opret::{OpretError, OpretProof}; -use bp::dbc::tapret::TapretProof; -use bp::dbc::Method; -use bp::{dbc, Tx}; -use commit_verify::mpc::Commitment; -use commit_verify::{ConvolveVerifyError, EmbedVerifyError}; -use strict_encoding::{StrictDeserialize, StrictDumb, StrictSerialize}; - -use crate::LIB_NAME_RGB_LOGIC; - -#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -#[display(doc_comments)] -pub enum DbcError { - /// transaction doesn't contain OP_RETURN output. - NoOpretOutput, - - /// first OP_RETURN output inside the transaction already contains some - /// data. - InvalidOpretScript, - - /// commitment doesn't match the message. - CommitmentMismatch, - - /// the proof is invalid and the commitment can't be verified since the - /// original container can't be restored from it. - UnrestorableProof, - - /// the proof does not match to the proof generated for the same message - /// during the verification. - ProofMismatch, - - /// the message is invalid since a valid commitment to it can't be created. - ImpossibleMessage, - - /// the proof is invalid and the commitment can't be verified. - InvalidProof, -} - -#[derive(Clone, Eq, PartialEq, Debug, From)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_LOGIC, tags = custom, dumb = Self::Tapret(strict_dumb!()))] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase", untagged) -)] -pub enum DbcProof { - #[from] - #[strict_type(tag = 0x01)] - Tapret(TapretProof), - - #[from] - #[strict_type(tag = 0x02)] - Opret(OpretProof), -} - -impl StrictSerialize for DbcProof {} -impl StrictDeserialize for DbcProof {} - -impl dbc::Proof for DbcProof { - type Error = DbcError; - - fn method(&self) -> Method { - match self { - DbcProof::Tapret(_) => Method::TapretFirst, - DbcProof::Opret(_) => Method::OpretFirst, - } - } - - fn verify(&self, msg: &Commitment, tx: &Tx) -> Result<(), Self::Error> { - match self { - DbcProof::Tapret(tapret) => tapret.verify(msg, tx).map_err(|err| match err { - ConvolveVerifyError::CommitmentMismatch => DbcError::CommitmentMismatch, - ConvolveVerifyError::ImpossibleMessage => DbcError::ImpossibleMessage, - ConvolveVerifyError::InvalidProof => DbcError::InvalidProof, - }), - DbcProof::Opret(opret) => opret.verify(msg, tx).map_err(|err| match err { - EmbedVerifyError::CommitmentMismatch => DbcError::CommitmentMismatch, - EmbedVerifyError::InvalidMessage(OpretError::NoOpretOutput) => { - DbcError::NoOpretOutput - } - EmbedVerifyError::InvalidMessage(OpretError::InvalidOpretScript) => { - DbcError::InvalidOpretScript - } - EmbedVerifyError::InvalidProof => DbcError::UnrestorableProof, - EmbedVerifyError::ProofMismatch => DbcError::ProofMismatch, - }), - } - } -} - -/// Anchor which DBC proof is either Tapret or Opret. -pub type EAnchor = dbc::Anchor; diff --git a/src/validation/consignment.rs b/src/validation/consignment.rs index 6f0c267a..24f3de44 100644 --- a/src/validation/consignment.rs +++ b/src/validation/consignment.rs @@ -23,10 +23,10 @@ //! Common API for accessing RGB contract operation graph, including individual //! state transitions, genesis, outputs, assignments & single-use-seal data. -use bp::Txid; +use bc::Txid; +use commit_verify::mpc; use strict_types::TypeSystem; -use super::EAnchor; use crate::{ AssignmentType, AssignmentsRef, ContractId, Genesis, GlobalState, GraphSeal, Metadata, OpFullType, OpId, Operation, Schema, Transition, TypedAssigns, @@ -119,7 +119,7 @@ impl ConsignmentApi for CheckedConsignment<'_, C> { fn transitions(&self) -> impl Iterator { self.0.transitions() } - fn anchor(&self, opid: OpId) -> Option<(Txid, &EAnchor)> { self.0.anchor(opid) } + fn anchor(&self, opid: OpId) -> Option<(&mpc::MerkleProof, Txid)> { self.0.anchor(opid) } fn op_witness_id(&self, opid: OpId) -> Option { self.0.op_witness_id(opid) } } @@ -148,8 +148,9 @@ pub trait ConsignmentApi { /// Returns iterator over all transition ids present in the consignment. fn transitions(&self) -> impl Iterator; - /// Returns a grip given a bundle id. - fn anchor(&self, opid: OpId) -> Option<(Txid, &EAnchor)>; + /// Returns a an anchor - MPC Merkle proof that a given opid is committed in deterministic + /// bitcoin commitment. + fn anchor(&self, opid: OpId) -> Option<(&mpc::MerkleProof, Txid)>; /// Returns witness id for a given operation. fn op_witness_id(&self, opid: OpId) -> Option; diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 36e540bd..fca886a9 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -25,9 +25,7 @@ mod logic; mod validator; mod consignment; mod status; -mod commitments; -pub use commitments::{DbcError, DbcProof, EAnchor}; pub use consignment::{CheckedConsignment, ConsignmentApi, OpRef, CONSIGNMENT_MAX_LIBS}; pub use status::{Failure, Info, Status, UnsafeHistoryMap, Validity, Warning}; pub use validator::{ResolveWitness, Validator, WitnessResolverError}; diff --git a/src/validation/status.rs b/src/validation/status.rs index 542783e0..b1f3c96b 100644 --- a/src/validation/status.rs +++ b/src/validation/status.rs @@ -25,7 +25,7 @@ use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt::{self, Display, Formatter}; use amplify::num::u24; -use bp::Txid; +use bc::Txid; use commit_verify::mpc::InvalidProof; use strict_types::SemId; diff --git a/src/validation/validator.rs b/src/validation/validator.rs index a11d88b0..887f0c17 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -22,16 +22,14 @@ use std::cell::RefCell; use std::collections::{BTreeSet, HashMap, HashSet}; -use std::num::NonZeroU32; use std::rc::Rc; -use bp::seals::txout::{CloseMethod, Witness}; -use bp::{dbc, Tx, Txid}; +use bc::{Tx, Txid}; use commit_verify::mpc; -use single_use_seals::SealWitness; +use seals::txout::Witness; use super::status::{Failure, Warning}; -use super::{CheckedConsignment, ConsignmentApi, EAnchor, Status, Validity}; +use super::{CheckedConsignment, ConsignmentApi, Status, Validity}; use crate::operation::seal::ExposedSeal; use crate::vm::{ContractStateAccess, ContractStateEvolve, OrdOpRef, WitnessOrd}; use crate::{ @@ -136,7 +134,7 @@ pub struct Validator< input_assignments: RefCell>, resolver: CheckedWitnessResolver<&'resolver R>, - safe_height: Option, + safe_height: Option, } impl< @@ -151,7 +149,7 @@ impl< consignment: &'consignment C, resolver: &'resolver R, context: S::Context<'_>, - safe_height: Option, + safe_height: Option, ) -> Self { // We use validation status object to store all detected failures and // warnings @@ -193,7 +191,7 @@ impl< resolver: &'resolver R, chain_net: ChainNet, context: S::Context<'_>, - safe_height: Option, + safe_height: Option, ) -> Status { let mut validator = Self::init(consignment, resolver, context, safe_height); // If the chain-network pair doesn't match there is no point in validating the contract @@ -270,10 +268,11 @@ impl< let mut unsafe_history_map: HashMap> = HashMap::new(); for transition in self.consignment.transitions() { let opid = transition.id(); - let (witness_id, _) = self + let (_, witness_id) = self .consignment .anchor(opid) .expect("invalid checked consignment"); + // TODO: Remove all ordering! let witness_ord = match self.resolver.resolve_pub_witness_ord(witness_id) { Ok(ord) => ord, Err(err) => { @@ -357,7 +356,7 @@ impl< fn validate_commitments(&mut self) { for transition in self.consignment.transitions() { let opid = transition.id(); - let Some((witness_id, anchor)) = self.consignment.anchor(opid) else { + let Some((proof, witness_id)) = self.consignment.anchor(opid) else { self.status .borrow_mut() .add_failure(Failure::AnchorAbsent(opid)); @@ -368,18 +367,17 @@ impl< let seals = self.validate_seal_definitions(transition); // [VALIDATION]: We validate that the seals were properly closed on BP-type layer - self.validate_seal_commitments(&seals, opid, witness_id, anchor); + self.validate_seal_commitments(seals, opid, proof, witness_id); } } - /// Bitcoin- and liquid-specific commitment validation using deterministic - /// bitcoin commitments with opret and tapret schema. + /// Bitcoin- and liquid-specific commitment validation using OP_RETURN commitments fn validate_seal_commitments( &self, - seals: impl AsRef<[OutputSeal]>, + seals: impl IntoIterator, opid: OpId, + mpc_proof: &mpc::MerkleProof, witness_id: Txid, - anchor: &EAnchor, ) { // Check that the anchor is committed into a transaction spending all the // transition inputs. @@ -401,9 +399,7 @@ impl< .add_failure(Failure::SealNoPubWitness(opid, witness_id, err)); } Ok(pub_witness) => { - let seals = seals.as_ref(); - let witness = Witness::with(pub_witness.clone(), anchor.dbc_proof.clone()); - self.validate_seal_closing(seals, opid, witness, anchor.mpc_proof.clone()); + self.validate_seal_closing(seals, opid, &pub_witness, mpc_proof); } } } @@ -494,34 +490,21 @@ impl< /// /// Additionally, checks that the provided message contains commitment to /// the bundle under the current contract. - fn validate_seal_closing<'seal, Seal: 'seal, Dbc: dbc::Proof>( + fn validate_seal_closing( &self, - seals: impl IntoIterator, + seals: impl IntoIterator, opid: OpId, - witness: Witness, - mpc_proof: mpc::MerkleProof, - ) where - Witness: SealWitness, - { + witness: &Tx, + mpc_proof: &mpc::MerkleProof, + ) { let message = mpc::Message::from(opid); let protocol = mpc::ProtocolId::from(self.contract_id); - let witness_id = witness.txid; - - // TODO: Remove these two temporary checks once getting rid of bp-core and bp-dbc - assert_eq!(witness.proof.method(), CloseMethod::OpretFirst); - for out in witness.tx.outputs() { - if out.script_pubkey.is_p2tr() { - panic!("Not an Opret commitment!"); - } - if out.script_pubkey.is_op_return() { - break; - } - } + let witness_id = witness.txid(); // [VALIDATION]: Checking anchor MPC commitment match mpc_proof.convolve(protocol, message) { Err(err) => { - // The operation is not committed to bitcoin transaction graph! + // The operation is not committed to the bitcoin transaction graph! // Ultimate failure. But continuing to detect the rest (after reporting it). self.status .borrow_mut() @@ -530,7 +513,7 @@ impl< Ok(commitment) => { // [VALIDATION]: CHECKING SINGLE-USE-SEALS witness - .verify_many_seals(seals, &commitment) + .verify_seals(seals, commitment) .map_err(|err| { self.status.borrow_mut().add_failure(Failure::SealsInvalid( opid, diff --git a/src/vm/contract.rs b/src/vm/contract.rs index 606033fc..0ac31359 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -23,15 +23,14 @@ use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt::{self, Debug, Display, Formatter}; -use std::num::NonZeroU32; use amplify::num::u24; -use bp::{BlockHeight, Outpoint, Txid}; +use bc::{Outpoint, Txid}; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use crate::{ AssignmentType, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, - GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, StructureddData, + GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, StructuredData, Transition, TransitionType, TypedAssigns, LIB_NAME_RGB_LOGIC, }; @@ -153,7 +152,7 @@ pub struct WitnessPos { layer1: Layer1, #[getter(as_copy)] - height: BlockHeight, + height: u32, // TODO: Remove #[getter(as_copy)] @@ -164,7 +163,7 @@ impl StrictDumb for WitnessPos { fn strict_dumb() -> Self { Self { layer1: Layer1::Bitcoin, - height: NonZeroU32::MIN, + height: 1, timestamp: 1231006505, } } @@ -177,15 +176,7 @@ const BITCOIN_GENESIS_TIMESTAMP: i64 = 1231006505; const LIQUID_GENESIS_TIMESTAMP: i64 = 1296692202; impl WitnessPos { - #[deprecated( - since = "0.11.0-beta.9", - note = "please use `WitnessPos::bitcoin` or `WitnessPos::liquid` instead" - )] - pub fn new(height: NonZeroU32, timestamp: i64) -> Option { - Self::bitcoin(height, timestamp) - } - - pub fn bitcoin(height: NonZeroU32, timestamp: i64) -> Option { + pub fn bitcoin(height: u32, timestamp: i64) -> Option { if timestamp < BITCOIN_GENESIS_TIMESTAMP { return None; } @@ -196,7 +187,7 @@ impl WitnessPos { }) } - pub fn liquid(height: NonZeroU32, timestamp: i64) -> Option { + pub fn liquid(height: u32, timestamp: i64) -> Option { if timestamp < LIQUID_GENESIS_TIMESTAMP { return None; } @@ -386,7 +377,7 @@ impl GlobalOrd { } pub trait GlobalStateIter { - type Data: Borrow; + type Data: Borrow; fn size(&mut self) -> u24; fn prev(&mut self) -> Option<(GlobalOrd, Self::Data)>; fn last(&mut self) -> Option<(GlobalOrd, Self::Data)>; @@ -438,7 +429,7 @@ impl GlobalContractState { /// Retrieves global state data located `depth` items back from the most /// recent global state value. Ensures that the global state ordering is /// consensus-based. - pub fn nth(&mut self, depth: u24) -> Option + '_> { + pub fn nth(&mut self, depth: u24) -> Option + '_> { if depth > self.iter.size() { return None; } @@ -491,7 +482,7 @@ pub trait ContractStateAccess: Debug { &self, outpoint: Outpoint, ty: AssignmentType, - ) -> impl DoubleEndedIterator>; + ) -> impl DoubleEndedIterator>; } pub trait ContractStateEvolve { @@ -507,23 +498,23 @@ mod test { #[test] fn witness_post_timestamp() { - assert_eq!(WitnessPos::bitcoin(NonZeroU32::MIN, BITCOIN_GENESIS_TIMESTAMP - 1), None); - assert_eq!(WitnessPos::liquid(NonZeroU32::MIN, LIQUID_GENESIS_TIMESTAMP - 1), None); - assert_eq!(WitnessPos::liquid(NonZeroU32::MIN, BITCOIN_GENESIS_TIMESTAMP), None); - assert!(WitnessPos::bitcoin(NonZeroU32::MIN, BITCOIN_GENESIS_TIMESTAMP).is_some()); - assert!(WitnessPos::liquid(NonZeroU32::MIN, LIQUID_GENESIS_TIMESTAMP).is_some()); - assert!(WitnessPos::bitcoin(NonZeroU32::MIN, LIQUID_GENESIS_TIMESTAMP).is_some()); + assert_eq!(WitnessPos::bitcoin(1, BITCOIN_GENESIS_TIMESTAMP - 1), None); + assert_eq!(WitnessPos::liquid(1, LIQUID_GENESIS_TIMESTAMP - 1), None); + assert_eq!(WitnessPos::liquid(1, BITCOIN_GENESIS_TIMESTAMP), None); + assert!(WitnessPos::bitcoin(1, BITCOIN_GENESIS_TIMESTAMP).is_some()); + assert!(WitnessPos::liquid(1, LIQUID_GENESIS_TIMESTAMP).is_some()); + assert!(WitnessPos::bitcoin(1, LIQUID_GENESIS_TIMESTAMP).is_some()); } #[test] fn witness_pos_getters() { - let pos = WitnessPos::bitcoin(NonZeroU32::MIN, BITCOIN_GENESIS_TIMESTAMP).unwrap(); - assert_eq!(pos.height(), NonZeroU32::MIN); + let pos = WitnessPos::bitcoin(1, BITCOIN_GENESIS_TIMESTAMP).unwrap(); + assert_eq!(pos.height(), 1); assert_eq!(pos.timestamp(), BITCOIN_GENESIS_TIMESTAMP); assert_eq!(pos.layer1(), Layer1::Bitcoin); - let pos = WitnessPos::liquid(NonZeroU32::MIN, LIQUID_GENESIS_TIMESTAMP).unwrap(); - assert_eq!(pos.height(), NonZeroU32::MIN); + let pos = WitnessPos::liquid(1, LIQUID_GENESIS_TIMESTAMP).unwrap(); + assert_eq!(pos.height(), 1); assert_eq!(pos.timestamp(), LIQUID_GENESIS_TIMESTAMP); assert_eq!(pos.layer1(), Layer1::Liquid); } From 12226c4381288ffccbb120560ed27d83f430ae2a Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:14:31 +0200 Subject: [PATCH 12/23] remove global state ordering and access --- src/bin/rgbcore-stl.rs | 18 ----- src/lib.rs | 1 - src/operation/layer1.rs | 4 +- src/stl.rs | 27 +------- src/vm/contract.rs | 143 +--------------------------------------- src/vm/mod.rs | 4 +- stl/RGBLogic@0.1.0.sta | 34 ---------- stl/RGBLogic@0.1.0.stl | Bin 1378 -> 0 bytes stl/RGBLogic@0.1.0.sty | 63 ------------------ 9 files changed, 7 insertions(+), 287 deletions(-) delete mode 100644 stl/RGBLogic@0.1.0.sta delete mode 100644 stl/RGBLogic@0.1.0.stl delete mode 100644 stl/RGBLogic@0.1.0.sty diff --git a/src/bin/rgbcore-stl.rs b/src/bin/rgbcore-stl.rs index 2edd5211..ba517583 100644 --- a/src/bin/rgbcore-stl.rs +++ b/src/bin/rgbcore-stl.rs @@ -36,7 +36,6 @@ fn main() { let (format, dir) = parse_args(); let rgb_commit = rgbcore::stl::rgb_commit_stl(); - let rgb_logic = rgbcore::stl::rgb_logic_stl(); rgb_commit .serialize( @@ -48,21 +47,6 @@ fn main() { Description: Consensus commitment layer for RGB smart contracts Author: Dr Maxim Orlovsky Copyright (C) 2023-2024 LNP/BP Standards Association. All rights reserved. - License: Apache-2.0", - ), - ) - .expect("unable to write to the file"); - - rgb_logic - .serialize( - format, - dir.as_ref(), - "0.1.0", - Some( - " - Description: Consensus logic layer for RGB smart contracts - Author: Dr Maxim Orlovsky - Copyright (C) 2023-2024 LNP/BP Standards Association. All rights reserved. License: Apache-2.0", ), ) @@ -76,8 +60,6 @@ fn main() { let st = strict_types_stl(); let sys = SystemBuilder::new() - .import(rgb_logic) - .unwrap() .import(rgb_commit) .unwrap() .import(bp) diff --git a/src/lib.rs b/src/lib.rs index 5bcf3294..d185d012 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,7 +57,6 @@ pub mod prelude { pub use prelude::*; pub const LIB_NAME_RGB_COMMIT: &str = "RGBCommit"; -pub const LIB_NAME_RGB_LOGIC: &str = "RGBLogic"; /// Fast-forward version code #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default, Debug, Display)] diff --git a/src/operation/layer1.rs b/src/operation/layer1.rs index 2eb42569..7a415fcf 100644 --- a/src/operation/layer1.rs +++ b/src/operation/layer1.rs @@ -25,12 +25,12 @@ use std::str::FromStr; use bc::BlockHash; use strict_encoding::{StrictDecode, StrictEncode, StrictType}; -use crate::{LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; +use crate::LIB_NAME_RGB_COMMIT; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)] #[display(lowercase)] #[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_LOGIC, tags = repr, into_u8, try_from_u8)] +#[strict_type(lib = LIB_NAME_RGB_COMMIT, tags = repr, into_u8, try_from_u8)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), diff --git a/src/stl.rs b/src/stl.rs index d4e58869..b472afb0 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -28,8 +28,7 @@ use strict_types::stl::{std_stl, strict_types_stl}; use strict_types::typelib::LibBuilder; use strict_types::{CompileError, TypeLib}; -use crate::vm::GlobalOrd; -use crate::{Genesis, Schema, Transition, LIB_NAME_RGB_COMMIT, LIB_NAME_RGB_LOGIC}; +use crate::{Genesis, Schema, Transition, LIB_NAME_RGB_COMMIT}; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_COMMIT: &str = @@ -53,29 +52,11 @@ fn _rgb_commit_stl() -> Result> { .compile()?) } -fn _rgb_logic_stl() -> Result> { - Ok(LibBuilder::with(libname!(LIB_NAME_RGB_LOGIC), [ - std_stl().to_dependency_types(), - strict_types_stl().to_dependency_types(), - commit_verify_stl().to_dependency_types(), - bp_consensus_stl().to_dependency_types(), - bp_seals_stl().to_dependency_types(), - rgb_commit_stl().to_dependency_types(), - ]) - .transpile::() - .compile()?) -} - /// Generates strict type library providing data types for RGB consensus. pub fn rgb_commit_stl() -> TypeLib { _rgb_commit_stl().expect("invalid strict type RGB consensus commitments library") } -/// Generates strict type library providing data types for RGB consensus. -pub fn rgb_logic_stl() -> TypeLib { - _rgb_logic_stl().expect("invalid strict type RGB consensus logic library") -} - #[cfg(test)] mod test { use super::*; @@ -85,10 +66,4 @@ mod test { let lib = rgb_commit_stl(); assert_eq!(lib.id().to_string(), LIB_ID_RGB_COMMIT); } - - #[test] - fn logic_lib_id() { - let lib = rgb_logic_stl(); - assert_eq!(lib.id().to_string(), LIB_ID_RGB_LOGIC); - } } diff --git a/src/vm/contract.rs b/src/vm/contract.rs index 0ac31359..abf8f7b6 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -24,14 +24,13 @@ use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt::{self, Debug, Display, Formatter}; -use amplify::num::u24; use bc::{Outpoint, Txid}; -use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; +use strict_encoding::StrictDumb; use crate::{ AssignmentType, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, StructuredData, - Transition, TransitionType, TypedAssigns, LIB_NAME_RGB_LOGIC, + Transition, TransitionType, TypedAssigns, }; /// The type is used during validation and computing a contract state. It @@ -140,8 +139,6 @@ impl<'op> Operation for OrdOpRef<'op> { } #[derive(Getters, Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_LOGIC)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -240,8 +237,6 @@ impl Display for WitnessPos { /// contract global state data, as they are presented to all contract users. #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, Display, From)] #[display(lowercase)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_LOGIC, tags = order)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), @@ -286,7 +281,6 @@ pub enum WitnessOrd { /// replaced by RBFed successors; /// - past state channel transactions once a new channel state is signed (and until they may /// become valid once again due to an uncooperative channel closing). - #[strict_type(dumb)] Archived, } @@ -307,17 +301,13 @@ impl WitnessOrd { /// /// [RCP-240731A]: https://github.com/RGB-WG/RFC/issues/10 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_LOGIC, tags = custom)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "camelCase") )] pub enum OpOrd { - #[strict_type(tag = 0x00, dumb)] Genesis, - #[strict_type(tag = 0xFF)] Transition { witness: WitnessOrd, ty: TransitionType, @@ -336,140 +326,11 @@ impl OpOrd { } } -/// Consensus ordering of global state -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_LOGIC)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct GlobalOrd { - pub op_ord: OpOrd, - pub idx: u16, -} - -impl GlobalOrd { - pub fn genesis(idx: u16) -> Self { - Self { - op_ord: OpOrd::Genesis, - idx, - } - } - pub fn transition( - opid: OpId, - idx: u16, - ty: TransitionType, - nonce: u64, - witness: WitnessOrd, - ) -> Self { - Self { - op_ord: OpOrd::Transition { - witness, - ty, - nonce, - opid, - }, - idx, - } - } -} - -pub trait GlobalStateIter { - type Data: Borrow; - fn size(&mut self) -> u24; - fn prev(&mut self) -> Option<(GlobalOrd, Self::Data)>; - fn last(&mut self) -> Option<(GlobalOrd, Self::Data)>; - fn reset(&mut self, depth: u24); -} - -impl GlobalStateIter for &mut I { - type Data = I::Data; - - #[inline] - fn size(&mut self) -> u24 { GlobalStateIter::size(*self) } - - #[inline] - fn prev(&mut self) -> Option<(GlobalOrd, Self::Data)> { (*self).prev() } - - #[inline] - fn last(&mut self) -> Option<(GlobalOrd, Self::Data)> { (*self).last() } - - #[inline] - fn reset(&mut self, depth: u24) { (*self).reset(depth) } -} - -pub struct GlobalContractState { - checked_depth: u24, - last_ord: Option, - iter: I, -} - -impl GlobalContractState { - #[inline] - pub fn new(iter: I) -> Self { - Self { - iter, - checked_depth: u24::ONE, - last_ord: None, - } - } - - #[inline] - pub fn size(&mut self) -> u24 { self.iter.size() } - - fn prev_checked(&mut self) -> Option<(GlobalOrd, I::Data)> { - let (ord, item) = self.iter.prev()?; - self.checked_depth += u24::ONE; - self.last_ord = Some(ord); - Some((ord, item)) - } - - /// Retrieves global state data located `depth` items back from the most - /// recent global state value. Ensures that the global state ordering is - /// consensus-based. - pub fn nth(&mut self, depth: u24) -> Option + '_> { - if depth > self.iter.size() { - return None; - } - if depth >= self.checked_depth { - self.iter.reset(depth); - } else { - self.iter.reset(self.checked_depth); - let size = self.iter.size(); - let to = (self.checked_depth - depth).to_u32(); - for inc in 0..to { - if self.prev_checked().is_none() { - panic!( - "global contract state iterator has invalid implementation: it reports \ - more global state items {size} than the contract has ({})", - self.checked_depth + inc - ); - } - } - } - self.iter.last().map(|(_, item)| item) - } -} - -impl Iterator for GlobalContractState { - type Item = I::Data; - - #[inline] - fn next(&mut self) -> Option { Some(self.prev_checked()?.1) } -} - #[derive(Copy, Clone, Debug, Display, Error)] #[display("unknown global state type {0} requested from the contract")] pub struct UnknownGlobalStateType(pub GlobalStateType); pub trait ContractStateAccess: Debug { - fn global( - &self, - ty: GlobalStateType, - ) -> Result, UnknownGlobalStateType>; - fn rights(&self, outpoint: Outpoint, ty: AssignmentType) -> u32; fn fungible( diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 592b419f..66ea4a37 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -27,6 +27,6 @@ mod contract; pub use contract::{ - ContractStateAccess, ContractStateEvolve, GlobalContractState, GlobalOrd, GlobalStateIter, - OpOrd, OrdOpRef, UnknownGlobalStateType, WitnessOrd, WitnessPos, + ContractStateAccess, ContractStateEvolve, OpOrd, OrdOpRef, UnknownGlobalStateType, WitnessOrd, + WitnessPos, }; diff --git a/stl/RGBLogic@0.1.0.sta b/stl/RGBLogic@0.1.0.sta deleted file mode 100644 index 389d51d4..00000000 --- a/stl/RGBLogic@0.1.0.sta +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN STRICT TYPE LIB----- -Id: stl:NsWww4jr-kCiM8Nn-cCkVgU4-d2BYla2-S0e7r9D-1B8AzBE#malta-dispute-trapeze -Name: RGBLogic -Dependencies: - BPCore#juliet-super-dominic, - Bitcoin#quiz-patent-exit, - RGBCommit#ralph-chris-hotel -Check-SHA256: adaaa59106db98a7b028564d10f545cd88f9fd3cdd86f892cb53051786e9a8fc - -2vSEvOmAmtV*@?wI}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlNNgzlT_m -3wFmfDB@ZlUF_{Gi(YuS4F^JLbYpL6ZrR5nTU(uIG6mBdqJVrErteTV6C-h`j{3VhrX2&htqD>`LPKwD -ZE17^20~CnZ*pY?00DdlT>wB!7L}MA7sFvK#<=RP4S#T1Vv-hhTICs&5fM~jaB^jIPH$voP+@X(Ze?;0 -wjY>38tto&d&=eG4cRAF#( -Wpq+$XJ~Xna$#;`Xh%-ZT+rxDK6vW;JU&?LxLM72H?wDC1Zo}=N}D)4mkLjCa%FT-a&K>D2SRCdV{d70 -1^^|i^|=xh7rLW4)L(lQb*FJl;d*r#UC=Q#deq4+>4pnaV{&P5bV7M_WpgpRuIPk`cg3&=F>*1@lJ+pR -DJ{*3f84s>#k$1lf7uIEVQ@}wWMxQUb7)_z*=^-NPQ?`2v5jYd+6t@dEhY>7H!Y*UdZb-BpG^u(WnpGh -V{&P5bg6}ecT=8d`>?<6$C@F;S3|*6`1-v+nBdcqJ?FPKcnV2wbY*gGVQf%qwlfK-7{9iX4Q|L-q$GzU -Mp|h#f#{Gz8SzLEaTf~c{WkYggkPIjuQHS#3Ua|L6d7%qre2Ut&TYs@(?%#f7ArN-=Rj?7Ns(14peesZgXjLX>V>+d2nTw$mV(; -bz)!CmQ_M(k?Vd!kfCo{nDM?)_qK{868FUfPjE?O1^@^|Vq;KpZ*OJ<0s#heVQ_L~bN~eb0zKhpP*aQYQxux_Ecpx^NEUkq@>Xm_HirtB!lh<{Yi-S-!KI0_27BH<@sVme~^s3<3pjaB^jI -00jX8J?lFX3Sj7m#S0l<6lWWUs|%1)CkG9>cz4~pa1P{=M^4XN(CAD)cag{2}f*iVqt7ga%2Vq1#fUqa%2Inp_$2edG9dLzy*OG4Oq4bRCJgzb0?22v{-Vn;AC_IX=Hc+00IU~ -VR>b8F#`ezVrg_^Z)t7-25f0@b!lV)1y68Ka%2Po00(DfZe??6a{vGU{|a<+VQzD2bZKvH00smHcWHEP -Wpi@@kLzIp{8F`MCJ5#v8Msl{)Y>tRJ&yoJw@!EgNsxtt0(5x-*~cMUTb*b!1=Ad&fP5LI?@%}sBXOvX -`nx-(9Rss@(?%#f7ArN-=Rj?7Ns(11#WL{V`TsU2n26%X=DP~$01u=ooF%z -(;T9Jd>N+iP&gAKaj1^^yE~>G1G%l0$mV(;bz)!CmQ_M(k?Vd!kfCo{nDM?)_qK{868FUlS7~%^Wpi^+ -a%2Pq00nJnZe?Tu1pxtE+zulZFL@%{hr{`tLyD)K8_+CBIb!yB_q58$0Duw!33O#{bYXO9c4Ytn00IYT -XKrtDWn=&V00RhNa${&|c4cG$000VCX>@L7b8}E{a|QzjY+-q2axnpU#Mns)Y&M6LqDeqU-jv95KHlTh -h+c{38p;h*Y8ns*Xk}??keDWGLg+Gz&XDt z^`QHaG}Yd1pEY&6_P0k&;4V9Es_`gFKK9L9-R`)GoxJQ$nI*~jnRz#lD@I4p%`jrU zEVHPgMsnHv01IK|!WDhLc3Ur#W!|}#6KJt>er|4N2{Y7WRtClz_E-i7Z?UN}q{R;> z>K@ziY8`KVL1fY-vC^ogl9L4mLlO&$QcL{uQ&IyGi%RlRi}<(6&#;$zySlIX)H9j2 zuOs(up3U^6^|SfRf{tl7g*kY*Avywz^7GS#j|2y$sqc1C?Xgb(a^_IozdujZx1W#W z|J&HFUsrvjh99anu_Obm-oidfuQ2%13B`#vr^{vM+os$v`=k*Xsr$ptd5V~CE-TbE zL7C|pB~C?&dC3{>e&=H@yzsHBc=g-HF5=CO$g}0nt=78#zM^vz(KrtaC!`a8Ss9o=>0W&KT%cR``!kyxA&zvgD{Q+vOoA~!eo zrZ?Q;TK!sAjr*^;?&1SgOJXhO`*QiDCZ<8mUfJ4G9y~AO_lEuNj?Yp&67GC3BI}x!&rCr%AD$~BmnSK9%+3Qxt zjeaNDL8gYK7X4YYTx;LNe`lLkY@9J6S?Q2p*{W5hpHwauvnDT)(Cdg~kMPgSsSLWODna-~V}SEhwJWlelt=QLqqe$rxT=ew4+(z%zx7fx{&!864y+OpI(L z-~`0L%E&}0xf4oROsx5!$Rx%nLdk;DJtsdYF~`3sg$-mXkY-%BaOTO1%J&8r4zM=L z@kVUp3@MpmSghW!yCtG%~*#A0_@lVj!G&PQADv~<_Z(O-$ z*l*j<;I`ebg3)tAYZFsRB@?0SOepSH^YZhOQyCaISn>-pQwSPIC~mpJA#Mlxk%fUZ zH#09a1sD~KF?aZsMfEF{Znq!)Imfwc`8??hIv$ou-zvUuIdy`eL5PvFBsH%ju_Ut$ z=oSVh_RRD=V40QzWHWOl7A0o@#X%gH@d5e8Y|Lyq;6P@qJaWU6Bgd?L>LO1E_j^-L r6x-c - Copyright (C) 2023-2024 LNP/BP Standards Association. All rights reserved. - License: Apache-2.0 --} - -@context -typelib RGBLogic - -import BPCore#juliet-super-dominic - use TapretNodePartner#roger-member-educate - use TapretProof#marco-border-sample - use TapretPathProof#kiwi-mirror-paris - use TapretRightBranch#miracle-patriot-touch - use OpretProof#good-village-flex - -import Bitcoin#quiz-patent-exit - use ScriptBytes#equator-cockpit-gong - use TapNodeHash#paprika-amanda-hunter - use LeafScript#bison-doctor-oscar - use InternalPk#habitat-paprika-oliver - use LeafVer#benefit-carbon-africa - use XOnlyPk#clever-swim-carpet - -import RGBCommit#ralph-chris-hotel - use TransitionType#picture-reflex-brigade - use OpId#picnic-single-gloria - - -@mnemonic(needle-change-forest) -data DbcProof : tapret#1 BPCore.TapretProof - | opret BPCore.OpretProof - -@mnemonic(east-sunset-extra) -data GlobalOrd : opOrd OpOrd, idx U16 - -@mnemonic(camilla-basket-justin) -data Layer1 : bitcoin | liquid - - -@mnemonic(disney-mama-rover) -data OpOrd : genesis () - | transition#255 (witness WitnessOrd - , ty RGBCommit.TransitionType - , nonce U64 - , opid RGBCommit.OpId) - -@mnemonic(forum-declare-market) -data WitnessOrd : mined WitnessPos - | tentative () - | ignored () - | archived () - -@mnemonic(giraffe-melody-aspirin) -data WitnessPos : layer1 Layer1 - , height U32 - , timestamp I64 - - From 736d384cbaa540bacb8fb123828e26b94c315ad8 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:18:42 +0200 Subject: [PATCH 13/23] validation: remove concept of witness ordering --- src/validation/validator.rs | 18 ++--- src/vm/contract.rs | 151 +++--------------------------------- src/vm/mod.rs | 5 +- 3 files changed, 22 insertions(+), 152 deletions(-) diff --git a/src/validation/validator.rs b/src/validation/validator.rs index 887f0c17..8a3c3321 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -31,7 +31,7 @@ use seals::txout::Witness; use super::status::{Failure, Warning}; use super::{CheckedConsignment, ConsignmentApi, Status, Validity}; use crate::operation::seal::ExposedSeal; -use crate::vm::{ContractStateAccess, ContractStateEvolve, OrdOpRef, WitnessOrd}; +use crate::vm::{ContractStateAccess, ContractStateEvolve, OrdOpRef, WitnessStatus}; use crate::{ validation, ChainNet, ContractId, OpFullType, OpId, Operation, Opout, OutputSeal, Schema, SchemaId, Transition, @@ -58,8 +58,10 @@ pub enum WitnessResolverError { pub trait ResolveWitness { fn resolve_pub_witness(&self, witness_id: Txid) -> Result; - fn resolve_pub_witness_ord(&self, witness_id: Txid) - -> Result; + fn resolve_pub_witness_ord( + &self, + witness_id: Txid, + ) -> Result; fn check_chain_net(&self, chain_net: ChainNet) -> Result<(), WitnessResolverError>; } @@ -72,7 +74,7 @@ impl ResolveWitness for &T { fn resolve_pub_witness_ord( &self, witness_id: Txid, - ) -> Result { + ) -> Result { ResolveWitness::resolve_pub_witness_ord(*self, witness_id) } @@ -106,7 +108,7 @@ impl ResolveWitness for CheckedWitnessResolver { fn resolve_pub_witness_ord( &self, witness_id: Txid, - ) -> Result { + ) -> Result { self.inner.resolve_pub_witness_ord(witness_id) } @@ -285,9 +287,7 @@ impl< }; if let Some(safe_height) = self.safe_height { match witness_ord { - WitnessOrd::Mined(witness_pos) => { - let witness_height = witness_pos.height(); - // TODO: Safe height can't be "injected" into the consensus! + WitnessStatus::Mined(witness_height) => { if witness_height > safe_height { unsafe_history_map .entry(witness_height.into()) @@ -295,7 +295,7 @@ impl< .insert(witness_id); } } - WitnessOrd::Tentative | WitnessOrd::Ignored | WitnessOrd::Archived => { + WitnessStatus::Tentative | WitnessStatus::Ignored | WitnessStatus::Archived => { unsafe_history_map.entry(0).or_default().insert(witness_id); } } diff --git a/src/vm/contract.rs b/src/vm/contract.rs index abf8f7b6..4d5cc966 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -22,15 +22,14 @@ use std::borrow::Borrow; use std::cmp::Ordering; -use std::fmt::{self, Debug, Display, Formatter}; +use std::fmt::Debug; use bc::{Outpoint, Txid}; -use strict_encoding::StrictDumb; use crate::{ AssignmentType, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, - GlobalStateType, GraphSeal, Layer1, Metadata, OpFullType, OpId, Operation, StructuredData, - Transition, TransitionType, TypedAssigns, + GlobalStateType, GraphSeal, Metadata, OpFullType, OpId, Operation, StructuredData, Transition, + TransitionType, TypedAssigns, }; /// The type is used during validation and computing a contract state. It @@ -41,7 +40,7 @@ use crate::{ pub enum OrdOpRef<'op> { #[from] Genesis(&'op Genesis), - Transition(&'op Transition, Txid, WitnessOrd, OpId), + Transition(&'op Transition, Txid, WitnessStatus, OpId), } impl PartialOrd for OrdOpRef<'_> { @@ -138,100 +137,6 @@ impl<'op> Operation for OrdOpRef<'op> { } } -#[derive(Getters, Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct WitnessPos { - #[getter(as_copy)] - layer1: Layer1, - - #[getter(as_copy)] - height: u32, - - // TODO: Remove - #[getter(as_copy)] - timestamp: i64, -} - -impl StrictDumb for WitnessPos { - fn strict_dumb() -> Self { - Self { - layer1: Layer1::Bitcoin, - height: 1, - timestamp: 1231006505, - } - } -} - -// Sat Jan 03 18:15:05 2009 UTC -const BITCOIN_GENESIS_TIMESTAMP: i64 = 1231006505; - -// Sat Jan 03 18:15:05 2009 UTC -const LIQUID_GENESIS_TIMESTAMP: i64 = 1296692202; - -impl WitnessPos { - pub fn bitcoin(height: u32, timestamp: i64) -> Option { - if timestamp < BITCOIN_GENESIS_TIMESTAMP { - return None; - } - Some(WitnessPos { - layer1: Layer1::Bitcoin, - height, - timestamp, - }) - } - - pub fn liquid(height: u32, timestamp: i64) -> Option { - if timestamp < LIQUID_GENESIS_TIMESTAMP { - return None; - } - Some(WitnessPos { - layer1: Layer1::Liquid, - height, - timestamp, - }) - } -} - -impl PartialOrd for WitnessPos { - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } -} - -impl Ord for WitnessPos { - /// Since we support multiple layer 1, we have to order basing on the - /// timestamp information and not height. The timestamp data are consistent - /// across multiple blockchains, while height evolves with a different - /// speed and can't be used in comparisons. - fn cmp(&self, other: &Self) -> Ordering { - assert!(self.timestamp > 0); - assert!(other.timestamp > 0); - const BLOCK_TIME: i64 = 10 /*min*/ * 60 /*secs*/; - match (self.layer1, other.layer1) { - (a, b) if a == b => self.height.cmp(&other.height), - (Layer1::Bitcoin, Layer1::Liquid) - if (self.timestamp - other.timestamp).abs() < BLOCK_TIME => - { - Ordering::Greater - } - (Layer1::Liquid, Layer1::Bitcoin) - if (other.timestamp - self.timestamp).abs() < BLOCK_TIME => - { - Ordering::Less - } - _ => self.timestamp.cmp(&other.timestamp), - } - } -} - -impl Display for WitnessPos { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}:{}@{}", self.layer1, self.height, self.timestamp) - } -} - /// RGB consensus information about the status of a witness transaction. This information is used /// in ordering state transitions during the validation, as well as consensus ordering of the /// contract global state data, as they are presented to all contract users. @@ -242,15 +147,11 @@ impl Display for WitnessPos { derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "camelCase") )] -pub enum WitnessOrd { - /// Transaction is included into layer 1 blockchain at a specific height and - /// timestamp. - /// - /// NB: only timestamp is used in consensus ordering though, see - /// [`WitnessPos::cmp`] for the details. +pub enum WitnessStatus { + /// Transaction is included into layer 1 blockchain at a specific height. #[from] #[display(inner)] - Mined(WitnessPos), + Mined(u32), /// Valid witness transaction which commits the most recent RGB state, but /// is not (yet) included into a layer 1 blockchain. Such transactions have @@ -284,7 +185,7 @@ pub enum WitnessOrd { Archived, } -impl WitnessOrd { +impl WitnessStatus { #[inline] pub fn is_valid(self) -> bool { self != Self::Archived } } @@ -294,8 +195,8 @@ impl WitnessOrd { /// /// The ordering is the following: /// - Genesis is processed first. -/// - Other operations are ordered according to their witness transactions (see [`WitnessOrd`] for -/// the details). +/// - Other operations are ordered according to their witness transactions (see [`WitnessStatus`] +/// for the details). /// - If two or more operations share the same witness transaction ordering, they are first ordered /// basing on their `nonce` value, and if it is also the same, basing on their operation id value. /// @@ -309,7 +210,7 @@ impl WitnessOrd { pub enum OpOrd { Genesis, Transition { - witness: WitnessOrd, + witness: WitnessStatus, ty: TransitionType, nonce: u64, opid: OpId, @@ -320,7 +221,7 @@ impl OpOrd { #[inline] pub fn is_archived(&self) -> bool { matches!(self, Self::Transition { - witness: WitnessOrd::Archived, + witness: WitnessStatus::Archived, .. }) } @@ -352,31 +253,3 @@ pub trait ContractStateEvolve { fn init(context: Self::Context<'_>) -> Self; fn evolve_state(&mut self, op: OrdOpRef) -> Result<(), Self::Error>; } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn witness_post_timestamp() { - assert_eq!(WitnessPos::bitcoin(1, BITCOIN_GENESIS_TIMESTAMP - 1), None); - assert_eq!(WitnessPos::liquid(1, LIQUID_GENESIS_TIMESTAMP - 1), None); - assert_eq!(WitnessPos::liquid(1, BITCOIN_GENESIS_TIMESTAMP), None); - assert!(WitnessPos::bitcoin(1, BITCOIN_GENESIS_TIMESTAMP).is_some()); - assert!(WitnessPos::liquid(1, LIQUID_GENESIS_TIMESTAMP).is_some()); - assert!(WitnessPos::bitcoin(1, LIQUID_GENESIS_TIMESTAMP).is_some()); - } - - #[test] - fn witness_pos_getters() { - let pos = WitnessPos::bitcoin(1, BITCOIN_GENESIS_TIMESTAMP).unwrap(); - assert_eq!(pos.height(), 1); - assert_eq!(pos.timestamp(), BITCOIN_GENESIS_TIMESTAMP); - assert_eq!(pos.layer1(), Layer1::Bitcoin); - - let pos = WitnessPos::liquid(1, LIQUID_GENESIS_TIMESTAMP).unwrap(); - assert_eq!(pos.height(), 1); - assert_eq!(pos.timestamp(), LIQUID_GENESIS_TIMESTAMP); - assert_eq!(pos.layer1(), Layer1::Liquid); - } -} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 66ea4a37..d3e65e42 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -26,7 +26,4 @@ mod contract; -pub use contract::{ - ContractStateAccess, ContractStateEvolve, OpOrd, OrdOpRef, UnknownGlobalStateType, WitnessOrd, - WitnessPos, -}; +pub use contract::{ContractStateAccess, ContractStateEvolve, OpOrd, OrdOpRef, WitnessStatus}; From 71291b2ba21ccb2a7c34a7594b46455b43702193 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:21:51 +0200 Subject: [PATCH 14/23] validation: remove any consensus operation ordering --- src/validation/consignment.rs | 4 ++ src/validation/logic.rs | 10 +-- src/validation/validator.rs | 23 ++++--- src/vm/contract.rs | 115 ++++++++-------------------------- src/vm/mod.rs | 2 +- 5 files changed, 47 insertions(+), 107 deletions(-) diff --git a/src/validation/consignment.rs b/src/validation/consignment.rs index 24f3de44..3a025fbf 100644 --- a/src/validation/consignment.rs +++ b/src/validation/consignment.rs @@ -146,6 +146,10 @@ pub trait ConsignmentApi { fn genesis(&self) -> &Genesis; /// Returns iterator over all transition ids present in the consignment. + /// + /// # Nota bene + /// + /// Operations are validated in the order they are reported by this consignment API fn transitions(&self) -> impl Iterator; /// Returns a an anchor - MPC Merkle proof that a given opid is committed in deterministic diff --git a/src/validation/logic.rs b/src/validation/logic.rs index cd23a189..3440004b 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -32,7 +32,7 @@ use strict_types::TypeSystem; use crate::assignments::AssignVec; use crate::schema::{AssignmentsSchema, GlobalSchema}; use crate::validation::{CheckedConsignment, ConsignmentApi}; -use crate::vm::{ContractStateAccess, ContractStateEvolve, OrdOpRef}; +use crate::vm::{ContractStateAccess, ContractStateEvolve, FullOpRef}; use crate::{ validation, AnyState, Assign, AssignmentType, Assignments, AssignmentsRef, ExposedSeal, ExposedState, GlobalState, GlobalStateSchema, GlobalValues, GraphSeal, Inputs, MetaSchema, @@ -48,7 +48,7 @@ impl Schema { >( &'validator self, consignment: &'validator CheckedConsignment<'_, C>, - op: OrdOpRef, + op: FullOpRef, contract_state: Rc>, ) -> validation::Status { let opid = op.id(); @@ -57,7 +57,7 @@ impl Schema { let empty_assign_schema = AssignmentsSchema::default(); let (metadata_schema, global_schema, owned_schema, assign_schema, validator, ty) = match op { - OrdOpRef::Genesis(genesis) => { + FullOpRef::Genesis(genesis) => { if genesis.seal_closing_strategy != SealClosingStrategy::FirstOpretOrTapret { return validation::Status::with_failure( validation::Failure::SchemaUnknownSealClosingStrategy( @@ -75,7 +75,7 @@ impl Schema { None::, ) } - OrdOpRef::Transition( + FullOpRef::Transition( Transition { transition_type, .. }, @@ -116,7 +116,7 @@ impl Schema { status += self.validate_metadata(opid, op.metadata(), metadata_schema, consignment.types()); status += self.validate_global_state(opid, op.globals(), global_schema, consignment.types()); - let prev_state = if let OrdOpRef::Transition(transition, ..) = op { + let prev_state = if let FullOpRef::Transition(transition, ..) = op { let prev_state = extract_prev_state(consignment, opid, &transition.inputs, &mut status); status += self.validate_prev_state(opid, &prev_state, owned_schema); prev_state diff --git a/src/validation/validator.rs b/src/validation/validator.rs index 8a3c3321..987607ca 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -31,7 +31,7 @@ use seals::txout::Witness; use super::status::{Failure, Warning}; use super::{CheckedConsignment, ConsignmentApi, Status, Validity}; use crate::operation::seal::ExposedSeal; -use crate::vm::{ContractStateAccess, ContractStateEvolve, OrdOpRef, WitnessStatus}; +use crate::vm::{ContractStateAccess, ContractStateEvolve, FullOpRef, WitnessStatus}; use crate::{ validation, ChainNet, ContractId, OpFullType, OpId, Operation, Opout, OutputSeal, Schema, SchemaId, Transition, @@ -260,13 +260,12 @@ impl< // [VALIDATION]: Validate genesis *self.status.borrow_mut() += schema.validate_state( &self.consignment, - OrdOpRef::Genesis(self.consignment.genesis()), + FullOpRef::Genesis(self.consignment.genesis()), self.contract_state.clone(), ); - // [VALIDATION]: Iterating over all consignment operations, ordering them according to the - // consensus ordering rules. - let mut ops = BTreeSet::::new(); + // [VALIDATION]: Iterating over all consignment operations + let mut ops = Vec::::new(); let mut unsafe_history_map: HashMap> = HashMap::new(); for transition in self.consignment.transitions() { let opid = transition.id(); @@ -274,8 +273,7 @@ impl< .consignment .anchor(opid) .expect("invalid checked consignment"); - // TODO: Remove all ordering! - let witness_ord = match self.resolver.resolve_pub_witness_ord(witness_id) { + let witness_status = match self.resolver.resolve_pub_witness_ord(witness_id) { Ok(ord) => ord, Err(err) => { self.status @@ -286,7 +284,7 @@ impl< } }; if let Some(safe_height) = self.safe_height { - match witness_ord { + match witness_status { WitnessStatus::Mined(witness_height) => { if witness_height > safe_height { unsafe_history_map @@ -300,13 +298,14 @@ impl< } } } - ops.insert(OrdOpRef::Transition(transition, witness_id, witness_ord, opid)); + ops.push(FullOpRef::Transition(transition, witness_id, witness_status, opid)); } if self.safe_height.is_some() && !unsafe_history_map.is_empty() { self.status .borrow_mut() .add_warning(Warning::UnsafeHistory(unsafe_history_map)); } + // Operations are validated in the order they are reported by the consignment API for op in ops { // We do not skip validating archive operations since after a re-org they may // become valid and thus must be added to the contract state and validated @@ -315,7 +314,7 @@ impl< } } - fn validate_operation(&self, operation: OrdOpRef<'consignment>) { + fn validate_operation(&self, operation: FullOpRef<'consignment>) { let schema = self.consignment.schema(); let opid = operation.id(); @@ -337,10 +336,10 @@ impl< schema.validate_state(&self.consignment, operation, self.contract_state.clone()); match operation { - OrdOpRef::Genesis(_) => { + FullOpRef::Genesis(_) => { unreachable!("genesis is not a part of the operation history") } - OrdOpRef::Transition(transition, ..) => { + FullOpRef::Transition(transition, ..) => { for input in &transition.inputs { if self.consignment.operation(input.op).is_none() { self.status diff --git a/src/vm/contract.rs b/src/vm/contract.rs index 4d5cc966..c6c0e866 100644 --- a/src/vm/contract.rs +++ b/src/vm/contract.rs @@ -21,15 +21,13 @@ // limitations under the License. use std::borrow::Borrow; -use std::cmp::Ordering; use std::fmt::Debug; use bc::{Outpoint, Txid}; use crate::{ - AssignmentType, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, - GlobalStateType, GraphSeal, Metadata, OpFullType, OpId, Operation, StructuredData, Transition, - TransitionType, TypedAssigns, + AssignmentType, AssignmentsRef, ContractId, FungibleState, Genesis, GlobalState, GraphSeal, + Metadata, OpFullType, OpId, Operation, StructuredData, Transition, TypedAssigns, }; /// The type is used during validation and computing a contract state. It @@ -37,102 +35,82 @@ use crate::{ /// in the contract history (via construction of [`OpOrd`]) according to the /// consensus rules. #[derive(Copy, Clone, PartialEq, Eq, Debug, From)] -pub enum OrdOpRef<'op> { +pub enum FullOpRef<'op> { #[from] Genesis(&'op Genesis), Transition(&'op Transition, Txid, WitnessStatus, OpId), } -impl PartialOrd for OrdOpRef<'_> { - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } -} - -impl Ord for OrdOpRef<'_> { - fn cmp(&self, other: &Self) -> Ordering { self.op_ord().cmp(&other.op_ord()) } -} - -impl OrdOpRef<'_> { +impl FullOpRef<'_> { pub fn witness_id(&self) -> Option { match self { - OrdOpRef::Genesis(_) => None, - OrdOpRef::Transition(_, witness_id, ..) => Some(*witness_id), + FullOpRef::Genesis(_) => None, + FullOpRef::Transition(_, witness_id, ..) => Some(*witness_id), } } pub fn opid(&self) -> Option { match self { - OrdOpRef::Genesis(_) => None, - OrdOpRef::Transition(_, _, _, opid) => Some(*opid), - } - } - - pub fn op_ord(&self) -> OpOrd { - match self { - OrdOpRef::Genesis(_) => OpOrd::Genesis, - OrdOpRef::Transition(op, _, witness_ord, _) => OpOrd::Transition { - witness: *witness_ord, - ty: op.transition_type, - nonce: op.nonce, - opid: op.id(), - }, + FullOpRef::Genesis(_) => None, + FullOpRef::Transition(_, _, _, opid) => Some(*opid), } } } -impl<'op> Operation for OrdOpRef<'op> { +impl<'op> Operation for FullOpRef<'op> { fn full_type(&self) -> OpFullType { match self { - OrdOpRef::Genesis(op) => op.full_type(), - OrdOpRef::Transition(op, ..) => op.full_type(), + FullOpRef::Genesis(op) => op.full_type(), + FullOpRef::Transition(op, ..) => op.full_type(), } } fn id(&self) -> OpId { match self { - OrdOpRef::Genesis(op) => op.id(), - OrdOpRef::Transition(op, ..) => op.id(), + FullOpRef::Genesis(op) => op.id(), + FullOpRef::Transition(op, ..) => op.id(), } } fn contract_id(&self) -> ContractId { match self { - OrdOpRef::Genesis(op) => op.contract_id(), - OrdOpRef::Transition(op, ..) => op.contract_id(), + FullOpRef::Genesis(op) => op.contract_id(), + FullOpRef::Transition(op, ..) => op.contract_id(), } } fn nonce(&self) -> u64 { match self { - OrdOpRef::Genesis(op) => op.nonce(), - OrdOpRef::Transition(op, ..) => op.nonce(), + FullOpRef::Genesis(op) => op.nonce(), + FullOpRef::Transition(op, ..) => op.nonce(), } } fn metadata(&self) -> &Metadata { match self { - OrdOpRef::Genesis(op) => op.metadata(), - OrdOpRef::Transition(op, ..) => op.metadata(), + FullOpRef::Genesis(op) => op.metadata(), + FullOpRef::Transition(op, ..) => op.metadata(), } } fn globals(&self) -> &GlobalState { match self { - OrdOpRef::Genesis(op) => op.globals(), - OrdOpRef::Transition(op, ..) => op.globals(), + FullOpRef::Genesis(op) => op.globals(), + FullOpRef::Transition(op, ..) => op.globals(), } } fn assignments(&self) -> AssignmentsRef<'op> { match self { - OrdOpRef::Genesis(op) => op.assignments(), - OrdOpRef::Transition(op, ..) => op.assignments(), + FullOpRef::Genesis(op) => op.assignments(), + FullOpRef::Transition(op, ..) => op.assignments(), } } fn assignments_by_type(&self, t: AssignmentType) -> Option> { match self { - OrdOpRef::Genesis(op) => op.assignments_by_type(t), - OrdOpRef::Transition(op, ..) => op.assignments_by_type(t), + FullOpRef::Genesis(op) => op.assignments_by_type(t), + FullOpRef::Transition(op, ..) => op.assignments_by_type(t), } } } @@ -190,47 +168,6 @@ impl WitnessStatus { pub fn is_valid(self) -> bool { self != Self::Archived } } -/// Operation ordering priority for contract state computation according to -/// [RCP-240731A]. -/// -/// The ordering is the following: -/// - Genesis is processed first. -/// - Other operations are ordered according to their witness transactions (see [`WitnessStatus`] -/// for the details). -/// - If two or more operations share the same witness transaction ordering, they are first ordered -/// basing on their `nonce` value, and if it is also the same, basing on their operation id value. -/// -/// [RCP-240731A]: https://github.com/RGB-WG/RFC/issues/10 -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub enum OpOrd { - Genesis, - Transition { - witness: WitnessStatus, - ty: TransitionType, - nonce: u64, - opid: OpId, - }, -} - -impl OpOrd { - #[inline] - pub fn is_archived(&self) -> bool { - matches!(self, Self::Transition { - witness: WitnessStatus::Archived, - .. - }) - } -} - -#[derive(Copy, Clone, Debug, Display, Error)] -#[display("unknown global state type {0} requested from the contract")] -pub struct UnknownGlobalStateType(pub GlobalStateType); - pub trait ContractStateAccess: Debug { fn rights(&self, outpoint: Outpoint, ty: AssignmentType) -> u32; @@ -251,5 +188,5 @@ pub trait ContractStateEvolve { type Context<'ctx>; type Error: std::error::Error; fn init(context: Self::Context<'_>) -> Self; - fn evolve_state(&mut self, op: OrdOpRef) -> Result<(), Self::Error>; + fn evolve_state(&mut self, op: FullOpRef) -> Result<(), Self::Error>; } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index d3e65e42..927d5ed6 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -26,4 +26,4 @@ mod contract; -pub use contract::{ContractStateAccess, ContractStateEvolve, OpOrd, OrdOpRef, WitnessStatus}; +pub use contract::{ContractStateAccess, ContractStateEvolve, FullOpRef, WitnessStatus}; From bd04e0d30c52b2032881bebae9c8c177c481d362 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:27:54 +0200 Subject: [PATCH 15/23] chore: remove unused Layer1 structure --- src/operation/layer1.rs | 28 ---------------------------- src/operation/mod.rs | 2 +- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/operation/layer1.rs b/src/operation/layer1.rs index 7a415fcf..250e757d 100644 --- a/src/operation/layer1.rs +++ b/src/operation/layer1.rs @@ -27,23 +27,6 @@ use strict_encoding::{StrictDecode, StrictEncode, StrictType}; use crate::LIB_NAME_RGB_COMMIT; -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)] -#[display(lowercase)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT, tags = repr, into_u8, try_from_u8)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -#[repr(u8)] -#[derive(Default)] -pub enum Layer1 { - #[default] - Bitcoin = 0, - Liquid = 1, -} - #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[display(inner)] #[derive(StrictType, StrictEncode, StrictDecode)] @@ -79,17 +62,6 @@ impl ChainNet { } } - pub fn layer1(&self) -> Layer1 { - match self { - ChainNet::BitcoinMainnet - | ChainNet::BitcoinTestnet3 - | ChainNet::BitcoinTestnet4 - | ChainNet::BitcoinSignet - | ChainNet::BitcoinRegtest => Layer1::Bitcoin, - ChainNet::LiquidMainnet | ChainNet::LiquidTestnet => Layer1::Liquid, - } - } - pub fn genesis_block_hash(&self) -> BlockHash { BlockHash::from_str(match self { ChainNet::BitcoinMainnet => { diff --git a/src/operation/mod.rs b/src/operation/mod.rs index 955c4d0d..d7f231f9 100644 --- a/src/operation/mod.rs +++ b/src/operation/mod.rs @@ -38,7 +38,7 @@ pub use commit::{ContractId, OpId}; pub use data::{StructuredData, VoidState}; pub use fungible::FungibleState; pub use global::{GlobalState, GlobalValues}; -pub use layer1::{ChainNet, Layer1}; +pub use layer1::ChainNet; pub use meta::{MetaValue, Metadata, MetadataError}; pub use operations::{ Genesis, Identity, Inputs, Operation, Opout, OpoutParseError, SealClosingStrategy, Signature, From 388739426e09f3ce94ea54eab7d142538b154a4f Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:32:04 +0200 Subject: [PATCH 16/23] stl: regenerate libs --- src/bin/rgbcore-stl.rs | 5 - stl/Genesis.vesper | 12 +- stl/RGBCommit@0.1.0.sta | 257 +++++++++++++++++++--------------------- stl/RGBCommit@0.1.0.stl | Bin 8430 -> 7502 bytes stl/RGBCommit@0.1.0.sty | 90 ++++++-------- stl/Transition.vesper | 46 +------ 6 files changed, 165 insertions(+), 245 deletions(-) diff --git a/src/bin/rgbcore-stl.rs b/src/bin/rgbcore-stl.rs index ba517583..5624ef6a 100644 --- a/src/bin/rgbcore-stl.rs +++ b/src/bin/rgbcore-stl.rs @@ -113,11 +113,6 @@ Transition vesper lexicon=types+commitments ) .unwrap(); let layout = Transition::commitment_layout(); - writeln!(file, "{layout}").unwrap(); - let tt = sys.type_tree("RGBCommit.OpCommitment").unwrap(); - writeln!(file, "{tt}").unwrap(); - let tt = sys.type_tree("RGBLogic.DbcProof").unwrap(); - writeln!(file, "{tt}").unwrap(); let tt = sys.type_tree("RGBCommit.Transition").unwrap(); writeln!(file, "{tt}").unwrap(); diff --git a/stl/Genesis.vesper b/stl/Genesis.vesper index e3ef95cf..c5508655 100644 --- a/stl/Genesis.vesper +++ b/stl/Genesis.vesper @@ -8,7 +8,7 @@ Bundles vesper lexicon=types+commitments commitment OpId, hasher SHA256, tagged urn:lnp-bp:rgb:operation#2024-02-03 - serialized OpCommitment + serialized Genesis rec Genesis is ffv, U16, aka Ffv @@ -23,7 +23,7 @@ rec Genesis map globals, len 0..MAX8, aka GlobalState is key, U16, aka GlobalStateType list value, len 1..MAX16, aka GlobalValues - bytes element, len 0..MAX16, aka StructureddData + bytes element, len 0..MAX16, aka StructuredData map assignments, len 0..MAX16, aka AssignmentsBlindSealTxid is key, U16, aka AssignmentType union value, TypedAssignsBlindSealTxid @@ -49,15 +49,15 @@ rec Genesis rec secretSeal, tag 1 bytes seal, len 32, aka SecretSeal is state, U64, aka FungibleState - list structured, len 1..MAX16, wrapped, aka AssignVecAssignStructureddDataBlindSealTxid, tag 2 - union AssignStructureddDataBlindSealTxid + list structured, len 1..MAX16, wrapped, aka AssignVecAssignStructuredDataBlindSealTxid, tag 2 + union AssignStructuredDataBlindSealTxid rec revealed, tag 0 rec seal, BlindSealTxid bytes txid, len 32, aka Txid is vout, U32, aka Vout is blinding, U64 - bytes state, len 0..MAX16, aka StructureddData + bytes state, len 0..MAX16, aka StructuredData rec secretSeal, tag 1 bytes seal, len 32, aka SecretSeal - bytes state, len 0..MAX16, aka StructureddData + bytes state, len 0..MAX16, aka StructuredData diff --git a/stl/RGBCommit@0.1.0.sta b/stl/RGBCommit@0.1.0.sta index 044c5c64..47c902b3 100644 --- a/stl/RGBCommit@0.1.0.sta +++ b/stl/RGBCommit@0.1.0.sta @@ -1,146 +1,131 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:2cchW1ud-aDIF0xy-igHwZpu-9QOBMjc-aiO_rs7-ph0Dua0#ralph-chris-hotel +Id: stl:eBR7hVUY-AAhMZQS-BxMGUdt-D5VCa4l-gvFPe4s-hXYkthg#enrico-ohio-maxwell Name: RGBCommit Dependencies: - BPCore#juliet-super-dominic, - CommitVerify#violet-panther-herbert, Std#delete-roman-hair, + BPSeals#balloon-oscar-george, StrictTypes#henry-heart-survive, Bitcoin#signal-color-cipher -Check-SHA256: 6f8d32a4a997f8ae3c8afc9be7621039597686d1729e4805f3fd99bff682c31a +Check-SHA256: a6812ee604501de3846fb1ded3af221f5a8791c53d8ca94ea5fc3a9523b494a0 -2~tNwLvL+uX>pKz(VCaX%3mIP&XB&sB3y@ML2MxM-cip;h4&;#rLQq3*a%D_q7H}ii_tAk8EiIL^ -F;WduOYhK!;vHZzZO$@xxWWuWZ*6U9bXH|@X=ZtXiR(=d3vg7gbV~*3!PlK51EySK%g?1}nECovJTYnm -Q*>nMo|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsOQ*?4^V{}w`aAkA#Y!hN5_Bp3Y36tDMM#=e# -tGI($UA5U3KNx<*C>ja}LTPkkZ)t7?20~CnZ*pY>04xKINJ~fc1UzTDb_LBRjrSXj?;k=^zm6d~Uh7!w -Pz^$CX>MdwWnpYocxhy48SA{&vly$FvzVnzHf7z~rv`86=_Ka^V5yX|y#`JSQ)OdvWpqi7rMzqbp%##b#$YG -Li5Yl(a@n1+Ku60FILp}Zw|!7cE!MGSxid=WmW`Kcxhw|LvL+uX>?X)a%pCH0suIkLxv|61vo|1ioJpYH;+t0eX2 -w~A!Q+0eaZ{MVycPK^aqWo=1hH2@(&b8~5DZbo%(XK7+=Wm9xvbY((pX>MdwWnpYocu;h51OfmEa%Fa9 -VQgh&00sgCb7f&{0zKhpP*aQYQxux_Ecpx^NEUk*BEgxdReUg_1Rxg;i+hpP*aQYQxux_Ecpx^NEUk!Ts~yw$T9tCzEwrAszt-P)%HZ|LbH -=L2A=l(W4CP6cyxVRU5ya8s&1i~(KPc+oy|5YcifETK|4Gx3F{F4yC1Gh5PkAVG6;X=iRmb#7;AVr*qo -bYXO5LTqVnWK(5fY*ct@WCQ{L2y$h1WnpY(WB>*N1aoC!Yyv&&I}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D --MVlN`(=BbYXO50dP~QJ&XZe*m%)CbP&;UDlDN= -IWzHvrY_gxY%^QZcL54>Wn*$>bW>$vYybuV1aoC!Yyv&&I}!?D=!eA%8DA7<8;7e4kWwcH4Z3)D-MVlN -%7&o7^|1Fn59cLW!>7R25;!;B*N1aoC! -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 -NAc?Tc{K-TY;R&=Y;yr~1*%39vO>-_DBy -8`Vb0jGrW9$=2qSMXvL3HGEG0000000000{{R30 -000003t@9}X=iS2Wo~qH015$z{^Dg=h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQnHo-KZ`k;Xmr`<4s -JYKN!!u{G5u+^j1lf!PF4>GEG0000000000{{R30000004M%KmVqt7VWprU_Y;y(z5oc^~Vqt7kbYXO5 -Q)6glZD9d+nB!jSlPQjTl%(2ntadXH-EO|kM)2Sug?ZeeX@0_mQT=Q}``f02HLt~iCiD@{1J -w0_*8A_pi$)ov?1P#d&Z0rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~atlXnZ(?C=Q*>c;Wd#8M3IWyb -k`76TvuW{aQ_%-X`?VwZ$5L?~`!+pRSq0(b70Uqz4Mioice*JsNExZXTBqWc!?;yX>tAhmw6GC?2vq<8 -0000000030000000000HM{I9mVQf=$VRU6vV`ybmw%Cdg|0Y-zbj2Rx3qrT -q9O+ioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^j{VR%V&Wo>f+00R$4Y;R&=Y*Tb$ -bY)a|aAgGn0006EM{I9mVQf}mY;|RG1pxpE0ap$M*HSPyML$lcIwZ0>heK_vfJDKdRfkLPI75mFCjkHe -000000RR600000000>EBWo~q7ba@2<00ja9f{E)*4-0TquXIZV=)u>WBLk*fW6RH_XPEi=Ry;9kNWLQ% -D(Hkon&*Qwpawq)`VKLB>Wd>h=Ype%b?27200;ttiR(=d3vg7gbV~*3!PlK51EySK%g?1}nECovJTYoW -z9SbZ=!8X@=Yuq$20sb<4l#S`iz7Vef}@Ca=a#qt00000000304*&oF00006Np5g;baMp(00{w;5WIk~ -G+K)5%bR49t5yk`^qQ9e0000000030{{R300000BO=WapL}hegX>4-_0tItrZAoMT ->7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0mw%Cdg|0Y-zbj2Rx3qrTq9O+QGbYWy+bYTSn -015$h4P{pQ?3(@m6s4{*=wy-PiS_k>Wl|t&* -Fr0fZ0000000000{{R30000003r}NXb#iiLZewM01_A?ZX>I@j0t0PfcmMzb3{P-FZ*6U9bZupBbOr|l -W@dH)+M7`mSQb`xkca!3ceuiB -udT)PryvH%qoUf%jN6#Tx81sfg4O?s`uaep_R|IjXKZg`VQg~(Ol1~uBiHxQff6k(m9sHY4N^<*(1+q3 -U@~paGIzMbIG#g>Clv)aMjKgwAH@`bu1x<7g|G$};xvA~n-$_S25D|^b#!wAOl1~uBiHxQff6k(m9sHY -4N^<*(1+q3U@~paGIzMbIG#g>Clv)aMjKgwAH@`bu1x<7g|G$};xvA~n-$_S3t@9}X=iS2Wo~qH0!(EV -a3k0E(SZ^zEtRt|QVmi|@6dsZfv!yd427@;7veO2zMB=|GXzg? -Nn`~900#g7Kp+4GPjGK_bOr+gZ*T#X$mV(;bz)!CmQ_M(k?Vd!kfCo{nDM?)_qK{868FUdba?@X{^Dg= -h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQoZf^hp0uWDkZe?UsbYXO5Q)6glZD9lh01ISgV{Bn^VRUJB -WdHyG0SIPwZf9v?Y-Iod00IhgbaHiLbairNWB>&L0_mQT=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1 -P-_IE6rQG)02XJT?*g=|B=zREie$*y(7k2+*P~cYjRsR=Xk~3-1_%RYW_AJEn^6;37FKqUhx?i3R+Mr! -fY&(;2BFL(m@EZk_srDU3Qf4cdUdGS4#Tk(yYN*ff#-&-~S0000000030000000000BXKZg`VQf@+aAk7< -3IWybk`76TvuW{aQ_%-X`?VwZ$5L?~`!+pRSq0(b70Uq+w#z7JBTYQ(6wA15KJe33N=y1k%8ssy_EyFt -I!|)|0000000030000000000AZ+C8GWK?-@Wpe-u0f+wLWmt%8=p4R=gtK{LClh6Z#kObxUW*hKHnBv9 -xdFK%KKY6{y^9(U*_!W#CeCf%@U$Ra$QlHXZNo -_Yhhx0Be79xh+o&58gBLg%$F9MUi-9%UHGxbaG*Cb7^#GZ*Fq{3IQ}y53UoI8eY9A{1GERg--GiI0S#x -1is&)M%fmnGH3x@!%VR!boT!l0ce6}iE2`s>&2w5gKr7m?oSuHf_Z2F0000000030000000000HWMyVy -b!>D&b8~5DZf#|5bN~bb00eGtZe;)f009JZZ*64&1pxtv{^Dg=h-~N_zJ`Red1EINWrM}GXaQb}6c#qI -M2EQuQ)6glZDC1d1pxpD002NB025PXVQfQeZ*ysGXH#@?VRU6@c>@6wW@&PBbWd<{Wpqz+RAF#(Wpn@u -Q)y>zVRUtJWd#8M2LJ#-KmZR@baHiLbairNWMo8PbYTSn00;m8KmY&$000000RR6000000018xcVQzD2 -bZKvH1_=XZW_AJEn^6;37FKqUhx?i3R+Mr!fY&(;2BFL(m@EZk_srD_V{dMBa$#e1Nn`<^2rNlD$O59e -#ogQsB77jPl+h5j^*S;IZf|a5WdHyO4s>#1ZgXjLX>V>+d2nR`G*S<)6P6lYy(#<=BR_>s -@(?%#f7ArN-=Rj?7Ns(12yJC_VPs)+VFC4eO*mP8`7qV21dnrCyk{{a-lF$FG0V5TNAc?Tc{K-TY;R&= -Y;yr~1*%39M?JbaMeV21}DyAtKyJp!y-llj5_1lAj$w -(~~K8Zku=D-c1t133F*@ZeetF -a%BJn0ssVVZ*FA(00035b8l^B00jX7M8fTce@(tLz$ZX87367p`iG2_*yhBBgBn-y*4#eJ5ma(vZgXjL -X>V>sWprU_Y;y(z5Oi{3ZgXjLX>V>*V`yb7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0V>*V`ybVZDn*}WMOn+00{wgM?JbaMa-0f+wLWmt%8 -=p4R=gtK{LClh6Z#kObxUW*hKHnBv9xdAr8G@<&SffJ|QFn~N>u=2wF+7z(Wqt=tdZk`V^s(Ana00000 -0093000000000YNb8~5DZf#|5baMa-0f+wLWmt%8=p4R=gtK{LClh6Z#kObxUW*hKHnBv9xdAr8G@<&S -ffJ|QFn~N>u=2wF+7z(Wqt=tdZk`V^s(Ana000000093000000000PfWpZg|X=QQ&S&9Jdz!fD%xD>w# -lyWiUB+!(H@tHM=pRv_mVsOaX4peesZgXjLX>V>+d2nR~0RR934pez?WkYXmZE19EWo~o?0sseRWo~72 -X>$Mt0RgihG4gRlb*0t|jsx5zO?CPp*w$VoGZuoxi65I6*X)C9iYp+?yjr7~z5RC#b^WI=Ot -X=iS8LTqVnWK(5fY*ctqbaDg(01ISgV{Bn^VRUJBWdH>M0jXmSzQi_Bob4h>{BE>m*T@oo-6oh0SIPwZf9v?Y-Ioi0RaQ+ -LUU)9P1F3fk)PC*KgHh%%41=0N|UI$lu$Tz`bPo^b98cbV{~SEP-*{> -tZNSyepJg@gxtasDgX#pWpZg|X=QQ)0R(PuZe;)oR&Qx!Q*>c;Wd#8M000 +2~tNwLvL+uX>mfM)c|rOrSAqOFlj|?PZGn +7*@S>vOg%-GTKs92V@urLQqp>VQh2ho|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsOQ*?4^V{}w` +aAkA#Y!hN5_Bp3Y36tDMM#=e#tGI($UA5U3KNx<*C>ja}LTPkkZ)t7>2SQL&WnpY{1OO}pjYvyJ^#nX; +x^@N4Cyn`)CtY-w&}Q)OXnRCsA*Xc_Cg)w39@m$R6qOEzWQ+NTC@=;JJaHJF7}X$37Y21E`BySDf%$MYb{T~|g9LTqVnWK(5fY*ctqbaJuf +I5`vwIKJ?28qdBQV5M*2;q-lY2q<~K(fZR6A>9R3cu;h52SRCdV{d700stZ7K10Q-T=FR=Q=>S+XYD&< +oK4xzy{V5hX&1W5Lv;jJZ*_E|f1ioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^aq +Wo=1hG5{e#b8~5DZbo%(XK7+=Wm9xvbY((pX>MdwWnpYocu;h51OfmEa%Fa9VQgh&00sgCb7f&{0;fjw +>JLnyF>6acJ~i!Siv1W?y>zlaDAzLDQd9?I7^kT6xdReUg_1Rxg;i+JLny +F>6acJ~i!Siv1W?y>zlaDAzLDQd9?I7-$*myw$T9tCzEwrAszt-P)%HZ|LbH=L2A=l(W4CP6cyxVRU5y +a8s&1i~(KPc+oy|5YcifETK|4Gx3F{F4yC1Gh5PkAVG6;X=iRmb#7;AVr*qobYXO5LTqVnWK(5fY*ct@ +WCQ{L2y$h1WnpY(WB>*N1aoC!Yyzi7^y&{xpfPJpK0Y<=Ws3b6R=sqxKPcBS+EP>pWEd<1jYvyJ^#nX; +x^@N4Cyn`(=BbYXO50dP~QJ&XZe*m%)CbP&;UDlDN=IWzHvrY_gxY%^QZcL54> +Wn*$>bW>$vYybuV1aoC!Yyzi7^y&{xpfPJpK0Y<=Ws3b6R=sqxKPcBS+EP>pWEf}}>%7&o7^|1Fn59cL +W!>7R25;!;BMdwWnpYocu;h51OfmEa%Fa9VQgh&00sgCb7f&{0;fjw>JLnyF>6acJ~i!S +iv1W?y>zlaDAzLDQd9?I7^kT6xdReUg_1Rxg;i+JLnyF>6acJ~i!Siv1W? +y>zlaDAzLDQd9?I7-$*myw$T9tCzEwrAszt-P)%HZ|LbH=L2A=l(W4CP6cyxVRU5y-xZ2WcZk9YpN?Ho +E37)V@UaB=xfkD;^Zy-df?{(#AwhFvOg%-GTKs92V@v51C2;aNA(0eXS#L;%_oib8;tKC +LQ=nuAv#{`SnN;*b97;JWdYw6ic5Eh!U~^`T~RBnI=Aq#1o*iZ-vOg%-GTKs92V@v%8SA{&vly$FvzVnzHf7z~rv`86=_Ka^ +V5yX|y#`JNb97;JWdYw6ic5Eh!U~^`T~RBnI=Aq#1o*iZ-eZ2myv`n7VI@{wG`9DTmNl&mEmXjREG}ON9t%?$wbAJd^eZ2m#KF$&TIzZZ!sYHp;}n^!M$4P3Lb#i57L}7GcLTqVnWK(5fY*ct@WCZ~L2mxUh +EZZtf=>3rT^b18dr4}$=B4vfEp+P~VjQ#Zjt_1-A000000096000000001UIb8~5DZdPSuL349yXKq$+ +X=GD$VRU6eY-w&}Q)OXnRCrKyas>eZ2mu)@`bp7b7}p@jt$c1>Y&)x;l{?fgTy9Yg2OLfE+l&DK00000 +0096000000001RHb8~5DZdPSuL349yXKq$+X=GD$VRU6eY-w&}Q)OXnRCsA*1pxpE0iaSbQa$WiQLrw+ +HljZgruH)j!GWP=tMpo04c;WkPIeZe&wsVQf@* +P;_zx0sshdWp-s@Y-MBs1_A_gWnpXrr$+SZ4@{sjYfC;pHSJ}J{TNogbh1Av*D~5tR0m`jr>OF|0}@Y# +k~NrxRcQq+F$P2q2)nlUE64L7%3W7R1#@&^bY%f9vZekPz%WEGnBZKS8(M7E9_@AwVcyGtCevi|7U8=A +3Ug&+a%FT=WnpXp1_A_gWnpXrr$+SZ4@{sjYfC;pHSJ}J{TNogbh1Av*D~5tR0m`jXc_Cg)w39@m$R6q +OEzWQ+NTC@=;JLnyF>6acJ~i!Siv1W? +y>zlaDAzLDQd9?I7%T&gNJ~fc1UzTDb_LBRjrSXj?;k=^zm6d~Uh7!wPz7^zVRU5yF0!Tm7r-z?Fqq(6 +n;Tke)*kJ44PoBPfF{#q^A_Q|0Sa?vV{&D5Q)OXn00sgCb7f&{0;fjw>JLnyF>6acJ~i!Siv1W?y>zla +DAzLDQd9?I7-$*myw$T9tCzEwrAszt-P)%HZ|LbH=L2A=l(W4CP6cyxVRU5yF0!Tm7r-z?Fqq(6n;Tke +)*kJ44PoBPfF{#q^A_Q|5kYfvX=iS2Wo~ptWprU_Y;y(!5N~&GWn@!yVRU6vV`yb>SKenA+;cP=FifXbr)e?kOqVQpms>7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj06 +5I6*X)C9iYp+?yjr7~y^L349yXKrm}Zgf<6aAgGn0006RL349yXKrm}Zgg`(Y-w&}Q)OXnRCrKyas>eZ +3IT`y;$>KfZ0H=mhJ>?uVXklq?PGxih2M%IsbYpL6ZcSlnZf<3C01skmbYpL6Zd7G+bZ%vIGXW1`X>?<6X>L?yb98QHbTk4D +Vrg_^Z)t8*X=iR_bOR1zX>?<6X>L+wXLMzAbOa4-X>oOFWKCgdZf<3C1r2Ozadl~ARAqB?Ze?@^3PW#h +baG*1bV+0d0RRU806-uB14d?c1pxp60u4rWZf9v?Y-Lk)VRU5$0RR992S;UYWpinB1_=XZW_AJEn^6;3 +7FKqUhx?i3R+Mr!fY&(;2BFL(m@EZk_srD@b7N>_ZDC1d0hChH+XJhss8OG%_CC-Q>(otsF+cqN0Qy}d +dQ=3E5D9c?ZDn(GVQp{#07wRDb8~fNasjsJfQB3>bs~EXcCXx(drQcb3B`Fx$)^%va$Ar)C7cLjXklq? +PGxiftsXy=AYX8dDQEQRO5D(yMKm~r|3!X*hx(?lDDx}U6LV!@Y(s2sb7^j8Q*?4+bY*9G0h%q;z`x)s +Sf3Z(2eI_JHZ((SFcY)Ilj-k! +|1*2$!tQ@{(#!VK)HH;NfH!Oz>RYeHtqn(IZe??6b5mnzWo=;w0|;$pbYWy+bYTDq0d?d}_}|Wp0vpvv +$c&#PW69R$ltr%da5t5w^x+8!q5uE@000000RI300000000(DmZ(?C=a{vkf)$WoGNrn+a000000RI3000000 +01IJrb7^O8ZDnqBa{vkfhyLPaScq)s9KMExvw34D6J>+NwrBxfixd_%u|$Wt0XD%jq57bK6Q|uUfIMEX +^1}Vv6tLB!)|10-o)0prc>n+a000000RI300000001ZcMZ(?C=L}hegX>4-_0ug6yZ(?C=Q*>c;Wm98l +Wo=;rc9`Q{>*YiE5tb$Y2vUw~^w5s+eR_{-?oF}sQU^t*1a4t%WdiA*lIJ@>mw%Cdg|0Y-zbj2Rx3qrT +q9O+Nn`@)o|5M~K$m}!eub_$g}*CJIJdNZ+@c}} +C`8q6D?CtZ1fvw5rj-B|XP@r^w5ufb=C_Ju$l1`nW&GEpSWb-yZDDvxbY*RG0009IM{I9mVQf=$VRU6w +d2nR~0RR933`cBlVqt7nVQh6}a|Hna2m#*}ic5Eh!U~^`T~RBnI=Aq#1o*iZ-@r70RRO80)mO_O%DrjRIhYP1?a)oog)LLTw}}6rDvG=`c^zKYDm5#7b@t4 +MVjY>G@u4Q3HlB(d+LiLJm-R=h;`?dxBv(Of{E)*4-0TquXIZV=)u>WBLk*fW6RH_XPEi=Ry;9kNWLQ% +D(Hkon&*Qwpawq)`VKLB>Wd>h=Ype%b?2720000000000{|^8F0000021#ykb#!wD0RRaBlMuXsu{2tX +FT+?;?hj39&>gq>HOrf1lB-q;n)I5N0RR9100000|Nj60000003r%HoVMJwgVQFl01_A|hWo=1h0_mQT +=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1P-_IE6rQG)02XJT?*g=|B=zREie$*y(7k2+*P~cYjRbCC +ZDj)Ko|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?Csev{(W1V6JV*{3!yZ{M3XW@z+pvO>-_DBy8`Vb0jGrW9$=2qSMXvL3Hj|&L0_mQT=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1P-_IE6rQG)02XJT?*g=| +B=zREie$*y(7k2+*P~cYjRsR=Xk~3-1_%RYW_AJEn^6;37FKqUhx?i3R+Mr!fY&(;2BFL(m@EZk_srD< +ZeeX@0_mQT=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1P*WBNgcQkwbf~^M){{|8P%hsRk~m~ep32F1 +51Y4WWC?9$bYWC^aAk7<3ITQGP59r=ivkU3Q +f4cdUdGS4#Tk(yYN*ff#-&-~S0000000030000000000BXKZg`VQf@+aAk7<3IWybk`76TvuW{aQ_%-X +`?VwZ$5L?~`!+pRSq0(b70Uq+w#z7JBTYQ(6wA15KJe33N=y1k%8ssy_EyFtI!|)|000000003000000 +0000AZ+C8GWK?-@Wpe-u0f+wLWmt%8=p4R=gtK{LClh6Z#kObxUW*hKHnBv9xdFK%KKY6{y^9(U*_!W# +CeCf%@U$Ra$QlHXZNo_Yhhx0Be79xh+o&58gBL +g%$F9MUi-9%UHGxbaG*Cb7^#GZ*Fq{3IQ}y53UoI8eY9A{1GERg--GiI0S#x1is&)M%fmnGH3x@!%VR! +boT!l0ce6}iE2`s>&2w5gKr7m?oSuHf_Z2F0000000030000000000HWMyVyb!>D&b8~5DZf#|5bN~bb +00eGtZe;)f009JZZ*64&1pxtv{^Dg=h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQuQ)6glZDC1d1pxpD +002NB025PXVQfQeZ*ysGXH#@?VRU6@c>@6wW@&PBbWd<{Wpqz+RAF#(Wpn@uQ)y>zVRUtJWd#8M2LJ#- +KmZO?baHiLbairNWJFV=@2?J(kb^+R(Q4?4e +R(6nw`65I6*X)C9iYp+?yjr7~y; +ZDn*}WMOn+0rh%KI9Y!AFx9LCk8@hQXE7w+qW3^C%eTEp@#^?_H3w&GZ(?C=a{&vwi5c8ynrLi66{6Eh +R2JZ)1oVmC*y|BUK&C!OC@}_UZg6#Ua{)F6OOsb2BHT!z`XR@Y;!tI8CO};e1CqOk7xis%Ku=2wF ++7z(Wqt=tdZk`V^s(Ana000000093000000000JQZg6#Ua{vkfhyLPaScq)s9KMExvw34D6J>+NwrBxf +ixd_%u|$Wt0XD%jq57bK6Q|uUfIMEX^1}Vv6tLB!)|10-o)0prc>n+a000000RI300000001IJrb7^O8 +ZDnqBa{vkfhyLPaScq)s9KMExvw34D6J>+NwrBxfixd_%u|$Wt0XD%jq57bK6Q|uUfIMEX^1}Vv6tLB! +)|10-o)0prc>n+a000000RI300000000?$va%pC1WpV*oiU94v6(vTv6u$_Raxvv3(3FSqnKg-@vDIE; +aLC#YRB~Z%b7^#GZ*Ek1aAgGn0006SRC#b^WI=OtX=iS8LTqVnWK(5fY*ctqbaDg(01ISgV{Bn^VRUJB +WdH>M0jXmSzQi_Bob4h>{BE>m*T@oo-6ohy*RC#b^WI=OtX=iS8LTqVnWK(5fY*ct@WCQ~M3uI+uY+-U?bZK^F00jX7W9*8jxQDoM*B7^7+wmzc +N4T^dBdjMp+)Kp2d0SIPwZf9v?Y-Ioi0RaQ+LUU)9P1F3fk)PC*KgHh%%41=0N|UI$lu$Tz`bPo^ +b98cbV{~H4Fp|NyLX=8(1mfVhcP$z*V~7Y=WpZg|X=QQ)0R(PuZe;)o +R&Qx!Q*>c;Wd#8M000 -----END STRICT TYPE LIB----- diff --git a/stl/RGBCommit@0.1.0.stl b/stl/RGBCommit@0.1.0.stl index ae09b6d0653bcb26ed66abd7fe82e49458e3da05..747555f9bb5087c0c6baa9bad720645e2abf41ad 100644 GIT binary patch delta 1389 zcmaFoc+QHOGsxY^IX^cyvxH@0yo$zhw=b{weHIvId)wKWzD@1=D-pK0WRtzdb)#EB zA?zs<>`no}sfjtolNBWtCN4JNWPu56ywAeO#vELd!oo1wUPNJY9+Mg)vk`;h}K@!ixAA6(;XvW1l>MC5*7*h1}|sby-abD@2&8AfV(}T%4Jn7hFw0DW$fqUg+q! zwCC?vrgf~7i#UG~4l-bTPd>p-LekRb4kB#oLT(bWfIhdv<`f=bMuo2-T~=F`JGXG> z#C}|7Q57>!Ve`z2_n{uVbL@_|C`2EdJe}9y;K%-5UHlVmw5BG=d6>OFnRi;|ogU{} zZ3A~>=NVTzWHvxUkO3Bin_2l!G5T`v>Xf{bJ}V=~QFPH|uMn{Zi&?&O-n;Qy(8FPw zori`YcOp2m1PUrTs&D>##Ev4g+YR~&$>JN7v7$C#q5T|A`PW*PYJo)_&~*ol*Z#b zHdn|LFikF(?@_q8okgt0^iY~-l9gyvji&>H&`H)rSs!U-?Rw3`?=4Z2l@+=bj;U-q me!Iu6zfq@lMZfon&MT?^60^ia$PCI-Gk>C)}1xhDjvv-9q%D8IX_fbYpf zHm3mR{GwE!RIvi(>)$Un3hC-j-E0`d8|3}|Li;1x1f$$@M&&yW@j#3VOD)PwtDHPX zNP&epxFlt=ps2#cauY6As3|NAlX0nm`w>QyEripO=(BaJ7Jz17R%N$*EW(rvEri=Z5{=YB^Sp3M>A(%6C_ffyV9Obs> z6Bgdnf5`bZ(`fQNj$ed>1eECHxrj?6lQ(cHOy139MA%eb?ieBzv8iv~z-`Q^;F|m1 ze8~laXE}>v?j4>iw{Q8@0NqPWcRvZa`;^?DbM($+W?p~C{~J&K_@`Li_QG<%(^Xfd zjrPsm#qT$!WGq^Gs9BVMDi;G3{QnPO@Hr(Gr$S1G+|;}hHrC0}e0GjZgbEWvS$y&? zzJ$%qyeAobi&2|xLkf77dJ#mlKtGWQDHrd-}p!l%a*wK(l>pDTAFI5&YTFJ|;K zX8kbBvMo@>HUY(nxg;smi_s-Z1YV1!;A`SysoNS%6DlRcu1~1 z5Vic#w8J|>{a?rDmT%c0*uW9WFu6u>9>HX{*-FTmiJ!;60Lk<0lcPjc>sj;i^O92; z7&zGS3qmRjQW^98*;lv#BlSTuh5~*>5>IZzI>nvL&PWx z69apCYF=t_W-$XRBjaWT!%u}SrAx1I_c7m5@h$zOaN}B>im_PJk?yHSZKM7(a+MS% z<`rj_Waj5Furf_fl~A0V$D=s;x^$1iJr+^VqM2E_d#6f$JjZa`O0THh#Gr TypedAssignsBlindSealTxPtr} @mnemonic(extra-signal-alaska) data AssignmentsBlindSealTxid : {AssignmentType -> TypedAssignsBlindSealTxid} -@mnemonic(fiesta-gilbert-fiber) -data BaseCommitment : schemaId SchemaId - , timestamp I64 - , issuer CommitVerify.StrictHash - , chainNet ChainNet - , sealClosingStrategy SealClosingStrategy - @mnemonic(ringo-fashion-enrico) data ChainNet : bitcoinMainnet | bitcoinTestnet3 | bitcoinTestnet4 | bitcoinSignet | bitcoinRegtest | liquidMainnet | liquidTestnet @@ -142,8 +131,8 @@ data GlobalStateSchema : semId StrictTypes.SemId, maxItems U24 @mnemonic(yoga-quick-jasmine) data GlobalStateType : U16 -@mnemonic(single-rodent-appear) -data GlobalValues : [StructureddData ^ 1..] +@mnemonic(john-ibiza-pony) +data GlobalValues : [StructuredData ^ 1..] @mnemonic(smart-pioneer-nominal) data Identity : Std.AsciiPrintable, [Std.AsciiPrintable ^ ..0xfff] @@ -166,15 +155,6 @@ data Metadata : {MetaType -> ^ ..0xff MetaValue} @mnemonic(source-olga-mirage) data Occurrences : min U16, max U16 -@mnemonic(oregano-dexter-exact) -data OpCommitment : ffv Ffv - , nonce U64 - , opType TypeCommitment - , metadata CommitVerify.StrictHash - , globals CommitVerify.MerkleHash - , inputs CommitVerify.MerkleHash - , assignments CommitVerify.MerkleHash - @mnemonic(picnic-single-gloria) data OpId : [Byte ^ 32] @@ -208,8 +188,8 @@ data SealClosingStrategy : firstOpretOrTapret | (|) @mnemonic(ferrari-zebra-tempo) data Signature : [Byte ^ 64] -@mnemonic(jerome-format-saga) -data StructureddData : [Byte] +@mnemonic(nirvana-modern-bonjour) +data StructuredData : [Byte] @mnemonic(remark-gravity-vitamin) data Transition : ffv Ffv @@ -235,19 +215,15 @@ data TransitionSchema : metadata {MetaType ^ ..0xff} @mnemonic(picture-reflex-brigade) data TransitionType : U16 -@mnemonic(yellow-young-stone) -data TypeCommitment : genesis BaseCommitment - | transition (ContractId, TransitionType) - -@mnemonic(civil-flex-palma) +@mnemonic(brother-nancy-accent) data TypedAssignsBlindSealTxPtr : declarative AssignVecAssignVoidStateBlindSealTxPtr | fungible AssignVecAssignFungibleStateBlindSealTxPtr - | structured AssignVecAssignStructureddDataBlindSealTxPtr + | structured AssignVecAssignStructuredDataBlindSealTxPtr -@mnemonic(switch-orchid-kevin) +@mnemonic(mailbox-royal-hydro) data TypedAssignsBlindSealTxid : declarative AssignVecAssignVoidStateBlindSealTxid | fungible AssignVecAssignFungibleStateBlindSealTxid - | structured AssignVecAssignStructureddDataBlindSealTxid + | structured AssignVecAssignStructuredDataBlindSealTxid @mnemonic(escort-pretend-comedy) data Verifier : none | (|) diff --git a/stl/Transition.vesper b/stl/Transition.vesper index 7a379926..5a2168d9 100644 --- a/stl/Transition.vesper +++ b/stl/Transition.vesper @@ -7,42 +7,6 @@ Transition vesper lexicon=types+commitments -commitment OpId, hasher SHA256, tagged urn:lnp-bp:rgb:operation#2024-02-03 - serialized OpCommitment - -rec OpCommitment - is ffv, U16, aka Ffv - is nonce, U64 - union opType, TypeCommitment - rec genesis, BaseCommitment, wrapped, tag 0 - bytes schemaId, len 32, aka SchemaId - is timestamp, I64 - bytes issuer, len 32, aka StrictHash - enum chainNet, ChainNet, bitcoinMainnet 0, bitcoinTestnet3 1, bitcoinTestnet4 2, bitcoinSignet 3, bitcoinRegtest 4, liquidMainnet 5, liquidTestnet 6 - enum sealClosingStrategy, SealClosingStrategy, firstOpretOrTapret 0 - tuple transition, tag 1 - bytes _, len 32, aka ContractId - is _, U16, aka TransitionType - bytes metadata, len 32, aka StrictHash - bytes globals, len 32, aka MerkleHash - bytes inputs, len 32, aka MerkleHash - bytes assignments, len 32, aka MerkleHash - -union DbcProof - rec tapret, TapretProof, wrapped, tag 0 - rec pathProof, TapretPathProof - union some, TapretNodePartner, option, wrapped, tag 1 - bytes leftNode, len 32, wrapped, aka TapNodeHash, tag 0 - rec rightLeaf, LeafScript, wrapped, tag 1 - is version, U8, aka LeafVer - bytes script, len 0..MAX32, aka ScriptBytes - rec rightBranch, TapretRightBranch, wrapped, tag 2 - bytes leftNodeHash, len 32, aka TapNodeHash - bytes rightNodeHash, len 32, aka TapNodeHash - is nonce, U8 - bytes internalPk, len 32, aka InternalPk, aka XOnlyPk - is opret, Unit, wrapped, aka OpretProof, tag 1 - rec Transition is ffv, U16, aka Ffv bytes contractId, len 32, aka ContractId @@ -54,7 +18,7 @@ rec Transition map globals, len 0..MAX8, aka GlobalState is key, U16, aka GlobalStateType list value, len 1..MAX16, aka GlobalValues - bytes element, len 0..MAX16, aka StructureddData + bytes element, len 0..MAX16, aka StructuredData set inputs, len 1..MAX16, aka Inputs rec Opout bytes op, len 32, aka OpId @@ -89,8 +53,8 @@ rec Transition rec secretSeal, tag 1 bytes seal, len 32, aka SecretSeal is state, U64, aka FungibleState - list structured, len 1..MAX16, wrapped, aka AssignVecAssignStructureddDataBlindSealTxPtr, tag 2 - union AssignStructureddDataBlindSealTxPtr + list structured, len 1..MAX16, wrapped, aka AssignVecAssignStructuredDataBlindSealTxPtr, tag 2 + union AssignStructuredDataBlindSealTxPtr rec revealed, tag 0 rec seal, BlindSealTxPtr union txid, TxPtr @@ -98,9 +62,9 @@ rec Transition bytes txid, len 32, wrapped, aka Txid, tag 1 is vout, U32, aka Vout is blinding, U64 - bytes state, len 0..MAX16, aka StructureddData + bytes state, len 0..MAX16, aka StructuredData rec secretSeal, tag 1 bytes seal, len 32, aka SecretSeal - bytes state, len 0..MAX16, aka StructureddData + bytes state, len 0..MAX16, aka StructuredData bytes some, len 64, option, wrapped, aka Signature, tag 1 From efcb8c4317273c13acbe0da5ec39a0b9a046f804 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:34:47 +0200 Subject: [PATCH 17/23] validation: simplify if condition --- src/validation/validator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation/validator.rs b/src/validation/validator.rs index 987607ca..4c4491b0 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -460,7 +460,7 @@ impl< continue; }; - let seal = if matches!(prev_op.full_type(), OpFullType::StateTransition(_)) { + let seal = if prev_op.full_type().is_transition() { let Some(witness_id) = self.consignment.op_witness_id(op) else { self.status .borrow_mut() From dcfba048db36b816db6308d17a08166729e996f0 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:45:04 +0200 Subject: [PATCH 18/23] validation: get rid of Rc, RefCell's and unnecessary clones --- src/validation/logic.rs | 6 +- src/validation/validator.rs | 358 ++++++++++++++---------------------- 2 files changed, 141 insertions(+), 223 deletions(-) diff --git a/src/validation/logic.rs b/src/validation/logic.rs index 3440004b..dcb3976d 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -20,10 +20,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::cell::RefCell; use std::collections::btree_map::Entry; use std::collections::{BTreeMap, BTreeSet}; -use std::rc::Rc; use amplify::confinement::{Confined, NonEmptyVec}; use amplify::Wrapper; @@ -49,7 +47,7 @@ impl Schema { &'validator self, consignment: &'validator CheckedConsignment<'_, C>, op: FullOpRef, - contract_state: Rc>, + contract_state: &mut S, ) -> validation::Status { let opid = op.id(); let mut status = validation::Status::new(); @@ -136,7 +134,7 @@ impl Schema { match validator { Verifier::None => {} } - if contract_state.borrow_mut().evolve_state(op).is_err() { + if contract_state.evolve_state(op).is_err() { status.add_failure(validation::Failure::ContractStateFilled(opid)); // We return here since all other validations will have no valid state to access return status; diff --git a/src/validation/validator.rs b/src/validation/validator.rs index 4c4491b0..ca1d8ddc 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -20,9 +20,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::cell::RefCell; use std::collections::{BTreeSet, HashMap, HashSet}; -use std::rc::Rc; use bc::{Tx, Txid}; use commit_verify::mpc; @@ -32,10 +30,7 @@ use super::status::{Failure, Warning}; use super::{CheckedConsignment, ConsignmentApi, Status, Validity}; use crate::operation::seal::ExposedSeal; use crate::vm::{ContractStateAccess, ContractStateEvolve, FullOpRef, WitnessStatus}; -use crate::{ - validation, ChainNet, ContractId, OpFullType, OpId, Operation, Opout, OutputSeal, Schema, - SchemaId, Transition, -}; +use crate::{validation, ChainNet, ContractId, OpFullType, Operation, Opout, Schema, SchemaId}; #[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] #[display(doc_comments)] @@ -126,14 +121,14 @@ pub struct Validator< > { consignment: CheckedConsignment<'consignment, C>, - status: RefCell, + status: Status, schema_id: SchemaId, contract_id: ContractId, chain_net: ChainNet, - contract_state: Rc>, - input_assignments: RefCell>, + contract_state: S, + input_assignments: BTreeSet, resolver: CheckedWitnessResolver<&'resolver R>, safe_height: Option, @@ -164,17 +159,15 @@ impl< let schema_id = genesis.schema_id; let chain_net = genesis.chain_net; - let input_transitions = RefCell::new(BTreeSet::::new()); - Self { consignment, - status: RefCell::new(status), + status, schema_id, contract_id, chain_net, - input_assignments: input_transitions, + input_assignments: none!(), resolver: CheckedWitnessResolver::from(resolver), - contract_state: Rc::new(RefCell::new(S::init(context))), + contract_state: S::init(context), safe_height, } } @@ -201,56 +194,52 @@ impl< if validator.chain_net != chain_net { validator .status - .borrow_mut() .add_failure(Failure::ContractChainNetMismatch(chain_net)); - return validator.status.into_inner(); + return validator.status; } if resolver.check_chain_net(chain_net).is_err() { validator .status - .borrow_mut() .add_failure(Failure::ResolverChainNetMismatch(chain_net)); - return validator.status.into_inner(); + return validator.status; } validator.validate_schema(consignment.schema()); // We must return here, since if the schema is not valid there is no reason to // validate contract nodes against it: it will produce a plenty of errors. - if validator.status.borrow().validity() == Validity::Invalid { - return validator.status.into_inner(); + if validator.status.validity() == Validity::Invalid { + return validator.status; } validator.validate_commitments(); // We must return here, since if there were no proper commitments, it is // pointless to validate the contract state. - if validator.status.borrow().validity() == Validity::Invalid { - return validator.status.into_inner(); + if validator.status.validity() == Validity::Invalid { + return validator.status; } validator.validate_logic(); // Done. Returning status report with all possible failures, issues, warnings // and notifications about transactions we were unable to obtain. - validator.status.into_inner() + validator.status } // *** PART I: Schema validation fn validate_schema(&mut self, schema: &Schema) { - *self.status.borrow_mut() += schema.verify(self.consignment.types()); + self.status += schema.verify(self.consignment.types()); } // *** PART II: Validating business logic - fn validate_logic(&self) { + fn validate_logic(&mut self) { let schema = self.consignment.schema(); // [VALIDATION]: Making sure that we were supplied with the schema // that corresponds to the schema of the contract genesis if schema.schema_id() != self.schema_id { - self.status - .borrow_mut() - .add_failure(Failure::SchemaMismatch { - expected: self.schema_id, - actual: schema.schema_id(), - }); + self.status.add_failure(Failure::SchemaMismatch { + expected: self.schema_id, + actual: schema.schema_id(), + }); // Unlike other failures, here we return immediately, since there is no point // to validate all consignment data against an invalid schema: it will result in // a plenty of meaningless errors @@ -258,10 +247,10 @@ impl< } // [VALIDATION]: Validate genesis - *self.status.borrow_mut() += schema.validate_state( + self.status += schema.validate_state( &self.consignment, FullOpRef::Genesis(self.consignment.genesis()), - self.contract_state.clone(), + &mut self.contract_state, ); // [VALIDATION]: Iterating over all consignment operations @@ -277,7 +266,6 @@ impl< Ok(ord) => ord, Err(err) => { self.status - .borrow_mut() .add_failure(validation::Failure::WitnessUnresolved(opid, witness_id, err)); // We need to stop validation there since we can't order operations return; @@ -302,49 +290,39 @@ impl< } if self.safe_height.is_some() && !unsafe_history_map.is_empty() { self.status - .borrow_mut() .add_warning(Warning::UnsafeHistory(unsafe_history_map)); } + // Operations are validated in the order they are reported by the consignment API - for op in ops { + for operation in ops { // We do not skip validating archive operations since after a re-org they may // become valid and thus must be added to the contract state and validated // beforehand. - self.validate_operation(op); - } - } - - fn validate_operation(&self, operation: FullOpRef<'consignment>) { - let schema = self.consignment.schema(); - let opid = operation.id(); + let opid = operation.id(); - if operation.contract_id() != self.contract_id { - self.status - .borrow_mut() - .add_failure(Failure::ContractMismatch(opid, operation.contract_id())); - } - - if !self.status.borrow_mut().validated_opids.contains(&opid) - && matches!(operation.full_type(), OpFullType::StateTransition(_)) - { - self.status - .borrow_mut() - .add_failure(Failure::SealsUnvalidated(opid)); - } - // [VALIDATION]: Verify operation against the schema and scripts - *self.status.borrow_mut() += - schema.validate_state(&self.consignment, operation, self.contract_state.clone()); + if operation.contract_id() != self.contract_id { + self.status + .add_failure(Failure::ContractMismatch(opid, operation.contract_id())); + } - match operation { - FullOpRef::Genesis(_) => { - unreachable!("genesis is not a part of the operation history") + if !self.status.validated_opids.contains(&opid) + && matches!(operation.full_type(), OpFullType::StateTransition(_)) + { + self.status.add_failure(Failure::SealsUnvalidated(opid)); } - FullOpRef::Transition(transition, ..) => { - for input in &transition.inputs { - if self.consignment.operation(input.op).is_none() { - self.status - .borrow_mut() - .add_failure(Failure::OperationAbsent(input.op)); + // [VALIDATION]: Verify operation against the schema and scripts + self.status += + schema.validate_state(&self.consignment, operation, &mut self.contract_state); + + match operation { + FullOpRef::Genesis(_) => { + unreachable!("genesis is not a part of the operation history") + } + FullOpRef::Transition(transition, ..) => { + for input in &transition.inputs { + if self.consignment.operation(input.op).is_none() { + self.status.add_failure(Failure::OperationAbsent(input.op)); + } } } } @@ -355,172 +333,114 @@ impl< fn validate_commitments(&mut self) { for transition in self.consignment.transitions() { let opid = transition.id(); - let Some((proof, witness_id)) = self.consignment.anchor(opid) else { - self.status - .borrow_mut() - .add_failure(Failure::AnchorAbsent(opid)); + let Some((mpc_proof, witness_id)) = self.consignment.anchor(opid) else { + self.status.add_failure(Failure::AnchorAbsent(opid)); continue; }; // [VALIDATION]: We validate that the seals were properly defined on BP-type layer - let seals = self.validate_seal_definitions(transition); + let mut seals = vec![]; - // [VALIDATION]: We validate that the seals were properly closed on BP-type layer - self.validate_seal_commitments(seals, opid, proof, witness_id); - } - } - - /// Bitcoin- and liquid-specific commitment validation using OP_RETURN commitments - fn validate_seal_commitments( - &self, - seals: impl IntoIterator, - opid: OpId, - mpc_proof: &mpc::MerkleProof, - witness_id: Txid, - ) { - // Check that the anchor is committed into a transaction spending all the - // transition inputs. - // Here the method can do SPV proof instead of querying the indexer. The SPV - // proofs can be part of the consignments, but do not require . - match self.resolver.resolve_pub_witness(witness_id) { - Err(err) => { - // We wre unable to retrieve corresponding transaction, so can't check. - // Reporting this incident and continuing further. Why this happens? No - // connection to Bitcoin Core, Electrum or other backend etc. So this is not a - // failure in a strict sense, however we can't be sure that the consignment is - // valid. - // This also can mean that there is no known transaction with the id provided by - // the anchor, i.e. consignment is invalid. We are proceeding with further - // validation in order to detect the rest of problems (and reporting the - // failure!) - self.status - .borrow_mut() - .add_failure(Failure::SealNoPubWitness(opid, witness_id, err)); - } - Ok(pub_witness) => { - self.validate_seal_closing(seals, opid, &pub_witness, mpc_proof); - } - } - } - - /// Single-use-seal definition validation. - /// - /// Takes state transition, extracts all seals from its inputs and validates them. - fn validate_seal_definitions(&self, transition: &Transition) -> Vec { - let mut seals = vec![]; - - let opid = transition.id(); - - if !self.status.borrow_mut().validated_opids.insert(opid) { - self.status - .borrow_mut() - .add_failure(Failure::CyclicGraph(opid)); - } - - // Checking that witness transaction closes seals defined by transition previous - // outputs. - for input in &transition.inputs { - let Opout { op, ty, no } = input; - if !self.input_assignments.borrow_mut().insert(input) { - self.status - .borrow_mut() - .add_failure(Failure::DoubleSpend(input)); + if !self.status.validated_opids.insert(opid) { + self.status.add_failure(Failure::CyclicGraph(opid)); } - let Some(prev_op) = self.consignment.operation(op) else { - // Node, referenced as the ancestor, was not found in the consignment. - // Usually this means that the consignment data are broken - self.status - .borrow_mut() - .add_failure(Failure::OperationAbsent(op)); - continue; - }; - - let Some(variant) = prev_op.assignments_by_type(ty) else { - self.status.borrow_mut().add_failure(Failure::NoPrevState { - opid, - prev_id: op, - state_type: ty, - }); - continue; - }; + // Checking that witness transaction closes seals defined by transition previous + // outputs. + for input in &transition.inputs { + let Opout { op, ty, no } = input; + if !self.input_assignments.insert(input) { + self.status.add_failure(Failure::DoubleSpend(input)); + } - let Ok(seal) = variant.revealed_seal_at(no) else { - self.status - .borrow_mut() - .add_failure(Failure::NoPrevOut(opid, input)); - continue; - }; - let Some(seal) = seal else { - // Everything is ok, but we have incomplete data (confidential), thus can't do a - // full verification and have to report the failure - self.status - .borrow_mut() - .add_failure(Failure::ConfidentialSeal(input)); - continue; - }; + let Some(prev_op) = self.consignment.operation(op) else { + // Node, referenced as the ancestor, was not found in the consignment. + // Usually this means that the consignment data are broken + self.status.add_failure(Failure::OperationAbsent(op)); + continue; + }; - let seal = if prev_op.full_type().is_transition() { - let Some(witness_id) = self.consignment.op_witness_id(op) else { - self.status - .borrow_mut() - .add_failure(Failure::OperationAbsent(op)); + let Some(variant) = prev_op.assignments_by_type(ty) else { + self.status.add_failure(Failure::NoPrevState { + opid, + prev_id: op, + state_type: ty, + }); continue; }; - seal.to_output_seal_or_default(witness_id) - } else { - seal.to_output_seal() - .expect("genesis must have explicit seals") - }; - seals.push(seal); - } + let Ok(seal) = variant.revealed_seal_at(no) else { + self.status.add_failure(Failure::NoPrevOut(opid, input)); + continue; + }; + let Some(seal) = seal else { + // Everything is ok, but we have incomplete data (confidential), thus can't do a + // full verification and have to report the failure + self.status.add_failure(Failure::ConfidentialSeal(input)); + continue; + }; - seals - } + let seal = if prev_op.full_type().is_transition() { + let Some(witness_id) = self.consignment.op_witness_id(op) else { + self.status.add_failure(Failure::OperationAbsent(op)); + continue; + }; + seal.to_output_seal_or_default(witness_id) + } else { + seal.to_output_seal() + .expect("genesis must have explicit seals") + }; - /// Single-use-seal closing validation. - /// - /// Checks that the set of seals is closed over the message, which is - /// multi-protocol commitment, by utilizing witness, consisting of - /// transaction with deterministic bitcoin commitments (defined by - /// generic type `Dbc`) and extra-transaction data, which are taken from - /// anchor's DBC proof. - /// - /// Additionally, checks that the provided message contains commitment to - /// the bundle under the current contract. - fn validate_seal_closing( - &self, - seals: impl IntoIterator, - opid: OpId, - witness: &Tx, - mpc_proof: &mpc::MerkleProof, - ) { - let message = mpc::Message::from(opid); - let protocol = mpc::ProtocolId::from(self.contract_id); - let witness_id = witness.txid(); - - // [VALIDATION]: Checking anchor MPC commitment - match mpc_proof.convolve(protocol, message) { - Err(err) => { - // The operation is not committed to the bitcoin transaction graph! - // Ultimate failure. But continuing to detect the rest (after reporting it). - self.status - .borrow_mut() - .add_failure(Failure::MpcInvalid(opid, witness_id, err)); + seals.push(seal); } - Ok(commitment) => { - // [VALIDATION]: CHECKING SINGLE-USE-SEALS - witness - .verify_seals(seals, commitment) - .map_err(|err| { - self.status.borrow_mut().add_failure(Failure::SealsInvalid( - opid, - witness_id, - err.to_string(), - )); - }) - .ok(); + + // [VALIDATION]: We validate that the seals were properly closed on BP-type layer + // Check that the anchor is committed into a transaction spending all the + // transition inputs. + // Here the method can do SPV proof instead of querying the indexer. The SPV + // proofs can be part of the consignments, but do not require . + match self.resolver.resolve_pub_witness(witness_id) { + Err(err) => { + // We wre unable to retrieve corresponding transaction, so can't check. + // Reporting this incident and continuing further. Why this happens? No + // connection to Bitcoin Core, Electrum or other backend etc. So this is not a + // failure in a strict sense, however we can't be sure that the consignment is + // valid. + // This also can mean that there is no known transaction with the id provided by + // the anchor, i.e. consignment is invalid. We are proceeding with further + // validation in order to detect the rest of problems (and reporting the + // failure!) + self.status + .add_failure(Failure::SealNoPubWitness(opid, witness_id, err)); + } + Ok(pub_witness) => { + let message = mpc::Message::from(opid); + let protocol = mpc::ProtocolId::from(self.contract_id); + + // [VALIDATION]: Checking anchor MPC commitment + match mpc_proof.convolve(protocol, message) { + Err(err) => { + // The operation is not committed to the bitcoin transaction graph! + // Ultimate failure. But continuing to detect the rest (after reporting + // it). + self.status + .add_failure(Failure::MpcInvalid(opid, witness_id, err)); + } + Ok(commitment) => { + // [VALIDATION]: CHECKING SINGLE-USE-SEALS + pub_witness + .verify_seals(seals, commitment) + .map_err(|err| { + self.status.add_failure(Failure::SealsInvalid( + opid, + witness_id, + err.to_string(), + )); + }) + .ok(); + } + } + } } } } From 853846ffb7c577dbc37eda93801703de11f7d5d4 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:46:10 +0200 Subject: [PATCH 19/23] stl: update --- src/bin/rgbcore-stl.rs | 1 + stl/Transition.vesper | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/bin/rgbcore-stl.rs b/src/bin/rgbcore-stl.rs index 5624ef6a..effbe5df 100644 --- a/src/bin/rgbcore-stl.rs +++ b/src/bin/rgbcore-stl.rs @@ -113,6 +113,7 @@ Transition vesper lexicon=types+commitments ) .unwrap(); let layout = Transition::commitment_layout(); + writeln!(file, "{layout}").unwrap(); let tt = sys.type_tree("RGBCommit.Transition").unwrap(); writeln!(file, "{tt}").unwrap(); diff --git a/stl/Transition.vesper b/stl/Transition.vesper index 5a2168d9..67ca767c 100644 --- a/stl/Transition.vesper +++ b/stl/Transition.vesper @@ -7,6 +7,9 @@ Transition vesper lexicon=types+commitments +commitment OpId, hasher SHA256, tagged urn:lnp-bp:rgb:operation#2024-02-03 + serialized Transition + rec Transition is ffv, U16, aka Ffv bytes contractId, len 32, aka ContractId From 0f8049c7f2206c058d21bf552032f6ec73996550 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 12:56:44 +0200 Subject: [PATCH 20/23] chore: update deps --- Cargo.lock | 1 + Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index e0c17c22..fcfa8b84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,6 +181,7 @@ dependencies = [ [[package]] name = "bp-seals" version = "0.11.1-beta.1" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11.1-revision#d684c4e1fcdb75527a7610ab90578d05117e8560" dependencies = [ "amplify", "baid64", diff --git a/Cargo.toml b/Cargo.toml index eb9974b9..37f50e6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,4 +60,4 @@ wasm-bindgen-test = "0.3" features = ["all"] [patch.crates-io] -bp-seals = { path = "../bp-core" } +bp-seals = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11.1-revision" } From 5b60d9dab048484fbcb90ff030e5c3f4e4843657 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 13:38:26 +0200 Subject: [PATCH 21/23] validation: add input/output assignment verifiers --- src/lib.rs | 4 +- src/schema/operations.rs | 23 ++++++- src/validation/logic.rs | 72 +++++++++++++++++++--- src/validation/mod.rs | 2 + src/validation/status.rs | 8 +-- src/{vm/contract.rs => validation/util.rs} | 0 src/validation/validator.rs | 21 ++++--- src/vm/mod.rs | 29 --------- 8 files changed, 102 insertions(+), 57 deletions(-) rename src/{vm/contract.rs => validation/util.rs} (100%) delete mode 100644 src/vm/mod.rs diff --git a/src/lib.rs b/src/lib.rs index d185d012..9d9b30c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,8 +38,6 @@ extern crate core; mod operation; pub mod schema; pub mod validation; -#[macro_use] -pub mod vm; #[cfg(feature = "stl")] pub mod stl; @@ -51,7 +49,7 @@ pub mod prelude { #[cfg(feature = "stl")] pub use super::stl; use super::*; - pub use super::{schema, validation, vm}; + pub use super::{schema, validation}; } pub use prelude::*; diff --git a/src/schema/operations.rs b/src/schema/operations.rs index 587a3369..3a2b84f6 100644 --- a/src/schema/operations.rs +++ b/src/schema/operations.rs @@ -149,14 +149,31 @@ impl OpSchema for TransitionSchema { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)] #[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_COMMIT, tags = repr, try_from_u8, into_u8)] +#[strict_type(lib = LIB_NAME_RGB_COMMIT, tags = custom)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "camelCase") )] -#[repr(u8)] pub enum Verifier { + /// No validation applied #[default] - None = 0, + #[strict_type(tag = 0x00)] + None, + + /// Checks that the sum of previous assignments of the given type is equal to the sum of + /// output assignments of the same type. + /// + /// Fails if the assignment is not a fungible state, the sum is not equal or if an overflow + /// happens. + #[strict_type(tag = 0x01)] + EqSums(AssignmentType), + + /// Checks that previous assignments of the given type are byte-equal to + /// output assignments of the same type. The order is not checked. + /// + /// Fails if the assignment is not a fungible state, or there is any mismatch between inputs + /// and outputs. + #[strict_type(tag = 0x02)] + EqVals(AssignmentType), } diff --git a/src/validation/logic.rs b/src/validation/logic.rs index dcb3976d..73c6d9da 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -27,10 +27,11 @@ use amplify::confinement::{Confined, NonEmptyVec}; use amplify::Wrapper; use strict_types::TypeSystem; +use super::{ + CheckedConsignment, ConsignmentApi, ContractStateAccess, ContractStateEvolve, FullOpRef, +}; use crate::assignments::AssignVec; use crate::schema::{AssignmentsSchema, GlobalSchema}; -use crate::validation::{CheckedConsignment, ConsignmentApi}; -use crate::vm::{ContractStateAccess, ContractStateEvolve, FullOpRef}; use crate::{ validation, AnyState, Assign, AssignmentType, Assignments, AssignmentsRef, ExposedSeal, ExposedState, GlobalState, GlobalStateSchema, GlobalValues, GraphSeal, Inputs, MetaSchema, @@ -53,8 +54,7 @@ impl Schema { let mut status = validation::Status::new(); let empty_assign_schema = AssignmentsSchema::default(); - let (metadata_schema, global_schema, owned_schema, assign_schema, validator, ty) = match op - { + let (metadata_schema, global_schema, owned_schema, assign_schema, verifier) = match op { FullOpRef::Genesis(genesis) => { if genesis.seal_closing_strategy != SealClosingStrategy::FirstOpretOrTapret { return validation::Status::with_failure( @@ -70,7 +70,6 @@ impl Schema { &empty_assign_schema, &self.genesis.assignments, Verifier::None, - None::, ) } FullOpRef::Transition( @@ -106,7 +105,6 @@ impl Schema { &transition_schema.inputs, &transition_schema.assignments, transition_schema.verifier, - Some(transition_type.into_inner()), ) } }; @@ -131,8 +129,68 @@ impl Schema { }; // Run the validation logic - match validator { + match verifier { Verifier::None => {} + Verifier::EqSums(ty) => { + let Some(sum_in) = prev_state + .get(&ty) + .into_iter() + .flat_map(TypedAssigns::as_fungible) + .map(Assign::as_state) + .try_fold(0u64, |sum, state| sum.checked_add(state.0)) + else { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + }; + let Some(sum_out) = op + .assignments() + .get(ty) + .iter() + .flat_map(TypedAssigns::as_fungible) + .map(Assign::as_state) + .try_fold(0u64, |sum, state| sum.checked_add(state.0)) + else { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + }; + if sum_in != sum_out { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + } + } + Verifier::EqVals(ty) => { + if prev_state + .get(&ty) + .map(TypedAssigns::len_u16) + .unwrap_or_default() + != op + .assignments() + .get(ty) + .as_ref() + .map(TypedAssigns::len_u16) + .unwrap_or_default() + { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + } + if prev_state + .get(&ty) + .into_iter() + .flat_map(TypedAssigns::as_declarative) + .map(Assign::as_state) + .collect::>() + != op + .assignments() + .get(ty) + .iter() + .flat_map(TypedAssigns::as_declarative) + .map(Assign::as_state) + .collect::>() + { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + } + } } if contract_state.evolve_state(op).is_err() { status.add_failure(validation::Failure::ContractStateFilled(opid)); diff --git a/src/validation/mod.rs b/src/validation/mod.rs index fca886a9..180ff8d5 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -25,7 +25,9 @@ mod logic; mod validator; mod consignment; mod status; +mod util; pub use consignment::{CheckedConsignment, ConsignmentApi, OpRef, CONSIGNMENT_MAX_LIBS}; pub use status::{Failure, Info, Status, UnsafeHistoryMap, Validity, Warning}; +pub use util::{ContractStateAccess, ContractStateEvolve, FullOpRef, WitnessStatus}; pub use validator::{ResolveWitness, Validator, WitnessResolverError}; diff --git a/src/validation/status.rs b/src/validation/status.rs index b1f3c96b..2a281be3 100644 --- a/src/validation/status.rs +++ b/src/validation/status.rs @@ -33,7 +33,7 @@ use crate::schema::{self, SchemaId}; use crate::validation::WitnessResolverError; use crate::{ ChainNet, ContractId, OccurrencesMismatch, OpFullType, OpId, Opout, SealClosingStrategy, - StateType, + StateType, Verifier, }; pub type UnsafeHistoryMap = HashMap>; @@ -291,12 +291,10 @@ pub enum Failure { found: StateType, }, + Verifier(Verifier, OpId), + /// contract state can't fit more data (at operation id {0}). ContractStateFilled(OpId), - - /// Custom error by external services on top of RGB Core. - #[display(inner)] - Custom(String), } #[derive(Clone, PartialEq, Eq, Debug, Display, From)] diff --git a/src/vm/contract.rs b/src/validation/util.rs similarity index 100% rename from src/vm/contract.rs rename to src/validation/util.rs diff --git a/src/validation/validator.rs b/src/validation/validator.rs index ca1d8ddc..d970c7bd 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -27,9 +27,11 @@ use commit_verify::mpc; use seals::txout::Witness; use super::status::{Failure, Warning}; -use super::{CheckedConsignment, ConsignmentApi, Status, Validity}; +use super::{ + CheckedConsignment, ConsignmentApi, ContractStateAccess, ContractStateEvolve, FullOpRef, + Status, Validity, WitnessStatus, +}; use crate::operation::seal::ExposedSeal; -use crate::vm::{ContractStateAccess, ContractStateEvolve, FullOpRef, WitnessStatus}; use crate::{validation, ChainNet, ContractId, OpFullType, Operation, Opout, Schema, SchemaId}; #[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] @@ -398,18 +400,17 @@ impl< // Check that the anchor is committed into a transaction spending all the // transition inputs. // Here the method can do SPV proof instead of querying the indexer. The SPV - // proofs can be part of the consignments, but do not require . + // proofs can be part of the consignments. match self.resolver.resolve_pub_witness(witness_id) { Err(err) => { - // We wre unable to retrieve corresponding transaction, so can't check. - // Reporting this incident and continuing further. Why this happens? No - // connection to Bitcoin Core, Electrum or other backend etc. So this is not a - // failure in a strict sense, however we can't be sure that the consignment is + // We were unable to retrieve the corresponding transaction, so can't check. + // Reporting this incident and continuing further. Why does this happen? No + // connection to Bitcoin Core, Electrum or another backend etc. So this is not a + // failure in a strict sense, however, we can't be sure that the consignment is // valid. // This also can mean that there is no known transaction with the id provided by - // the anchor, i.e. consignment is invalid. We are proceeding with further - // validation in order to detect the rest of problems (and reporting the - // failure!) + // the anchor, i.e., consignment is invalid. We are proceeding with further + // validation to detect the rest of the problems (and reporting the failure!) self.status .add_failure(Failure::SealNoPubWitness(opid, witness_id, err)); } diff --git a/src/vm/mod.rs b/src/vm/mod.rs deleted file mode 100644 index 927d5ed6..00000000 --- a/src/vm/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2024 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 -//! -//! Concrete virtual machine implementations must be wrapped into this API - -mod contract; - -pub use contract::{ContractStateAccess, ContractStateEvolve, FullOpRef, WitnessStatus}; From 6c950013e02cde88bb45522222e358574c14272b Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 13:54:31 +0200 Subject: [PATCH 22/23] validation: add signature verifier. Remove remnants of VM --- src/operation/global.rs | 9 +- src/operation/operations.rs | 1 - src/schema/operations.rs | 4 + src/stl.rs | 5 +- src/validation/logic.rs | 32 ++ src/vm/op_contract.rs | 674 ------------------------------------ stl/RGBCommit@0.1.0.sta | 57 +-- stl/RGBCommit@0.1.0.stl | Bin 7502 -> 7594 bytes stl/RGBCommit@0.1.0.sty | 16 +- stl/Schema.vesper | 8 +- stl/Transition.vesper | 1 - 11 files changed, 88 insertions(+), 719 deletions(-) delete mode 100644 src/vm/op_contract.rs diff --git a/src/operation/global.rs b/src/operation/global.rs index ba037150..d96c0012 100644 --- a/src/operation/global.rs +++ b/src/operation/global.rs @@ -21,7 +21,7 @@ // limitations under the License. use std::collections::btree_map; -use std::vec; +use std::{slice, vec}; use amplify::confinement::{Confined, TinyOrdMap, U16}; use amplify::{confinement, Wrapper}; @@ -56,6 +56,13 @@ impl IntoIterator for GlobalValues { fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } +impl<'a> IntoIterator for &'a GlobalValues { + type Item = &'a StructuredData; + type IntoIter = slice::Iter<'a, StructuredData>; + + fn into_iter(self) -> Self::IntoIter { self.0.iter() } +} + #[derive(Wrapper, WrapperMut, Clone, PartialEq, Eq, Hash, Default, Debug, From)] #[wrapper(Deref)] #[wrapper_mut(DerefMut)] diff --git a/src/operation/operations.rs b/src/operation/operations.rs index e7466624..4b3faa89 100644 --- a/src/operation/operations.rs +++ b/src/operation/operations.rs @@ -233,7 +233,6 @@ pub struct Transition { pub globals: GlobalState, pub inputs: Inputs, pub assignments: Assignments, - pub signature: Option, } impl StrictSerialize for Transition {} diff --git a/src/schema/operations.rs b/src/schema/operations.rs index 3a2b84f6..ed16364c 100644 --- a/src/schema/operations.rs +++ b/src/schema/operations.rs @@ -176,4 +176,8 @@ pub enum Verifier { /// and outputs. #[strict_type(tag = 0x02)] EqVals(AssignmentType), + + /// Checks that metadata contains a valid ECDSA signature over the operation id. + #[strict_type(tag = 0x03)] + CheckSigEcdsa(GlobalStateType, MetaType), } diff --git a/src/stl.rs b/src/stl.rs index b472afb0..f1cacf73 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -32,10 +32,7 @@ use crate::{Genesis, Schema, Transition, LIB_NAME_RGB_COMMIT}; /// Strict types id for the library providing data types for RGB consensus. pub const LIB_ID_RGB_COMMIT: &str = - "stl:eBR7hVUY-AAhMZQS-BxMGUdt-D5VCa4l-gvFPe4s-hXYkthg#enrico-ohio-maxwell"; -/// Strict types id for the library providing data types for RGB consensus. -pub const LIB_ID_RGB_LOGIC: &str = - "stl:u28Zbwug-pBA9hRj-v_2ofr6-hz9QvYb-_rU0Luy-tBs2YUg#dynamic-first-middle"; + "stl:w_Ksa~Fy-cqURYmx-8ve0xzB-LSPh_ZM-pnVta9N-wFdJuxA#hope-gong-pedro"; fn _rgb_commit_stl() -> Result> { Ok(LibBuilder::with(libname!(LIB_NAME_RGB_COMMIT), [ diff --git a/src/validation/logic.rs b/src/validation/logic.rs index 73c6d9da..443b5940 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -25,6 +25,7 @@ use std::collections::{BTreeMap, BTreeSet}; use amplify::confinement::{Confined, NonEmptyVec}; use amplify::Wrapper; +use secp256k1::{ecdsa, Message, PublicKey}; use strict_types::TypeSystem; use super::{ @@ -191,6 +192,37 @@ impl Schema { return status; } } + Verifier::CheckSigEcdsa(glob_ty, meta_ty) => { + let genesis = consignment.genesis(); + let Some(pk) = genesis + .globals + .get(&glob_ty) + .into_iter() + .flatten() + .map(|pk| PublicKey::from_slice(pk.as_slice()).ok()) + .next() + .flatten() + else { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + }; + let Some(sig) = op + .metadata() + .get(&meta_ty) + .into_iter() + .map(|meta| ecdsa::Signature::from_compact(&meta).ok()) + .next() + .flatten() + else { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + }; + let msg = Message::from_digest(opid.to_byte_array()); + if sig.verify(&msg, &pk).is_err() { + status.add_failure(validation::Failure::Verifier(verifier, opid)); + return status; + } + } } if contract_state.evolve_state(op).is_err() { status.add_failure(validation::Failure::ContractStateFilled(opid)); diff --git a/src/vm/op_contract.rs b/src/vm/op_contract.rs deleted file mode 100644 index 73b43686..00000000 --- a/src/vm/op_contract.rs +++ /dev/null @@ -1,674 +0,0 @@ -// RGB Core Library: consensus layer for RGB smart contracts. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// Copyright (C) 2019-2024 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)] - -use std::borrow::Borrow; -use std::cell::RefCell; -use std::collections::BTreeSet; -use std::marker::PhantomData; -use std::ops::RangeInclusive; - -use aluvm::isa::{Bytecode, BytecodeError, ExecStep, InstructionSet}; -use aluvm::library::{CodeEofError, IsaSeg, LibSite, Read, Write}; -use aluvm::reg::{CoreRegs, Reg, Reg16, Reg32, RegA, RegS}; -use amplify::num::{u24, u3, u4}; -use amplify::Wrapper; -use secp256k1::{ecdsa, Message, PublicKey}; - -use super::opcodes::*; -use super::{ContractStateAccess, VmContext}; -use crate::vm::OrdOpRef; -use crate::{Assign, AssignmentType, GlobalStateType, MetaType, TypedAssigns}; - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -pub enum ContractOp { - /// Counts number of inputs (previous state entries) of the provided type - /// and puts the number to the destination `a16` register. - /// - /// If the operation doesn't contain inputs with a given assignment type, - /// sets destination index to zero. Does not change `st0` register. - #[display("cnp {0},a16{1}")] - CnP(AssignmentType, Reg32), - - /// Counts number of outputs (owned state entries) of the provided type - /// and puts the number to the destination `a16` register. - /// - /// If the operation doesn't contain inputs with a given assignment type, - /// sets destination index to zero. Does not change `st0` register. - #[display("cns {0},a16{1}")] - CnS(AssignmentType, Reg32), - - /// Counts number of global state items of the provided type affected by the - /// current operation and puts the number to the destination `a8` register. - /// - /// If the operation doesn't contain inputs with a given assignment type, - /// sets destination index to zero. Does not change `st0` register. - #[display("cng {0},a8{1}")] - CnG(GlobalStateType, Reg32), - - /// Counts number of global state items of the provided type in the contract - /// state and puts the number to the destination `a32` register. - /// - /// If the operation doesn't contain inputs with a given assignment type, - /// sets destination index to zero. Does not change `st0` register. - #[display("cnc {0},a32{1}")] - CnC(GlobalStateType, Reg32), - - /// Loads input (previous) structured state with type id from the first - /// argument and index from the second argument `a16` register into a - /// register provided in the third argument. - /// - /// If the state is absent or is not a structured state sets `st0` to - /// `false` and terminates the program. - /// - /// If the state at the index is concealed, sets destination to `None`. - #[display("ldp {0},a16{1},{2}")] - LdP(AssignmentType, Reg16, RegS), - - /// Loads owned structured state with type id from the first argument and - /// index from the second argument `a16` register into a register provided - /// in the third argument. - /// - /// If the state is absent or is not a structured state sets `st0` to - /// `false` and terminates the program. - /// - /// If the state at the index is concealed, sets destination to `None`. - #[display("lds {0},a16{1},{2}")] - LdS(AssignmentType, Reg16, RegS), - - /// Loads owned fungible state with type id from the first argument and - /// index from the second argument `a16` register into `a64` register - /// provided in the third argument. - /// - /// If the state is absent or is not a fungible state sets `st0` to - /// `false` and terminates the program. - /// - /// If the state at the index is concealed, sets destination to `None`. - #[display("ldf {0},a16{1},a64{2}")] - LdF(AssignmentType, Reg16, Reg16), - - /// Loads global state from the current operation with type id from the - /// first argument and index from the second argument `a8` register into a - /// register provided in the third argument. - /// - /// If the state is absent sets `st0` to `false` and terminates the program. - #[display("ldg {0},a8{1},{2}")] - LdG(GlobalStateType, Reg16, RegS), - - /// Loads part of the contract global state with type id from the first - /// argument at the depth from the second argument `a32` register into a - /// register provided in the third argument. - /// - /// If the contract doesn't have the provided global state type, or it - /// doesn't contain a value at the requested index, sets `st0` - /// to fail state and terminates the program. The value of the - /// destination register is not changed. - #[display("ldc {0},a32{1},{2}")] - LdC(GlobalStateType, Reg16, RegS), - - /// Loads operation metadata with a type id from the first argument into a - /// register provided in the second argument. - /// - /// If the operation doesn't have metadata, sets `st0` to fail state and - /// terminates the program. The value of the destination register is not - /// changed. - #[display("ldm {0},{1}")] - LdM(MetaType, RegS), - - /// Verify sum of inputs and outputs are equal. - /// - /// The only argument specifies owned state type for the sum operation. If - /// this state does not exist, or either inputs or outputs does not have - /// any data for the state, the verification fails. - /// - /// If verification succeeds, doesn't change `st0` value; otherwise sets it - /// to `false` and stops execution. - #[display("svs {0}")] - Svs(AssignmentType), - - /// Verify sum of outputs and value in `a64[0]` register are equal. - /// - /// The first argument specifies owned state type for the sum operation. If - /// this state does not exist, or either inputs or outputs does not have - /// any data for the state, the verification fails. - /// - /// If `a64[0]` register does not contain value, the verification fails. - /// - /// If verification succeeds, doesn't change `st0` value; otherwise sets it - /// to `false` and stops execution. - #[display("sas {0}")] - Sas(/** owned state type */ AssignmentType), - - /// Verify sum of inputs and value in `a64[0]` register are equal. - /// - /// The first argument specifies owned state type for the sum operation. If - /// this state does not exist, or either inputs or outputs does not have - /// any data for the state, the verification fails. - /// - /// If `a64[0]` register does not contain value, the verification fails. - /// - /// If verification succeeds, doesn't change `st0` value; otherwise sets it - /// to `false` and stops execution. - #[display("sps {0}")] - Sps(/** owned state type */ AssignmentType), - - /// Verifies the signature of a transition against the pubkey in the first argument. - /// - /// If the register doesn't contain a valid public key or the operation - /// signature is missing or invalid, sets `st0` to fail state and terminates - /// the program. - #[display("vts {0}")] - Vts(RegS), - - /// All other future unsupported operations, which must set `st0` to - /// `false` and stop the execution. - #[display("fail {0}")] - Fail(u8, PhantomData), -} - -impl InstructionSet for ContractOp { - type Context<'ctx> = VmContext<'ctx, S>; - - fn isa_ids() -> IsaSeg { IsaSeg::with("RGB") } - - fn src_regs(&self) -> BTreeSet { - match self { - ContractOp::LdP(_, reg, _) - | ContractOp::LdF(_, reg, _) - | ContractOp::LdS(_, reg, _) => bset![Reg::A(RegA::A16, (*reg).into())], - ContractOp::LdG(_, reg, _) => bset![Reg::A(RegA::A8, (*reg).into())], - ContractOp::LdC(_, reg, _) => bset![Reg::A(RegA::A32, (*reg).into())], - - ContractOp::CnP(_, _) - | ContractOp::CnS(_, _) - | ContractOp::CnG(_, _) - | ContractOp::CnC(_, _) - | ContractOp::LdM(_, _) => bset![], - ContractOp::Svs(_) => bset![], - ContractOp::Sas(_) | ContractOp::Sps(_) => bset![Reg::A(RegA::A64, Reg32::Reg0)], - - ContractOp::Vts(_) => bset![], - - ContractOp::Fail(_, _) => bset![], - } - } - - fn dst_regs(&self) -> BTreeSet { - match self { - ContractOp::CnG(_, reg) => { - bset![Reg::A(RegA::A8, *reg)] - } - ContractOp::CnP(_, reg) | ContractOp::CnS(_, reg) | ContractOp::CnC(_, reg) => { - bset![Reg::A(RegA::A16, *reg)] - } - ContractOp::LdF(_, _, reg) => { - bset![Reg::A(RegA::A64, (*reg).into())] - } - ContractOp::LdG(_, _, reg) - | ContractOp::LdS(_, _, reg) - | ContractOp::LdP(_, _, reg) - | ContractOp::LdC(_, _, reg) - | ContractOp::LdM(_, reg) => { - bset![Reg::S(*reg)] - } - ContractOp::Svs(_) | ContractOp::Sas(_) | ContractOp::Sps(_) => { - bset![] - } - ContractOp::Vts(reg) => bset![Reg::S(*reg)], - ContractOp::Fail(_, _) => bset![], - } - } - - fn complexity(&self) -> u64 { - match self { - ContractOp::CnP(_, _) - | ContractOp::CnS(_, _) - | ContractOp::CnG(_, _) - | ContractOp::CnC(_, _) => 2, - ContractOp::LdP(_, _, _) - | ContractOp::LdS(_, _, _) - | ContractOp::LdF(_, _, _) - | ContractOp::LdG(_, _, _) - | ContractOp::LdC(_, _, _) => 8, - ContractOp::LdM(_, _) => 6, - ContractOp::Svs(_) | ContractOp::Sas(_) | ContractOp::Sps(_) => 20, - ContractOp::Vts(_) => 512, - ContractOp::Fail(_, _) => u64::MAX, - } - } - - fn exec(&self, regs: &mut CoreRegs, _site: LibSite, context: &Self::Context<'_>) -> ExecStep { - macro_rules! fail { - () => {{ - regs.set_failure(); - return ExecStep::Stop; - }}; - } - macro_rules! load_revealed_inputs { - ($state_type:ident) => {{ - match context.op_info.prev_state.get($state_type) { - Some(TypedAssigns::Fungible(state)) => { - let mut values = vec![]; - for val in state.iter().map(Assign::as_state) { - values.push(val.into_inner()) - } - values - } - None => vec![], - _ => fail!(), - } - }}; - } - macro_rules! load_revealed_outputs { - ($state_type:ident) => {{ - match context.op_info.owned_state().get(*$state_type) { - Some(TypedAssigns::Fungible(state)) => { - let mut values = vec![]; - for val in state.iter().map(Assign::as_state) { - values.push(val.into_inner()) - } - values - } - None => vec![], - _ => fail!(), - } - }}; - } - - match self { - ContractOp::CnP(state_type, reg) => { - regs.set_n( - RegA::A16, - *reg, - context - .op_info - .prev_state - .get(state_type) - .map(|a| a.len_u16()), - ); - } - ContractOp::CnS(state_type, reg) => { - regs.set_n( - RegA::A16, - *reg, - context - .op_info - .owned_state() - .get(*state_type) - .map(|a| a.len_u16()), - ); - } - ContractOp::CnG(state_type, reg) => { - regs.set_n( - RegA::A8, - *reg, - context - .op_info - .global() - .get(state_type) - .map(|a| a.len_u16()), - ); - } - ContractOp::CnC(state_type, reg) => { - if let Ok(mut global) = RefCell::borrow(&context.contract_state).global(*state_type) - { - regs.set_n(RegA::A32, *reg, global.size().to_u32()); - } else { - regs.set_n(RegA::A32, *reg, None::); - } - } - ContractOp::LdP(state_type, reg_32, reg) => { - let Some(reg_32) = *regs.get_n(RegA::A16, *reg_32) else { - fail!() - }; - let index: u16 = reg_32.into(); - - let Some(Ok(state)) = context - .op_info - .prev_state - .get(state_type) - .map(|a| a.as_structured_state_at(index)) - else { - fail!() - }; - let state = state.as_inner(); - regs.set_s16(*reg, state); - } - ContractOp::LdS(state_type, reg_32, reg) => { - let Some(reg_32) = *regs.get_n(RegA::A16, *reg_32) else { - fail!() - }; - let index: u16 = reg_32.into(); - - let Some(Ok(state)) = context - .op_info - .owned_state() - .get(*state_type) - .map(|a| a.into_structured_state_at(index)) - else { - fail!() - }; - let state = state.into_inner(); - regs.set_s16(*reg, state); - } - ContractOp::LdF(state_type, reg_32, reg) => { - let Some(reg_32) = *regs.get_n(RegA::A16, *reg_32) else { - fail!() - }; - let index: u16 = reg_32.into(); - - let Some(Ok(state)) = context - .op_info - .owned_state() - .get(*state_type) - .map(|a| a.into_fungible_state_at(index)) - else { - fail!() - }; - regs.set_n(RegA::A64, *reg, state.as_inner()); - } - ContractOp::LdG(state_type, reg_8, reg_s) => { - let Some(reg_32) = *regs.get_n(RegA::A8, *reg_8) else { - fail!() - }; - let index: u8 = reg_32.into(); - - let Some(state) = context - .op_info - .global() - .get(state_type) - .and_then(|a| a.get(index as usize)) - else { - fail!() - }; - regs.set_s16(*reg_s, state.as_inner()); - } - - ContractOp::LdC(state_type, reg_32, reg_s) => { - let state = RefCell::borrow(&context.contract_state); - let Ok(mut global) = state.global(*state_type) else { - fail!() - }; - let Some(reg_32) = *regs.get_n(RegA::A32, *reg_32) else { - fail!() - }; - let index: u32 = reg_32.into(); - let Ok(index) = u24::try_from(index) else { - fail!() - }; - let Some(state) = global.nth(index) else { - fail!() - }; - regs.set_s16(*reg_s, state.borrow().as_inner()); - } - ContractOp::LdM(type_id, reg) => { - let Some(meta) = context.op_info.metadata().get(type_id) else { - fail!() - }; - regs.set_s16(*reg, meta.to_inner()); - } - ContractOp::Svs(state_type) => { - let Some(input_amt) = load_revealed_inputs!(state_type) - .iter() - .try_fold(0u64, |acc, &x| acc.checked_add(x)) - else { - fail!() - }; - let Some(output_amt) = load_revealed_outputs!(state_type) - .iter() - .try_fold(0u64, |acc, &x| acc.checked_add(x)) - else { - fail!() - }; - if input_amt != output_amt { - fail!() - } - } - ContractOp::Sas(owned_state) => { - let Some(sum) = *regs.get_n(RegA::A64, Reg32::Reg0) else { - fail!() - }; - let sum = u64::from(sum); - - let outputs = load_revealed_outputs!(owned_state); - if outputs.contains(&0) { - fail!() - } - let Some(output_amt) = outputs.iter().try_fold(0u64, |acc, &x| acc.checked_add(x)) - else { - fail!() - }; - - if sum != output_amt { - fail!() - } - } - ContractOp::Sps(owned_state) => { - let Some(sum) = *regs.get_n(RegA::A64, Reg32::Reg0) else { - fail!() - }; - let sum = u64::from(sum); - - let Some(input_amt) = load_revealed_inputs!(owned_state) - .iter() - .try_fold(0u64, |acc, &x| acc.checked_add(x)) - else { - fail!() - }; - - if sum != input_amt { - fail!() - } - } - ContractOp::Vts(reg_s) => match context.op_info.op { - OrdOpRef::Genesis(_) => fail!(), - OrdOpRef::Transition(transition, _, _, _) => { - let Some(pubkey) = regs.s16(*reg_s) else { - fail!() - }; - let Ok(pubkey) = PublicKey::from_slice(&pubkey.to_vec()) else { - fail!() - }; - let Some(ref witness) = transition.signature else { - fail!() - }; - let sig_bytes = witness.clone().into_inner().into_inner(); - let Ok(sig) = ecdsa::Signature::from_compact(&sig_bytes) else { - fail!() - }; - - let transition_id = context.op_info.id.into_inner().into_inner(); - let msg = Message::from_digest(transition_id); - - if sig.verify(&msg, &pubkey).is_err() { - fail!() - } - } - }, - // All other future unsupported operations, which must set `st0` to `false`. - _ => fail!(), - } - ExecStep::Next - } -} - -impl Bytecode for ContractOp { - fn instr_range() -> RangeInclusive { INSTR_CONTRACT_FROM..=INSTR_CONTRACT_TO } - - fn instr_byte(&self) -> u8 { - match self { - ContractOp::CnP(_, _) => INSTR_CNP, - ContractOp::CnS(_, _) => INSTR_CNS, - ContractOp::CnG(_, _) => INSTR_CNG, - ContractOp::CnC(_, _) => INSTR_CNC, - - ContractOp::LdG(_, _, _) => INSTR_LDG, - ContractOp::LdS(_, _, _) => INSTR_LDS, - ContractOp::LdP(_, _, _) => INSTR_LDP, - ContractOp::LdF(_, _, _) => INSTR_LDF, - ContractOp::LdC(_, _, _) => INSTR_LDC, - ContractOp::LdM(_, _) => INSTR_LDM, - - ContractOp::Svs(_) => INSTR_SVS, - ContractOp::Sas(_) => INSTR_SAS, - ContractOp::Sps(_) => INSTR_SPS, - - ContractOp::Vts(_) => INSTR_VTS, - - ContractOp::Fail(other, _) => *other, - } - } - - fn encode_args(&self, writer: &mut W) -> Result<(), BytecodeError> - where W: Write { - match self { - ContractOp::CnP(state_type, reg) => { - writer.write_u16(*state_type)?; - writer.write_u5(reg)?; - writer.write_u3(u3::ZERO)?; - } - ContractOp::CnS(state_type, reg) => { - writer.write_u16(*state_type)?; - writer.write_u5(reg)?; - writer.write_u3(u3::ZERO)?; - } - ContractOp::CnG(state_type, reg) => { - writer.write_u16(*state_type)?; - writer.write_u5(reg)?; - writer.write_u3(u3::ZERO)?; - } - ContractOp::CnC(state_type, reg) => { - writer.write_u16(*state_type)?; - writer.write_u5(reg)?; - writer.write_u3(u3::ZERO)?; - } - ContractOp::LdP(state_type, reg_a, reg_s) => { - writer.write_u16(*state_type)?; - writer.write_u4(reg_a)?; - writer.write_u4(reg_s)?; - } - ContractOp::LdS(state_type, reg_a, reg_s) => { - writer.write_u16(*state_type)?; - writer.write_u4(reg_a)?; - writer.write_u4(reg_s)?; - } - ContractOp::LdF(state_type, reg_a, reg_dst) => { - writer.write_u16(*state_type)?; - writer.write_u4(reg_a)?; - writer.write_u4(reg_dst)?; - } - ContractOp::LdG(state_type, reg_a, reg_s) => { - writer.write_u16(*state_type)?; - writer.write_u4(reg_a)?; - writer.write_u4(reg_s)?; - } - ContractOp::LdC(state_type, reg_a, reg_s) => { - writer.write_u16(*state_type)?; - writer.write_u4(reg_a)?; - writer.write_u4(reg_s)?; - } - ContractOp::LdM(state_type, reg) => { - writer.write_u16(*state_type)?; - writer.write_u4(reg)?; - writer.write_u4(u4::ZERO)?; - } - - ContractOp::Svs(state_type) => writer.write_u16(*state_type)?, - ContractOp::Sas(owned_type) => writer.write_u16(*owned_type)?, - ContractOp::Sps(owned_type) => writer.write_u16(*owned_type)?, - - ContractOp::Vts(reg_s) => writer.write_u4(*reg_s)?, - - ContractOp::Fail(_, _) => {} - } - Ok(()) - } - - fn decode(reader: &mut R) -> Result - where - Self: Sized, - R: Read, - { - Ok(match reader.read_u8()? { - INSTR_CNP => { - let i = Self::CnP(reader.read_u16()?.into(), reader.read_u5()?.into()); - reader.read_u3()?; // Discard garbage bits - i - } - INSTR_CNS => { - let i = Self::CnS(reader.read_u16()?.into(), reader.read_u5()?.into()); - reader.read_u3()?; // Discard garbage bits - i - } - INSTR_CNG => { - let i = Self::CnG(reader.read_u16()?.into(), reader.read_u5()?.into()); - reader.read_u3()?; // Discard garbage bits - i - } - INSTR_CNC => { - let i = Self::CnC(reader.read_u16()?.into(), reader.read_u5()?.into()); - reader.read_u3()?; // Discard garbage bits - i - } - - INSTR_LDP => Self::LdP( - reader.read_u16()?.into(), - reader.read_u4()?.into(), - reader.read_u4()?.into(), - ), - INSTR_LDF => Self::LdF( - reader.read_u16()?.into(), - reader.read_u4()?.into(), - reader.read_u4()?.into(), - ), - INSTR_LDG => Self::LdG( - reader.read_u16()?.into(), - reader.read_u4()?.into(), - reader.read_u4()?.into(), - ), - INSTR_LDS => Self::LdS( - reader.read_u16()?.into(), - reader.read_u4()?.into(), - reader.read_u4()?.into(), - ), - INSTR_LDC => Self::LdC( - reader.read_u16()?.into(), - reader.read_u4()?.into(), - reader.read_u4()?.into(), - ), - INSTR_LDM => { - let i = Self::LdM(reader.read_u16()?.into(), reader.read_u4()?.into()); - reader.read_u4()?; // Discard garbage bits - i - } - - INSTR_SVS => Self::Svs(reader.read_u16()?.into()), - INSTR_SAS => Self::Sas(reader.read_u16()?.into()), - INSTR_SPS => Self::Sps(reader.read_u16()?.into()), - - INSTR_VTS => Self::Vts(reader.read_u4()?.into()), - - x => Self::Fail(x, PhantomData), - }) - } -} diff --git a/stl/RGBCommit@0.1.0.sta b/stl/RGBCommit@0.1.0.sta index 47c902b3..5286549c 100644 --- a/stl/RGBCommit@0.1.0.sta +++ b/stl/RGBCommit@0.1.0.sta @@ -1,12 +1,12 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:eBR7hVUY-AAhMZQS-BxMGUdt-D5VCa4l-gvFPe4s-hXYkthg#enrico-ohio-maxwell +Id: stl:w_Ksa~Fy-cqURYmx-8ve0xzB-LSPh_ZM-pnVta9N-wFdJuxA#hope-gong-pedro Name: RGBCommit Dependencies: Std#delete-roman-hair, BPSeals#balloon-oscar-george, StrictTypes#henry-heart-survive, Bitcoin#signal-color-cipher -Check-SHA256: a6812ee604501de3846fb1ded3af221f5a8791c53d8ca94ea5fc3a9523b494a0 +Check-SHA256: 89c1109048727f1a087553ca086378ac7e3ab4cf7eecba09aa690c35c5b9ff9a 2~tNwLvL+uX>mfM)c|rOrSAqOFlj|?PZGn 7*@S>vOg%-GTKs92V@urLQqp>VQh2ho|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsOQ*?4^V{}w` @@ -20,7 +20,7 @@ jxz)>1ioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^aq -Wo=1hG5{e#b8~5DZbo%(XK7+=Wm9xvbY((pX>MdwWnpYocu;h51OfmEa%Fa9VQgh&00sgCb7f&{0;fjw +Wo=1hF#sV!b8~5DZbo%(XK7+=Wm9xvbY((pX>MdwWnpYocu;h51OfmEa%Fa9VQgh&00sgCb7f&{0;fjw >JLnyF>6acJ~i!Siv1W?y>zlaDAzLDQd9?I7^kT6xdReUg_1Rxg;i+JLny F>6acJ~i!Siv1W?y>zlaDAzLDQd9?I7-$*myw$T9tCzEwrAszt-P)%HZ|LbH=L2A=l(W4CP6cyxVRU5y @@ -100,32 +100,33 @@ f4cdUdGS4#Tk(yYN*ff#-&-~S0000000030000000000BXKZg`VQf@+aAk7<3IWybk`76TvuW{aQ_%-X `?VwZ$5L?~`!+pRSq0(b70Uq+w#z7JBTYQ(6wA15KJe33N=y1k%8ssy_EyFtI!|)|000000003000000 0000AZ+C8GWK?-@Wpe-u0f+wLWmt%8=p4R=gtK{LClh6Z#kObxUW*hKHnBv9xdFK%KKY6{y^9(U*_!W# CeCf%@U$Ra$QlHXZNo_Yhhx0Be79xh+o&58gBL -g%$F9MUi-9%UHGxbaG*Cb7^#GZ*Fq{3IQ}y53UoI8eY9A{1GERg--GiI0S#x1is&)M%fmnGH3x@!%VR! -boT!l0ce6}iE2`s>&2w5gKr7m?oSuHf_Z2F0000000030000000000HWMyVyb!>D&b8~5DZf#|5bN~bb +g%$F9MUi-9%UHGxbaG*Cb7^#GZ*Fq{3IQ}y53UoI8eY9A{1GERg--GiI0S#x1is&)M%fmnGH3xyy008h +Gn{|Lm}w#lgp0VE^~G;M6*q>|HOcI}fxVUh0000000030000000000HWMyVyb!>D&b8~5DZf#|5bN~bb 00eGtZe;)f009JZZ*64&1pxtv{^Dg=h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQuQ)6glZDC1d1pxpD -002NB025PXVQfQeZ*ysGXH#@?VRU6@c>@6wW@&PBbWd<{Wpqz+RAF#(Wpn@uQ)y>zVRUtJWd#8M2LJ#- -KmZO?baHiLbairNWJFV=@2?J(kb^+R(Q4?4e -R(6nw`65I6*X)C9iYp+?yjr7~y; -ZDn*}WMOn+0rh%KI9Y!AFx9LCk8@hQXE7w+qW3^C%eTEp@#^?_H3w&GZ(?C=a{&vwi5c8ynrLi66{6Eh -R2JZ)1oVmC*y|BUK&C!OC@}_UZg6#Ua{)F6OOsb2BHT!z`XR@Y;!tI8CO};e1CqOk7xis%Ku=2wF -+7z(Wqt=tdZk`V^s(Ana000000093000000000JQZg6#Ua{vkfhyLPaScq)s9KMExvw34D6J>+NwrBxf -ixd_%u|$Wt0XD%jq57bK6Q|uUfIMEX^1}Vv6tLB!)|10-o)0prc>n+a000000RI300000001IJrb7^O8 -ZDnqBa{vkfhyLPaScq)s9KMExvw34D6J>+NwrBxfixd_%u|$Wt0XD%jq57bK6Q|uUfIMEX^1}Vv6tLB! -)|10-o)0prc>n+a000000RI300000000?$va%pC1WpV*oiU94v6(vTv6u$_Raxvv3(3FSqnKg-@vDIE; -aLC#YRB~Z%b7^#GZ*Ek1aAgGn0006SRC#b^WI=OtX=iS8LTqVnWK(5fY*ctqbaDg(01ISgV{Bn^VRUJB -WdH>M0jXmSzQi_Bob4h>{BE>m*T@oo-6ohy*RC#b^WI=OtX=iS8LTqVnWK(5fY*ct@WCQ~M3uI+uY+-U?bZK^F00jX7W9*8jxQDoM*B7^7+wmzc -N4T^dBdjMp+)Kp2d0SIPwZf9v?Y-Ioi0RaQ+LUU)9P1F3fk)PC*KgHh%%41=0N|UI$lu$Tz`bPo^ -b98cbV{~H4Fp|NyLX=8(1mfVhcP$z*V~7Y=WpZg|X=QQ)0R(PuZe;)o -R&Qx!Q*>c;Wd#8M000 +002NB025PXVQfQeZ*ysGXH#@?VRU6@c>@6wW@&PBbWd<{Wpqz+RAF#(Wpn@zQ*?55V{~h5j^*S;IZf|a5WdHyO4s>#1 +ZgXjLX>V>+d2nR`G*S<)6P6lYy(#<=BR_>s@(?%#f7ArN-=Rj?7Ns(12yJC_VPs)+VFC4eO*mP8`7qV2 +1dnrCyk{{a-lF$FG0V5TNAc?Tc{K-TY;R&=Y;yq%x``RwXPRhiK^3CYN>mo$qXhJc-q`CANI<4ONGLG| +X>M?JbaMeV21}DyAtKyJp!y-llj5_1lAj$w(~~K8ZkuV>sWprU_Y;y(z5Oi{3ZgXjLX>V>*V`ybvg4VQpms>7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0V>*V`ybVZDn*}WMOn+00{wg +M?JbaMa-0f+wLWmt%8=p4R=gtK{LClh6Z#kObxUW*hKHnBv9xdAr8G@<&SffJ|Q +Fn~N>u=2wF+7z(Wqt=tdZk`V^s(Ana000000093000000000YNb8~5DZf#|5baMa-0f+wLWmt%8=p4R= +gtK{LClh6Z#kObxUW*hKHnBv9xdAr8G@<&SffJ|QFn~N>u=2wF+7z(Wqt=tdZk`V^s(Ana0000000930 +00000000PfWpZg|X=QQ&ao0!7eG&w_){??`5buAwtLKE%n%_j}gtcIo&2Szu4peesZgXjLX>V>+d2nR~ +0RR938dQ03Wn@8fb7^O8b3$xsZe&wsVQf@*P;_zx0{{zTWn*k%a$$67c4Yts0RgFF4!*=TQJn1}N&IfK +W!K0Of88dSS6KW9oA>I29k>AqW_507X<}?;00jX7B7Q(M`BG5_r8gUX$GAUK#)*tSP9ga~G=;toqhtCn +0t$0Lb#i5700jX7(YFK^gf+ruNn$z`f_zCp020XsVI52xBP)L?VfTbu8B}?2Wn@8fb7^O8b3$xs +Ze&wsVQf@*X=DTg01ISgV{Bn^VRUJBWdH>M0b}fnr?`i>a@QBPVB7I2FGskv9V4tKJlspfzkCRxdI1P# +b#7;AVr*pq1pxsA>q2v9mQBpbkcrcQ|w?dRkcLd_#xOXiYF=L1bR%LQ&W@%+|1OxyCZf|a70000124!(mb!~G11pxtv{^Dg= +h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQo24!(pVQg~%1pxtv{^Dg=h-~N_zJ`Red1EINWrM}GXaQb} +6c#qIM2EQp4P$6!V{21sXGLRVb724l0s+c;Wd#8M000 -----END STRICT TYPE LIB----- diff --git a/stl/RGBCommit@0.1.0.stl b/stl/RGBCommit@0.1.0.stl index 747555f9bb5087c0c6baa9bad720645e2abf41ad..3e34d9af5622d2b75649fe55cd1c0c0b459a0d16 100644 GIT binary patch delta 242 zcmV1Gf_(OS-QdPcxi<#h7U#3xtcfn)StR zKovKJ)HTWMyn(%zlUo;*lL8nrlUWrevsxGp0h6a0CLj(&pYtXK8Fh;>vgJ8gKz1ao0!7eG&w_){??`5buAwtLKE%n%_j} zgtcIo&2Szuv%?#70TToS00eGtZe;)f009PNaZ`0|bCZu3BnScqWpP$vY;%*37bFq` s4P$6!V{21sXGLRVb724l0+TToB9qb;AP)&vZ)s#xbYXO51pxp601UEQ6951J delta 268 zcmZ2wea>nF3p2A3gW_aG7P-j>IO8|BFmD%Dh&k-DQN85be@VuSru5FNpjoevE?L){ z&w1~izxeK^%8bd;;!}h;gEQ0f5=%;pQdt=p*clic945aLH)iCV93`r{*k(!v4h0|$y@VwPp%hL+k8NB z0;57?7sJ~FqN;8?MD}w`DKdPja$!pQ$C;*`^EY0NODZ^VYjc5g38OeOBg7$`VfmRU N!6k_$Am=kM001qwXEFc) diff --git a/stl/RGBCommit@0.1.0.sty b/stl/RGBCommit@0.1.0.sty index 0be97eec..a3894146 100644 --- a/stl/RGBCommit@0.1.0.sty +++ b/stl/RGBCommit@0.1.0.sty @@ -1,5 +1,5 @@ {- - Id: stl:eBR7hVUY-AAhMZQS-BxMGUdt-D5VCa4l-gvFPe4s-hXYkthg#enrico-ohio-maxwell + Id: stl:w_Ksa~Fy-cqURYmx-8ve0xzB-LSPh_ZM-pnVta9N-wFdJuxA#hope-gong-pedro Name: RGBCommit Version: 0.1.0 Description: Consensus commitment layer for RGB smart contracts @@ -185,13 +185,10 @@ data SchemaId : [Byte ^ 32] data SealClosingStrategy : firstOpretOrTapret | (|) -@mnemonic(ferrari-zebra-tempo) -data Signature : [Byte ^ 64] - @mnemonic(nirvana-modern-bonjour) data StructuredData : [Byte] -@mnemonic(remark-gravity-vitamin) +@mnemonic(matrix-yogurt-vienna) data Transition : ffv Ffv , contractId ContractId , nonce U64 @@ -200,7 +197,6 @@ data Transition : ffv Ffv , globals GlobalState , inputs Inputs , assignments AssignmentsBlindSealTxPtr - , signature Signature? @mnemonic(orbit-pattern-goblin) data TransitionDetails : transitionSchema TransitionSchema, name StrictTypes.FieldName @@ -225,9 +221,11 @@ data TypedAssignsBlindSealTxid : declarative AssignVecAssignVoidStateBlindSealTx | fungible AssignVecAssignFungibleStateBlindSealTxid | structured AssignVecAssignStructuredDataBlindSealTxid -@mnemonic(escort-pretend-comedy) -data Verifier : none | (|) - +@mnemonic(dynasty-domingo-robot) +data Verifier : none () + | eqSums AssignmentType + | eqVals AssignmentType + | checkSigEcdsa (GlobalStateType, MetaType) @mnemonic(email-snow-safari) data VoidState : () diff --git a/stl/Schema.vesper b/stl/Schema.vesper index 75e5b011..809a2efc 100644 --- a/stl/Schema.vesper +++ b/stl/Schema.vesper @@ -83,7 +83,13 @@ rec Schema rec value, Occurrences is min, U16 is max, U16 - enum verifier, Verifier, none 0 + union verifier, Verifier + is none, Unit, tag 0 + is eqSums, U16, wrapped, aka AssignmentType, tag 1 + is eqVals, U16, wrapped, aka AssignmentType, tag 2 + tuple checkSigEcdsa, tag 3 + is _, U16, aka GlobalStateType + is _, U16, aka MetaType ascii name, aka FieldName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 is some, U16, option, wrapped, aka AssignmentType, tag 1 diff --git a/stl/Transition.vesper b/stl/Transition.vesper index 67ca767c..c8e14dfe 100644 --- a/stl/Transition.vesper +++ b/stl/Transition.vesper @@ -69,5 +69,4 @@ rec Transition rec secretSeal, tag 1 bytes seal, len 32, aka SecretSeal bytes state, len 0..MAX16, aka StructuredData - bytes some, len 64, option, wrapped, aka Signature, tag 1 From bda74afddbce65cb4b306d54f8fd3e97265a0d4f Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 2 Jun 2025 13:56:33 +0200 Subject: [PATCH 23/23] chore: fix clippy lints --- src/validation/logic.rs | 2 +- src/validation/validator.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validation/logic.rs b/src/validation/logic.rs index 443b5940..3dd63429 100644 --- a/src/validation/logic.rs +++ b/src/validation/logic.rs @@ -210,7 +210,7 @@ impl Schema { .metadata() .get(&meta_ty) .into_iter() - .map(|meta| ecdsa::Signature::from_compact(&meta).ok()) + .map(|meta| ecdsa::Signature::from_compact(meta).ok()) .next() .flatten() else { diff --git a/src/validation/validator.rs b/src/validation/validator.rs index d970c7bd..67f5c612 100644 --- a/src/validation/validator.rs +++ b/src/validation/validator.rs @@ -278,7 +278,7 @@ impl< WitnessStatus::Mined(witness_height) => { if witness_height > safe_height { unsafe_history_map - .entry(witness_height.into()) + .entry(witness_height) .or_default() .insert(witness_id); }