diff --git a/Cargo.lock b/Cargo.lock index 2420f764..60158c23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -668,7 +668,7 @@ dependencies = [ [[package]] name = "rgb-core" version = "0.11.0-beta.9" -source = "git+https://github.com/RGB-WG/rgb-core?branch=feat/fungible-nonconf#b59f1ca4c13c62ce53152f7f4c34094e435a1be4" +source = "git+https://github.com/RGB-WG/rgb-core?branch=feat/fungible-nonconf#e92e5b176886b3f04d8cfbb41714ab8f7d0b8046" dependencies = [ "aluvm", "amplify", @@ -906,8 +906,7 @@ dependencies = [ [[package]] name = "strict_types" version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3188d65ee78a90da3545df762a1363b5b4f9c3b845f182a18fc40ae991c235ce" +source = "git+https://github.com/strict-types/strict-types?branch=develop#729a4f86d25dfcea15ed15bbeb1e027473401c58" dependencies = [ "amplify", "ascii-armor", diff --git a/Cargo.toml b/Cargo.toml index e4200e51..3837c078 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ features = ["all"] [patch.crates-io] commit_verify = { git = "https://github.com/LNP-BP/client_side_validation", branch = "develop" } single_use_seals = { git = "https://github.com/LNP-BP/client_side_validation", branch = "develop" } +strict_types = { git = "https://github.com/strict-types/strict-types", branch = "develop" } aluvm = { git = "https://github.com/AluVM/rust-aluvm", branch = "develop" } bp-consensus = { git = "https://github.com/BP-WG/bp-core", branch = "develop" } bp-dbc = { git = "https://github.com/BP-WG/bp-core", branch = "develop" } diff --git a/src/interface/builder.rs b/src/interface/builder.rs index 5f444a82..4905aca1 100644 --- a/src/interface/builder.rs +++ b/src/interface/builder.rs @@ -28,11 +28,10 @@ use chrono::Utc; use rgb::validation::Scripts; use rgb::{ validation, AltLayer1, AltLayer1Set, AssignmentType, Assignments, AttachId, ContractId, - ExposedSeal, Genesis, GenesisSeal, GlobalState, GraphSeal, Identity, Input, Layer1, - MetadataError, Opout, Schema, State, StateData, Transition, TransitionType, TypedAssigns, - XChain, XOutpoint, + ExposedSeal, Genesis, GenesisSeal, GlobalState, GlobalStateSchema, GlobalStateType, GraphSeal, + Identity, Input, Layer1, MetaType, Metadata, MetadataError, Opout, Schema, State, StateData, + Transition, TransitionType, TypedAssigns, ValencyType, XChain, XOutpoint, STATE_DATA_MAX_LEN, }; -use rgbcore::{GlobalStateSchema, GlobalStateType, MetaType, Metadata, ValencyType}; use strict_encoding::{FieldName, SerializeError, StrictSerialize}; use strict_types::{decode, typify, SemId, StrictVal, TypeSystem}; @@ -203,26 +202,44 @@ impl ContractBuilder { self.builder.valency_name(type_id) } - #[inline] pub fn add_metadata( mut self, name: impl Into, - value: impl StrictSerialize, + value: StrictVal, ) -> Result { self.builder = self.builder.add_metadata(name, value)?; Ok(self) } #[inline] + pub fn serialize_metadata( + mut self, + name: impl Into, + value: &impl StrictSerialize, + ) -> Result { + self.builder = self.builder.serialize_metadata(name, value)?; + Ok(self) + } + pub fn add_global_state( mut self, name: impl Into, - value: impl StrictSerialize, + value: StrictVal, ) -> Result { self.builder = self.builder.add_global_state(name, value)?; Ok(self) } + #[inline] + pub fn serialize_global_state( + mut self, + name: impl Into, + value: &impl StrictSerialize, + ) -> Result { + self.builder = self.builder.serialize_global_state(name, value)?; + Ok(self) + } + pub fn add_owned_state_raw( mut self, type_id: AssignmentType, @@ -400,39 +417,31 @@ impl TransitionBuilder { pub fn transition_type(&self) -> TransitionType { self.transition_type } - pub fn set_nonce(mut self, nonce: u64) -> Self { - self.nonce = nonce; - self + #[inline] + pub fn global_type(&self, name: impl Into) -> Result { + self.builder.global_type(name) } #[inline] - pub fn add_metadata( - mut self, + pub fn assignments_type( + &self, name: impl Into, - value: impl StrictSerialize, - ) -> Result { - self.builder = self.builder.add_metadata(name, value)?; - Ok(self) + ) -> Result { + self.builder.assignments_type(name) } #[inline] - pub fn add_global_state( - mut self, - name: impl Into, - value: impl StrictSerialize, - ) -> Result { - self.builder = self.builder.add_global_state(name, value)?; - Ok(self) + pub fn valency_type(&self, name: impl Into) -> Result { + self.builder.valency_type(name) } - pub fn add_input(mut self, opout: Opout, state: State) -> Result { - if let Some(calc) = &mut self.calc { - calc.reg_input(opout.ty, &state)?; - } - self.inputs.insert(Input::with(opout), state)?; - Ok(self) + #[inline] + pub fn valency_name(&self, type_id: ValencyType) -> &FieldName { + self.builder.valency_name(type_id) } + pub fn meta_name(&self, type_id: MetaType) -> &FieldName { self.builder.meta_name(type_id) } + pub fn default_assignment(&self) -> Result<&FieldName, BuilderError> { self.builder .transition_iface(self.transition_type) @@ -441,31 +450,57 @@ impl TransitionBuilder { .ok_or(BuilderError::NoDefaultAssignment) } - #[inline] - pub fn assignments_type( - &self, + pub fn set_nonce(mut self, nonce: u64) -> Self { + self.nonce = nonce; + self + } + + pub fn add_input(mut self, opout: Opout, state: State) -> Result { + if let Some(calc) = &mut self.calc { + calc.reg_input(opout.ty, &state)?; + } + self.inputs.insert(Input::with(opout), state)?; + Ok(self) + } + + pub fn add_metadata( + mut self, name: impl Into, - ) -> Result { - self.builder.assignments_type(name) + value: StrictVal, + ) -> Result { + self.builder = self.builder.add_metadata(name, value)?; + Ok(self) } #[inline] - pub fn global_type(&self, name: impl Into) -> Result { - self.builder.global_type(name) + pub fn serialize_metadata( + mut self, + name: impl Into, + value: &impl StrictSerialize, + ) -> Result { + self.builder = self.builder.serialize_metadata(name, value)?; + Ok(self) } - #[inline] - pub fn valency_type(&self, name: impl Into) -> Result { - self.builder.valency_type(name) + pub fn add_global_state( + mut self, + name: impl Into, + value: StrictVal, + ) -> Result { + self.builder = self.builder.add_global_state(name, value)?; + Ok(self) } #[inline] - pub fn valency_name(&self, type_id: ValencyType) -> &FieldName { - self.builder.valency_name(type_id) + pub fn serialize_global_state( + mut self, + name: impl Into, + value: &impl StrictSerialize, + ) -> Result { + self.builder = self.builder.serialize_global_state(name, value)?; + Ok(self) } - pub fn meta_name(&self, type_id: MetaType) -> &FieldName { self.builder.meta_name(type_id) } - // TODO: We won't need this once we will have Blank Transition builder /// NB: This does not process the state with VM pub fn add_owned_state_blank( @@ -610,8 +645,9 @@ impl OperationBuilder { } #[inline] - fn meta_schema(&self, type_id: MetaType) -> &SemId { - self.schema + fn meta_schema(&self, type_id: MetaType) -> SemId { + *self + .schema .meta_types .get(&type_id) .expect("schema should match interface: must be checked by the constructor") @@ -625,29 +661,78 @@ impl OperationBuilder { .expect("schema should match interface: must be checked by the constructor") } - pub fn add_metadata( + fn add_metadata( mut self, name: impl Into, - value: impl StrictSerialize, + value: StrictVal, + ) -> Result { + let type_id = self.meta_type(name)?; + + let types = self.type_system(); + let sem_id = *self + .schema + .meta_types + .get(&type_id) + .expect("schema-interface inconsistency"); + let value = types.typify(value, sem_id)?; + let data = types.strict_serialize_value::(&value)?; + + self.meta.add_value(type_id, data.into())?; + Ok(self) + } + + fn serialize_metadata( + mut self, + name: impl Into, + value: &impl StrictSerialize, ) -> Result { let type_id = self.meta_type(name)?; let serialized = value.to_strict_serialized::<{ u16::MAX as usize }>()?; let sem_id = self.meta_schema(type_id); - self.types.strict_deserialize_type(*sem_id, &serialized)?; + + #[cfg(debug_assertions)] + self.types + .strict_deserialize_type(sem_id, &serialized) + .expect("failed deserialization"); + self.meta.add_value(type_id, serialized.into())?; Ok(self) } - pub fn add_global_state( + fn add_global_state( mut self, name: impl Into, - value: impl StrictSerialize, + value: StrictVal, + ) -> Result { + let type_id = self.global_type(name)?; + + let types = self.type_system(); + let sem_id = self + .schema + .global_types + .get(&type_id) + .expect("schema-interface inconsistency") + .sem_id; + let value = types.typify(value, sem_id)?; + let data = types.strict_serialize_value::(&value)?; + + self.global.add_state(type_id, data.into())?; + Ok(self) + } + + fn serialize_global_state( + mut self, + name: impl Into, + value: &impl StrictSerialize, ) -> Result { let type_id = self.global_type(name)?; let serialized = value.to_strict_serialized::<{ u16::MAX as usize }>()?; - // Check value matches type requirements let sem_id = self.global_schema(type_id).sem_id; - self.types.strict_deserialize_type(sem_id, &serialized)?; + + #[cfg(debug_assertions)] + self.types + .strict_deserialize_type(sem_id, &serialized) + .expect("failed deserialization"); self.global.add_state(type_id, serialized.into())?; @@ -687,12 +772,10 @@ impl OperationBuilder { .schema .owned_types .get(&type_id) - .expect("schema-interface inconsistence") + .expect("schema-interface inconsistency") .sem_id; let value = types.typify(value, sem_id)?; - let data = types - .strict_serialize_type::<{ confinement::U16 }>(&value)? - .to_strict_serialized()?; + let data = types.strict_serialize_value::(&value)?; let mut state = State::from(StateData::from(data)); state.attach = attach; diff --git a/src/interface/contract.rs b/src/interface/contract.rs index 075fafb1..2f92e710 100644 --- a/src/interface/contract.rs +++ b/src/interface/contract.rs @@ -22,13 +22,12 @@ use std::borrow::Borrow; use std::collections::{BTreeSet, HashMap, HashSet}; -use amplify::confinement; use rgb::validation::Scripts; use rgb::{ AssignmentType, AttachId, ContractId, OpId, Opout, Schema, State, StateData, XOutputSeal, - XWitnessId, + XWitnessId, STATE_DATA_MAX_LEN, }; -use strict_encoding::{FieldName, SerializeError, StrictSerialize}; +use strict_encoding::{FieldName, SerializeError}; use strict_types::{typify, SemId, StrictVal, TypeSystem}; use crate::contract::{Allocation, WitnessInfo}; @@ -189,8 +188,7 @@ impl ContractIface { let t = self.types.typify(value, self.assignment_sem_id(ty))?; let value = self .types - .strict_serialize_type::<{ confinement::U16 }>(&t)? - .to_strict_serialized()?; + .strict_serialize_value::(&t)?; Ok(value.into()) }