diff --git a/Cargo.lock b/Cargo.lock index 57477c2..ba885df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,12 +133,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys", ] @@ -150,9 +150,9 @@ checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "aora" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0da0aa3a98a56f9002e0d30d642b62ba55b39821075951a764121bfe098ee98" +checksum = "fa0b56f69d2c47f8ee387f40849742d552e8b94596d997c19095809ac5c6b377" dependencies = [ "amplify", "binfile", @@ -192,9 +192,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", @@ -255,9 +255,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "cc" -version = "1.2.23" +version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" dependencies = [ "shlex", ] @@ -484,6 +484,7 @@ version = "0.12.0-rc.1" dependencies = [ "aluvm", "amplify", + "binfile", "commit_verify", "getrandom 0.2.16", "getrandom 0.3.3", @@ -608,6 +609,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "paste" version = "1.0.15" @@ -725,9 +732,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" @@ -837,8 +844,10 @@ dependencies = [ "commit_verify", "getrandom 0.2.16", "getrandom 0.3.3", + "indexmap", "rand", "serde", + "serde_yaml", "sonic-callreq", "strict_encoding", "strict_types", @@ -875,6 +884,7 @@ dependencies = [ "amplify", "aora", "binfile", + "commit_verify", "hypersonic", "serde_yaml", "strict_encoding", @@ -1053,8 +1063,7 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ultrasonic" version = "0.12.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5245198eb653a287955cd0ddaf7b7918373375592a28c189bd54a5345ce05377" +source = "git+https://github.com/AluVM/ultrasonic?branch=feat/opwitness#342c6746635af97bdd4843283faa729264a88811" dependencies = [ "amplify", "baid64", diff --git a/Cargo.toml b/Cargo.toml index ab1f48c..038bd6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,14 +25,14 @@ sonic-api = { version = "0.12.0-rc.1", path = "api" } sonic-callreq = { version = "0.12.0-rc.1", path = "callreq" } sonic-persist-fs = { version = "0.12.0-rc.1", path = "persistence/fs" } hypersonic = { version = "0.12.0-rc.1", path = "." } -aora = ">=0.6.3" +aora = ">=0.6.4" binfile = "0.2.0" baid64 = "0.4.1" indexmap = "2.9.0" chrono = "0.4.38" serde = { version = "1", features = ["derive"] } -toml = "0.8.22" serde_yaml = "0.9.34" +toml = "0.8.22" [package] name = "hypersonic" @@ -74,6 +74,7 @@ aluvm.workspace = true ultrasonic.workspace = true sonic-api.workspace = true sonic-callreq.workspace = true +binfile = { workspace = true, optional = true } indexmap.workspace = true serde = { workspace = true, optional = true } @@ -87,7 +88,7 @@ petgraph = "0.8.1" default = ["std"] all = ["stl", "vesper", "binfile", "std", "serde"] -binfile = ["sonic-api/binfile"] +binfile = ["sonic-api/binfile", "dep:binfile"] std = ["sonic-api/std", "sonic-callreq/std"] vesper = ["ultrasonic/vesper"] stl = ["commit_verify/stl", "ultrasonic/stl", "strict_types/armor"] @@ -116,3 +117,6 @@ features = ["all"] [lints.rust] unexpected_cfgs = { level = "allow", check-cfg = ['cfg(coverage_nightly)'] } + +[patch.crates-io] +ultrasonic = { git = "https://github.com/AluVM/ultrasonic", branch = "feat/opwitness" } diff --git a/api/Cargo.toml b/api/Cargo.toml index 2f8ef59..d03afcb 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -26,7 +26,9 @@ aluvm.workspace = true ultrasonic.workspace = true sonic-callreq.workspace = true binfile = { workspace = true, optional = true } +indexmap.workspace = true serde = { workspace = true, optional = true } +serde_yaml = { workspace = true, optional = true } chrono.workspace = true [features] @@ -38,6 +40,7 @@ binfile = ["dep:binfile", "std"] stl = ["commit_verify/stl", "ultrasonic/stl", "strict_types/armor"] serde = [ "dep:serde", + "dep:serde_yaml", "chrono/serde", "amplify/serde", "strict_encoding/serde", diff --git a/api/src/api.rs b/api/src/api.rs index d8ab339..dac16c4 100644 --- a/api/src/api.rs +++ b/api/src/api.rs @@ -21,7 +21,7 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. -//! API defines how a contract can be interfaced by software. +//! API defines how software can interface a contract. //! //! SONIC provides four types of actions for working with contract (ROVT): //! 1. _Read_ the state of the contract; @@ -36,20 +36,291 @@ use core::cmp::Ordering; use core::fmt::Debug; use core::hash::{Hash, Hasher}; +use core::num::ParseIntError; -use amplify::confinement::{TinyOrdMap, TinyString}; +use aluvm::{Lib, LibId}; +use amplify::confinement::{SmallOrdMap, SmallOrdSet, TinyOrdMap, TinyOrdSet, TinyString}; use amplify::num::u256; -use amplify::Bytes32; -use commit_verify::{CommitId, ReservedBytes}; +use amplify::Bytes4; +use baid64::Baid64ParseError; +use commit_verify::{CommitEncode, CommitEngine, CommitId, StrictHash}; +use indexmap::{indexset, IndexMap, IndexSet}; use sonic_callreq::{CallState, MethodName, StateName}; -use strict_types::{SemId, StrictDecode, StrictDumb, StrictEncode, StrictVal, TypeName, TypeSystem}; -use ultrasonic::{CallId, CodexId, Identity, StateData, StateValue}; +use strict_encoding::TypeName; +use strict_types::{SemId, StrictDecode, StrictDumb, StrictEncode, StrictVal, TypeSystem}; +use ultrasonic::{CallId, Codex, CodexId, StateData, StateValue}; use crate::{ - RawBuilder, RawConvertor, StateAggregator, StateArithm, StateAtom, StateBuildError, StateBuilder, StateCalc, + Aggregator, RawBuilder, RawConvertor, StateArithm, StateAtom, StateBuildError, StateBuilder, StateCalc, StateConvertError, StateConvertor, LIB_NAME_SONIC, }; +/// Errors happening during parsing of a versioned contract or codex ID. +#[derive(Debug, Display, Error, From)] +#[display(doc_comments)] +pub enum ParseVersionedError { + /// the versioned id '{0}' misses the version component, which should be provided after a `/` + /// sign. + NoVersion(String), + /// the versioned id '{0}' misses the API checksum component, which should be provided after a + /// `#` sign. + NoChecksum(String), + /// invalid versioned identifier; {0} + Id(Baid64ParseError), + #[from] + /// invalid versioned number; {0} + Version(ParseIntError), + /// invalid API checksum value; {0} + Checksum(Baid64ParseError), +} + +/// API checksum computed from a set of contract APIs present in [`Semantics`]. +/// +/// # Nota bene +/// +/// This is not a unique identifier! +/// It is created just for UI, so users can easily visually distinguish different sets of APIs from +/// each other. +/// +/// This type is not - and must not be used in any verification. +#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] +#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_SONIC)] +pub struct ApisChecksum( + #[from] + #[from([u8; 4])] + Bytes4, +); + +mod _baid4 { + use core::fmt::{self, Display, Formatter}; + use core::str::FromStr; + + use amplify::ByteArray; + use baid64::{Baid64ParseError, DisplayBaid64, FromBaid64Str}; + use commit_verify::{CommitmentId, DigestExt, Sha256}; + + use super::*; + + impl DisplayBaid64<4> for ApisChecksum { + const HRI: &'static str = "api"; + const CHUNKING: bool = false; + const PREFIX: bool = false; + const EMBED_CHECKSUM: bool = false; + const MNEMONIC: bool = false; + fn to_baid64_payload(&self) -> [u8; 4] { self.to_byte_array() } + } + impl FromBaid64Str<4> for ApisChecksum {} + impl FromStr for ApisChecksum { + type Err = Baid64ParseError; + fn from_str(s: &str) -> Result { Self::from_baid64_str(s) } + } + impl Display for ApisChecksum { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.fmt_baid64(f) } + } + + impl From for ApisChecksum { + fn from(hasher: Sha256) -> Self { + let hash = hasher.finish(); + Self::from_slice_checked(&hash[..4]) + } + } + + impl CommitmentId for ApisChecksum { + const TAG: &'static str = "urn:ubideco:sonic:apis#2025-05-25"; + } + + #[cfg(feature = "serde")] + ultrasonic::impl_serde_str_bin_wrapper!(ApisChecksum, Bytes4); +} + +/// A helper structure to store the contract semantics, made of a set of APIs, corresponding type +/// system, and libs, used by the codex. +/// +/// A contract may have multiple APIs defined; this structure summarizes information about them. +/// The structure also holds a set of AluVM libraries for the codex and type system used by the +/// APIs. +#[derive(Clone, Eq, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_SONIC)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] +pub struct Semantics { + /// Backward-compatible version number for the issuer. + /// + /// This version number is used to decide which contract APIs to apply if multiple + /// contract APIs are available. + pub version: u16, + /// The default API. + pub default: Api, + /// The custom named APIs. + /// + /// The mechanism of the custom APIs allows a contract to have multiple implementations + /// of the same interface. + /// + /// For instance, a contract may provide multiple tokens using different token names. + pub custom: SmallOrdMap, + /// A set of zk-AluVM libraries called from the contract codex. + pub codex_libs: SmallOrdSet, + /// A set of AluVM libraries called from the APIs. + pub api_libs: SmallOrdSet, + /// The type system used by the contract APIs. + pub types: TypeSystem, +} + +impl PartialEq for Semantics { + fn eq(&self, other: &Self) -> bool { + self.default.codex_id == other.default.codex_id + && self.version == other.version + && self.commit_id() == other.commit_id() + } +} +impl PartialOrd for Semantics { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +} +impl Ord for Semantics { + fn cmp(&self, other: &Self) -> Ordering { + match self.default.codex_id.cmp(&other.default.codex_id) { + Ordering::Equal => match self.version.cmp(&other.version) { + Ordering::Equal => self.commit_id().cmp(&other.commit_id()), + other => other, + }, + other => other, + } + } +} + +impl CommitEncode for Semantics { + type CommitmentId = ApisChecksum; + fn commit_encode(&self, e: &mut CommitEngine) { + e.commit_to_serialized(&self.version); + e.commit_to_hash(&self.default); + // We do not commit to the codex_libs since they are not a part of APIs + // and are commit to inside the codex. + // The fact that there are no other libs + // is verified in the Articles and Issuer constructors. + let apis = SmallOrdMap::from_iter_checked( + self.custom + .iter() + .map(|(name, api)| (name.clone(), api.api_id())), + ); + e.commit_to_linear_map(&apis); + let libs = SmallOrdSet::from_iter_checked(self.api_libs.iter().map(Lib::lib_id)); + e.commit_to_linear_set(&libs); + e.commit_to_serialized(&self.types.id()); + } +} + +impl Semantics { + pub fn apis_checksum(&self) -> ApisChecksum { self.commit_id() } + + /// Iterates over all APIs, including default and named ones. + pub fn apis(&self) -> impl Iterator { [&self.default].into_iter().chain(self.custom.values()) } + + /// Check whether this semantics object matches codex and the provided set of libraries for it. + pub fn check(&self, codex: &Codex) -> Result<(), SemanticError> { + let codex_id = codex.codex_id(); + + let mut ids = bset![]; + for api in self.apis() { + if api.codex_id != codex_id { + return Err(SemanticError::CodexMismatch); + } + let api_id = api.api_id(); + if !ids.insert(api_id) { + return Err(SemanticError::DuplicatedApi(api_id)); + } + } + + // Check codex libs for redundancies and completeness + let lib_map = self + .codex_libs + .iter() + .map(|lib| (lib.lib_id(), lib)) + .collect::>(); + + let mut lib_ids = codex + .verifiers + .values() + .map(|entry| entry.lib_id) + .collect::>(); + let mut i = 0usize; + let mut count = lib_ids.len(); + while i < count { + let id = lib_ids.get_index(i).expect("index is valid"); + let lib = lib_map.get(id).ok_or(SemanticError::MissedCodexLib(*id))?; + lib_ids.extend(lib.libs.iter().copied()); + count = lib_ids.len(); + i += 1; + } + for id in lib_map.keys() { + if !lib_ids.contains(id) { + return Err(SemanticError::ExcessiveCodexLib(*id)); + } + } + + // Check API libs for redundancies and completeness + let lib_map = self + .api_libs + .iter() + .map(|lib| (lib.lib_id(), lib)) + .collect::>(); + + let mut lib_ids = indexset![]; + for api in self.apis() { + for agg in api.aggregators.values() { + if let Aggregator::AluVM(entry) = agg { + lib_ids.insert(entry.lib_id); + } + } + for glob in api.global.values() { + if let StateConvertor::AluVM(entry) = glob.convertor { + lib_ids.insert(entry.lib_id); + } + if let StateBuilder::AluVM(entry) = glob.builder { + lib_ids.insert(entry.lib_id); + } + if let RawConvertor::AluVM(entry) = glob.raw_convertor { + lib_ids.insert(entry.lib_id); + } + if let RawBuilder::AluVM(entry) = glob.raw_builder { + lib_ids.insert(entry.lib_id); + } + } + for owned in api.owned.values() { + if let StateConvertor::AluVM(entry) = owned.convertor { + lib_ids.insert(entry.lib_id); + } + if let StateBuilder::AluVM(entry) = owned.builder { + lib_ids.insert(entry.lib_id); + } + if let StateBuilder::AluVM(entry) = owned.witness_builder { + lib_ids.insert(entry.lib_id); + } + if let StateArithm::AluVM(entry) = owned.arithmetics { + lib_ids.insert(entry.lib_id); + } + } + } + let mut i = 0usize; + let mut count = lib_ids.len(); + while i < count { + let id = lib_ids.get_index(i).expect("index is valid"); + let lib = lib_map.get(id).ok_or(SemanticError::MissedApiLib(*id))?; + lib_ids.extend(lib.libs.iter().copied()); + count = lib_ids.len(); + i += 1; + } + for id in lib_map.keys() { + if !lib_ids.contains(id) { + return Err(SemanticError::ExcessiveApiLib(*id)); + } + } + + Ok(()) + } +} + /// API is an interface implementation. /// /// API should work without requiring runtime to have corresponding interfaces; it should provide @@ -58,44 +329,37 @@ use crate::{ /// /// API does not commit to an interface, since it can match multiple interfaces in the interface /// hierarchy. -#[derive(Clone, Getters, Debug)] +#[derive(Getters, Clone, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_SONIC)] #[derive(CommitEncode)] -#[commit_encode(strategy = strict, id = ApiId)] +#[commit_encode(strategy = strict, id = StrictHash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase", bound = ""))] pub struct Api { - /// Version of the API structure. - #[getter(as_copy)] - pub version: ReservedBytes<1>, - /// Commitment to the codex under which the API is valid. #[getter(as_copy)] pub codex_id: CodexId, - /// Developer identity string. - pub developer: Identity, - - /// Interface standard to which the API conforms. - pub conforms: Option, + /// Interface standards to which the API conforms. + pub conforms: TinyOrdSet, - /// Name for the default API call and destructible state name. + /// Name for the default API call and owned state name. pub default_call: Option, - /// State API defines how a structured contract state is constructed out of (and converted into) - /// UltraSONIC immutable memory cells. - pub immutable: TinyOrdMap, + /// State API defines how a structured global contract state is constructed out of (and + /// converted into) UltraSONIC immutable memory cells. + pub global: TinyOrdMap, - /// State API defines how a structured contract state is constructed out of (and converted into) - /// UltraSONIC destructible memory cells. - pub destructible: TinyOrdMap, + /// State API defines how a structured owned contract state is constructed out of (and converted + /// into) UltraSONIC destructible memory cells. + pub owned: TinyOrdMap, /// Readers have access to the converted global `state` and can construct a derived state out of /// it. /// /// The typical examples when readers are used are to sum individual asset issues and compute /// the number of totally issued assets. - pub aggregators: TinyOrdMap, + pub aggregators: TinyOrdMap, /// Links between named transaction methods defined in the interface - and corresponding /// verifier call ids defined by the contract. @@ -106,10 +370,6 @@ pub struct Api { /// Maps error type reported by a contract verifier via `EA` value to an error description taken /// from the interfaces. pub errors: TinyOrdMap, - - /// Reserved for future use. - #[getter(skip)] - pub reserved: ReservedBytes<8>, } impl PartialEq for Api { @@ -127,13 +387,13 @@ impl Hash for Api { } impl Api { - pub fn api_id(&self) -> ApiId { self.commit_id() } + pub fn api_id(&self) -> StrictHash { self.commit_id() } pub fn verifier(&self, method: impl Into) -> Option { self.verifiers.get(&method.into()).copied() } - pub fn convert_immutable( + pub fn convert_global( &self, data: &StateData, sys: &TypeSystem, @@ -142,7 +402,7 @@ impl Api { // of `StateValue`. Thus, we are trying all available convertors until they succeed, since the // convertors check the state type. Then, we use the state name associated with the succeeding // convertor. - for (name, api) in &self.immutable { + for (name, api) in &self.global { if let Some(verified) = api.convertor.convert(api.sem_id, data.value, sys)? { let unverified = if let Some(raw) = data.raw.as_ref() { Some(api.raw_convertor.convert(raw, sys)?) } else { None }; @@ -153,7 +413,7 @@ impl Api { Ok(None) } - pub fn convert_destructible( + pub fn convert_owned( &self, value: StateValue, sys: &TypeSystem, @@ -162,7 +422,7 @@ impl Api { // of `StateValue`. Thus, we are trying all available convertors until they succeed, since the // convertors check the state type. Then, we use the state name associated with the succeeding // convertor. - for (name, api) in &self.destructible { + for (name, api) in &self.owned { if let Some(atom) = api.convertor.convert(api.sem_id, value, sys)? { return Ok(Some((name.clone(), atom))); } @@ -181,7 +441,7 @@ impl Api { ) -> Result { let name = name.into(); let api = self - .immutable + .global .get(&name) .ok_or(StateBuildError::UnknownStateName(name))?; let value = api.builder.build(api.sem_id, data, sys)?; @@ -198,7 +458,7 @@ impl Api { ) -> Result { let name = name.into(); let api = self - .destructible + .owned .get(&name) .ok_or(StateBuildError::UnknownStateName(name))?; @@ -214,7 +474,7 @@ impl Api { ) -> Result { let name = name.into(); let api = self - .destructible + .owned .get(&name) .ok_or(StateBuildError::UnknownStateName(name))?; @@ -223,62 +483,13 @@ impl Api { pub fn calculate(&self, name: impl Into) -> Result { let name = name.into(); - let api = self.destructible.get(&name).ok_or(StateUnknown(name))?; + let api = self.owned.get(&name).ok_or(StateUnknown(name))?; Ok(api.arithmetics.calculator()) } } -#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] -#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_SONIC)] -pub struct ApiId( - #[from] - #[from([u8; 32])] - Bytes32, -); - -mod _baid4 { - use core::fmt::{self, Display, Formatter}; - use core::str::FromStr; - - use amplify::ByteArray; - use baid64::{Baid64ParseError, DisplayBaid64, FromBaid64Str}; - use commit_verify::{CommitmentId, DigestExt, Sha256}; - - use super::*; - - impl DisplayBaid64 for ApiId { - const HRI: &'static str = "api"; - const CHUNKING: bool = true; - const PREFIX: bool = false; - const EMBED_CHECKSUM: bool = false; - const MNEMONIC: bool = true; - fn to_baid64_payload(&self) -> [u8; 32] { self.to_byte_array() } - } - impl FromBaid64Str for ApiId {} - impl FromStr for ApiId { - type Err = Baid64ParseError; - fn from_str(s: &str) -> Result { Self::from_baid64_str(s) } - } - impl Display for ApiId { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.fmt_baid64(f) } - } - - impl From for ApiId { - fn from(hasher: Sha256) -> Self { hasher.finish().into() } - } - - impl CommitmentId for ApiId { - const TAG: &'static str = "urn:ubideco:sonic:api#2024-11-20"; - } - - #[cfg(feature = "serde")] - ultrasonic::impl_serde_str_bin_wrapper!(ApiId, Bytes32); -} - -/// API for immutable (append-only) state. +/// API for global (immutable, or append-only) state. /// /// API covers two main functions: taking structured data from the user input and _building_ a valid /// state included in a new contract operation - and taking contract state and _converting_ it @@ -288,7 +499,7 @@ mod _baid4 { #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_SONIC)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] -pub struct ImmutableApi { +pub struct GlobalApi { /// Semantic type id for verifiable part of the state. pub sem_id: SemId, @@ -312,7 +523,7 @@ pub struct ImmutableApi { pub raw_builder: RawBuilder, } -/// API for destructible (read-once) state. +/// API for owned (destrictible, or read-once) state. /// /// API covers two main functions: taking structured data from the user input and _building_ a valid /// state included in a new contract operation - and taking contract state and _converting_ it @@ -322,7 +533,7 @@ pub struct ImmutableApi { #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_SONIC)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] -pub struct DestructibleApi { +pub struct OwnedApi { /// Semantic type id for the structured converted state data. pub sem_id: SemId, @@ -350,3 +561,33 @@ pub struct DestructibleApi { #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] #[display("unknown state name '{0}'")] pub struct StateUnknown(pub StateName); + +/// Errors happening if it is attempted to construct an invalid semantic object [`Semantics`] or +/// upgrade it inside a contract issuer or articles. +#[derive(Clone, Eq, PartialEq, Debug, Display, Error)] +#[display(doc_comments)] +pub enum SemanticError { + /// contract id for the merged contract articles doesn't match. + ContractMismatch, + + /// codex id for the merged articles doesn't match. + CodexMismatch, + + /// articles contain duplicated API {0} under a different name. + DuplicatedApi(StrictHash), + + /// library {0} is used by the contract codex verifiers but absent from the articles. + MissedCodexLib(LibId), + + /// library {0} is present in the contract articles but not used in the codex verifiers. + ExcessiveCodexLib(LibId), + + /// library {0} is used by the contract APIs but absent from the articles. + MissedApiLib(LibId), + + /// library {0} is present in the contract articles but not used in the APIs. + ExcessiveApiLib(LibId), + + /// invalid signature over the contract articles. + InvalidSignature, +} diff --git a/api/src/articles.rs b/api/src/articles.rs index de6629b..2ac4854 100644 --- a/api/src/articles.rs +++ b/api/src/articles.rs @@ -21,139 +21,191 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. -use core::error::Error; +#![allow(unused_braces)] + +use core::fmt; +use core::fmt::{Display, Formatter}; +use core::str::FromStr; use aluvm::{Lib, LibId}; -use amplify::confinement::{NonEmptyBlob, SmallOrdMap, SmallOrdSet}; -use amplify::Bytes32; -use commit_verify::{CommitId, CommitmentId, DigestExt, Sha256}; +use amplify::confinement::NonEmptyBlob; +use amplify::Wrapper; +use baid64::DisplayBaid64; +use commit_verify::{CommitEncode, CommitId, StrictHash}; use sonic_callreq::MethodName; use strict_encoding::TypeName; use strict_types::TypeSystem; -use ultrasonic::{CallId, Codex, CodexId, ContractId, Genesis, Identity, Issue, LibRepo, Opid}; - -use crate::{Api, ApiId, LIB_NAME_SONIC}; +use ultrasonic::{ + CallId, Codex, CodexId, ContractId, ContractMeta, ContractName, Genesis, Identity, Issue, LibRepo, Opid, +}; -pub const ARTICLES_MAGIC_NUMBER: [u8; 8] = *b"ARTICLES"; -pub const ARTICLES_VERSION: [u8; 2] = [0x00, 0x01]; +use crate::{Api, ApisChecksum, ParseVersionedError, SemanticError, Semantics, LIB_NAME_SONIC}; -#[derive(Clone, Eq, PartialEq, Debug)] +/// Articles id is a versioned variant for the contract id, which includes information about a +/// specific API version. +/// +/// Contracts may have multiple API implementations, which may be versioned. +/// Articles include a specific version of the contract APIs. +/// This structure provides the necessary information for the user about a specific API version +/// known and used by a system, so a user may avoid confusion when an API change due to upgrade +/// happens. +/// +/// # See also +/// +/// - [`ContractId`] +/// - [`crate::IssuerId`] +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_SONIC)] #[derive(CommitEncode)] -#[commit_encode(strategy = strict, id = ArticlesId)] -pub struct ArticlesCommitment { +#[commit_encode(strategy = strict, id = StrictHash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] +pub struct ArticlesId { + /// An identifier of the contract. pub contract_id: ContractId, - pub default_api_id: ApiId, - pub custom_api_ids: SmallOrdMap, + /// Version number of the API. + pub version: u16, + /// A checksum for the APIs from the Semantics structure. + pub checksum: ApisChecksum, } -/// A helper structure to store all API-related data. -/// -/// A contract may have multiple APIs defined. All of them a summarized in this structure. -#[derive(Clone, Eq, PartialEq, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_SONIC)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] -pub struct ApiDescriptor { - pub default: Api, - pub custom: SmallOrdMap, - pub libs: SmallOrdSet, - pub types: TypeSystem, - /// Signature from the contract issuer (`issue.meta.issuer`) over the articles' id. - pub sig: Option, +impl Display for ArticlesId { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}/{}#", self.contract_id, self.version)?; + self.checksum.fmt_baid64(f) + } } -impl ApiDescriptor { - pub fn all(&self) -> impl Iterator { [&self.default].into_iter().chain(self.custom.values()) } +impl FromStr for ArticlesId { + type Err = ParseVersionedError; + fn from_str(s: &str) -> Result { + let (id, remnant) = s + .split_once('/') + .ok_or_else(|| ParseVersionedError::NoVersion(s.to_string()))?; + let (version, api_id) = remnant + .split_once('#') + .ok_or_else(|| ParseVersionedError::NoChecksum(s.to_string()))?; + Ok(Self { + contract_id: id.parse().map_err(ParseVersionedError::Id)?, + version: version.parse().map_err(ParseVersionedError::Version)?, + checksum: api_id.parse().map_err(ParseVersionedError::Checksum)?, + }) + } } /// Articles contain the contract and all related codex and API information for interacting with it. /// /// # Invariance /// -/// The structure provides the following invariance garantees: +/// The structure provides the following invariance guarantees: /// - all the API codex matches the codex under which the contract was issued; /// - all the API ids are unique; -/// - the only type of API adapter VM which can be used is [`crate::embedded::EmbeddedProc`] (see -/// [`crate::Api`] for more details). +/// - all custom APIs have unique names; +/// - the signature, if present, is a valid sig over the [`ArticlesId`]. #[derive(Clone, Eq, PartialEq, Debug)] #[derive(StrictType, StrictDumb, StrictEncode)] +// We must not derive or implement StrictDecode for Issuer, since we cannot validate signature +// inside it #[strict_type(lib = LIB_NAME_SONIC)] pub struct Articles { - apis: ApiDescriptor, + /// We can't use [`Issuer`] here since we will duplicate the codex between it and the [`Issue`]. + /// Thus, a dedicated substructure [`Semantics`] is introduced, which keeps a shared part of + /// both [`Issuer`] and [`Articles`]. + semantics: Semantics, + /// Signature from the contract issuer (`issue.meta.issuer`) over the articles' id. + /// + /// NB: it must precede the issue, which contains genesis! + /// Since genesis is read with a stream-supporting procedure later. + sig: Option, + /// The contract issue. issue: Issue, } impl Articles { - fn articles_id(&self) -> ArticlesId { - let custom_api_ids = SmallOrdMap::from_iter_checked( - self.apis - .custom - .iter() - .map(|(name, api)| (name.clone(), api.api_id())), - ); - ArticlesCommitment { - contract_id: self.contract_id(), - default_api_id: self.apis.default.api_id(), - custom_api_ids, + /// Construct articles from a signed contract semantic and the contract issue under that + /// semantics. + pub fn with( + semantics: Semantics, + issue: Issue, + sig: Option, + sig_validator: impl FnOnce(StrictHash, &Identity, &SigBlob) -> Result<(), E>, + ) -> Result { + semantics.check(&issue.codex)?; + let mut me = Self { semantics, issue, sig: None }; + let id = me.articles_id().commit_id(); + if let Some(sig) = &sig { + sig_validator(id, &me.issue.meta.issuer, sig).map_err(|_| SemanticError::InvalidSignature)?; } - .commit_id() + me.sig = sig; + Ok(me) } + /// Compute an article id, which includes information about the contract id, API version and + /// checksum. + pub fn articles_id(&self) -> ArticlesId { + ArticlesId { + contract_id: self.issue.contract_id(), + version: self.semantics.version, + checksum: self.semantics.apis_checksum(), + } + } + /// Compute a contract id. pub fn contract_id(&self) -> ContractId { self.issue.contract_id() } + /// Compute a codex id. pub fn codex_id(&self) -> CodexId { self.issue.codex_id() } + /// Compute a genesis opid. pub fn genesis_opid(&self) -> Opid { self.issue.genesis_opid() } - pub fn apis(&self) -> &ApiDescriptor { &self.apis } - pub fn default_api(&self) -> &Api { &self.apis.default } - pub fn custom_apis(&self) -> impl Iterator { self.apis.custom.iter() } - pub fn types(&self) -> &TypeSystem { &self.apis.types } + /// Get a reference to the contract semantic. + pub fn semantics(&self) -> &Semantics { &self.semantics } + /// Get a reference to the default API. + pub fn default_api(&self) -> &Api { &self.semantics.default } + /// Get an iterator over the custom APIs. + pub fn custom_apis(&self) -> impl Iterator { self.semantics.custom.iter() } + /// Get a reference to the type system. + pub fn types(&self) -> &TypeSystem { &self.semantics.types } + /// Iterates over all APIs, including the default and the named ones. + pub fn apis(&self) -> impl Iterator { self.semantics.apis() } + /// Iterates over all codex libraries. + pub fn codex_libs(&self) -> impl Iterator { self.semantics.codex_libs.iter() } + /// Get a reference to the contract issue information. pub fn issue(&self) -> &Issue { &self.issue } + /// Get a reference to the contract codex. pub fn codex(&self) -> &Codex { &self.issue.codex } + /// Get a reference to the contract genesis. pub fn genesis(&self) -> &Genesis { &self.issue.genesis } + /// Get a reference to the contract meta-information. + pub fn contract_meta(&self) -> &ContractMeta { &self.issue.meta } + /// Get a reference to the contract name. + pub fn contract_name(&self) -> &ContractName { &self.issue.meta.name } - pub fn with(apis: ApiDescriptor, issue: Issue) -> Result { - let mut ids = bset![]; - for api in apis.all() { - if api.codex_id != issue.codex_id() { - return Err(ArticlesError::CodexMismatch); - } - let api_id = api.api_id(); - if !ids.insert(api_id) { - return Err(ArticlesError::DuplicatedApi(api_id)); - } - } - - Ok(Self { apis, issue }) - } + /// Get a reference to a signature over the contract semantics. + pub fn sig(&self) -> &Option { &self.sig } + /// Detect whether the articles are signed. + pub fn is_signed(&self) -> bool { self.sig.is_some() } - pub fn merge(&mut self, other: Self, sig_validator: impl SigValidator) -> Result { + /// Upgrades contract APIs if a newer version is available. + /// + /// # Returns + /// + /// Whether the upgrade has happened, i.e. `other` represents a valid later version of the APIs. + pub fn upgrade_apis(&mut self, other: Self) -> Result { if self.contract_id() != other.contract_id() { - return Err(ArticlesError::ContractMismatch); - } - - let ts1 = self - .apis - .sig - .as_ref() - .and_then(|sig| { - sig_validator - .validate_sig(self.articles_id().to_byte_array(), &self.issue.meta.issuer, sig) - .ok() - }) - .unwrap_or_default(); - let Some(sig) = &other.apis.sig else { return Ok(false) }; - let ts2 = sig_validator - .validate_sig(other.articles_id().to_byte_array(), &other.issue.meta.issuer, sig) - .map_err(|_| ArticlesError::InvalidSignature)?; - - if ts2 > ts1 { - self.apis = other.apis; + return Err(SemanticError::ContractMismatch); } - Ok(true) + Ok(match (&self.sig, &other.sig) { + (None, None) | (Some(_), Some(_)) if other.semantics.version > self.semantics.version => { + self.semantics = other.semantics; + true + } + (None, Some(_)) => { + self.semantics = other.semantics; + true + } + _ => false, // No upgrade + }) } /// Get a [`CallId`] for a method from the default API. @@ -164,7 +216,7 @@ impl Articles { pub fn call_id(&self, method: impl Into) -> CallId { let method = method.into(); let name = method.to_string(); - self.apis + self.semantics .default .verifier(method) .unwrap_or_else(|| panic!("requesting a method `{name}` absent in the contract API")) @@ -172,61 +224,39 @@ impl Articles { } impl LibRepo for Articles { - fn get_lib(&self, lib_id: LibId) -> Option<&Lib> { self.apis.libs.iter().find(|lib| lib.lib_id() == lib_id) } -} - -#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] -#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_SONIC)] -pub struct ArticlesId( - #[from] - #[from([u8; 32])] - Bytes32, -); - -impl From for ArticlesId { - fn from(hasher: Sha256) -> Self { hasher.finish().into() } -} - -impl CommitmentId for ArticlesId { - const TAG: &'static str = "urn:ubideco:sonic:articles#2025-05-18"; -} - -pub trait SigValidator { - /// Validate the signature using the provided identity information. - /// - /// # Returns - /// - /// If successful, returns the timestamp of ths signature. - fn validate_sig(&self, message: impl Into<[u8; 32]>, identity: &Identity, sig: &SigBlob) - -> Result; + fn get_lib(&self, lib_id: LibId) -> Option<&Lib> { + self.semantics + .codex_libs + .iter() + .find(|lib| lib.lib_id() == lib_id) + } } +/// A signature blob. +/// +/// Helps to abstract from a specific signing algorithm. #[derive(Wrapper, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From, Display)] #[wrapper(Deref, AsSlice, BorrowSlice, Hex)] #[display(LowerHex)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_SONIC)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_SONIC, dumb = { Self(NonEmptyBlob::with(0)) })] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))] pub struct SigBlob(NonEmptyBlob<4096>); -impl Default for SigBlob { - fn default() -> Self { SigBlob(NonEmptyBlob::with(0)) } -} - -#[derive(Clone, Eq, PartialEq, Debug, Display, Error)] -#[display(doc_comments)] -pub enum ArticlesError { - /// contract id for the merged contract articles doesn't match. - ContractMismatch, - - /// codex id for the merged articles doesn't match. - CodexMismatch, - - /// articles contain duplicated API {0} under a different name. - DuplicatedApi(ApiId), +impl SigBlob { + /// Constrict sig blob from byte slice. + /// + /// # Panics + /// + /// If the slice length is zero or larger than 4096. + pub fn from_slice_checked(data: impl AsRef<[u8]>) -> SigBlob { + Self(NonEmptyBlob::from_checked(data.as_ref().to_vec())) + } - /// invalid signature over the contract articles. - InvalidSignature, + /// Constrict sig blob from byte vector. + /// + /// # Panics + /// + /// If the slice length is zero or larger than 4096. + pub fn from_vec_checked(data: Vec) -> SigBlob { Self(NonEmptyBlob::from_checked(data)) } } diff --git a/api/src/builders.rs b/api/src/builders.rs index 4563670..3fa9a5e 100644 --- a/api/src/builders.rs +++ b/api/src/builders.rs @@ -21,20 +21,20 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. +use std::convert::Infallible; use std::ops::{Deref, DerefMut}; -use aluvm::LibSite; use amplify::confinement::SmallVec; use amplify::num::u256; use chrono::{DateTime, Utc}; use strict_encoding::TypeName; use strict_types::{StrictVal, TypeSystem}; use ultrasonic::{ - fe256, AuthToken, CallId, CellAddr, CodexId, Consensus, ContractId, ContractMeta, ContractName, Genesis, Identity, - Input, Issue, Operation, StateCell, StateData, StateValue, + fe256, AuthToken, CallId, CellAddr, CellLock, CodexId, Consensus, ContractId, ContractMeta, ContractName, Genesis, + Identity, Input, Issue, Operation, StateCell, StateData, StateValue, }; -use crate::{Api, ApiDescriptor, Articles, DataCell, Issuer, MethodName, StateAtom, StateName}; +use crate::{Api, Articles, DataCell, Issuer, IssuerId, MethodName, StateAtom, StateName}; #[derive(Clone, PartialEq, Eq, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -78,9 +78,64 @@ impl CoreParams { } } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase", untagged))] +pub enum VersionRange { + Range { min: u16, max: u16 }, + After { min: u16 }, + Before { max: u16 }, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, From)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase", untagged))] +pub enum IssuerSpec { + #[from] + Exact(IssuerId), + + #[from] + Latest(CodexId), + + #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] + ExactVer { codex_id: CodexId, version: u16 }, + + #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] + VersionRange { codex_id: CodexId, version: VersionRange }, +} + +impl IssuerSpec { + pub fn check(&self, issuer_id: IssuerId) -> bool { + match self { + IssuerSpec::Exact(id) => *id == issuer_id, + IssuerSpec::Latest(codex_id) => *codex_id == issuer_id.codex_id, + IssuerSpec::ExactVer { codex_id, version } => { + *codex_id == issuer_id.codex_id && *version == issuer_id.version + } + IssuerSpec::VersionRange { codex_id, version: VersionRange::After { min } } => { + *codex_id == issuer_id.codex_id && issuer_id.version >= *min + } + IssuerSpec::VersionRange { codex_id, version: VersionRange::Before { max } } => { + *codex_id == issuer_id.codex_id && issuer_id.version < *max + } + IssuerSpec::VersionRange { codex_id, version: VersionRange::Range { min, max } } => { + *codex_id == issuer_id.codex_id && (*min..*max).contains(&issuer_id.version) + } + } + } + + pub fn codex_id(&self) -> CodexId { + match self { + IssuerSpec::Exact(id) => id.codex_id, + IssuerSpec::Latest(codex_id) => *codex_id, + IssuerSpec::ExactVer { codex_id, .. } => *codex_id, + IssuerSpec::VersionRange { codex_id, .. } => *codex_id, + } + } +} + #[derive(Clone, PartialEq, Eq, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct IssueParams { + pub issuer: IssuerSpec, pub name: TypeName, pub consensus: Consensus, pub testnet: bool, @@ -100,8 +155,9 @@ impl DerefMut for IssueParams { } impl IssueParams { - pub fn new_testnet(name: impl Into, consensus: Consensus) -> Self { + pub fn new_testnet(codex_id: CodexId, name: impl Into, consensus: Consensus) -> Self { Self { + issuer: IssuerSpec::Latest(codex_id), name: name.into(), consensus, testnet: true, @@ -129,6 +185,10 @@ impl Issuer { } pub fn issue(self, params: IssueParams) -> Articles { + if !params.issuer.check(self.issuer_id()) { + panic!("issuer version does not match requested version"); + } + let mut builder = self.start_issue(params.core.method, params.consensus, params.testnet); for NamedState { name, state } in params.core.global { @@ -155,7 +215,7 @@ impl IssueBuilder { pub fn append(mut self, name: impl Into, data: StrictVal, raw: Option) -> Self { self.builder = self .builder - .add_immutable(name, data, raw, &self.issuer.api, &self.issuer.types); + .add_global(name, data, raw, self.issuer.default_api(), self.issuer.types()); self } @@ -164,11 +224,11 @@ impl IssueBuilder { name: impl Into, auth: AuthToken, data: StrictVal, - lock: Option, + lock: Option, ) -> Self { self.builder = self .builder - .add_destructible(name, auth, data, lock, &self.issuer.api, &self.issuer.types); + .add_owned(name, auth, data, lock, self.issuer.default_api(), self.issuer.types()); self } @@ -177,19 +237,15 @@ impl IssueBuilder { consensus: self.consensus, testnet: self.testnet, timestamp, + features: default!(), name: ContractName::Named(name.into()), issuer: Identity::default(), }; - let genesis = self.builder.issue_genesis(self.issuer.codex.codex_id()); - let issue = Issue { version: default!(), meta, codex: self.issuer.codex, genesis }; - let apis = ApiDescriptor { - default: self.issuer.api, - custom: none!(), - libs: self.issuer.libs, - types: self.issuer.types, - sig: None, - }; - Articles::with(apis, issue).expect("broken issue builder") + let genesis = self.builder.issue_genesis(self.issuer.codex_id()); + let (codex, semantics) = self.issuer.dismember(); + let issue = Issue { version: default!(), meta, codex, genesis }; + Articles::with(semantics, issue, None, |_, _, _| -> Result<_, Infallible> { unreachable!() }) + .expect("broken issue builder") } } @@ -203,7 +259,7 @@ pub struct Builder { impl Builder { pub fn new(call_id: CallId) -> Self { Builder { call_id, destructible_out: none!(), immutable_out: none!() } } - pub fn add_immutable( + pub fn add_global( mut self, name: impl Into, data: StrictVal, @@ -211,21 +267,22 @@ impl Builder { api: &Api, sys: &TypeSystem, ) -> Self { + let name = name.into(); let data = api - .build_immutable(name, data, raw, sys) - .expect("invalid immutable state"); + .build_immutable(name.clone(), data, raw, sys) + .unwrap_or_else(|e| panic!("invalid immutable state '{name}'; {e}")); self.immutable_out .push(data) .expect("too many state elements"); self } - pub fn add_destructible( + pub fn add_owned( mut self, name: impl Into, auth: AuthToken, data: StrictVal, - lock: Option, + lock: Option, api: &Api, sys: &TypeSystem, ) -> Self { @@ -245,6 +302,7 @@ impl Builder { codex_id, call_id: self.call_id, nonce: fe256::from(u256::ZERO), + blank0: zero!(), blank1: zero!(), blank2: zero!(), destructible_out: self.destructible_out, @@ -265,23 +323,23 @@ impl<'c> BuilderRef<'c> { BuilderRef { type_system: sys, api, inner: Builder::new(call_id) } } - pub fn add_immutable(mut self, name: impl Into, data: StrictVal, raw: Option) -> Self { + pub fn add_global(mut self, name: impl Into, data: StrictVal, raw: Option) -> Self { self.inner = self .inner - .add_immutable(name, data, raw, self.api, self.type_system); + .add_global(name, data, raw, self.api, self.type_system); self } - pub fn add_destructible( + pub fn add_owned( mut self, name: impl Into, auth: AuthToken, data: StrictVal, - lock: Option, + lock: Option, ) -> Self { self.inner = self .inner - .add_destructible(name, auth, data, lock, self.api, self.type_system); + .add_owned(name, auth, data, lock, self.api, self.type_system); self } @@ -307,7 +365,7 @@ impl OpBuilder { } } - pub fn add_immutable( + pub fn add_global( mut self, name: impl Into, data: StrictVal, @@ -315,22 +373,20 @@ impl OpBuilder { api: &Api, sys: &TypeSystem, ) -> Self { - self.inner = self.inner.add_immutable(name, data, raw, api, sys); + self.inner = self.inner.add_global(name, data, raw, api, sys); self } - pub fn add_destructible( + pub fn add_owned( mut self, name: impl Into, auth: AuthToken, data: StrictVal, - lock: Option, + lock: Option, api: &Api, sys: &TypeSystem, ) -> Self { - self.inner = self - .inner - .add_destructible(name, auth, data, lock, api, sys); + self.inner = self.inner.add_owned(name, auth, data, lock, api, sys); self } @@ -373,6 +429,7 @@ impl OpBuilder { contract_id: self.contract_id, call_id: self.inner.call_id, nonce: fe256::from(u256::ZERO), + witness: none!(), destructible_in: self.destructible_in, immutable_in: self.immutable_in, destructible_out: self.inner.destructible_out, @@ -394,23 +451,23 @@ impl<'c> OpBuilderRef<'c> { Self { api, type_system: sys, inner } } - pub fn add_immutable(mut self, name: impl Into, data: StrictVal, raw: Option) -> Self { + pub fn add_global(mut self, name: impl Into, data: StrictVal, raw: Option) -> Self { self.inner = self .inner - .add_immutable(name, data, raw, self.api, self.type_system); + .add_global(name, data, raw, self.api, self.type_system); self } - pub fn add_destructible( + pub fn add_owned( mut self, name: impl Into, auth: AuthToken, data: StrictVal, - lock: Option, + lock: Option, ) -> Self { self.inner = self .inner - .add_destructible(name, auth, data, lock, self.api, self.type_system); + .add_owned(name, auth, data, lock, self.api, self.type_system); self } @@ -438,3 +495,120 @@ impl<'c> OpBuilderRef<'c> { pub fn finalize(self) -> Operation { self.inner.finalize() } } + +#[cfg(test)] +mod test { + #![cfg_attr(coverage_nightly, coverage(off))] + + use core::str::FromStr; + + use super::*; + use crate::ApisChecksum; + + #[test] + fn issuer_spec_yaml_latest() { + let val = IssuerSpec::Latest(strict_dumb!()); + let s = "AAAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA#origami-bruno-life +"; + assert_eq!(serde_yaml::to_string(&val).unwrap(), s); + assert_eq!(serde_yaml::from_str::(s).unwrap(), val); + } + + #[test] + fn issuer_spec_yaml_exact() { + let val = IssuerSpec::Exact(strict_dumb!()); + let s = "\ +codexId: AAAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA#origami-bruno-life +version: 0 +checksum: AAAAAA +"; + assert_eq!(serde_yaml::to_string(&val).unwrap(), s); + assert_eq!(serde_yaml::from_str::(s).unwrap(), val); + } + + #[test] + fn issuer_spec_yaml_ver_nosum() { + let val = IssuerSpec::ExactVer { codex_id: strict_dumb!(), version: 0 }; + let s = "\ +codexId: AAAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA#origami-bruno-life +version: 0 +"; + assert_eq!(serde_yaml::to_string(&val).unwrap(), s); + assert_eq!(serde_yaml::from_str::(s).unwrap(), val); + } + + #[test] + fn issuer_spec_yaml_min() { + let val = IssuerSpec::VersionRange { + codex_id: strict_dumb!(), + version: VersionRange::After { min: 0 }, + }; + let s = "\ +codexId: AAAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA#origami-bruno-life +version: + min: 0 +"; + assert_eq!(serde_yaml::to_string(&val).unwrap(), s); + assert_eq!(serde_yaml::from_str::(s).unwrap(), val); + } + + #[test] + fn issuer_spec_yaml_max() { + let val = IssuerSpec::VersionRange { + codex_id: strict_dumb!(), + version: VersionRange::Before { max: 1 }, + }; + let s = "\ +codexId: AAAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA#origami-bruno-life +version: + max: 1 +"; + assert_eq!(serde_yaml::to_string(&val).unwrap(), s); + assert_eq!(serde_yaml::from_str::(s).unwrap(), val); + } + + #[test] + fn issuer_spec_yaml_range() { + let val = IssuerSpec::VersionRange { + codex_id: strict_dumb!(), + version: VersionRange::Range { min: 0, max: 1 }, + }; + let s = "\ +codexId: AAAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA-AAAAAAA#origami-bruno-life +version: + min: 0 + max: 1 +"; + assert_eq!(serde_yaml::to_string(&val).unwrap(), s); + assert_eq!(serde_yaml::from_str::(s).unwrap(), val); + } + + #[test] + fn issuer_display_fromstr() { + let s = "nmThRWDr-0hOJgJt-OFVCZTA-XX8aOWj-bkqWzK7-_jAtdhQ/0#NRIsWA"; + let issuer_id = IssuerId::from_str(s).unwrap(); + assert_eq!(issuer_id.to_string(), s); + assert_eq!(issuer_id.codex_id, CodexId::from_str(s.split_once("/").unwrap().0).unwrap()); + assert_eq!(issuer_id.checksum, ApisChecksum::from_str(s.split_once("#").unwrap().1).unwrap()); + assert_eq!(issuer_id.version, 0); + } + + #[test] + fn issuer_check() { + let s = "nmThRWDr-0hOJgJt-OFVCZTA-XX8aOWj-bkqWzK7-_jAtdhQ/0#NRIsWA"; + let issuer_id = IssuerId::from_str(s).unwrap(); + assert!(IssuerSpec::Exact(issuer_id).check(issuer_id)); + + let mut changed_ver = issuer_id; + changed_ver.version += 1; + assert!(!IssuerSpec::Exact(issuer_id).check(changed_ver)); + assert!(IssuerSpec::Latest(issuer_id.codex_id).check(changed_ver)); + assert!(!IssuerSpec::ExactVer { codex_id: issuer_id.codex_id, version: issuer_id.version }.check(changed_ver)); + + let mut changed_sum = issuer_id; + changed_sum.checksum = ApisChecksum::from_str("rLAuRQ").unwrap(); + assert!(!IssuerSpec::Exact(issuer_id).check(changed_sum)); + assert!(IssuerSpec::Latest(issuer_id.codex_id).check(changed_sum)); + assert!(IssuerSpec::ExactVer { codex_id: issuer_id.codex_id, version: issuer_id.version }.check(changed_sum)); + } +} diff --git a/api/src/issuer.rs b/api/src/issuer.rs index a5c39be..7ea2bcb 100644 --- a/api/src/issuer.rs +++ b/api/src/issuer.rs @@ -21,49 +21,152 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. -use std::io; +use core::fmt; +use core::fmt::{Display, Formatter}; +use core::str::FromStr; use aluvm::{Lib, LibId}; -use amplify::confinement::SmallOrdSet; -use amplify::hex::ToHex; +use amplify::confinement::TinyString; +use baid64::DisplayBaid64; +use commit_verify::{CommitEncode, CommitId, StrictHash}; use sonic_callreq::MethodName; -use strict_encoding::{DecodeError, ReadRaw, StrictDecode, StrictEncode, StrictReader, StrictWriter, WriteRaw}; +use strict_encoding::{StrictDecode, StrictDumb, StrictEncode, TypeName}; use strict_types::TypeSystem; -use ultrasonic::{CallId, Codex, LibRepo}; +use ultrasonic::{CallId, Codex, CodexId, Identity, LibRepo}; + +use crate::{Api, ApisChecksum, ParseVersionedError, SemanticError, Semantics, SigBlob, LIB_NAME_SONIC}; + +/// Issuer id is a versioned variant for the codex id, which includes information about a +/// specific API version. +/// +/// Codexes may have multiple API implementations, which may be versioned. +/// Issuers include a specific version of the codex APIs. +/// This structure provides the necessary information for the user about a specific API version +/// known and used by a system, so a user may avoid confusion when an API change due to upgrade +/// happens. +/// +/// # See also +/// +/// - [`CodexId`] +/// - [`crate::ArticlesId`] +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_SONIC)] +#[derive(CommitEncode)] +#[commit_encode(strategy = strict, id = StrictHash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] +pub struct IssuerId { + /// An identifier of the codex. + pub codex_id: CodexId, + /// Version number of the API. + pub version: u16, + /// A checksum for the APIs from the Semantics structure. + pub checksum: ApisChecksum, +} -use crate::{Api, SigBlob, LIB_NAME_SONIC}; +impl Display for IssuerId { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{:#}/{}#", self.codex_id, self.version)?; + self.checksum.fmt_baid64(f) + } +} -pub const ISSUER_MAGIC_NUMBER: [u8; 8] = *b"COISSUER"; -pub const ISSUER_VERSION: [u8; 2] = [0x00, 0x01]; +impl FromStr for IssuerId { + type Err = ParseVersionedError; + fn from_str(s: &str) -> Result { + let (id, remnant) = s + .split_once('/') + .ok_or_else(|| ParseVersionedError::NoVersion(s.to_string()))?; + let (version, api_id) = remnant + .split_once('#') + .ok_or_else(|| ParseVersionedError::NoChecksum(s.to_string()))?; + Ok(Self { + codex_id: id.parse().map_err(ParseVersionedError::Id)?, + version: version.parse().map_err(ParseVersionedError::Version)?, + checksum: api_id.parse().map_err(ParseVersionedError::Checksum)?, + }) + } +} -/// An issuer contains information required for the creation of a contract. +/// An issuer contains information required for the creation of a contract and interaction with an +/// existing contract. +/// +/// # Invariance +/// +/// The structure provides the following invariance guarantees: +/// - all the API codex matches the codex under which the contract was issued; +/// - all the API ids are unique; +/// - all custom APIs have unique names. #[derive(Clone, Eq, PartialEq, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[derive(StrictType, StrictDumb, StrictEncode)] +// We must not derive or implement StrictDecode for Issuer, since we cannot validate signature +// inside it #[strict_type(lib = LIB_NAME_SONIC)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] pub struct Issuer { - pub codex: Codex, - pub api: Api, - pub libs: SmallOrdSet, - pub types: TypeSystem, - /// Signature of the `codex.developer` over the API Id. - pub sig: Option, -} - -impl LibRepo for Issuer { - fn get_lib(&self, lib_id: LibId) -> Option<&Lib> { self.libs.iter().find(|lib| lib.lib_id() == lib_id) } + /// Codex data. + codex: Codex, + /// A dedicated substructure [`Semantics`] keeping shared parts of both [`Issuer`] and + /// [`Articles`]. + semantics: Semantics, + /// Signature of a developer (`codex.developer`) over the [`IssuerId`] for a standalone issuer; + /// and from a contract issuer (`issue.meta.issuer`) for an issuer instance within a contract. + sig: Option, } impl Issuer { - pub fn new(codex: Codex, api: Api, libs: impl IntoIterator, types: TypeSystem) -> Self { - Issuer { - codex, - api, - libs: SmallOrdSet::from_iter_checked(libs), - types, - sig: none!(), + /// Construct issuer from a codex and its semantics. + pub fn new(codex: Codex, semantics: Semantics) -> Result { + semantics.check(&codex)?; + Ok(Self { semantics, codex, sig: None }) + } + + /// Construct issuer from a codex and signed semantics. + pub fn with( + codex: Codex, + semantics: Semantics, + sig: SigBlob, + sig_validator: impl FnOnce(StrictHash, &Identity, &SigBlob) -> Result<(), E>, + ) -> Result { + let mut me = Self::new(codex, semantics)?; + let id = me.issuer_id().commit_id(); + sig_validator(id, &me.codex.developer, &sig).map_err(|_| SemanticError::InvalidSignature)?; + me.sig = Some(sig); + Ok(me) + } + + pub fn dismember(self) -> (Codex, Semantics) { (self.codex, self.semantics) } + + /// Compute an issuer id, which includes information about the codex id, API version and + /// checksum. + pub fn issuer_id(&self) -> IssuerId { + IssuerId { + codex_id: self.codex.codex_id(), + version: self.semantics.version, + checksum: self.semantics.apis_checksum(), } } + /// Compute a codex id. + pub fn codex_id(&self) -> CodexId { self.codex.codex_id() } + /// Get a reference to the underlying codex. + pub fn codex(&self) -> &Codex { &self.codex } + /// Get the name of the underlying codex. + pub fn codex_name(&self) -> &TinyString { &self.codex.name } + + /// Get a reference to the contract semantic. + pub fn semantics(&self) -> &Semantics { &self.semantics } + /// Get a reference to the default API. + pub fn default_api(&self) -> &Api { &self.semantics.default } + /// Get an iterator over the custom APIs. + pub fn custom_apis(&self) -> impl Iterator { self.semantics.custom.iter() } + /// Get a reference to the type system. + pub fn types(&self) -> &TypeSystem { &self.semantics.types } + /// Iterates over all APIs, including the default and the named ones. + pub fn apis(&self) -> impl Iterator { self.semantics.apis() } + /// Iterates over all codex libraries. + pub fn codex_libs(&self) -> impl Iterator { self.semantics.codex_libs.iter() } + + /// Detect whether the issuer is signed. + pub fn is_signed(&self) -> bool { self.sig.is_some() } /// Get a [`CallId`] for a method from the default API. /// @@ -71,36 +174,19 @@ impl Issuer { /// /// If the method name is not known. pub fn call_id(&self, method: impl Into) -> CallId { - self.api + self.semantics + .default .verifier(method) .expect("calling to method absent in Codex API") } +} - pub fn decode(reader: &mut StrictReader) -> Result { - let magic_bytes = <[u8; 8]>::strict_decode(reader)?; - if magic_bytes != ISSUER_MAGIC_NUMBER { - return Err(DecodeError::DataIntegrityError(format!( - "wrong contract issuer magic bytes {}", - magic_bytes.to_hex() - ))); - } - let version = <[u8; 2]>::strict_decode(reader)?; - if version != ISSUER_VERSION { - return Err(DecodeError::DataIntegrityError(format!( - "unsupported contract issuer version {}", - u16::from_be_bytes(version) - ))); - } - Self::strict_decode(reader) - } - - pub fn encode(&self, mut writer: StrictWriter) -> io::Result<()> { - // This is compatible with BinFile - writer = ISSUER_MAGIC_NUMBER.strict_encode(writer)?; - // Version - writer = ISSUER_VERSION.strict_encode(writer)?; - self.strict_encode(writer)?; - Ok(()) +impl LibRepo for Issuer { + fn get_lib(&self, lib_id: LibId) -> Option<&Lib> { + self.semantics + .codex_libs + .iter() + .find(|lib| lib.lib_id() == lib_id) } } @@ -111,19 +197,42 @@ mod _fs { use amplify::confinement::U24 as U24MAX; use binfile::BinFile; - use strict_encoding::{DeserializeError, StreamReader, StreamWriter, StrictReader, StrictWriter}; + use commit_verify::{CommitId, StrictHash}; + use strict_encoding::{DecodeError, DeserializeError, StreamReader, StreamWriter, StrictDecode, StrictEncode}; + use ultrasonic::{Codex, Identity}; - use crate::Issuer; + use crate::{Issuer, Semantics, SigBlob}; - pub const ISSUER_MAGIC_NUMBER: u64 = u64::from_be_bytes(*b"COISSUER"); + /// The magic number used in storing issuer as a binary file. + pub const ISSUER_MAGIC_NUMBER: u64 = u64::from_be_bytes(*b"ISSUER "); + /// The issuer encoding version used in storing issuer as a binary file. pub const ISSUER_VERSION: u16 = 0; impl Issuer { - pub fn load(path: impl AsRef) -> Result { + pub fn load( + path: impl AsRef, + sig_validator: impl FnOnce(StrictHash, &Identity, &SigBlob) -> Result<(), E>, + ) -> Result { + // We use a manual implementation since we can't validate signature inside StrictDecode + // implementation for the Issuer let file = BinFile::::open(path)?; - let mut reader = StrictReader::with(StreamReader::new::(file)); - let me = Self::decode(&mut reader)?; - match reader.unbox().unconfine().read_exact(&mut [0u8; 1]) { + let mut reader = StreamReader::new::(file); + + let codex = Codex::strict_read(&mut reader)?; + let semantics = Semantics::strict_read(&mut reader)?; + semantics + .check(&codex) + .map_err(|e| DecodeError::DataIntegrityError(e.to_string()))?; + + let sig = Option::::strict_read(&mut reader)?; + let me = Self { codex, semantics, sig }; + + if let Some(sig) = &me.sig { + sig_validator(me.issuer_id().commit_id(), &me.codex.developer, sig) + .map_err(|_| DecodeError::DataIntegrityError(s!("invalid signature")))?; + } + + match reader.unconfine().read_exact(&mut [0u8; 1]) { Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => Ok(me), Err(e) => Err(e.into()), Ok(()) => Err(DeserializeError::DataNotEntirelyConsumed), @@ -132,8 +241,10 @@ mod _fs { pub fn save(&self, path: impl AsRef) -> io::Result<()> { let file = BinFile::::create_new(path)?; - let writer = StrictWriter::with(StreamWriter::new::(file)); - self.encode(writer) + let writer = StreamWriter::new::(file); + self.strict_write(writer) } } } +#[cfg(feature = "binfile")] +pub use _fs::*; diff --git a/api/src/lib.rs b/api/src/lib.rs index d01a5e2..7ecad1d 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -46,8 +46,6 @@ extern crate alloc; extern crate amplify; #[macro_use] extern crate strict_types; -#[macro_use] -extern crate commit_verify; #[cfg(feature = "serde")] #[macro_use] @@ -59,13 +57,12 @@ mod articles; mod builders; mod state; -pub use api::{Api, ApiId, DestructibleApi, ImmutableApi, StateUnknown}; -pub use articles::{ - ApiDescriptor, Articles, ArticlesCommitment, ArticlesError, ArticlesId, SigBlob, SigValidator, - ARTICLES_MAGIC_NUMBER, ARTICLES_VERSION, +pub use api::{Api, ApisChecksum, GlobalApi, OwnedApi, ParseVersionedError, SemanticError, Semantics, StateUnknown}; +pub use articles::{Articles, ArticlesId, SigBlob}; +pub use builders::{ + Builder, BuilderRef, CoreParams, IssueParams, IssuerSpec, NamedState, OpBuilder, OpBuilderRef, VersionRange, }; -pub use builders::{Builder, BuilderRef, CoreParams, IssueParams, NamedState, OpBuilder, OpBuilderRef}; -pub use issuer::{Issuer, ISSUER_MAGIC_NUMBER, ISSUER_VERSION}; +pub use issuer::{Issuer, IssuerId, ISSUER_MAGIC_NUMBER, ISSUER_VERSION}; pub use sonic_callreq::*; pub use state::*; pub use ultrasonic::*; diff --git a/api/src/state/adaptors.rs b/api/src/state/adaptors.rs index 68d39bd..f2f6556 100644 --- a/api/src/state/adaptors.rs +++ b/api/src/state/adaptors.rs @@ -23,17 +23,19 @@ use std::io; -use amplify::confinement::ConfinedBlob; +use aluvm::LibSite; +use amplify::confinement::{Confined, ConfinedBlob}; use amplify::num::u256; use sonic_callreq::StateName; use strict_encoding::{SerializeError, StreamReader}; -use strict_types::{decode, typify, SemId, StrictVal, TypeSystem}; +use strict_types::value::{EnumTag, StrictNum}; +use strict_types::{decode, typify, Cls, SemId, StrictVal, Ty, TypeSystem}; use ultrasonic::StateValue; -use crate::{StateTy, LIB_NAME_SONIC}; +use crate::{fe256, StateTy, LIB_NAME_SONIC}; pub(super) const USED_FIEL_BYTES: usize = u256::BYTES as usize - 2; -pub(super) const TOTAL_BYTES: usize = USED_FIEL_BYTES * 3; +pub(super) const MAX_BYTES: usize = USED_FIEL_BYTES * 3; #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] @@ -41,12 +43,25 @@ pub(super) const TOTAL_BYTES: usize = USED_FIEL_BYTES * 3; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] pub enum StateConvertor { #[strict_type(tag = 0x00)] + Unit, + + #[strict_type(tag = 0x10)] TypedEncoder(StateTy), + + #[strict_type(tag = 0x11)] + TypedFieldEncoder(StateTy), // In the future we can add more adaptors: - // - doing more compact encoding (storing type in bits, not a full field element); + // - doing more compact encoding (storing state type in bits, not using a full field element); // - using just a specific range of field element bits, not a full value - such that multiple APIs may read // different parts of the same data; - // - using a Turing complete grammar with some VM (AluVM? RISC-V? WASM?). + /// Execute a custom function. + // AluVM is reserved for the future. We need it here to avoid breaking changes. + #[strict_type(tag = 0xFF)] + AluVM( + /// The entry point to the script (virtual machine uses libraries from + /// [`crate::Semantics`]). + LibSite, + ), } impl StateConvertor { @@ -57,7 +72,11 @@ impl StateConvertor { sys: &TypeSystem, ) -> Result, StateConvertError> { match self { + Self::Unit if StateValue::None == value => Ok(Some(StrictVal::Unit)), + Self::Unit => Err(StateConvertError::UnitState), Self::TypedEncoder(ty) => typed_convert(*ty, sem_id, value, sys), + Self::TypedFieldEncoder(ty) => typed_field_convert(*ty, sem_id, value, sys), + Self::AluVM(_) => Err(StateConvertError::Unsupported), } } } @@ -68,19 +87,38 @@ impl StateConvertor { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] pub enum StateBuilder { #[strict_type(tag = 0x00)] + Unit, + + #[strict_type(tag = 0x10)] TypedEncoder(StateTy), + + #[strict_type(tag = 0x11)] + TypedFieldEncoder(StateTy), // In the future we can add more adaptors: - // - doing more compact encoding (storing type in bits, not a full field element); - // - using a Turing complete grammar with some VM (AluVM? RISC-V? WASM?). + // - doing more compact encoding (storing state type in bits, not using a full field element); + /// Execute a custom function. + // AluVM is reserved for the future. We need it here to avoid breaking changes. + #[strict_type(tag = 0xFF)] + AluVM( + /// The entry point to the script (virtual machine uses libraries from + /// [`crate::Semantics`]). + LibSite, + ), } impl StateBuilder { #[allow(clippy::result_large_err)] pub fn build(&self, sem_id: SemId, value: StrictVal, sys: &TypeSystem) -> Result { - let typed = sys.typify(value, sem_id)?; - let ser = sys.strict_serialize_value::(&typed)?; + let typed = sys.typify(value.clone(), sem_id)?; Ok(match self { - Self::TypedEncoder(ty) => typed_build(*ty, ser), + Self::Unit if typed.as_val() == &StrictVal::Unit => StateValue::None, + Self::Unit => return Err(StateBuildError::InvalidUnit), + Self::TypedEncoder(ty) => { + let ser = sys.strict_serialize_value::(&typed)?; + typed_build(*ty, ser) + } + Self::TypedFieldEncoder(ty) => typed_field_build(*ty, value)?, + Self::AluVM(_) => return Err(StateBuildError::Unsupported), }) } } @@ -98,8 +136,17 @@ pub enum StateBuildError { #[display("state data is too large to be encoded")] TooLarge, + #[display("state data ({0:?}) have an unsupported type for the encoding")] + UnsupportedValue(StrictVal), + #[from] Serialize(SerializeError), + + #[display("the provided value doesn't match the required unit type")] + InvalidUnit, + + #[display("AluVM is not yet supported for a state builder.")] + Unsupported, } #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] @@ -114,8 +161,33 @@ pub enum StateConvertError { #[display("state value is not fully consumed")] NotEntirelyConsumed, - #[display("state has not data")] + #[display("state has no data")] UnitState, + + #[display("unknown type {0}")] + TypeUnknown(SemId), + + #[display("type of class {0} is not supported by field-based convertor")] + TypeClassUnsupported(Cls), + + #[display("number of fields doesn't match the number of fields in the type")] + TypeFieldCountMismatch, + + #[display("AluVM is not yet supported for a state conversion.")] + Unsupported, +} + +// Simplify newtype-like tuples +fn reduce_tuples(mut val: StrictVal) -> StrictVal { + loop { + if let StrictVal::Tuple(ref mut vec) = val { + if vec.len() == 1 { + val = vec.remove(0); + continue; + } + } + return val; + } } fn typed_convert( @@ -130,7 +202,7 @@ fn typed_convert( return Ok(None); } - let mut buf = [0u8; TOTAL_BYTES]; + let mut buf = [0u8; MAX_BYTES]; let mut i = 1u8; while let Some(el) = value.get(i) { let from = USED_FIEL_BYTES * (i - 1) as usize; @@ -138,27 +210,80 @@ fn typed_convert( buf[from..to].copy_from_slice(&el.to_u256().to_le_bytes()[..USED_FIEL_BYTES]); i += 1; } + let used_bytes = USED_FIEL_BYTES * (i - 1) as usize; debug_assert!(i <= 4); + debug_assert!(used_bytes <= MAX_BYTES); - let mut cursor = StreamReader::cursor::(buf); - // We do not check here that we have reached the end of the buffer, since it may be filled with - // zeros up to the field element length. + let mut cursor = StreamReader::cursor::(&buf[..used_bytes]); let mut val = sys.strict_read_type(sem_id, &mut cursor)?.unbox(); - loop { - if let StrictVal::Tuple(ref mut vec) = val { - if vec.len() == 1 { - val = vec.remove(0); - continue; - } + // We check here that we have reached the end of the buffer data, + // and the rest of the elements are zeros. + let cursor = cursor.unconfine(); + let position = cursor.position() as usize; + let data = cursor.into_inner(); + for item in data.iter().take(used_bytes).skip(position) { + if *item != 0 { + return Err(StateConvertError::NotEntirelyConsumed); } - break; } + val = reduce_tuples(val); + Ok(Some(val)) } -fn typed_build(ty: StateTy, ser: ConfinedBlob<0, TOTAL_BYTES>) -> StateValue { +fn typed_field_convert( + ty: StateTy, + sem_id: SemId, + value: StateValue, + sys: &TypeSystem, +) -> Result, StateConvertError> { + let from_ty = value.get(0).ok_or(StateConvertError::UnitState)?.to_u256(); + // State type does not match + if from_ty != ty { + return Ok(None); + } + + let ty = sys + .get(sem_id) + .ok_or(StateConvertError::TypeUnknown(sem_id))?; + let fields = match ty { + Ty::Tuple(fields) => fields.iter().copied().collect::>(), + Ty::Struct(fields) => fields.iter().map(|f| f.ty).collect::>(), + _ => return Err(StateConvertError::TypeClassUnsupported(ty.cls())), + }; + + if fields.len() != value.into_iter().count() - 1 { + return Err(StateConvertError::TypeFieldCountMismatch); + } + + let mut items = vec![]; + for (el, sem_id) in value.into_iter().skip(1).zip(fields.into_iter()) { + let mut cursor = StreamReader::cursor::(el.to_u256().to_le_bytes()); + let val = sys.strict_read_type(sem_id, &mut cursor)?.unbox(); + items.push(val); + } + + let mut val = match ty { + Ty::Tuple(_) => StrictVal::Tuple(items), + Ty::Struct(fields) => StrictVal::Struct( + fields + .iter() + .zip(items) + .map(|(f, val)| (f.name.clone(), reduce_tuples(val))) + .collect(), + ), + _ => unreachable!(), + }; + + // Simplify tuples with a single element + val = reduce_tuples(val); + + Ok(Some(val)) +} + +fn typed_build(ty: StateTy, ser: ConfinedBlob<0, MAX_BYTES>) -> StateValue { let mut elems = Vec::with_capacity(4); elems.push(ty); for chunk in ser.chunks(USED_FIEL_BYTES) { @@ -169,3 +294,288 @@ fn typed_build(ty: StateTy, ser: ConfinedBlob<0, TOTAL_BYTES>) -> StateValue { StateValue::from_iter(elems) } + +#[allow(clippy::result_large_err)] +fn typed_field_build(ty: StateTy, val: StrictVal) -> Result { + let mut elems = Vec::with_capacity(4); + elems.push(ty); + + Ok(match val { + StrictVal::Unit => StateValue::Single { first: fe256::from(ty) }, + StrictVal::Number(StrictNum::Uint(i)) => StateValue::Double { first: fe256::from(ty), second: fe256::from(i) }, + StrictVal::String(s) if s.len() < MAX_BYTES => { + typed_build(ty, Confined::from_iter_checked(s.as_bytes().iter().cloned())) + } + StrictVal::Bytes(b) if b.len() < MAX_BYTES => typed_build(ty, Confined::from_checked(b.0)), + StrictVal::Struct(fields) if fields.len() <= 3 => typed_field_build_items(ty, fields.into_values())?, + StrictVal::Enum(EnumTag::Ord(tag)) => StateValue::Double { first: fe256::from(ty), second: fe256::from(tag) }, + StrictVal::List(items) | StrictVal::Set(items) | StrictVal::Tuple(items) if items.len() <= 3 => { + typed_field_build_items(ty, items)? + } + _ => return Err(StateBuildError::UnsupportedValue(val)), + }) +} + +#[allow(clippy::result_large_err)] +fn typed_field_build_items( + ty: StateTy, + vals: impl IntoIterator, +) -> Result { + let mut items = Vec::with_capacity(4); + items.push(ty); + for val in vals { + if let Some(val) = typed_field_build_item(val)? { + items.push(val); + } + } + Ok(StateValue::from_iter(items)) +} + +#[allow(clippy::result_large_err)] +fn typed_field_build_item(val: StrictVal) -> Result, StateBuildError> { + Ok(match val { + StrictVal::Unit => None, + StrictVal::Tuple(items) if items.len() == 1 => typed_field_build_item(items[0].clone())?, + StrictVal::Number(StrictNum::Uint(i)) => Some(u256::from(i)), + StrictVal::String(s) if s.len() < USED_FIEL_BYTES => { + let mut buf = [0u8; u256::BYTES as usize]; + buf[..s.len()].copy_from_slice(s.as_bytes()); + Some(u256::from_le_bytes(buf)) + } + StrictVal::Bytes(b) if b.len() < USED_FIEL_BYTES => { + let mut buf = [0u8; u256::BYTES as usize]; + buf[..b.len()].copy_from_slice(&b.0); + Some(u256::from_le_bytes(buf)) + } + StrictVal::Enum(EnumTag::Ord(tag)) => Some(u256::from(tag)), + _ => return Err(StateBuildError::UnsupportedValue(val)), + }) +} + +#[cfg(test)] +mod tests { + #![cfg_attr(coverage_nightly, coverage(off))] + + use strict_types::stl::std_stl; + use strict_types::{LibBuilder, SymbolicSys, SystemBuilder, TypeLib}; + + use super::*; + + pub const LIB_NAME_TEST: &str = "Test"; + + #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] + #[display(lowercase)] + #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] + #[strict_type(lib = LIB_NAME_TEST, tags = repr, try_from_u8, into_u8)] + #[repr(u8)] + pub enum Vote { + #[strict_type(dumb)] + Contra = 0, + Pro = 1, + } + + #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] + #[display(inner)] + #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] + #[strict_type(lib = LIB_NAME_TEST)] + pub struct VoteId(u64); + + #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)] + #[display(inner)] + #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] + #[strict_type(lib = LIB_NAME_TEST)] + pub struct PartyId(u64); + + #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Display)] + #[display("Participant #{party_id} voted {vote} in voting #{vote_id}")] + #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] + #[strict_type(lib = LIB_NAME_TEST)] + pub struct CastVote { + pub vote_id: VoteId, + pub vote: Vote, + pub party_id: PartyId, + } + + pub fn stl() -> TypeLib { + LibBuilder::with(libname!(LIB_NAME_TEST), [std_stl().to_dependency_types()]) + .transpile::() + .compile() + .expect("invalid Test type library") + } + + #[derive(Debug)] + pub struct Types(SymbolicSys); + + impl Types { + pub fn new() -> Self { + Self( + SystemBuilder::new() + .import(std_stl()) + .unwrap() + .import(stl()) + .unwrap() + .finalize() + .unwrap(), + ) + } + + pub fn type_system(&self) -> TypeSystem { + let stdtypes = std_stl().types; + let types = stl().types; + let types = stdtypes + .into_iter() + .chain(types) + .map(|(tn, ty)| ty.sem_id_named(&tn)); + self.0.as_types().extract(types).unwrap() + } + + pub fn get(&self, name: &'static str) -> SemId { + *self + .0 + .resolve(name) + .unwrap_or_else(|| panic!("type '{name}' is absent in RGB21 type library")) + } + } + + fn typed_roundtrip(name: &'static str, src: StateValue, dst: StrictVal) { + let types = Types::new(); + + let ty = types.get(name); + let val = StateConvertor::TypedEncoder(u256::ONE) + .convert(ty, src, &types.type_system()) + .unwrap() + .unwrap(); + assert_eq!(val, dst); + + let res = StateBuilder::TypedEncoder(u256::ONE) + .build(ty, dst, &types.type_system()) + .unwrap(); + assert_eq!(res, src); + } + + fn typed_field_roundtrip(name: &'static str, src1: StateValue, dst: StrictVal, src2: StrictVal) { + let types = Types::new(); + + let ty = types.get(name); + let val = StateConvertor::TypedFieldEncoder(u256::ONE) + .convert(ty, src1, &types.type_system()) + .unwrap() + .unwrap(); + assert_eq!(val, dst); + + let res = StateBuilder::TypedFieldEncoder(u256::ONE) + .build(ty, src2, &types.type_system()) + .unwrap(); + assert_eq!(res, src1); + } + + #[test] + fn typed() { + typed_roundtrip( + "Std.Bool", + StateValue::Double { first: fe256::from(1u8), second: fe256::from(1u8) }, + svenum!("true"), + ); + } + + #[test] + #[should_panic(expected = "Decode(Decode(Io(Kind(UnexpectedEof))))")] + fn typed_convert_lack() { + let types = Types::new(); + StateConvertor::TypedEncoder(u256::ONE) + .convert(types.get("Std.Bool"), StateValue::Single { first: fe256::from(1u8) }, &types.type_system()) + .unwrap(); + } + + #[test] + #[should_panic(expected = "NotEntirelyConsumed")] + fn typed_convert_excess() { + let types = Types::new(); + StateConvertor::TypedEncoder(u256::ONE) + .convert( + types.get("Std.Bool"), + StateValue::Triple { + first: fe256::from(1u8), + second: fe256::from(1u8), + third: fe256::from(1u8), + }, + &types.type_system(), + ) + .unwrap(); + } + + #[test] + fn typed_field() { + typed_field_roundtrip( + "Test.CastVote", + StateValue::Quadruple { + first: fe256::from(1u8), + second: fe256::from(3u8), + third: fe256::from(1u8), + fourth: fe256::from(5u8), + }, + ston!(voteId 3u8, vote svenum!("pro"), partyId 5u8), + ston!(voteId 3u8, vote svenum!(1), partyId 5u8), + ); + } + + #[test] + #[should_panic(expected = "TypeClassUnsupported(Enum)")] + fn typed_field_convert_enum() { + let types = Types::new(); + let val = StateConvertor::TypedFieldEncoder(u256::ONE) + .convert( + types.get("Std.Bool"), + StateValue::Double { first: fe256::from(1u8), second: fe256::from(1u8) }, + &types.type_system(), + ) + .unwrap(); + assert_eq!(val, Some(svenum!("true"))); + } + + #[test] + #[should_panic(expected = "TypeFieldCountMismatch")] + fn typed_field_convert_lack() { + let types = Types::new(); + StateConvertor::TypedFieldEncoder(u256::ONE) + .convert(types.get("Test.CastVote"), StateValue::Single { first: fe256::from(1u8) }, &types.type_system()) + .unwrap(); + } + + #[test] + #[should_panic(expected = "TypeFieldCountMismatch")] + fn typed_field_convert_excess() { + let types = Types::new(); + StateConvertor::TypedFieldEncoder(u256::ONE) + .convert( + types.get("Test.PartyId"), + StateValue::Triple { + first: fe256::from(1u8), + second: fe256::from(1u8), + third: fe256::from(1u8), + }, + &types.type_system(), + ) + .unwrap(); + } + + #[test] + #[should_panic( + expected = r#"Decode(Decode(EnumTagNotKnown("semid:kr1DHi~j-YSw4n54-o9KnZ9Q-Dlo0pWP-_V9U5oh-Wlzfemk#break-secret-delphi", 5)))"# + )] + fn typed_field_convert_invalid() { + let types = Types::new(); + StateConvertor::TypedFieldEncoder(u256::ONE) + .convert( + types.get("Test.CastVote"), + StateValue::Quadruple { + first: fe256::from(1u8), + second: fe256::from(1u8), + third: fe256::from(5u8), + fourth: fe256::from(1u8), + }, + &types.type_system(), + ) + .unwrap(); + } +} diff --git a/api/src/state/aggregators.rs b/api/src/state/aggregators.rs index 96c3150..31d2179 100644 --- a/api/src/state/aggregators.rs +++ b/api/src/state/aggregators.rs @@ -21,194 +21,1039 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. +use alloc::collections::BTreeMap; + +use aluvm::{Lib, LibId, LibSite}; +use amplify::confinement::TinyBlob; +use indexmap::IndexMap; use sonic_callreq::StateName; -use strict_types::value::StrictNum; -use strict_types::StrictVal; +use strict_encoding::StrictDumb; +use strict_types::value::{EnumTag, StrictNum}; +use strict_types::{SemId, StrictVal, TypeSystem}; +use ultrasonic::CellAddr; use crate::{StateAtom, LIB_NAME_SONIC}; +/// Structure which allows applying aggregators either to a global or a different aggregated +/// state. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_SONIC, tags = custom, dumb = Self::Count(strict_dumb!()))] +#[strict_type(lib = LIB_NAME_SONIC, tags = custom, dumb = Self::Aggregated(strict_dumb!()))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] -pub enum StateAggregator { - // #[strict_type(tag = 0)] - // Const(StrictVal), +pub enum StateSelector { + #[strict_type(tag = 0)] + Global( + StateName, + /** Flag indicating that if multiple state elements are known, only the first one should + * be used. */ + bool, + ), #[strict_type(tag = 1)] - Count(StateName), + Aggregated(StateName), +} - /// Sum over verifiable field-element-based part of state. +/// A set of pre-defined top-level state aggregators (see [`crate::Api::aggregators`]. +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_SONIC, tags = custom, dumb = Self::Some(strict_dumb!()))] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] +pub enum Aggregator { + /// Produces constant value of `Option::None` type. + #[strict_type(tag = 0)] + None, + + /// Wrap into an optional value. /// - /// If any of the verifiable state is absent or not in a form of unsigned integer, it is treated - /// as zero. + /// If the underlying aggregated state fails, sets the aggregated state to `None`. + #[strict_type(tag = 1)] + #[cfg_attr(feature = "serde", serde(with = "serde_yaml::with::singleton_map"))] + Some(SubAggregator), + + /// Takes the underlying aggregated state and applies nothing on top. + /// + /// If the underlying aggregator fails, the aggregated state is not produced. #[strict_type(tag = 2)] - SumV(StateName), + // https://github.com/dtolnay/serde-yaml/issues/363 + // We should repeat this if we encounter any other nested enums. + #[cfg_attr(feature = "serde", serde(with = "serde_yaml::with::singleton_map"))] + Take(SubAggregator), + + /// If the underlying aggregated state fails, returns the other state. + /// + /// If the other state fails, the aggregated state is not produced. + #[strict_type(tag = 3)] + Or( + #[cfg_attr(feature = "serde", serde(with = "serde_yaml::with::singleton_map"))] SubAggregator, + #[cfg_attr(feature = "serde", serde(with = "serde_yaml::with::singleton_map"))] SubAggregator, + ), + + /// Execute a custom function on the state. + #[strict_type(tag = 0xFF)] + AluVM( + /// The entry point to the script (virtual machine uses libraries from + /// [`crate::Semantics`]). + LibSite, + ), +} + +impl Aggregator { + /// Returns names of the other computed state which this aggregator depends on + /// and which needs to be computed before running this aggregator. + pub fn depends_on(&self) -> impl Iterator { + match self { + Self::Some(sub) | Self::Take(sub) => sub.depends_on(), + Self::Or(some, other) => { + let mut deps = some.depends_on(); + deps.append(&mut other.depends_on()); + deps + } + Self::None | Self::AluVM(_) => vec![], + } + .into_iter() + } + + /// Compute state via applying some aggregator function. + /// + /// # Returns + /// + /// Aggregated state value. If the computing fails due to any exception, `None`. + pub fn aggregate<'libs>( + &self, + global: &BTreeMap>, + aggregated: &BTreeMap, + libs: impl IntoIterator, + types: &TypeSystem, + ) -> Option { + match self { + Self::None => Some(StrictVal::none()), + + Self::Take(sub) => sub.aggregate(global, aggregated, types), + + Self::Some(sub) => Some(match sub.aggregate(global, aggregated, types) { + Some(val) => StrictVal::some(val), + None => StrictVal::none(), + }), - /* - /// Count values which verifiable field-element part binary representation is prefixed with a - /// given byte string. + Self::Or(some, other) => some + .aggregate(global, aggregated, types) + .or_else(|| other.aggregate(global, aggregated, types)), + + Self::AluVM(entry) => { + let libs = libs + .into_iter() + .map(|lib| (lib.lib_id(), lib)) + .collect::>(); + let mut vm = aluvm::Vm::>::new(); + // For now, we ignore all computations and return `None` anyway. + // This leaves a way to add proper VM computing in the future + // in a backward-compatible way. + let _status = vm.exec(*entry, &(), |id| libs.get(&id)); + None + } + } + } +} + +/// A set of pre-defined state sub-aggregators (see [`crate::Api::aggregators`]. +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_SONIC, tags = custom, dumb = Self::Neg(strict_dumb!()))] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] +pub enum SubAggregator { + /// The aggregated state is generated with a predefined constant strict-encoded value. + /// + /// To produce a state with a unit value, use `Self::Const(SemId::unit(), none!())`. + #[strict_type(tag = 0)] + Const(SemId, TinyBlob), + + /// Takes the only element of the global state. + /// + /// Fails if the state is not defined or has more than one defined element. + #[strict_type(tag = 1)] + TheOnly(StateName), + + /// Takes some other aggregated and copies it. + /// + /// Fails if the other aggregated state is not defined. + #[strict_type(tag = 2)] + Copy(StateName), + + /// Unwraps an optional value. + /// + /// Fails if the value is `None`, is not defined, multiple, or not an optional. + #[strict_type(tag = 3)] + Unwrap(StateName), + + /// Takes the first element of the global state. + /// + /// Fails if the global state is not defined, i.e., has zero elements. + /// + /// # Nota bene + /// + /// The global state does not have only a partial ordering (it is a lattice). + /// + /// It is only in the case when one operation depends on outputs of another + /// (via global or owned state) there is a guarantee that the global state + /// defined by the second operation will always follow the first one. + /// + /// It is the responsibility of the codex developer + /// to ensure non-ambiguity when this aggregator is used. + #[strict_type(tag = 4)] + First(StateName), + + /// Takes the nth element of the global state. + /// + /// Fails if the global state is not defined, i.e., has zero elements, + /// or if the nth-element is empty. + /// + /// # Nota bene + /// + /// The global state does not have only a partial ordering (it is a lattice). + /// + /// It is only in the case when one operation depends on outputs of another + /// (via global or owned state) there is a guarantee that the global state + /// defined by the second operation will always follow the first one. + /// + /// It is the responsibility of the codex developer + /// to ensure non-ambiguity when this aggregator is used. + #[strict_type(tag = 5)] + Nth(StateName, u16), + + /// Takes the last element of the global state. + /// + /// Fails if the global state is not defined, i.e., has zero elements. + /// + /// # Nota bene + /// + /// The global state does not have only a partial ordering (it is a lattice). + /// + /// It is only in the case when one operation depends on outputs of another + /// (via global or owned state) there is a guarantee that the global state + /// defined by the second operation will always follow the first one. + /// + /// It is the responsibility of the codex developer + /// to ensure non-ambiguity when this aggregator is used. + #[strict_type(tag = 6)] + Last(StateName), + + /// Takes the nth element of the global state, counting from the end of the list. + /// + /// Fails if the global state is not defined, i.e., has zero elements, + /// or if the nth-element is empty. + /// + /// # Nota bene + /// + /// The global state does not have only a partial ordering (it is a lattice). + /// + /// It is only in the case when one operation depends on outputs of another + /// (via global or owned state) there is a guarantee that the global state + /// defined by the second operation will always follow the first one. + /// + /// It is the responsibility of the codex developer + /// to ensure non-ambiguity when this aggregator is used. + #[strict_type(tag = 7)] + NthBack(StateName, u16), + + /// Integer-negate state. + /// + /// Fails if the state is not defined or contains multiple elements. + /// Also fails if the state is not an unsigned 64-bit integer or is greater than `i64::MAX`. #[strict_type(tag = 0x10)] - CountPrefixedV(StateName, TinyBlob), - */ - /// Convert a verified state under the same state type into a vector. + Neg(StateSelector), + + /// Sum two states of different types, expecting them to be integers. + /// + /// Fails if any of the state is not defined or contains multiple elements. + /// Also fails if the state is not an unsigned 64-bit integer or there is an overflow. + #[strict_type(tag = 0x11)] + Add(StateSelector, StateSelector), + + /// Substracts the second state from the first state, expecting both to be integers. + /// + /// Fails if any of the state is not defined or contains multiple elements. + /// Also fails if the state is not an unsigned 64-bit integer or there is an overflow. + #[strict_type(tag = 0x12)] + Sub(StateSelector, StateSelector), + + /// Product two states of different types, expecting them to be integers. + /// + /// Fails if any of the state is not defined or contains multiple elements. + /// Also fails if the state is not an unsigned 64-bit integer or there is an overflow. + #[strict_type(tag = 0x13)] + Mul(StateSelector, StateSelector), + + /// Divide the first state on the second state, expecting them to be integers. + /// The resulting value is rounded towards zero. + /// + /// Fails if any of the state is not defined or contains multiple elements. + /// Also fails if the state is not an unsigned 64-bit integer, or the second state is zero. + #[strict_type(tag = 0x14)] + Div(StateSelector, StateSelector), + + /// Modulo-divide the first state on the second state, expecting them to be integers. + /// + /// Fails if any of the state is not defined or contains multiple elements. + /// Also fails if the state is not an unsigned 64-bit integer, or the second state is zero. + #[strict_type(tag = 0x15)] + Rem(StateSelector, StateSelector), + + /// Exponentiates the first state with the second state, expecting them to be integers. + /// The resulting value is rounded towards zero. + /// + /// Fails if any of the state is not defined or contains multiple elements. + /// Also fails if the first state is not an unsigned 64-bit integer, + /// the second state is not an unsigned 32-bit integer, or there is an overflow. + #[strict_type(tag = 0x16)] + Exp(StateSelector, StateSelector), + + /// Count the number of elements of the global state of a certain type. #[strict_type(tag = 0x20)] - ListV(StateName), + Count(StateName), + + /// Count the number of unique elements of the global state of a certain type. + #[strict_type(tag = 0x21)] + CountUnique(StateName), - /// Convert a verified state under the same state type into a sorted set. + /// Convert a verified state under the same state type into an ordered set. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// If the global state with the name is absent returns an empty set. #[strict_type(tag = 0x22)] SetV(StateName), - /// Map from a field-based element state to a non-verifiable structured state - #[strict_type(tag = 0x30)] + /// Map from a field-based element state to a non-verifiable structured state; + /// when the field-based element state repeats, it is ignored and only the initial state is + /// kept. + /// + /// The map is sorted by its values, lexicographically. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// If the global state with the name is absent returns an empty map. + /// + /// # Nota bene + /// + /// The global state does not have only a partial ordering (it is a lattice). + /// + /// It is only in the case when one operation depends on outputs of another + /// (via global or owned state) there is a guarantee that the global state + /// defined by the second operation will always follow the first one. + /// + /// It is the responsibility of the codex developer + /// to ensure non-ambiguity when this aggregator is used. + #[strict_type(tag = 0x23)] MapV2U(StateName), + + /// Map from a field-based element state to a list of non-verifiable structured state; + /// when the field-based element state repeats, the list is extended with the non-verifiable + /// state. + /// + /// The map is ordered according to the global state element order. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// If the global state with the name is absent returns an empty map. + /// + /// # Nota bene + /// + /// The global state does not have only a partial ordering (it is a lattice). + /// + /// It is only in the case when one operation depends on outputs of another + /// (via global or owned state) there is a guarantee that the global state + /// defined by the second operation will always follow the first one. + /// + /// It is the responsibility of the codex developer + /// to ensure non-ambiguity when this aggregator is used. + #[strict_type(tag = 0x24)] + MapV2ListU(StateName), + + /// Map from a field-based element state to a set of non-verifiable structured state; + /// when the field-based element state repeats, the set is extended with the non-verifiable + /// state. + /// + /// The map is ordered according to the global state element order. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// If the global state with the name is absent returns an empty map. + /// + /// # Nota bene + /// + /// The global state does not have only a partial ordering (it is a lattice). + /// + /// It is only in the case when one operation depends on outputs of another + /// (via global or owned state) there is a guarantee that the global state + /// defined by the second operation will always follow the first one. + /// + /// It is the responsibility of the codex developer + /// to ensure non-ambiguity when this aggregator is used. + #[strict_type(tag = 0x25)] + MapV2SetU(StateName), + + /// Sums over verifiable part of a global state. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// Fails if the global state doesn't have any elements, or if there is an overflow, + /// or the state type is not an unsigned integer. + #[strict_type(tag = 0x30)] + SumUnwrap(StateName), + + /// Sums over verifiable part of a global state. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// Produces zero f the global state doesn't have any elements, or if there is an overflow. + /// + /// If any of the elements of the global state are not an unsigner integer, treats them as zero. + #[strict_type(tag = 0x31)] + SumOrDefault(StateName), + + /// Takes a product of the elements of a global state, taking their verifiable part. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// Fails if the global state doesn't have any elements, or if there is an overflow, + /// or the state type is not an unsigned integer. + #[strict_type(tag = 0x32)] + ProdUnwrap(StateName), + + /// Takes a product of the elements of a global state, taking their verifiable part. + /// + /// Acts only on a global state; doesn't recognize aggregated state. + /// + /// Produces zero f the global state doesn't have any elements, or if there is an overflow. + /// + /// If any of the elements of the global state are not an unsigner integer, treats them as one. + #[strict_type(tag = 0x33)] + ProdOrDefault(StateName), } -impl StateAggregator { - pub fn read<'s, I: IntoIterator>(&self, state: impl Fn(&StateName) -> I) -> StrictVal { +impl SubAggregator { + /// Returns names of the other computed state which this aggregator depends on + /// and which needs to be computed before running this aggregator. + pub fn depends_on(&self) -> Vec<&StateName> { + match self { + Self::Neg(StateSelector::Aggregated(state)) + | Self::Add(StateSelector::Global(_, _), StateSelector::Aggregated(state)) + | Self::Sub(StateSelector::Global(_, _), StateSelector::Aggregated(state)) + | Self::Mul(StateSelector::Global(_, _), StateSelector::Aggregated(state)) + | Self::Div(StateSelector::Global(_, _), StateSelector::Aggregated(state)) + | Self::Rem(StateSelector::Global(_, _), StateSelector::Aggregated(state)) + | Self::Exp(StateSelector::Global(_, _), StateSelector::Aggregated(state)) + | Self::Add(StateSelector::Aggregated(state), StateSelector::Global(_, _)) + | Self::Sub(StateSelector::Aggregated(state), StateSelector::Global(_, _)) + | Self::Mul(StateSelector::Aggregated(state), StateSelector::Global(_, _)) + | Self::Div(StateSelector::Aggregated(state), StateSelector::Global(_, _)) + | Self::Rem(StateSelector::Aggregated(state), StateSelector::Global(_, _)) + | Self::Exp(StateSelector::Aggregated(state), StateSelector::Global(_, _)) => vec![state], + + Self::Add(StateSelector::Aggregated(a), StateSelector::Aggregated(b)) + | Self::Sub(StateSelector::Aggregated(a), StateSelector::Aggregated(b)) + | Self::Mul(StateSelector::Aggregated(a), StateSelector::Aggregated(b)) + | Self::Div(StateSelector::Aggregated(a), StateSelector::Aggregated(b)) + | Self::Rem(StateSelector::Aggregated(a), StateSelector::Aggregated(b)) + | Self::Exp(StateSelector::Aggregated(a), StateSelector::Aggregated(b)) => vec![a, b], + + Self::Const(_, _) + | Self::TheOnly(_) + | Self::Count(_) + | Self::CountUnique(_) + | Self::Copy(_) + | Self::Unwrap(_) + | Self::First(_) + | Self::Nth(_, _) + | Self::Last(_) + | Self::NthBack(_, _) + | Self::Neg(_) + | Self::Add(_, _) + | Self::Sub(_, _) + | Self::Mul(_, _) + | Self::Div(_, _) + | Self::Rem(_, _) + | Self::Exp(_, _) + | Self::SetV(_) + | Self::MapV2U(_) + | Self::MapV2ListU(_) + | Self::MapV2SetU(_) + | Self::SumUnwrap(_) + | Self::SumOrDefault(_) + | Self::ProdUnwrap(_) + | Self::ProdOrDefault(_) => vec![], + } + } + + /// Compute state via applying some aggregator function. + /// + /// # Returns + /// + /// Aggregated state value. + /// If the computing fails due to any exception, `None`. + pub fn aggregate( + &self, + global: &BTreeMap>, + aggregated: &BTreeMap, + types: &TypeSystem, + ) -> Option { + let get_u64 = |sel: &StateSelector| -> Option { + let state = match sel { + StateSelector::Global(name, first) => { + let map = global.get(name)?; + if map.len() != 1 && !*first { + return None; + } + let (_, atom) = map.first_key_value()?; + &atom.verified + } + StateSelector::Aggregated(name) => aggregated.get(name)?, + }; + match state { + StrictVal::Number(StrictNum::Uint(val)) => Some(*val), + _ => None, + } + }; + match self { - //EmbeddedReaders::Const(val) => val.clone(), - StateAggregator::Count(name) => { - let count = state(name).into_iter().count(); - svnum!(count as u64) + Self::Const(sem_id, val) => deserialize(*sem_id, val, types), + + Self::TheOnly(name) => { + let state = global.get(name)?; + if state.len() != 1 { + return None; + } + Some(state.first_key_value()?.1.verified.clone()) } - StateAggregator::SumV(name) => { - let sum = state(name) - .into_iter() - .map(|atom| match &atom.verified { - StrictVal::Number(StrictNum::Uint(val)) => *val, - _ => 0u64, - }) - .sum::(); - svnum!(sum) - } - StateAggregator::ListV(name) => StrictVal::List( - state(name) + + Self::Copy(name) => aggregated.get(name).cloned(), + + Self::Unwrap(name) => { + let state = global.get(name)?; + if state.len() != 1 { + return None; + } + let (_, atom) = state.first_key_value()?; + let StrictVal::Union(tag, sv) = &atom.verified else { + return None; + }; + Some(match tag { + EnumTag::Name(name) if name.as_str() == "some" => sv.as_ref().clone(), + EnumTag::Ord(1) => sv.as_ref().clone(), + _ => return None, + }) + } + + Self::First(name) => { + let state = global.get(name)?; + Some(state.first_key_value()?.1.verified.clone()) + } + + Self::Nth(name, pos) => { + let state = global.get(name)?; + Some(state.iter().nth(*pos as usize)?.1.verified.clone()) + } + + Self::Last(name) => { + let state = global.get(name)?; + Some(state.last_key_value()?.1.verified.clone()) + } + + Self::NthBack(name, pos) => { + let state = global.get(name)?; + Some(state.iter().nth_back(*pos as usize)?.1.verified.clone()) + } + + Self::Neg(name) => { + let val = get_u64(name)?; + let neg = (val as i64).checked_neg()?; + Some(svnum!(neg)) + } + Self::Add(a, b) => { + let a = get_u64(a)?; + let b = get_u64(b)?; + let sum = a.checked_add(b)?; + Some(svnum!(sum)) + } + Self::Sub(a, b) => { + let a = get_u64(a)?; + let b = get_u64(b)?; + let sub = a.checked_sub(b)?; + Some(svnum!(sub)) + } + Self::Mul(a, b) => { + let a = get_u64(a)?; + let b = get_u64(b)?; + let sub = a.checked_mul(b)?; + Some(svnum!(sub)) + } + Self::Div(a, b) => { + let a = get_u64(a)?; + let b = get_u64(b)?; + let sub = a.checked_div(b)?; + Some(svnum!(sub)) + } + Self::Rem(a, b) => { + let a = get_u64(a)?; + let b = get_u64(b)?; + let sub = a.checked_rem(b)?; + Some(svnum!(sub)) + } + Self::Exp(a, b) => { + let a = get_u64(a)?; + let b = get_u64(b)?; + let sub = a.checked_pow(b.try_into().ok()?)?; + Some(svnum!(sub)) + } + + Self::Count(name) => { + let count = global + .get(name) .into_iter() - .map(|atom| atom.verified.clone()) - .collect(), - ), - StateAggregator::SetV(name) => { + .flat_map(BTreeMap::values) + .count(); + Some(svnum!(count as u64)) + } + + Self::CountUnique(name) => { + let mut unique = Vec::new(); + for item in global.get(name)?.values() { + if !unique.contains(&item) { + unique.push(item); + } + } + Some(svnum!(unique.len() as u64)) + } + + Self::SetV(name) => { let mut set = Vec::new(); - for atom in state(name) { - if !set.contains(&atom.verified) { - set.push(atom.verified.clone()); + for state in global.get(name).into_iter().flat_map(BTreeMap::values) { + if !set.contains(&state.verified) { + set.push(state.verified.clone()); } } - StrictVal::Set(set) + Some(StrictVal::Set(set)) } - StateAggregator::MapV2U(name) => { + + Self::MapV2U(name) => { let mut map = Vec::new(); - for atom in state(name) { + for atom in global.get(name)?.values() { let Some(val) = &atom.unverified else { continue }; if map.iter().any(|(key, _)| &atom.verified == key) { continue; } map.push((atom.verified.clone(), val.clone())); } - StrictVal::Map(map) + Some(StrictVal::Map(map)) + } + + Self::MapV2ListU(name) => { + let mut map = Vec::<(StrictVal, StrictVal)>::new(); + for atom in global.get(name)?.values() { + let Some(val) = &atom.unverified else { continue }; + if let Some((_key, list)) = map.iter_mut().find(|(key, _)| &atom.verified == key) { + let StrictVal::List(list) = list else { + unreachable!(); + }; + list.push(val.clone()); + } else { + map.push((atom.verified.clone(), StrictVal::List(vec![val.clone()]))); + } + } + Some(StrictVal::Map(map)) + } + + Self::MapV2SetU(name) => { + let mut map = Vec::<(StrictVal, StrictVal)>::new(); + for atom in global.get(name)?.values() { + let Some(val) = &atom.unverified else { continue }; + if let Some((_key, list)) = map.iter_mut().find(|(key, _)| &atom.verified == key) { + let StrictVal::Set(list) = list else { + unreachable!(); + }; + if !list.contains(val) { + list.push(val.clone()); + } + } else { + map.push((atom.verified.clone(), StrictVal::Set(vec![val.clone()]))); + } + } + Some(StrictVal::Map(map)) + } + + Self::SumUnwrap(name) => { + let sum = global + .get(name) + .into_iter() + .flat_map(BTreeMap::values) + .try_fold(0u64, |sum, val| match &val.verified { + StrictVal::Number(StrictNum::Uint(val)) => sum.checked_add(*val), + _ => None, + })?; + Some(svnum!(sum)) + } + + Self::SumOrDefault(name) => { + let sum = global + .get(name) + .into_iter() + .flat_map(BTreeMap::values) + .try_fold(0u64, |sum, val| match &val.verified { + StrictVal::Number(StrictNum::Uint(val)) => sum.checked_add(*val), + _ => Some(sum), + })?; + Some(svnum!(sum)) + } + + Self::ProdUnwrap(name) => { + let sum = global + .get(name) + .into_iter() + .flat_map(BTreeMap::values) + .try_fold(1u64, |prod, val| match &val.verified { + StrictVal::Number(StrictNum::Uint(val)) => prod.checked_mul(*val), + _ => None, + })?; + Some(svnum!(sum)) + } + + Self::ProdOrDefault(name) => { + let sum = global + .get(name) + .into_iter() + .flat_map(BTreeMap::values) + .try_fold(1u64, |prod, val| match &val.verified { + StrictVal::Number(StrictNum::Uint(val)) => prod.checked_mul(*val), + _ => Some(prod), + })?; + Some(svnum!(sum)) } } } } +fn deserialize(sem_id: SemId, val: &TinyBlob, types: &TypeSystem) -> Option { + let ty = types + .strict_deserialize_type(sem_id, val.as_slice()) + .unwrap(); + Some(ty.unbox()) +} + #[cfg(test)] mod test { #![cfg_attr(coverage_nightly, coverage(off))] + + use aluvm::aluasm; + use strict_types::stl::std_stl; + use strict_types::SystemBuilder; + use super::*; + fn addr(no: u16) -> CellAddr { CellAddr::new(strict_dumb!(), no) } + fn state() -> BTreeMap> { + bmap! { + vname!("pairs") => bmap! { + addr(0) => StateAtom::with(5u64, "state 1"), + addr(1) => StateAtom::with(1u64, "state 2"), + addr(2) => StateAtom::with(2u64, "state 3"), + addr(3) => StateAtom::with(3u64, "state 4"), + addr(4) => StateAtom::with(4u64, "state 5"), + addr(5) => StateAtom::with(5u64, "state 6"), + }, + vname!("verified") => bmap! { + addr(0) => StateAtom::new_verified(5u64), + addr(1) => StateAtom::new_verified(1u64), + addr(2) => StateAtom::new_verified(2u64), + addr(3) => StateAtom::new_verified(3u64), + addr(4) => StateAtom::new_verified(4u64), + addr(5) => StateAtom::new_verified(5u64), + }, + vname!("unverified") => bmap! { + addr(0) => StateAtom::new_unverified("state 1"), + addr(1) => StateAtom::new_unverified("state 2"), + addr(2) => StateAtom::new_unverified("state 3"), + addr(3) => StateAtom::new_unverified("state 4"), + addr(4) => StateAtom::new_unverified("state 5"), + addr(5) => StateAtom::new_unverified("state 6"), + }, + } + } + fn types() -> TypeSystem { + let sys = SystemBuilder::new() + .import(std_stl()) + .unwrap() + .finalize() + .unwrap(); + let types = std_stl() + .types + .into_iter() + .map(|(tn, ty)| ty.sem_id_named(&tn)); + sys.as_types().extract(types).unwrap() + } + fn success_lib() -> Lib { + let code = aluasm! { ret; }; + Lib::assemble(&code).unwrap() + } + fn call(aggregator: &Aggregator) -> StrictVal { + aggregator + .aggregate(&state(), &none!(), &[success_lib()], &types()) + .unwrap() + } + fn call2(aggregator: &Aggregator) -> StrictVal { + let aggregated = bmap! { + vname!("zero") => svnum!(0u64), + vname!("two") => svnum!(2u64), + vname!("three") => svnum!(3u64), + vname!("str") => svstr!("Hi"), + }; + aggregator + .aggregate(&state(), &aggregated, &[success_lib()], &types()) + .unwrap() + } + #[test] - fn verified_readers() { - let state = [ - StateAtom::new_verified(5u64), - StateAtom::new_verified(1u64), - StateAtom::new_verified(2u64), - StateAtom::new_verified(3u64), - StateAtom::new_verified(4u64), - StateAtom::new_verified(5u64), - ]; - - let adaptor = StateAggregator::Count(vname!("test1")); - assert_eq!( - adaptor.read(|name| { - assert_eq!(name.as_str(), "test1"); - state.iter() - }), - svnum!(6u64) - ); + fn none() { + let agg = Aggregator::None; + assert_eq!(call(&agg), svnone!()); + assert_eq!(agg.depends_on().count(), 0); + } - let adaptor = StateAggregator::SumV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svnum!(5u64 + 1 + 2 + 3 + 4 + 5)); + #[test] + fn some() { + let agg = Aggregator::Some(SubAggregator::Count(vname!("verified"))); + assert_eq!(call(&agg), svsome!(6u64)); + assert_eq!(agg.depends_on().count(), 0); + } - let adaptor = StateAggregator::ListV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svlist!([5u64, 1u64, 2u64, 3u64, 4u64, 5u64])); + #[test] + fn or() { + let agg = + Aggregator::Or(SubAggregator::Unwrap(vname!("nonExisting")), SubAggregator::Count(vname!("verified"))); + assert_eq!(call(&agg), svnum!(6u64)); + assert_eq!(agg.depends_on().count(), 0); + } + + #[test] + #[should_panic] + fn non_existing() { call(&Aggregator::Take(SubAggregator::Unwrap(vname!("nonExisting")))); } - let adaptor = StateAggregator::SetV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svset!([5u64, 1u64, 2u64, 3u64, 4u64])); + #[test] + fn sum() { + #![allow(clippy::identity_op)] + let agg = Aggregator::Take(SubAggregator::SumUnwrap(vname!("verified"))); + assert_eq!(call(&agg), svnum!(5u64 + 1 + 2 + 3 + 4 + 5)); + assert_eq!(agg.depends_on().count(), 0); + + let agg = Aggregator::Take(SubAggregator::SumOrDefault(vname!("verified"))); + assert_eq!(call(&agg), svnum!(5u64 + 1 + 2 + 3 + 4 + 5)); + assert_eq!(agg.depends_on().count(), 0); - let adaptor = StateAggregator::MapV2U(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), StrictVal::Map(none!())); + let agg = Aggregator::Take(SubAggregator::SumOrDefault(vname!("unverified"))); + assert_eq!(call(&agg), svnum!(0u64)); + assert_eq!(agg.depends_on().count(), 0); } #[test] - fn unverified_readers() { - let state = [ - StateAtom::new_unverified(5u64), - StateAtom::new_unverified(1u64), - StateAtom::new_unverified(2u64), - StateAtom::new_unverified(3u64), - StateAtom::new_unverified(4u64), - StateAtom::new_unverified(5u64), - ]; + fn prod() { + #![allow(clippy::identity_op)] + let agg = Aggregator::Take(SubAggregator::ProdUnwrap(vname!("verified"))); + assert_eq!(call(&agg), svnum!(5u64 * 1 * 2 * 3 * 4 * 5)); + assert_eq!(agg.depends_on().count(), 0); + + let agg = Aggregator::Take(SubAggregator::ProdOrDefault(vname!("verified"))); + assert_eq!(call(&agg), svnum!(5u64 * 1 * 2 * 3 * 4 * 5)); + assert_eq!(agg.depends_on().count(), 0); + + let agg = Aggregator::Take(SubAggregator::ProdOrDefault(vname!("unverified"))); + assert_eq!(call(&agg), svnum!(1u64)); + assert_eq!(agg.depends_on().count(), 0); + } + + #[test] + fn add() { + let agg = Aggregator::Take(SubAggregator::Add( + StateSelector::Aggregated(vname!("two")), + StateSelector::Aggregated(vname!("three")), + )); + assert_eq!(agg.depends_on().collect::>(), vec![&vname!("two"), &vname!("three")]); + assert_eq!(call2(&agg), svnum!(5u64)); + } + + #[test] + fn meg() { + let agg = Aggregator::Take(SubAggregator::Neg(StateSelector::Aggregated(vname!("two")))); + assert_eq!(agg.depends_on().collect::>(), vec![&vname!("two")]); + assert_eq!(call2(&agg), svnum!(-2i64)); + } + + #[test] + fn sub() { + let agg = Aggregator::Take(SubAggregator::Sub( + StateSelector::Aggregated(vname!("three")), + StateSelector::Aggregated(vname!("two")), + )); + assert_eq!(agg.depends_on().collect::>(), vec![&vname!("three"), &vname!("two")]); + assert_eq!(call2(&agg), svnum!(1u64)); + } + + #[test] + #[should_panic] + fn sub_overflow() { + let agg = Aggregator::Take(SubAggregator::Sub( + StateSelector::Aggregated(vname!("two")), + StateSelector::Aggregated(vname!("three")), + )); + call2(&agg); + } + + #[test] + fn mul() { + let agg = Aggregator::Take(SubAggregator::Mul( + StateSelector::Aggregated(vname!("two")), + StateSelector::Aggregated(vname!("three")), + )); + assert_eq!(agg.depends_on().collect::>(), vec![&vname!("two"), &vname!("three")]); + assert_eq!(call2(&agg), svnum!(6u64)); + } - let adaptor = StateAggregator::Count(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svnum!(6u64)); + #[test] + fn div() { + let agg = Aggregator::Take(SubAggregator::Div( + StateSelector::Aggregated(vname!("two")), + StateSelector::Aggregated(vname!("three")), + )); + assert_eq!(agg.depends_on().collect::>(), vec![&vname!("two"), &vname!("three")]); + assert_eq!(call2(&agg), svnum!(0u64)); + } - let adaptor = StateAggregator::SumV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svnum!(0u64)); + #[test] + #[should_panic] + fn div_zero() { + let agg = Aggregator::Take(SubAggregator::Div( + StateSelector::Aggregated(vname!("two")), + StateSelector::Aggregated(vname!("zero")), + )); + call2(&agg); + } - let adaptor = StateAggregator::ListV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svlist!([(), (), (), (), (), ()])); + #[test] + fn rem() { + let agg = Aggregator::Take(SubAggregator::Rem( + StateSelector::Aggregated(vname!("two")), + StateSelector::Aggregated(vname!("three")), + )); + assert_eq!(agg.depends_on().collect::>(), vec![&vname!("two"), &vname!("three")]); + assert_eq!(call2(&agg), svnum!(2u64)); + } - let adaptor = StateAggregator::SetV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svset!([()])); + #[test] + fn exp() { + let agg = Aggregator::Take(SubAggregator::Exp( + StateSelector::Aggregated(vname!("two")), + StateSelector::Aggregated(vname!("three")), + )); + assert_eq!(agg.depends_on().collect::>(), vec![&vname!("two"), &vname!("three")]); + assert_eq!(call2(&agg), svnum!(8u64)); + } - let adaptor = StateAggregator::MapV2U(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), StrictVal::Map(vec![(StrictVal::Unit, svnum!(5u64)),])); + #[test] + #[should_panic] + fn math_sum_fail() { call(&Aggregator::Take(SubAggregator::SumUnwrap(vname!("unverified")))); } + + #[test] + #[should_panic] + fn math_prod_fail() { call(&Aggregator::Take(SubAggregator::ProdUnwrap(vname!("unverified")))); } + + fn independent(agg: Aggregator, val: StrictVal) { + assert_eq!(call(&agg), val); + assert_eq!(agg.depends_on().count(), 0); + } + + #[test] + fn verified_readers() { + independent(Aggregator::Take(SubAggregator::First(vname!("verified"))), svnum!(5u64)); + independent(Aggregator::Take(SubAggregator::Nth(vname!("verified"), 0)), svnum!(5u64)); + independent(Aggregator::Take(SubAggregator::Nth(vname!("verified"), 1)), svnum!(1u64)); + independent(Aggregator::Take(SubAggregator::Last(vname!("verified"))), svnum!(5u64)); + independent(Aggregator::Take(SubAggregator::NthBack(vname!("verified"), 0)), svnum!(5u64)); + independent(Aggregator::Take(SubAggregator::NthBack(vname!("verified"), 1)), svnum!(4u64)); + independent(Aggregator::Take(SubAggregator::Count(vname!("verified"))), svnum!(6u64)); + independent(Aggregator::Take(SubAggregator::CountUnique(vname!("verified"))), svnum!(5u64)); + independent(Aggregator::Take(SubAggregator::SetV(vname!("verified"))), svset!([5u64, 1u64, 2u64, 3u64, 4u64])); + independent(Aggregator::Take(SubAggregator::MapV2U(vname!("verified"))), StrictVal::Map(none!())); + independent(Aggregator::Take(SubAggregator::MapV2ListU(vname!("verified"))), StrictVal::Map(none!())); + independent(Aggregator::Take(SubAggregator::MapV2SetU(vname!("verified"))), StrictVal::Map(none!())); + } + + #[test] + fn unverified_readers() { + independent(Aggregator::Take(SubAggregator::Count(vname!("verified"))), svnum!(6u64)); + independent(Aggregator::Take(SubAggregator::SetV(vname!("unverified"))), svset!([()])); + independent( + Aggregator::Take(SubAggregator::MapV2U(vname!("unverified"))), + StrictVal::Map(vec![(StrictVal::Unit, svstr!("state 1"))]), + ); + independent( + Aggregator::Take(SubAggregator::MapV2ListU(vname!("unverified"))), + StrictVal::Map(vec![(StrictVal::Unit, svlist![[ + svstr!("state 1"), + svstr!("state 2"), + svstr!("state 3"), + svstr!("state 4"), + svstr!("state 5"), + svstr!("state 6"), + ]])]), + ); + independent( + Aggregator::Take(SubAggregator::MapV2SetU(vname!("unverified"))), + StrictVal::Map(vec![(StrictVal::Unit, svset![[ + svstr!("state 1"), + svstr!("state 2"), + svstr!("state 3"), + svstr!("state 4"), + svstr!("state 5"), + svstr!("state 6"), + ]])]), + ); + } + + #[test] + #[should_panic] + fn unverified_sum() { call(&Aggregator::Take(SubAggregator::SumUnwrap(vname!("unverified")))); } + + #[test] + fn unverified_sum_default() { + independent(Aggregator::Take(SubAggregator::SumOrDefault(vname!("unverified"))), svnum!(0u64)); } #[test] fn pair_readers() { - let state = [ - StateAtom::with(5u64, "state 1"), - StateAtom::with(1u64, "state 2"), - StateAtom::with(2u64, "state 3"), - StateAtom::with(3u64, "state 4"), - StateAtom::with(4u64, "state 5"), - StateAtom::with(5u64, "state 6"), - ]; - - let adaptor = StateAggregator::Count(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svnum!(6u64)); - - let adaptor = StateAggregator::SumV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svnum!(5u64 + 1 + 2 + 3 + 4 + 5)); - - let adaptor = StateAggregator::ListV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svlist!([5u64, 1u64, 2u64, 3u64, 4u64, 5u64])); - - let adaptor = StateAggregator::SetV(vname!("test")); - assert_eq!(adaptor.read(|_| { state.iter() }), svset!([5u64, 1u64, 2u64, 3u64, 4u64])); - - let adaptor = StateAggregator::MapV2U(vname!("test")); - assert_eq!( - adaptor.read(|_| { state.iter() }), + independent(Aggregator::Take(SubAggregator::Count(vname!("verified"))), svnum!(6u64)); + independent(Aggregator::Take(SubAggregator::SumUnwrap(vname!("pairs"))), svnum!(5u64 + 1 + 2 + 3 + 4 + 5)); + independent(Aggregator::Take(SubAggregator::SetV(vname!("pairs"))), svset!([5u64, 1u64, 2u64, 3u64, 4u64])); + independent( + Aggregator::Take(SubAggregator::MapV2U(vname!("pairs"))), StrictVal::Map(vec![ (svnum!(5u64), svstr!("state 1")), (svnum!(1u64), svstr!("state 2")), (svnum!(2u64), svstr!("state 3")), (svnum!(3u64), svstr!("state 4")), - (svnum!(4u64), svstr!("state 5")) - ]) + (svnum!(4u64), svstr!("state 5")), + ]), + ); + independent( + Aggregator::Take(SubAggregator::MapV2ListU(vname!("pairs"))), + StrictVal::Map(vec![ + (svnum!(5u64), svlist![[svstr!("state 1"), svstr!("state 6")]]), + (svnum!(1u64), svlist![[svstr!("state 2")]]), + (svnum!(2u64), svlist![[svstr!("state 3")]]), + (svnum!(3u64), svlist![[svstr!("state 4")]]), + (svnum!(4u64), svlist![[svstr!("state 5")]]), + ]), ); } + + #[test] + #[should_panic] + // For now, the fail here indicates forward compatibility with when we allow AluVM + fn aluvm() { call(&Aggregator::AluVM(LibSite::new(success_lib().lib_id(), 0))); } } diff --git a/api/src/state/arithmetics.rs b/api/src/state/arithmetics.rs index 78192db..f62bd7f 100644 --- a/api/src/state/arithmetics.rs +++ b/api/src/state/arithmetics.rs @@ -23,6 +23,7 @@ use core::str::FromStr; +use aluvm::LibSite; use strict_types::value::StrictNum; use strict_types::StrictVal; @@ -30,14 +31,22 @@ use crate::LIB_NAME_SONIC; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_SONIC, tags = repr, try_from_u8, into_u8)] +#[strict_type(lib = LIB_NAME_SONIC, tags = custom)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] -#[repr(u8)] pub enum StateArithm { - #[strict_type(dumb)] - Fungible = 0, - NonFungible = 1, - // In the future more arithmetics can be added, for instance, based on Tunring-complete VMs. + #[strict_type(tag = 0x00, dumb)] + Fungible, + + #[strict_type(tag = 0x01)] + NonFungible, + // In the future more arithmetics can be added. + /// Execute a custom function. + #[strict_type(tag = 0xFF)] + AluVM( + /// The entry point to the script (virtual machine uses libraries from + /// [`crate::Semantics`]). + LibSite, + ), } impl StateArithm { @@ -45,6 +54,7 @@ impl StateArithm { match self { Self::Fungible => StateCalc::Fungible(StrictVal::Number(StrictNum::Uint(0))), Self::NonFungible => StateCalc::NonFungible(vec![]), + Self::AluVM(_) => StateCalc::AluVM, } } } @@ -57,13 +67,17 @@ pub enum StateCalcError { /// state cannot be computed. UncountableState, + + /// AluVM is not yet supported for the state arithmetics. + Unsupported, } #[derive(Clone, Eq, PartialEq, Debug)] pub enum StateCalc { NonFungible(Vec), Fungible(StrictVal), - // In the future more calculators can be added, for instance, keeping a state of a Turing-complete VM. + // AluVM is reserved for the future. We need it here to avoid breaking changes. + AluVM, } impl StateCalc { @@ -86,6 +100,7 @@ impl StateCalc { *val = val.checked_add(add).ok_or(StateCalcError::Overflow)?; Ok(()) } + Self::AluVM => Err(StateCalcError::Unsupported), } } @@ -115,6 +130,7 @@ impl StateCalc { *val -= dec; Ok(()) } + Self::AluVM => Err(StateCalcError::Unsupported), } } @@ -131,6 +147,7 @@ impl StateCalc { } _ => return Err(StateCalcError::UncountableState), }, + Self::AluVM => return Err(StateCalcError::Unsupported), }) } @@ -150,6 +167,7 @@ impl StateCalc { false } } + Self::AluVM => false, } } } diff --git a/api/src/state/data.rs b/api/src/state/data.rs index 2deba0e..d5df0f3 100644 --- a/api/src/state/data.rs +++ b/api/src/state/data.rs @@ -21,10 +21,9 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. -use aluvm::LibSite; use amplify::num::u256; use strict_types::StrictVal; -use ultrasonic::AuthToken; +use ultrasonic::{AuthToken, CellLock}; pub type StateTy = u256; @@ -58,7 +57,7 @@ impl StateAtom { pub struct DataCell { pub data: StrictVal, pub auth: AuthToken, - pub lock: Option, + pub lock: Option, } impl DataCell { diff --git a/api/src/state/mod.rs b/api/src/state/mod.rs index 4a0b363..09496b0 100644 --- a/api/src/state/mod.rs +++ b/api/src/state/mod.rs @@ -28,7 +28,7 @@ mod data; mod raw; pub use adaptors::{StateBuildError, StateBuilder, StateConvertError, StateConvertor}; -pub use aggregators::StateAggregator; +pub use aggregators::{Aggregator, StateSelector, SubAggregator}; pub use arithmetics::{StateArithm, StateCalc, StateCalcError}; pub use data::{DataCell, StateAtom, StateTy}; pub use raw::{RawBuilder, RawConvertor, TOTAL_RAW_BYTES}; diff --git a/api/src/state/raw.rs b/api/src/state/raw.rs index 15199c8..00a5f24 100644 --- a/api/src/state/raw.rs +++ b/api/src/state/raw.rs @@ -21,6 +21,7 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. +use aluvm::LibSite; use amplify::confinement::{SmallBlob, U24 as U24MAX}; use strict_encoding::StreamReader; use strict_types::{SemId, StrictVal, TypeSystem}; @@ -41,13 +42,21 @@ pub enum RawConvertor { // In the future we can add more adaptors: // - using just a specific range of raw bytes, not a full value - such that multiple APIs may read different parts // of the same data; - // - using a Turing complete grammar with some VM (AluVM? RISC-V? WASM?). + /// Execute a custom function. + // AluVM is reserved for the future. We need it here to avoid breaking changes. + #[strict_type(tag = 0xFF)] + AluVM( + /// The entry point to the script (virtual machine uses libraries from + /// [`crate::Semantics`]). + LibSite, + ), } impl RawConvertor { pub fn convert(&self, raw: &RawData, sys: &TypeSystem) -> Result { match self { Self::StrictDecode(sem_id) => strict_convert(*sem_id, raw, sys), + Self::AluVM(_) => Err(StateConvertError::Unsupported), } } } @@ -60,8 +69,15 @@ pub enum RawBuilder { /// Convert strict value into raw bytes using strict encoding. #[strict_type(tag = 0x00)] StrictEncode(SemId), - // In the future we can add more adaptors: - // - using a Turing complete grammar with some VM (AluVM? RISC-V? WASM?). + + /// Execute a custom function. + // AluVM is reserved for the future. We need it here to avoid breaking changes. + #[strict_type(tag = 0xFF)] + AluVM( + /// The entry point to the script (virtual machine uses libraries from + /// [`crate::Semantics`]). + LibSite, + ), } impl RawBuilder { @@ -69,6 +85,7 @@ impl RawBuilder { pub fn build(&self, val: StrictVal, sys: &TypeSystem) -> Result { match self { Self::StrictEncode(sem_id) => strict_build(*sem_id, val, sys), + Self::AluVM(_) => Err(StateBuildError::Unsupported), } } } diff --git a/callreq/src/builder.rs b/callreq/src/builder.rs index ff097fe..4733f5f 100644 --- a/callreq/src/builder.rs +++ b/callreq/src/builder.rs @@ -78,7 +78,7 @@ impl CallRequest { let mut call = self .call .expect("use_method must be called before use_state"); - call.destructible = Some(state); + call.owned = Some(state); self.call = Some(call); self } diff --git a/callreq/src/data.rs b/callreq/src/data.rs index 420d893..1eec15b 100644 --- a/callreq/src/data.rs +++ b/callreq/src/data.rs @@ -21,9 +21,9 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. +use core::convert::Infallible; use core::fmt::{self, Display, Formatter}; use core::str::FromStr; -use std::convert::Infallible; use amplify::confinement::{ConfinedVec, TinyBlob}; use baid64::Baid64ParseError; @@ -38,23 +38,20 @@ pub type StateName = VariantName; pub type MethodName = VariantName; /// Combination of a method name and an optional state name used in API requests. -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_SONIC)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase", bound = ""))] pub struct CallState { pub method: MethodName, - pub destructible: Option, + pub owned: Option, } impl CallState { - pub fn new(method: impl Into) -> Self { Self { method: method.into(), destructible: None } } + pub fn new(method: impl Into) -> Self { Self { method: method.into(), owned: None } } - pub fn with(method: impl Into, destructible: impl Into) -> Self { - Self { - method: method.into(), - destructible: Some(destructible.into()), - } + pub fn with(method: impl Into, owned: impl Into) -> Self { + Self { method: method.into(), owned: Some(owned.into()) } } } diff --git a/callreq/src/uri.rs b/callreq/src/uri.rs index 44ec0ae..a0eb0f2 100644 --- a/callreq/src/uri.rs +++ b/callreq/src/uri.rs @@ -74,7 +74,7 @@ where } if let Some(call) = &self.call { write!(f, "{}/", call.method)?; - if let Some(state) = &call.destructible { + if let Some(state) = &call.owned { write!(f, "{state}/")?; } } @@ -175,12 +175,12 @@ where let mut call = None; if let Some(method) = method { let method = method.as_str().parse().map_err(ParseError::MethodInvalid)?; - let destructible = if let Some(state) = state { + let owned = if let Some(state) = state { Some(state.as_str().parse().map_err(ParseError::StateInvalid)?) } else { None }; - call = Some(CallState { method, destructible }); + call = Some(CallState { method, owned }); } let mut query_params: IndexMap = IndexMap::new(); diff --git a/cli/src/cmd.rs b/cli/src/cmd.rs index 8ba1853..070d6ac 100644 --- a/cli/src/cmd.rs +++ b/cli/src/cmd.rs @@ -22,12 +22,11 @@ // the License. use std::convert::Infallible; -use std::error::Error; use std::fs::File; use std::path::PathBuf; use clap::ValueHint; -use hypersonic::{AuthToken, CallParams, Identity, IssueParams, Issuer, SigBlob, SigValidator}; +use hypersonic::{AuthToken, CallParams, IssueParams, Issuer}; use sonic_persist_fs::LedgerDir; use crate::dump::dump_ledger; @@ -115,7 +114,7 @@ impl Cmd { } fn issue(issuer_file: PathBuf, form: PathBuf, output: Option) -> anyhow::Result<()> { - let issuer = Issuer::load(issuer_file)?; + let issuer = Issuer::load(issuer_file, |_, _, _| -> Result<_, Infallible> { todo!("signature validation") })?; let file = File::open(&form)?; let params = serde_yaml::from_reader::<_, IssueParams>(file)?; @@ -147,21 +146,14 @@ fn call(dir: PathBuf, form: PathBuf) -> anyhow::Result<()> { } fn export(dir: PathBuf, terminals: impl IntoIterator, output: PathBuf) -> anyhow::Result<()> { - let mut ledger = LedgerDir::load(dir)?; + let ledger = LedgerDir::load(dir)?; ledger.export_to_file(terminals, output)?; Ok(()) } fn accept(dir: PathBuf, input: PathBuf) -> anyhow::Result<()> { - // TODO: (v0.13) Use some real signature validator - pub struct DumbValidator; - impl SigValidator for DumbValidator { - fn validate_sig(&self, _: impl Into<[u8; 32]>, _: &Identity, _: &SigBlob) -> Result { - Result::<_, Infallible>::Ok(0) - } - } let mut ledger = LedgerDir::load(dir)?; - ledger.accept_from_file(input, DumbValidator)?; + ledger.accept_from_file(input, |_, _, _| Err("signature validation is not implemented yet"))?; Ok(()) } diff --git a/cli/src/dump.rs b/cli/src/dump.rs index 5743afa..c432765 100644 --- a/cli/src/dump.rs +++ b/cli/src/dump.rs @@ -55,7 +55,7 @@ pub fn dump_articles(articles: &Articles, dst: &Path) -> anyhow::Result { serde_yaml::to_writer(&out, &api)?; } - for lib in &articles.apis().libs { + for lib in articles.codex_libs() { let lib_id = lib.lib_id(); let name = lib_id.to_baid64_mnemonic(); lib.strict_serialize_to_file::(dst.join(format!("{name}.alu")))?; diff --git a/examples/dao/main.rs b/examples/dao/main.rs index 66cee9f..4768102 100644 --- a/examples/dao/main.rs +++ b/examples/dao/main.rs @@ -36,9 +36,11 @@ use std::path::Path; use aluvm::{CoreConfig, LibSite}; use amplify::num::u256; use commit_verify::{Digest, Sha256}; -use hypersonic::{Api, DestructibleApi, ImmutableApi}; +use hypersonic::{Api, GlobalApi, OwnedApi}; use sonic_persist_fs::LedgerDir; -use sonicapi::{Issuer, RawBuilder, RawConvertor, StateAggregator, StateArithm, StateBuilder, StateConvertor}; +use sonicapi::{ + Aggregator, Issuer, RawBuilder, RawConvertor, Semantics, StateArithm, StateBuilder, StateConvertor, SubAggregator, +}; use strict_types::{SemId, StrictVal}; use ultrasonic::aluvm::FIELD_ORDER_SECP; use ultrasonic::{AuthToken, CellAddr, Codex, Consensus, Identity}; @@ -51,6 +53,7 @@ fn codex() -> Codex { developer: Identity::default(), version: default!(), timestamp: 1732529307, + features: none!(), field_order: FIELD_ORDER_SECP, input_config: CoreConfig::default(), verification_config: CoreConfig::default(), @@ -68,13 +71,11 @@ fn api() -> Api { let codex = codex(); Api { - version: default!(), codex_id: codex.codex_id(), - developer: Identity::default(), - conforms: None, + conforms: none!(), default_call: None, - immutable: tiny_bmap! { - vname!("_parties") => ImmutableApi { + global: tiny_bmap! { + vname!("_parties") => GlobalApi { published: true, sem_id: types.get("DAO.PartyId"), convertor: StateConvertor::TypedEncoder(u256::ZERO), @@ -82,7 +83,7 @@ fn api() -> Api { raw_convertor: RawConvertor::StrictDecode(types.get("DAO.Party")), raw_builder: RawBuilder::StrictEncode(types.get("DAO.Party")), }, - vname!("_votings") => ImmutableApi { + vname!("_votings") => GlobalApi { published: true, sem_id: types.get("DAO.VoteId"), convertor: StateConvertor::TypedEncoder(u256::ONE), @@ -90,7 +91,7 @@ fn api() -> Api { raw_convertor: RawConvertor::StrictDecode(types.get("DAO.Voting")), raw_builder: RawBuilder::StrictEncode(types.get("DAO.Voting")), }, - vname!("_votes") => ImmutableApi { + vname!("_votes") => GlobalApi { published: true, sem_id: types.get("DAO.CastVote"), convertor: StateConvertor::TypedEncoder(u256::from(2u8)), @@ -99,8 +100,8 @@ fn api() -> Api { raw_builder: RawBuilder::StrictEncode(SemId::unit()), }, }, - destructible: tiny_bmap! { - vname!("signers") => DestructibleApi { + owned: tiny_bmap! { + vname!("signers") => OwnedApi { sem_id: types.get("DAO.PartyId"), arithmetics: StateArithm::NonFungible, convertor: StateConvertor::TypedEncoder(u256::ZERO), @@ -110,10 +111,10 @@ fn api() -> Api { } }, aggregators: tiny_bmap! { - vname!("parties") => StateAggregator::MapV2U(vname!("_parties")), - vname!("votings") => StateAggregator::MapV2U(vname!("_votings")), - vname!("votes") => StateAggregator::SetV(vname!("_votes")), - vname!("votingCount") => StateAggregator::Count(vname!("_votings")), + vname!("parties") => Aggregator::Take(SubAggregator::MapV2U(vname!("_parties"))), + vname!("votings") => Aggregator::Take(SubAggregator::MapV2U(vname!("_votings"))), + vname!("votes") => Aggregator::Take(SubAggregator::SetV(vname!("_votes"))), + vname!("votingCount") => Aggregator::Take(SubAggregator::Count(vname!("_votings"))), }, verifiers: tiny_bmap! { vname!("setup") => 0, @@ -121,7 +122,6 @@ fn api() -> Api { vname!("castVote") => 2, }, errors: Default::default(), - reserved: Default::default(), } } @@ -132,7 +132,15 @@ fn main() { let api = api(); // Creating DAO with three participants - let issuer = Issuer::new(codex, api, [libs::success()], types.type_system()); + let semantics = Semantics { + version: 0, + default: api, + custom: none!(), + codex_libs: small_bset![libs::success()], + api_libs: none!(), + types: types.type_system(), + }; + let issuer = Issuer::new(codex, semantics).unwrap(); let filename = "examples/dao/data/SimpleDAO.issuer"; fs::remove_file(filename).ok(); issuer diff --git a/persistence/fs/Cargo.toml b/persistence/fs/Cargo.toml index cbfa8d9..86ecd57 100644 --- a/persistence/fs/Cargo.toml +++ b/persistence/fs/Cargo.toml @@ -16,6 +16,7 @@ exclude = [".github"] [dependencies] amplify = { workspace = true, features = ["serde"] } strict_encoding = { workspace = true, features = ["serde"] } +commit_verify = { workspace = true, features = ["serde"] } hypersonic = { workspace = true, features = ["serde", "binfile"] } aora.workspace = true binfile.workspace = true diff --git a/persistence/fs/src/fs.rs b/persistence/fs/src/fs.rs index 76497cd..1eccc39 100644 --- a/persistence/fs/src/fs.rs +++ b/persistence/fs/src/fs.rs @@ -21,7 +21,7 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. -use std::borrow::Borrow; +use std::convert::Infallible; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; @@ -32,12 +32,10 @@ use aora::file::{FileAoraIndex, FileAoraMap, FileAuraMap}; use aora::{AoraIndex, AoraMap, AuraMap, TransactionalMap}; use binfile::BinFile; use hypersonic::{ - AcceptError, ApiDescriptor, Articles, ArticlesError, AuthToken, CellAddr, EffectiveState, Genesis, Issue, - IssueError, Ledger, Operation, Opid, RawState, SigValidator, Stock, Transition, -}; -use strict_encoding::{ - DecodeError, StreamReader, StreamWriter, StrictDecode, StrictEncode, StrictReader, StrictWriter, + Articles, CellAddr, EffectiveState, Genesis, Issue, IssueError, Ledger, Operation, Opid, RawState, SemanticError, + Semantics, SigBlob, Stock, Transition, }; +use strict_encoding::{DecodeError, StreamReader, StreamWriter, StrictDecode, StrictEncode, StrictWriter}; #[derive(Wrapper, WrapperMut, Debug, From)] #[wrapper(Deref)] @@ -50,11 +48,11 @@ const SPENT_MAGIC: u64 = u64::from_be_bytes(*b"OPSPENT "); const READ_MAGIC: u64 = u64::from_be_bytes(*b"OPREADBY"); const VALID_MAGIC: u64 = u64::from_be_bytes(*b"OPVALID "); -const APIS_MAGIC: u64 = u64::from_be_bytes(*b"CONAPIS "); +const SEMANTICS_MAGIC: u64 = u64::from_be_bytes(*b"SEMANTIC"); const STATE_MAGIC: u64 = u64::from_be_bytes(*b"CONSTATE"); const GENESIS_MAGIC: u64 = u64::from_be_bytes(*b"CGENESIS"); -const VERSION_0: u16 = 0; +const PERSISTENCE_VERSION_0: u16 = 0; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] enum OpValidity { @@ -105,7 +103,7 @@ impl StockFs { const FILENAME_CODEX: &'static str = "codex.yaml"; const FILENAME_META: &'static str = "meta.toml"; const FILENAME_GENESIS: &'static str = "genesis.dat"; - const FILENAME_APIS: &'static str = "apis.dat"; + const FILENAME_SEMANTICS: &'static str = "semantics.dat"; const FILENAME_STATE_RAW: &'static str = "state.dat"; } @@ -127,15 +125,16 @@ impl Stock for StockFs { let file = File::create_new(path.join(Self::FILENAME_CODEX))?; serde_yaml::to_writer(file, articles.codex())?; - let file = BinFile::::create_new(path.join(Self::FILENAME_GENESIS))?; + let file = BinFile::::create_new(path.join(Self::FILENAME_GENESIS))?; let writer = StreamWriter::new::<{ usize::MAX }>(file); articles.genesis().strict_write(writer)?; - let file = BinFile::::create_new(path.join(Self::FILENAME_APIS))?; - let writer = StreamWriter::new::<{ usize::MAX }>(file); - articles.apis().strict_write(writer)?; + let file = BinFile::::create_new(path.join(Self::FILENAME_SEMANTICS))?; + let mut writer = StreamWriter::new::<{ usize::MAX }>(file); + articles.semantics().strict_write(&mut writer)?; + articles.sig().strict_write(writer)?; - let file = BinFile::::create_new(path.join(Self::FILENAME_STATE_RAW))?; + let file = BinFile::::create_new(path.join(Self::FILENAME_STATE_RAW))?; let writer = StreamWriter::new::<{ usize::MAX }>(file); state.raw.strict_write(writer)?; @@ -157,20 +156,23 @@ impl Stock for StockFs { let file = File::open(path.join(Self::FILENAME_CODEX))?; let codex = serde_yaml::from_reader(file)?; - let file = BinFile::::open(path.join(Self::FILENAME_GENESIS))?; + // TODO: Check there is no content left at the end of reading + let file = BinFile::::open(path.join(Self::FILENAME_GENESIS))?; let reader = StreamReader::new::<{ usize::MAX }>(file); let genesis = Genesis::strict_read(reader)?; - let file = BinFile::::open(path.join(Self::FILENAME_APIS))?; - let reader = StreamReader::new::<{ usize::MAX }>(file); - let apis = ApiDescriptor::strict_read(reader)?; + let file = BinFile::::open(path.join(Self::FILENAME_SEMANTICS))?; + let mut reader = StreamReader::new::<{ usize::MAX }>(file); + let semantics = Semantics::strict_read(&mut reader)?; + let sig = Option::::strict_read(reader)?; - let file = BinFile::::open(path.join(Self::FILENAME_STATE_RAW))?; + let file = BinFile::::open(path.join(Self::FILENAME_STATE_RAW))?; let reader = StreamReader::new::<{ usize::MAX }>(file); let raw = RawState::strict_read(reader)?; let issue = Issue { version: default!(), meta, codex, genesis }; - let articles = Articles::with(apis, issue)?; + // We trust the storage + let articles = Articles::with(semantics, issue, sig, |_, _, _| -> Result<_, Infallible> { Ok(()) })?; let state = EffectiveState::with_raw_state(raw, &articles); @@ -194,6 +196,8 @@ impl Stock for StockFs { #[inline] fn has_operation(&self, opid: Opid) -> bool { self.stash.contains_key(opid) } #[inline] + fn operation_count(&self) -> u64 { self.stash.len() as u64 } + #[inline] fn operation(&self, opid: Opid) -> Operation { self.stash.get_expect(opid) } #[inline] fn operations(&self) -> impl Iterator { self.stash.iter() } @@ -208,29 +212,33 @@ impl Stock for StockFs { fn update_articles( &mut self, - f: impl FnOnce(&mut Articles) -> Result<(), ArticlesError>, - ) -> Result<(), MultiError> { - f(&mut self.articles).map_err(MultiError::A)?; + f: impl FnOnce(&mut Articles) -> Result, + ) -> Result> { + let res = f(&mut self.articles).map_err(MultiError::A)?; - let file = BinFile::::create(self.path.join(Self::FILENAME_APIS)) + let file = BinFile::::create(self.path.join(Self::FILENAME_SEMANTICS)) + .map_err(MultiError::from_b)?; + let mut writer = StreamWriter::new::<{ usize::MAX }>(file); + self.articles + .semantics() + .strict_write(&mut writer) .map_err(MultiError::from_b)?; - let writer = StreamWriter::new::<{ usize::MAX }>(file); self.articles - .apis() + .sig() .strict_write(writer) .map_err(MultiError::from_b)?; - Ok(()) + Ok(res) } fn update_state(&mut self, f: impl FnOnce(&mut EffectiveState, &Articles) -> R) -> Result { let res = f(&mut self.state, &self.articles); - let file = BinFile::::create(self.path.join(Self::FILENAME_STATE_RAW))?; + let file = BinFile::::create(self.path.join(Self::FILENAME_STATE_RAW))?; let writer = StreamWriter::new::<{ usize::MAX }>(file); self.state.raw.strict_write(writer)?; - self.state.recompute(self.articles.apis()); + self.state.recompute(self.articles.semantics()); Ok(res) } @@ -263,26 +271,6 @@ impl LedgerDir { self.export_all(writer) } - pub fn export_to_file( - &mut self, - terminals: impl IntoIterator>, - output: impl AsRef, - ) -> io::Result<()> { - let file = File::create_new(output)?; - let writer = StrictWriter::with(StreamWriter::new::<{ usize::MAX }>(file)); - self.export(terminals, writer) - } - - pub fn accept_from_file( - &mut self, - input: impl AsRef, - sig_validator: impl SigValidator, - ) -> Result<(), MultiError> { - let file = File::open(input).map_err(MultiError::from_b)?; - let mut reader = StrictReader::with(StreamReader::new::<{ usize::MAX }>(file)); - self.accept(&mut reader, sig_validator) - } - pub fn path(&self) -> &Path { &self.0.stock().path } } @@ -296,7 +284,7 @@ pub enum FsError { Decode(DecodeError), #[from] - Articles(ArticlesError), + Articles(SemanticError), #[from] Yaml(serde_yaml::Error), diff --git a/src/bin/sonic-stl.rs b/src/bin/sonic-stl.rs index d9c5ee4..eb0b5a7 100644 --- a/src/bin/sonic-stl.rs +++ b/src/bin/sonic-stl.rs @@ -31,7 +31,7 @@ use commit_verify::stl::commit_verify_stl; use commit_verify::CommitmentLayout; use hypersonic::aluvm::zkstl::finite_field_stl; use hypersonic::stl::sonic_stl; -use sonicapi::ArticlesCommitment; +use sonicapi::Semantics; use strict_types::stl::{std_stl, strict_types_stl}; use strict_types::{parse_args, SystemBuilder}; use ultrasonic::stl::usonic_stl; @@ -100,9 +100,11 @@ fn main() { .unwrap(); writeln!(file, "\n-- Contract Articles\n").unwrap(); - let layout = ArticlesCommitment::commitment_layout(); + let layout = Semantics::commitment_layout(); writeln!(file, "{layout}").unwrap(); - let tt = sys.type_tree("SONIC.ArticlesCommitment").unwrap(); + let tt = sys.type_tree("SONIC.Semantics").unwrap(); + writeln!(file, "{tt}").unwrap(); + let tt = sys.type_tree("SONIC.Issuer").unwrap(); writeln!(file, "{tt}").unwrap(); let tt = sys.type_tree("SONIC.Articles").unwrap(); writeln!(file, "{tt}").unwrap(); diff --git a/src/deed.rs b/src/deed.rs index 8032948..15d09d7 100644 --- a/src/deed.rs +++ b/src/deed.rs @@ -23,12 +23,11 @@ use std::collections::BTreeMap; -use aluvm::LibSite; use amplify::MultiError; use sonic_callreq::StateName; use sonicapi::{CoreParams, OpBuilder}; use strict_types::StrictVal; -use ultrasonic::{AuthToken, CellAddr, Opid}; +use ultrasonic::{AuthToken, CellAddr, CellLock, Opid}; use crate::{AcceptError, Ledger, Stock}; @@ -76,7 +75,7 @@ impl DeedBuilder<'_, S> { pub fn append(mut self, name: impl Into, data: StrictVal, raw: Option) -> Self { let api = &self.ledger.articles().default_api(); let types = &self.ledger.articles().types(); - self.builder = self.builder.add_immutable(name, data, raw, api, types); + self.builder = self.builder.add_global(name, data, raw, api, types); self } @@ -85,13 +84,11 @@ impl DeedBuilder<'_, S> { name: impl Into, auth: AuthToken, data: StrictVal, - lock: Option, + lock: Option, ) -> Self { let api = &self.ledger.articles().default_api(); let types = &self.ledger.articles().types(); - self.builder = self - .builder - .add_destructible(name, auth, data, lock, api, types); + self.builder = self.builder.add_owned(name, auth, data, lock, api, types); self } diff --git a/src/ledger.rs b/src/ledger.rs index 6c2693d..21e1f62 100644 --- a/src/ledger.rs +++ b/src/ledger.rs @@ -25,21 +25,20 @@ use alloc::collections::BTreeSet; use core::borrow::Borrow; use std::io; -use amplify::hex::ToHex; use amplify::MultiError; +use commit_verify::{ReservedBytes, StrictHash}; use indexmap::IndexSet; use sonic_callreq::MethodName; -use sonicapi::{Api, ApiDescriptor, ArticlesError, NamedState, OpBuilder, SigValidator}; +use sonicapi::{Api, NamedState, OpBuilder, SemanticError, Semantics, SigBlob}; use strict_encoding::{ - DecodeError, ReadRaw, SerializeError, StrictDecode, StrictEncode, StrictReader, StrictWriter, WriteRaw, + DecodeError, ReadRaw, SerializeError, StrictDecode, StrictEncode, StrictReader, StrictWriter, TypedRead, WriteRaw, }; -use ultrasonic::{AuthToken, CallError, CellAddr, ContractId, Issue, Operation, Opid, VerifiedOperation}; +use ultrasonic::{AuthToken, CallError, CellAddr, ContractId, Identity, Issue, Operation, Opid, VerifiedOperation}; use crate::deed::{CallParams, DeedBuilder}; use crate::{Articles, EffectiveState, IssueError, ProcessedState, Stock, Transition}; -pub const LEDGER_MAGIC_NUMBER: [u8; 8] = *b"DEEDLDGR"; -pub const LEDGER_VERSION: [u8; 2] = [0x00, 0x01]; +pub const DEEDS_VERSION: u16 = 0; /// Contract with all its state and operations, supporting updates and rollbacks. // We need this structure to hide internal persistence methods and not to expose them. @@ -278,38 +277,38 @@ impl Ledger { chain.into_iter() } - pub fn export_all(&self, mut writer: StrictWriter) -> io::Result<()> { - // Write articles - writer = self.0.articles().strict_encode(writer)?; - // Stream operations - for (_, op) in self.0.operations() { - writer = op.strict_encode(writer)?; - } - Ok(()) + /// Exports contract with all known operations. + pub fn export_all(&self, writer: StrictWriter) -> io::Result<()> { + self.export_internal(self.0.operation_count() as u32, writer, |_| true, |_, _, w| Ok(w)) + } + + /// Exports contract with all known operations with some auxiliary information returned by + /// `aux`. + pub fn export_all_aux( + &self, + writer: StrictWriter, + aux: impl FnMut(Opid, &Operation, StrictWriter) -> io::Result>, + ) -> io::Result<()> { + self.export_internal(self.0.operation_count() as u32, writer, |_| true, aux) } + /// Export a part of a contract history: a graph between a set of terminals and genesis. pub fn export( &self, terminals: impl IntoIterator>, - mut writer: StrictWriter, + writer: StrictWriter, ) -> io::Result<()> { - // This is compatible with BinFile - writer = LEDGER_MAGIC_NUMBER.strict_encode(writer)?; - // Version - writer = LEDGER_VERSION.strict_encode(writer)?; - writer = self.contract_id().strict_encode(writer)?; self.export_aux(terminals, writer, |_, _, w| Ok(w)) } - // TODO: (v0.13) Return statistics + /// Exports contract and operations to a stream, extending operation data with some auxiliary + /// information returned by `aux`. pub fn export_aux( &self, terminals: impl IntoIterator>, - mut writer: StrictWriter, - mut aux: impl FnMut(Opid, &Operation, StrictWriter) -> io::Result>, + writer: StrictWriter, + aux: impl FnMut(Opid, &Operation, StrictWriter) -> io::Result>, ) -> io::Result<()> { - let contract_id = self.contract_id(); - let mut queue = terminals .into_iter() .map(|terminal| self.0.state().addr(*terminal.borrow()).opid) @@ -331,17 +330,17 @@ impl Ledger { // Include all operations defining published state let state = self.state(); let mut collect = |api: &Api, state: &ProcessedState| { - for (state_name, immutable) in &api.immutable { - if immutable.published { - let Some(cells) = state.immutable.get(state_name) else { + for (state_name, owned) in &api.global { + if owned.published { + let Some(cells) = state.global.get(state_name) else { continue; }; opids.extend(cells.keys().map(|addr| addr.opid)); } } }; - collect(&articles.apis().default, &state.main); - for (api_name, api) in &articles.apis().custom { + collect(&articles.semantics().default, &state.main); + for (api_name, api) in &articles.semantics().custom { let Some(state) = state.aux.get(api_name) else { continue; }; @@ -349,17 +348,7 @@ impl Ledger { } opids.remove(&genesis_opid); - // Write articles - writer = articles.strict_encode(writer)?; - writer = aux(genesis_opid, &articles.genesis().to_operation(contract_id), writer)?; - // Stream operations - for (opid, op) in self.0.operations() { - if !opids.remove(&opid) { - continue; - } - writer = op.strict_encode(writer)?; - writer = aux(opid, &op, writer)?; - } + self.export_internal(opids.len() as u32, writer, |opid| opids.remove(opid), aux)?; debug_assert!( opids.is_empty(), @@ -374,56 +363,88 @@ impl Ledger { Ok(()) } - pub fn merge_articles( - &mut self, - new_articles: Articles, - sig_validator: V, - ) -> Result<(), MultiError> { - self.0.update_articles(|articles| { - articles.merge(new_articles, sig_validator)?; - Ok(()) - }) + /// Exports only operations for which `should_include` returns `true`. + /// + /// # Nota bene + /// + /// Does not write the contract id. + pub fn export_internal( + &self, + count: u32, + mut writer: StrictWriter, + mut should_include: impl FnMut(&Opid) -> bool, + mut aux: impl FnMut(Opid, &Operation, StrictWriter) -> io::Result>, + ) -> io::Result<()> { + let articles = self.articles(); + let genesis_opid = articles.genesis_opid(); + + // Write version number + writer = (DEEDS_VERSION as u8).strict_encode(writer)?; + // Write contract id + let contract_id = self.contract_id(); + writer = self.contract_id().strict_encode(writer)?; + // Write an empty extension block + writer = 0u8.strict_encode(writer)?; + // Write articles + writer = articles.strict_encode(writer)?; + writer = aux(genesis_opid, &articles.genesis().to_operation(contract_id), writer)?; + // Write no of operations + writer = count.strict_encode(writer)?; + // Stream operations + for (opid, op) in self.0.operations() { + if !should_include(&opid) { + continue; + } + writer = op.strict_encode(writer)?; + writer = aux(opid, &op, writer)?; + } + Ok(()) } - pub fn accept( + pub fn upgrade_apis(&mut self, new_articles: Articles) -> Result> { + self.0 + .update_articles(|articles| articles.upgrade_apis(new_articles)) + } + + pub fn accept( &mut self, reader: &mut StrictReader, - sig_validator: impl SigValidator, + sig_validator: impl FnOnce(StrictHash, &Identity, &SigBlob) -> Result<(), E>, ) -> Result<(), MultiError> { // We need this closure to avoid multiple `map_err`. - (|| -> Result<(), AcceptError> { - let magic_bytes = <[u8; 8]>::strict_decode(reader)?; - if magic_bytes != LEDGER_MAGIC_NUMBER { - return Err(DecodeError::DataIntegrityError(format!( - "wrong contract ledger magic bytes {}", - magic_bytes.to_hex() - )) - .into()); - } - let version = <[u8; 2]>::strict_decode(reader)?; - if version != LEDGER_VERSION { - return Err(DecodeError::DataIntegrityError(format!( - "unsupported contract ledger version {}", - u16::from_be_bytes(version) - )) - .into()); - } + let count = (|| -> Result { + // Check version number + let _ = ReservedBytes::<1, { DEEDS_VERSION as u8 }>::strict_decode(reader)?; let contract_id = ContractId::strict_decode(reader)?; - let apis = ApiDescriptor::strict_decode(reader)?; + + // Read and ignore the extension block + let ext_blocks = u8::strict_decode(reader)?; + for _ in 0..ext_blocks { + let len = u16::strict_decode(reader)?; + let r = unsafe { reader.raw_reader() }; + let _ = r.read_raw::<{ u16::MAX as usize }>(len as usize)?; + } + + // Read articles + let semantics = Semantics::strict_decode(reader)?; + let sig = Option::::strict_decode(reader)?; let issue = Issue::strict_decode(reader)?; - let articles = Articles::with(apis, issue)?; + let articles = Articles::with(semantics, issue, sig, sig_validator)?; if articles.contract_id() != contract_id { - return Err(AcceptError::Articles(ArticlesError::ContractMismatch)); + return Err(AcceptError::Articles(SemanticError::ContractMismatch)); } - self.merge_articles(articles, sig_validator) + self.upgrade_apis(articles) .map_err(|e| AcceptError::Persistence(e.to_string()))?; - Ok(()) + + let count = u32::strict_decode(reader)?; + Ok(count) })() .map_err(MultiError::A)?; - loop { + // We need to account for genesis, which is not included in the `count` + for _ in 0..=count { let op = match Operation::strict_decode(reader) { Ok(operation) => operation, Err(DecodeError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => break, @@ -431,6 +452,9 @@ impl Ledger { }; self.apply_verify(op, false)?; } + // Here we do not check for the end of the stream, + // so in the future we can have arbitrary extensions + // put here with no backward compatibility issues. self.commit_transaction(); Ok(()) } @@ -451,7 +475,7 @@ impl Ledger { } } self.0.update_state(|state, articles| { - state.rollback(transition, articles.apis()); + state.rollback(transition, articles.semantics()); })?; self.0.mark_invalid(opid); } @@ -523,7 +547,7 @@ impl Ledger { force: bool, ) -> Result> { if operation.contract_id != self.contract_id() { - return Err(MultiError::A(AcceptError::Articles(ArticlesError::ContractMismatch))); + return Err(MultiError::A(AcceptError::Articles(SemanticError::ContractMismatch))); } let opid = operation.opid(); @@ -581,7 +605,7 @@ impl Ledger { let transition = self .0 - .update_state(|state, articles| state.apply(operation, articles.apis()))?; + .update_state(|state, articles| state.apply(operation, articles.semantics()))?; self.0.add_transition(opid, &transition); self.0.mark_valid(opid); @@ -598,7 +622,7 @@ pub enum AcceptError { Io(io::Error), #[from] - Articles(ArticlesError), + Articles(SemanticError), #[from] Verify(CallError), @@ -610,4 +634,52 @@ pub enum AcceptError { Serialize(SerializeError), Persistence(String), + + #[cfg(feature = "binfile")] + #[display("Invalid file format")] + InvalidFileFormat, +} + +#[cfg(feature = "binfile")] +mod _fs { + use std::path::Path; + + use binfile::BinFile; + use strict_encoding::{StreamReader, StreamWriter}; + + use super::*; + + pub const DEEDS_MAGIC_NUMBER: u64 = u64::from_be_bytes(*b"DEEDLDGR"); + + impl Ledger { + pub fn export_all_to_file(&self, output: impl AsRef) -> io::Result<()> { + let file = BinFile::::create_new(output)?; + let writer = StrictWriter::with(StreamWriter::new::<{ usize::MAX }>(file)); + self.export_all(writer) + } + + pub fn export_to_file( + &self, + terminals: impl IntoIterator>, + output: impl AsRef, + ) -> io::Result<()> { + let file = BinFile::::create_new(output)?; + let writer = StrictWriter::with(StreamWriter::new::<{ usize::MAX }>(file)); + self.export(terminals, writer) + } + + pub fn accept_from_file( + &mut self, + input: impl AsRef, + sig_validator: impl FnOnce(StrictHash, &Identity, &SigBlob) -> Result<(), E>, + ) -> Result<(), MultiError> { + let file = BinFile::::open(input) + .map_err(|_| AcceptError::InvalidFileFormat) + .map_err(MultiError::from_a)?; + let mut reader = StrictReader::with(StreamReader::new::<{ usize::MAX }>(file)); + self.accept(&mut reader, sig_validator) + } + } } +#[cfg(feature = "binfile")] +pub use _fs::*; diff --git a/src/lib.rs b/src/lib.rs index ab3ee4d..b84ec72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,8 @@ // TODO: Activate once StrictEncoding will be no_std // #![cfg_attr(not(feature = "std"), no_std)] #![deny( - unsafe_code, + // TODO: Activate once StrictEncoding removes invalid unsafe fn modifiers from the raw reader + // unsafe_code, dead_code, // TODO: Complete documentation // missing_docs, @@ -63,6 +64,8 @@ mod ledger; pub mod stl; pub use deed::{CallParams, DeedBuilder, Satisfaction}; -pub use ledger::{AcceptError, Ledger, LEDGER_MAGIC_NUMBER, LEDGER_VERSION}; +pub use ledger::{AcceptError, Ledger}; +#[cfg(feature = "binfile")] +pub use ledger::{DEEDS_MAGIC_NUMBER, DEEDS_VERSION}; pub use state::{EffectiveState, ProcessedState, RawState, Transition}; pub use stock::{IssueError, Stock}; diff --git a/src/state.rs b/src/state.rs index efeee28..bbb54fe 100644 --- a/src/state.rs +++ b/src/state.rs @@ -22,10 +22,10 @@ // the License. use alloc::collections::BTreeMap; -use std::mem; -use amplify::confinement::{LargeOrdMap, SmallOrdMap}; -use sonicapi::{Api, ApiDescriptor, Articles, StateAtom, StateName}; +use aluvm::Lib; +use amplify::confinement::{LargeOrdMap, SmallOrdMap, SmallOrdSet}; +use sonicapi::{Api, Articles, Semantics, StateAtom, StateName}; use strict_encoding::{StrictDeserialize, StrictSerialize, TypeName}; use strict_types::{StrictVal, TypeSystem}; use ultrasonic::{AuthToken, CallError, CellAddr, Memory, Opid, StateCell, StateData, StateValue, VerifiedOperation}; @@ -66,7 +66,7 @@ impl EffectiveState { .verify(contract_id, genesis, &state.raw, articles)?; // We do not need state transition for genesis. - let _ = state.apply(verified, articles.apis()); + let _ = state.apply(verified, articles.semantics()); Ok(state) } @@ -79,7 +79,7 @@ impl EffectiveState { let state = ProcessedState::with(&me.raw, api, articles.types()); me.aux.insert(name.clone(), state); } - me.recompute(articles.apis()); + me.recompute(articles.semantics()); me } @@ -95,18 +95,19 @@ impl EffectiveState { } /// Re-evaluates computable part of the state - pub fn recompute(&mut self, apis: &ApiDescriptor) { - self.main.aggregate(&apis.default); + pub fn recompute(&mut self, apis: &Semantics) { + self.main + .aggregate(&apis.default, &apis.api_libs, &apis.types); self.aux = bmap! {}; for (name, api) in &apis.custom { let mut state = ProcessedState::default(); - state.aggregate(api); + state.aggregate(api, &apis.api_libs, &apis.types); self.aux.insert(name.clone(), state); } } #[must_use] - pub(crate) fn apply(&mut self, op: VerifiedOperation, apis: &ApiDescriptor) -> Transition { + pub(crate) fn apply(&mut self, op: VerifiedOperation, apis: &Semantics) -> Transition { self.main.apply(&op, &apis.default, &apis.types); for (name, api) in &apis.custom { let state = self.aux.entry(name.clone()).or_default(); @@ -115,7 +116,7 @@ impl EffectiveState { self.raw.apply(op) } - pub(crate) fn rollback(&mut self, transition: Transition, apis: &ApiDescriptor) { + pub(crate) fn rollback(&mut self, transition: Transition, apis: &Semantics) { self.main.rollback(&transition, &apis.default, &apis.types); let mut count = 0usize; for (name, api) in &apis.custom { @@ -199,16 +200,8 @@ impl RawState { pub(self) fn rollback(&mut self, transition: Transition) { let opid = transition.opid; - let mut immutable = mem::take(&mut self.global); - let mut owned = mem::take(&mut self.owned); - immutable = LargeOrdMap::from_iter_checked(immutable.into_iter().filter(|(addr, _)| addr.opid != opid)); - owned = LargeOrdMap::from_iter_checked(owned.into_iter().filter(|(addr, _)| addr.opid != opid)); - self.global = immutable; - self.owned = owned; - - // TODO: Use `retain` instead of the above workaround once supported by amplify - // self.immutable.retain(|addr, _| addr.opid != opid); - // self.owned.retain(|addr, _| addr.opid != opid); + self.global.retain(|addr, _| addr.opid != opid); + self.owned.retain(|addr, _| addr.opid != opid); for (addr, cell) in transition.destroyed { self.owned @@ -221,40 +214,55 @@ impl RawState { #[derive(Clone, Eq, PartialEq, Debug, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))] pub struct ProcessedState { - pub immutable: BTreeMap>, - pub destructible: BTreeMap>, + pub global: BTreeMap>, + pub owned: BTreeMap>, pub aggregated: BTreeMap, - pub invalid_immutable: BTreeMap, - pub invalid_destructible: BTreeMap, + pub invalid_global: BTreeMap, + pub invalid_owned: BTreeMap, } impl ProcessedState { pub fn with(raw: &RawState, api: &Api, sys: &TypeSystem) -> Self { let mut me = ProcessedState::default(); for (addr, state) in &raw.global { - me.process_immutable(*addr, state, api, sys); + me.process_global(*addr, state, api, sys); } for (addr, state) in &raw.owned { - me.process_destructible(*addr, state, api, sys); + me.process_owned(*addr, state, api, sys); } me } - pub fn immutable(&self, name: &StateName) -> Option<&BTreeMap> { self.immutable.get(name) } + pub fn global(&self, name: &StateName) -> Option<&BTreeMap> { self.global.get(name) } - pub fn destructible(&self, name: &StateName) -> Option<&BTreeMap> { - self.destructible.get(name) - } + pub fn owned(&self, name: &StateName) -> Option<&BTreeMap> { self.owned.get(name) } - pub(super) fn aggregate(&mut self, api: &Api) { - let empty = bmap![]; + /// Computes aggregated state. + /// + /// Ignores cycle dependencies between aggregators; the computed state with them is not + /// produced. + pub(super) fn aggregate(&mut self, api: &Api, libs: &SmallOrdSet, types: &TypeSystem) { self.aggregated = bmap! {}; - for (name, aggregator) in api.aggregators() { - let val = aggregator.read(|state_name| match self.immutable(state_name) { - None => empty.values(), - Some(src) => src.values(), - }); - self.aggregated.insert(name.clone(), val); + let mut computed = 0usize; + loop { + for (name, aggregator) in api.aggregators() { + if aggregator + .depends_on() + .any(|s| !self.global.contains_key(s) && !self.aggregated.contains_key(s)) + { + break; + } + let val = aggregator.aggregate(&self.global, &self.aggregated, libs, types); + if let Some(val) = val { + if self.aggregated.insert(name.clone(), val).is_none() { + computed += 1; + } + } + } + if computed == 0 { + break; + } + computed = 0; } } @@ -263,59 +271,56 @@ impl ProcessedState { let op = op.as_operation(); for (no, state) in op.immutable_out.iter().enumerate() { let addr = CellAddr::new(opid, no as u16); - self.process_immutable(addr, state, api, sys); + self.process_global(addr, state, api, sys); } for input in &op.destructible_in { - for map in self.destructible.values_mut() { + for map in self.owned.values_mut() { map.remove(&input.addr); } } for (no, state) in op.destructible_out.iter().enumerate() { let addr = CellAddr::new(opid, no as u16); - self.process_destructible(addr, state, api, sys); + self.process_owned(addr, state, api, sys); } } pub(self) fn rollback(&mut self, transition: &Transition, api: &Api, sys: &TypeSystem) { let opid = transition.opid; - self.immutable + self.global .values_mut() .for_each(|state| state.retain(|addr, _| addr.opid != opid)); - self.destructible + self.owned .values_mut() .for_each(|state| state.retain(|addr, _| addr.opid != opid)); for (addr, cell) in &transition.destroyed { - self.process_destructible(*addr, cell, api, sys); + self.process_owned(*addr, cell, api, sys); } } - fn process_immutable(&mut self, addr: CellAddr, state: &StateData, api: &Api, sys: &TypeSystem) { - match api.convert_immutable(state, sys) { + fn process_global(&mut self, addr: CellAddr, state: &StateData, api: &Api, sys: &TypeSystem) { + match api.convert_global(state, sys) { // This means this state is unrelated to this API Ok(None) => {} Ok(Some((name, atom))) => { - self.immutable.entry(name).or_default().insert(addr, atom); + self.global.entry(name).or_default().insert(addr, atom); } Err(_) => { - self.invalid_immutable.insert(addr, state.clone()); + self.invalid_global.insert(addr, state.clone()); } } } - fn process_destructible(&mut self, addr: CellAddr, state: &StateCell, api: &Api, sys: &TypeSystem) { - match api.convert_destructible(state.data, sys) { + fn process_owned(&mut self, addr: CellAddr, state: &StateCell, api: &Api, sys: &TypeSystem) { + match api.convert_owned(state.data, sys) { // This means this state is unrelated to this API Ok(None) => {} Ok(Some((name, atom))) => { - self.destructible - .entry(name) - .or_default() - .insert(addr, atom); + self.owned.entry(name).or_default().insert(addr, atom); } Err(_) => { - self.invalid_destructible.insert(addr, state.data); + self.invalid_owned.insert(addr, state.data); } } } diff --git a/src/stl.rs b/src/stl.rs index 23c0fd4..ffd3055 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -24,7 +24,7 @@ use aluvm::stl::aluvm_stl; use commit_verify::stl::commit_verify_stl; use sonic_callreq::LIB_NAME_SONIC; -use sonicapi::{Articles, ArticlesCommitment, ArticlesId}; +use sonicapi::{Articles, ArticlesId, Issuer, IssuerId}; use strict_types::stl::{std_stl, strict_types_stl}; use strict_types::typelib::LibBuilder; use strict_types::{CompileError, TypeLib}; @@ -34,7 +34,7 @@ pub use ultrasonic::stl::usonic_stl; use crate::Transition; /// Strict types id for the library providing data types for RGB consensus. -pub const LIB_ID_SONIC: &str = "stl:UbCQQ8_w-HU0Pv~L-dwNVHSM-TBrsBQC-N_vdFIG-DYFnUjs#page-ventura-shelf"; +pub const LIB_ID_SONIC: &str = "stl:FOnI~0yx-bcvd_Wq-~xjW37p-uqzQ3Nq-GGH8AtN-dO64ac8#river-atomic-dallas"; #[allow(clippy::result_large_err)] fn _sonic_stl() -> Result { @@ -47,8 +47,9 @@ fn _sonic_stl() -> Result { usonic_stl().to_dependency_types(), ]) .transpile::() + .transpile::() .transpile::() - .transpile::() + .transpile::() .transpile::() .compile() } diff --git a/src/stock.rs b/src/stock.rs index 4eb11a8..aa9807d 100644 --- a/src/stock.rs +++ b/src/stock.rs @@ -24,7 +24,7 @@ use core::error::Error; use amplify::MultiError; -use sonicapi::ArticlesError; +use sonicapi::SemanticError; use ultrasonic::{CallError, CellAddr, ContractName, Operation, Opid}; use crate::{Articles, EffectiveState, Transition}; @@ -117,6 +117,17 @@ pub trait Stock { /// This call MAY BE blocking. fn has_operation(&self, opid: Opid) -> bool; + /// Count the number of all known operations in the contract. + /// + /// # Nota bene + /// + /// Does not include genesis operation. + /// + /// # Blocking I/O + /// + /// This call MAY BE blocking. + fn operation_count(&self) -> u64; + /// Returns an operation ([`Operation`]) with a given `opid` from the set of known contract /// operations ("stash"). /// @@ -236,7 +247,7 @@ pub trait Stock { /// transitions that were ever provided via [`Self::add_transition`]. fn trace(&self) -> impl Iterator; - /// Returns an id of an operation reading a provided address (operation immutable state + /// Returns an id of an operation reading a provided address (operation global state /// output). /// /// # Nota bene @@ -255,8 +266,7 @@ pub trait Stock { /// [`Self::add_reading`] as an `addr` argument. fn read_by(&self, addr: CellAddr) -> impl Iterator; - /// Returns an id of an operation spending a provided address (operation destructible state - /// output). + /// Returns an id of an operation spending a provided address (operation-owned state output). /// /// # Nota bene /// @@ -286,8 +296,8 @@ pub trait Stock { /// updated state after calling the callback `f` method. fn update_articles( &mut self, - f: impl FnOnce(&mut Articles) -> Result<(), ArticlesError>, - ) -> Result<(), MultiError>; + f: impl FnOnce(&mut Articles) -> Result, + ) -> Result>; /// Updates contract effective state inside a callback method. /// @@ -339,7 +349,7 @@ pub trait Stock { /// the `transition` itself matches the known data for it. fn add_transition(&mut self, opid: Opid, transition: &Transition); - /// Registers a given operation immutable output (`addr`) to be read (used as an input) in + /// Registers a given operation global output (`addr`) to be read (used as an input) in /// operation `reader`. /// /// # Blocking I/O @@ -352,7 +362,7 @@ pub trait Stock { /// - add the `reader` to the list of readers who had accessed the address. fn add_reading(&mut self, addr: CellAddr, reader: Opid); - /// Registers a given operation destructible output (`spent`) to be spent (used as an input) in + /// Registers a given operation-owned output (`spent`) to be spent (used as an input) in /// operation `spender`. /// /// # Blocking I/O diff --git a/stl/SONIC.vesper b/stl/SONIC.vesper index 5d26c87..11659af 100644 --- a/stl/SONIC.vesper +++ b/stl/SONIC.vesper @@ -12,117 +12,2966 @@ -- Contract Articles -commitment ArticlesId, hasher SHA256, tagged urn:ubideco:sonic:articles#2025-05-18 - serialized ArticlesCommitment +commitment ApisChecksum, hasher SHA256, tagged urn:ubideco:sonic:apis#2025-05-25 + serialized U16 + hashed Api + map StrictHash, len 0..MAX16 + mapKey TypeName + mapValue StrictHash + set LibId, len 0..MAX16 + element LibId + serialized TypeSysId -rec ArticlesCommitment - bytes contractId, len 32, aka ContractId - bytes defaultApiId, len 32, aka ApiId - map customApiIds, len 0..MAX16 +rec Semantics + is version, U16 + rec default, Api + bytes codexId, len 32, aka CodexId + set conforms, len 0..MAX8 + is element, U16 + rec some, CallState, option, wrapped, tag 1 + ascii method, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + ascii some, option, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + map global, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, GlobalApi + bytes semId, len 32, aka SemId + enum published, Bool, false 0, true 1 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union rawConvertor, RawConvertor + bytes strictDecode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + union rawBuilder, RawBuilder + bytes strictEncode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + map owned, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, OwnedApi + bytes semId, len 32, aka SemId + union arithmetics, StateArithm + is fungible, Unit, tag 0 + is nonFungible, Unit, tag 1 + rec aluVm, LibSite, wrapped, tag 2 + bytes libId, len 32, aka LibId + is offset, U16 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + bytes witnessSemId, len 32, aka SemId + union witnessBuilder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + map aggregators, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + union value, Aggregator + is none, Unit, tag 0 + union some, SubAggregator, wrapped, tag 1 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union take, SubAggregator, wrapped, tag 2 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + tuple or, tag 3 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + rec aluVm, LibSite, wrapped, tag 4 + bytes libId, len 32, aka LibId + is offset, U16 + map verifiers, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is value, U16 + map errors, len 0..MAX8 + is key, U256 + str value, len 0..MAX8 + map custom, len 0..MAX16 ascii key, aka TypeName, first AlphaCapsLodash, rest AlphaNumLodash, len 1..100 - bytes value, len 32, aka ApiId + rec value, Api + bytes codexId, len 32, aka CodexId + set conforms, len 0..MAX8 + is element, U16 + rec some, CallState, option, wrapped, tag 1 + ascii method, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + ascii some, option, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + map global, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, GlobalApi + bytes semId, len 32, aka SemId + enum published, Bool, false 0, true 1 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union rawConvertor, RawConvertor + bytes strictDecode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + union rawBuilder, RawBuilder + bytes strictEncode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + map owned, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, OwnedApi + bytes semId, len 32, aka SemId + union arithmetics, StateArithm + is fungible, Unit, tag 0 + is nonFungible, Unit, tag 1 + rec aluVm, LibSite, wrapped, tag 2 + bytes libId, len 32, aka LibId + is offset, U16 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + bytes witnessSemId, len 32, aka SemId + union witnessBuilder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + map aggregators, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + union value, Aggregator + is none, Unit, tag 0 + union some, SubAggregator, wrapped, tag 1 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union take, SubAggregator, wrapped, tag 2 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + tuple or, tag 3 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + rec aluVm, LibSite, wrapped, tag 4 + bytes libId, len 32, aka LibId + is offset, U16 + map verifiers, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is value, U16 + map errors, len 0..MAX8 + is key, U256 + str value, len 0..MAX8 + set codexLibs, len 0..MAX16 + rec Lib + set isae, len 0..MAX8 + ascii element, aka IsaId, first AlphaCapsNum, rest AlphaCapsNum, len 1..16 + bytes code, len 0..MAX16 + bytes data, len 0..MAX16 + set libs, len 0..MAX8 + bytes element, len 32, aka LibId + set apiLibs, len 0..MAX16 + rec Lib + set isae, len 0..MAX8 + ascii element, aka IsaId, first AlphaCapsNum, rest AlphaCapsNum, len 1..16 + bytes code, len 0..MAX16 + bytes data, len 0..MAX16 + set libs, len 0..MAX8 + bytes element, len 32, aka LibId + map types, len 0..MAX24, aka TypeSystem + bytes key, len 32, aka SemId + union value, TySemId + is primitive, U8, wrapped, aka Primitive, tag 0 + is unicode, Unit, tag 1 + set enum, len 1..MAX8, wrapped, aka EnumVariants, tag 2 + rec Variant + ascii name, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is tag, U8 + map union, len 0..MAX8, wrapped, aka UnionVariantsSemId, tag 3 + is key, U8 + rec value, VariantInfoSemId + ascii name, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + bytes ty, len 32, aka SemId + list tuple, len 1..MAX8, wrapped, aka UnnamedFieldsSemId, tag 4 + bytes element, len 32, aka SemId + list struct, len 1..MAX8, wrapped, aka NamedFieldsSemId, tag 5 + rec FieldSemId + ascii name, aka FieldName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + bytes ty, len 32, aka SemId + tuple array, tag 6 + bytes _, len 32, aka SemId + is _, U16 + tuple list, tag 7 + bytes _, len 32, aka SemId + rec Sizing + is min, U64 + is max, U64 + tuple set, tag 8 + bytes _, len 32, aka SemId + rec Sizing + is min, U64 + is max, U64 + tuple map, tag 9 + bytes _, len 32, aka SemId + bytes _, len 32, aka SemId + rec Sizing + is min, U64 + is max, U64 + +rec Issuer + rec codex, Codex + bytes version, len 1, aka ReservedBytes1 + str name, len 0..MAX8 + ascii developer, aka Identity, first AsciiPrintable, rest AsciiPrintable, len 1..4096 + is timestamp, I64 + bytes features, len 4, aka ReservedBytes4 + is fieldOrder, U256 + rec verificationConfig, CoreConfig + enum halt, Bool, false 0, true 1 + is some, U64, option, wrapped, tag 1 + rec inputConfig, CoreConfig + enum halt, Bool, false 0, true 1 + is some, U64, option, wrapped, tag 1 + map verifiers, len 0..MAX8 + is key, U16 + rec value, LibSite + bytes libId, len 32, aka LibId + is offset, U16 + rec semantics, Semantics + is version, U16 + rec default, Api + bytes codexId, len 32, aka CodexId + set conforms, len 0..MAX8 + is element, U16 + rec some, CallState, option, wrapped, tag 1 + ascii method, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + ascii some, option, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + map global, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, GlobalApi + bytes semId, len 32, aka SemId + enum published, Bool, false 0, true 1 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union rawConvertor, RawConvertor + bytes strictDecode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + union rawBuilder, RawBuilder + bytes strictEncode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + map owned, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, OwnedApi + bytes semId, len 32, aka SemId + union arithmetics, StateArithm + is fungible, Unit, tag 0 + is nonFungible, Unit, tag 1 + rec aluVm, LibSite, wrapped, tag 2 + bytes libId, len 32, aka LibId + is offset, U16 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + bytes witnessSemId, len 32, aka SemId + union witnessBuilder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + map aggregators, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + union value, Aggregator + is none, Unit, tag 0 + union some, SubAggregator, wrapped, tag 1 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union take, SubAggregator, wrapped, tag 2 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + tuple or, tag 3 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + rec aluVm, LibSite, wrapped, tag 4 + bytes libId, len 32, aka LibId + is offset, U16 + map verifiers, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is value, U16 + map errors, len 0..MAX8 + is key, U256 + str value, len 0..MAX8 + map custom, len 0..MAX16 + ascii key, aka TypeName, first AlphaCapsLodash, rest AlphaNumLodash, len 1..100 + rec value, Api + bytes codexId, len 32, aka CodexId + set conforms, len 0..MAX8 + is element, U16 + rec some, CallState, option, wrapped, tag 1 + ascii method, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + ascii some, option, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + map global, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, GlobalApi + bytes semId, len 32, aka SemId + enum published, Bool, false 0, true 1 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union rawConvertor, RawConvertor + bytes strictDecode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + union rawBuilder, RawBuilder + bytes strictEncode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + map owned, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + rec value, OwnedApi + bytes semId, len 32, aka SemId + union arithmetics, StateArithm + is fungible, Unit, tag 0 + is nonFungible, Unit, tag 1 + rec aluVm, LibSite, wrapped, tag 2 + bytes libId, len 32, aka LibId + is offset, U16 + union convertor, StateConvertor + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + union builder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + bytes witnessSemId, len 32, aka SemId + union witnessBuilder, StateBuilder + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 + map aggregators, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + union value, Aggregator + is none, Unit, tag 0 + union some, SubAggregator, wrapped, tag 1 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union take, SubAggregator, wrapped, tag 2 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + tuple or, tag 3 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + rec aluVm, LibSite, wrapped, tag 4 + bytes libId, len 32, aka LibId + is offset, U16 + map verifiers, len 0..MAX8 + ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is value, U16 + map errors, len 0..MAX8 + is key, U256 + str value, len 0..MAX8 + set codexLibs, len 0..MAX16 + rec Lib + set isae, len 0..MAX8 + ascii element, aka IsaId, first AlphaCapsNum, rest AlphaCapsNum, len 1..16 + bytes code, len 0..MAX16 + bytes data, len 0..MAX16 + set libs, len 0..MAX8 + bytes element, len 32, aka LibId + set apiLibs, len 0..MAX16 + rec Lib + set isae, len 0..MAX8 + ascii element, aka IsaId, first AlphaCapsNum, rest AlphaCapsNum, len 1..16 + bytes code, len 0..MAX16 + bytes data, len 0..MAX16 + set libs, len 0..MAX8 + bytes element, len 32, aka LibId + map types, len 0..MAX24, aka TypeSystem + bytes key, len 32, aka SemId + union value, TySemId + is primitive, U8, wrapped, aka Primitive, tag 0 + is unicode, Unit, tag 1 + set enum, len 1..MAX8, wrapped, aka EnumVariants, tag 2 + rec Variant + ascii name, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is tag, U8 + map union, len 0..MAX8, wrapped, aka UnionVariantsSemId, tag 3 + is key, U8 + rec value, VariantInfoSemId + ascii name, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + bytes ty, len 32, aka SemId + list tuple, len 1..MAX8, wrapped, aka UnnamedFieldsSemId, tag 4 + bytes element, len 32, aka SemId + list struct, len 1..MAX8, wrapped, aka NamedFieldsSemId, tag 5 + rec FieldSemId + ascii name, aka FieldName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + bytes ty, len 32, aka SemId + tuple array, tag 6 + bytes _, len 32, aka SemId + is _, U16 + tuple list, tag 7 + bytes _, len 32, aka SemId + rec Sizing + is min, U64 + is max, U64 + tuple set, tag 8 + bytes _, len 32, aka SemId + rec Sizing + is min, U64 + is max, U64 + tuple map, tag 9 + bytes _, len 32, aka SemId + bytes _, len 32, aka SemId + rec Sizing + is min, U64 + is max, U64 + bytes some, len 1..4096, option, wrapped, aka SigBlob, tag 1 rec Articles - rec apis, ApiDescriptor + rec semantics, Semantics + is version, U16 rec default, Api - bytes version, len 1, aka ReservedBytes1 bytes codexId, len 32, aka CodexId - ascii developer, aka Identity, first AsciiPrintable, rest AsciiPrintable, len 1..4096 - ascii some, option, wrapped, aka TypeName, first AlphaCapsLodash, rest AlphaNumLodash, len 1..100, tag 1 + set conforms, len 0..MAX8 + is element, U16 rec some, CallState, option, wrapped, tag 1 ascii method, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 ascii some, option, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 - map immutable, len 0..MAX8 + map global, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 - rec value, ImmutableApi + rec value, GlobalApi bytes semId, len 32, aka SemId enum published, Bool, false 0, true 1 union convertor, StateConvertor - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 union builder, StateBuilder - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 union rawConvertor, RawConvertor bytes strictDecode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 union rawBuilder, RawBuilder bytes strictEncode, len 32, wrapped, aka SemId, tag 0 - map destructible, len 0..MAX8 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + map owned, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 - rec value, DestructibleApi + rec value, OwnedApi bytes semId, len 32, aka SemId - enum arithmetics, StateArithm, fungible 0, nonFungible 1 + union arithmetics, StateArithm + is fungible, Unit, tag 0 + is nonFungible, Unit, tag 1 + rec aluVm, LibSite, wrapped, tag 2 + bytes libId, len 32, aka LibId + is offset, U16 union convertor, StateConvertor - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 union builder, StateBuilder - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 bytes witnessSemId, len 32, aka SemId union witnessBuilder, StateBuilder - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 map aggregators, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 - union value, StateAggregator - ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 0 - ascii sumV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 - ascii listV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 - ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 - ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + union value, Aggregator + is none, Unit, tag 0 + union some, SubAggregator, wrapped, tag 1 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union take, SubAggregator, wrapped, tag 2 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + tuple or, tag 3 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + rec aluVm, LibSite, wrapped, tag 4 + bytes libId, len 32, aka LibId + is offset, U16 map verifiers, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 is value, U16 map errors, len 0..MAX8 is key, U256 str value, len 0..MAX8 - bytes reserved, len 8, aka ReservedBytes8 map custom, len 0..MAX16 ascii key, aka TypeName, first AlphaCapsLodash, rest AlphaNumLodash, len 1..100 rec value, Api - bytes version, len 1, aka ReservedBytes1 bytes codexId, len 32, aka CodexId - ascii developer, aka Identity, first AsciiPrintable, rest AsciiPrintable, len 1..4096 - ascii some, option, wrapped, aka TypeName, first AlphaCapsLodash, rest AlphaNumLodash, len 1..100, tag 1 + set conforms, len 0..MAX8 + is element, U16 rec some, CallState, option, wrapped, tag 1 ascii method, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 ascii some, option, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 - map immutable, len 0..MAX8 + map global, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 - rec value, ImmutableApi + rec value, GlobalApi bytes semId, len 32, aka SemId enum published, Bool, false 0, true 1 union convertor, StateConvertor - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 union builder, StateBuilder - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 union rawConvertor, RawConvertor bytes strictDecode, len 32, wrapped, aka SemId, tag 0 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 union rawBuilder, RawBuilder bytes strictEncode, len 32, wrapped, aka SemId, tag 0 - map destructible, len 0..MAX8 + rec aluVm, LibSite, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 + map owned, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 - rec value, DestructibleApi + rec value, OwnedApi bytes semId, len 32, aka SemId - enum arithmetics, StateArithm, fungible 0, nonFungible 1 + union arithmetics, StateArithm + is fungible, Unit, tag 0 + is nonFungible, Unit, tag 1 + rec aluVm, LibSite, wrapped, tag 2 + bytes libId, len 32, aka LibId + is offset, U16 union convertor, StateConvertor - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 union builder, StateBuilder - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 bytes witnessSemId, len 32, aka SemId union witnessBuilder, StateBuilder - is typedEncoder, U256, wrapped, tag 0 + is unit, Unit, tag 0 + is typedEncoder, U256, wrapped, tag 1 + is typedFieldEncoder, U256, wrapped, tag 2 + rec aluVm, LibSite, wrapped, tag 3 + bytes libId, len 32, aka LibId + is offset, U16 map aggregators, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 - union value, StateAggregator - ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 0 - ascii sumV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 - ascii listV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 - ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 - ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + union value, Aggregator + is none, Unit, tag 0 + union some, SubAggregator, wrapped, tag 1 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union take, SubAggregator, wrapped, tag 2 + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + tuple or, tag 3 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + union SubAggregator + tuple const, tag 0 + bytes _, len 32, aka SemId + bytes _, len 0..MAX8 + ascii theOnly, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii copy, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 2 + ascii unwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 3 + ascii first, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 4 + tuple nth, tag 5 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + ascii last, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 6 + tuple nthBack, tag 7 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + is _, U16 + union neg, StateSelector, wrapped, tag 8 + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple add, tag 9 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple sub, tag 10 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple mul, tag 11 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple div, tag 12 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple rem, tag 13 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + tuple exp, tag 14 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + union StateSelector + tuple global, tag 0 + ascii _, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 + enum Bool, false 0, true 1 + ascii aggregated, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 1 + ascii count, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 15 + ascii countUnique, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 16 + ascii setV, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 17 + ascii mapV2u, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 18 + ascii mapV2ListU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 19 + ascii mapV2SetU, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 20 + ascii sumUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 21 + ascii sumOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 22 + ascii prodUnwrap, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 23 + ascii prodOrDefault, wrapped, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100, tag 24 + rec aluVm, LibSite, wrapped, tag 4 + bytes libId, len 32, aka LibId + is offset, U16 map verifiers, len 0..MAX8 ascii key, aka VariantName, first AlphaSmallLodash, rest AlphaNumLodash, len 1..100 is value, U16 map errors, len 0..MAX8 is key, U256 str value, len 0..MAX8 - bytes reserved, len 8, aka ReservedBytes8 - set libs, len 0..MAX16 + set codexLibs, len 0..MAX16 + rec Lib + set isae, len 0..MAX8 + ascii element, aka IsaId, first AlphaCapsNum, rest AlphaCapsNum, len 1..16 + bytes code, len 0..MAX16 + bytes data, len 0..MAX16 + set libs, len 0..MAX8 + bytes element, len 32, aka LibId + set apiLibs, len 0..MAX16 rec Lib set isae, len 0..MAX8 ascii element, aka IsaId, first AlphaCapsNum, rest AlphaCapsNum, len 1..16 @@ -169,13 +3018,14 @@ rec Articles rec Sizing is min, U64 is max, U64 - bytes some, len 1..4096, option, wrapped, aka SigBlob, tag 1 + bytes some, len 1..4096, option, wrapped, aka SigBlob, tag 1 rec issue, Issue bytes version, len 1, aka ReservedBytes1 rec meta, ContractMeta enum testnet, Bool, false 0, true 1 enum consensus, Consensus, none 0, bitcoin 16, liquid 17, prime 32 is timestamp, I64 + bytes features, len 6, aka ReservedBytes6 union name, ContractName is unnamed, Unit, tag 0 ascii named, wrapped, aka TypeName, first AlphaCapsLodash, rest AlphaNumLodash, len 1..100, tag 1 @@ -185,11 +3035,12 @@ rec Articles str name, len 0..MAX8 ascii developer, aka Identity, first AsciiPrintable, rest AsciiPrintable, len 1..4096 is timestamp, I64 + bytes features, len 4, aka ReservedBytes4 is fieldOrder, U256 - rec inputConfig, CoreConfig + rec verificationConfig, CoreConfig enum halt, Bool, false 0, true 1 is some, U64, option, wrapped, tag 1 - rec verificationConfig, CoreConfig + rec inputConfig, CoreConfig enum halt, Bool, false 0, true 1 is some, U64, option, wrapped, tag 1 map verifiers, len 0..MAX8 @@ -202,6 +3053,7 @@ rec Articles bytes codexId, len 32, aka CodexId is callId, U16 is nonce, U256, aka Fe256 + bytes blank0, len 1, aka ReservedBytes1 bytes blank1, len 2, aka ReservedBytes2 bytes blank2, len 2, aka ReservedBytes2 list destructibleOut, len 0..MAX16 @@ -217,15 +3069,32 @@ rec Articles is first, U256, aka Fe256 is second, U256, aka Fe256 is third, U256, aka Fe256 - rec quadripple, tag 4 + rec quadruple, tag 4 is first, U256, aka Fe256 is second, U256, aka Fe256 is third, U256, aka Fe256 is fourth, U256, aka Fe256 is auth, U256, aka AuthToken, aka Fe256 - rec some, LibSite, option, wrapped, tag 1 - bytes libId, len 32, aka LibId - is offset, U16 + rec some, CellLock, option, wrapped, tag 1 + union aux, StateValue + is none, Unit, tag 0 + rec single, tag 1 + is first, U256, aka Fe256 + rec double, tag 2 + is first, U256, aka Fe256 + is second, U256, aka Fe256 + rec triple, tag 3 + is first, U256, aka Fe256 + is second, U256, aka Fe256 + is third, U256, aka Fe256 + rec quadruple, tag 4 + is first, U256, aka Fe256 + is second, U256, aka Fe256 + is third, U256, aka Fe256 + is fourth, U256, aka Fe256 + rec some, LibSite, option, wrapped, tag 1 + bytes libId, len 32, aka LibId + is offset, U16 list immutableOut, len 0..MAX16 rec StateData union value, StateValue @@ -239,7 +3108,7 @@ rec Articles is first, U256, aka Fe256 is second, U256, aka Fe256 is third, U256, aka Fe256 - rec quadripple, tag 4 + rec quadruple, tag 4 is first, U256, aka Fe256 is second, U256, aka Fe256 is third, U256, aka Fe256 diff --git a/stl/SONIC@0.12.0.sta b/stl/SONIC@0.12.0.sta index 04cb3bc..aacc04c 100644 --- a/stl/SONIC@0.12.0.sta +++ b/stl/SONIC@0.12.0.sta @@ -1,108 +1,148 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:UbCQQ8_w-HU0Pv~L-dwNVHSM-TBrsBQC-N_vdFIG-DYFnUjs#page-ventura-shelf +Id: stl:FOnI~0yx-bcvd_Wq-~xjW37p-uqzQ3Nq-GGH8AtN-dO64ac8#river-atomic-dallas Name: SONIC Dependencies: - UltraSONIC#stuart-memphis-english, + UltraSONIC#korea-helena-moral, FiniteField#report-canal-convert, Std#delete-roman-hair, AluVM#reward-accent-swim, CommitVerify#biology-news-adam, StrictTypes#henry-heart-survive -Check-SHA256: 51ebeec2ece1cc4224690d1f571b20f2ee7ce457e9ad25311f0cf22560373fe6 +Check-SHA256: b34662b632c92fa486f67da170dfe364d4566dba66eb5e6517acda1ff2328203 -1yfH>Nkax2{ckC{@g>lC**6;}%ie4wrTWpLzfxZ1G^f?j#teQ6Rcv%}VN*{|NkcYmGKAh0u07FCu`OJL +1yfH>Nkaw%;f44dg~&Q2=;?I9qH&bcwM9oixB$7nbmjvJRcv%}VN*{|NkcYmGKAh0u07FCu`OJL wc+Ab)ZtUdGtGq-ROf^i(%1_|X>MtBWkzXbY-ECo>rD>}a8$2!O9kk`*PSB+rd(so&!uOW`TABoF=_)- bY!<#DYTERN5LY|W}eb+cSx&f8ZJNz$h;V?MKQD~=g$Q}Y;{&mz -0|-HmqX$fBVpC~!Weh`aZEb0ER%LQ&W_beullNeFa6}P}rq7L!(40)FbL%msz%JU8hqvFyoea2o4pL=v -WpZ|9WI}m#WpgphxGg*8X!CPrawgw_sqk4BX8}k^^xj-FXm+)yumJ%MQe|^xa&~28LV0v$b29#d7D?ZD -zCQez5c=X9w<(f6`q$DH-G17V_XV{1(H;&`Wpib6c4cHjd30rSI15H;ZfSI7MrmbiWB~v%@u@)Mrf2N# -*9;Bok=Lw{#;}1pYA|B&5l=sLg;{n5MrATJHUm?1WCj38z9SbZ=!8X@=Yuq$20sb<4l#S`iz7Vef}@Ca -=a#q*L33kiX;5-$ZggQ{Y-M4FBGG%U@MZ$v=XJ?|;InIPy66cFfOYp#JM2r7_DuvrZ*OdRM~0;jPqm@t -3InIR0Ny%Ft`YGAh^_-OV-~qNrBQ4QL2PhnVMAeXb53<_mBYQsO#)!~acU7f_DL;WP9vC(GXyXN$~M|< -ZtiEa4nb^iXkkuuZA@=uVRLA?gMQ~gu96el>ojDN{iR+YxT1qeJQTRI%yh?{hxxA$L2PhnVMAeXb4+h! -VRLBFJq*Jt8?Abrta^#~Iw-!oZ%zqO(A&rh^vGm~tg_w^L2PhnVN-2kY-~(#WMOk?3sZD*X=8L$d2nTO -4*&^LN2X=Q9=Q)O*QWK$LhgcQkwbf~^M){{|8P%hsRk~m~ep32F151Y4WWC&DwaAi(mZDnMP -)DN(0hN+Kdp}ZAoN($wDX8VgT7DmW3qm%zcviBmGB|7z0dgBIJ4&sCG^VR$+2!VQzGR -(<~&{!{{>E!(#o&^pB98KZhv1GEPn8Orhb4n;8ZMQ)zl>ZfBCy0{K32d-H~a`3x8b375ImR&CF_#3#*g -z1^xtuG$bzVQpn(MrmbiWOGwxZAoO8A%m*X98W>f2s0TH8C&EH;|vtDTYgh)4~t7}WW`YoMQ(L%R$+2! -VQzGDn938Qb#DiI%LhXtBc@pg0t!L7$2{bU&sPXOO(dS=5LRJwX<=@3Np5CuQ)O*QWc?UbbJ9Xwr}~3w -v^yxa@v}v^+kiGSR2X#8M$tG2GZIy9X>V>;VRC6_vj93RHP;Wm9=`bY*P{Rcv%}VN*{|Nkb3-20V5ur0u+o0?}LIOoa(bEuT%$d<#qu_#(K#)`wcVHr!+M; -CFW=`nIc;Wkg|gVV6$1HFC=y{}}R_Q*J0R1B>UK2GYvJ63|a_$rvECDhxw!Zgg^CV{}br -bYYnU{T?dQJ?d;o1M7&`K~vb;q0WUv*UkDBz!||TdTRtvaA{h5j^*S;NLvL<$a$#e1No1*c{_J;U_rqi{QnVN{nRqfLcrXOCpfhv|^|vQ>r$q`=bYXO5R$**)WwVJm -&y+EOWgjT<3G&iWor^UN2TqE@U#9z`!g(#dX9+=dbZAs>Yh`Y=tm{9}qo!Lcbf&x`)m=B!6PPbxdmBJ+ysRCuhj -fe;8oWo&FgWMp#vS;NBVT;TAYsL|^P+?^W;{W$E31sqn+dpk{-*m~XvQek&QVRT^;00TjAX$A`ic4cyN -X>V=D) -VQg#w1OfmAZf|a7000011aog~WdH>M0X%2<`V5Xnw4=-d1_`8fg(m2+l}g^fB0Ix1nd=gGR0(NqZFO{E -Vr*pq3Ige#lIJ@>mw%Cdg|0Y-zbj2Rx3qrTq9O+L -X<}?;015)>o|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsMhQW&>`ZdvNB=ndTz*X~v;Uq>`<)y^X -ImOPdju4LltNnE-i;TQ3%drg8%%I^CQIwq*dJYu;XHGe+*SPIz0000000000{{R30000003t?wxa%E>> -bZ>HV015)>o|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsMhQW&>`ZdvNB=ndTz*X~v;Uq>`<)y^X -ImOPdju4LlP_|gH@^X90*fSzmn?9WqPQ+$h-?iz50p(P||0m=?fQ^Mv6fMp@;h#Lzj# -&aRFSj{pDy0000000000{{R300000024!+`Z*p@03IG5g00;m90000000000{{R30000000000000000 -{{R30000002y$g}WpZ|9WCFl_aF}ei((p}N63i?Ao0t8`jX>$SJ -9siF)3+wX*?!T{$^^}9&=~=CYDEP^!wu&X>)URWda)gZz;O*CD3`V{ckC{@g>lC**6;}%ie4wrTWpLzfxZ1G^f?j#teR+2rNlD$O59e#ogQsB77jPl+h5j^*S;PWMyVyb!>D&aA`?o0aYcT@|=XRf8Y4DYa&&29Y-Mvv -WCZ~L2LJ#-AOHzNVQg$ubYXO51_B0cWprq7WCH1)lIJ@>mw%Cdg|0Y-zbj2Rx3qrTq9O+M -0_mQT=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1Pzi>?iz50p(P||0m=?fQ^Mv6fMp@;h#Lzj#&aRFS -j}Js;b98cbV{~a^Y-K@kX$A%bb7gHwWCH1)lIJ@>mw%Cdg|0Y-zbj2Rx3qrTq9O+ioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^s;a%psEZDn+6V{-u$>DSa*F}@^iR=SSZsl%<9x7%5c`Pgg1 ->*6SA4`go%V{dMDWpZ?Hask!tc##wDDTpb41x7TQGY_({=Mml9HeuWd+bur_-FgRNb!lv5WpV+sv@tSo -n5m^R`PKb@ckeY@gb5%flTc|INn`@)o|5M~K$m}!eub_$g}*CJ -IJdNZ+@c}}C`8q6D?CtZ1fvw5rj-B|XP@r^w5ufb=C_Ju$l1`nW&GEpSWb-zaCKsAX>(|0WCDVT>rD>} -a8$2!O9kk`*PSB+rd(so&!uOW`TABoF=}CkBGG%U@MZ$v=XJ?|;InIPy66cFfOYp#JM2r7_Du<6Z*F#F -a&&KU0oCnzkrVGJh$(&rMl_l;53;f65#8K2VcZDYEk6g{dIw^4X>4R=asjfmF*0wMsiiad)%|~W?=@S5 -2_PnuP-zG2)3bR@KyMnJsLn`3qQl3l$S_}cqNugy+RLGsy^KRA3UXn0 -LUn0uWMy&zswNGMM3Wf{@wTE{xZtXp*v(*K-`<$zXObH-yflim3Q}QrLUn0uWMy&$0RRkhbaH89bVY7s -Z)9Zv1pxx-o|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CtZ1fvw5rj-B|XP@r^w5ufb=C_Ju$l1`n -W&GEpSWb-$Qek&PZ*F#Fa&&KU1OWgHb98cPV{}AiV{c?-00jX8>7J73J3yCzk$#1)IEB9}O*pr-e%zuW -2Pj0c;WkF|Wa%E>>bZ>G51px(PZ*^{T00jX8>7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0< -ZYw-c35LOoBKkGaY9#cS7Qj{WgyAGcS>>g~&^g7mw%Cdg|0Y-zbj2R -x3qrTq9O+?iz50p(P||0m=?fQ^Mv6fMp@;h#Lzj#&aRFSk0JzfWpq{m -1pxx-o|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsMhQW&>`ZdvNB=ndTz*X~v;Uq>`<)y^XImOPd -ju4M925n(*Rx)(}1pxx-o|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsMhQW&>`ZdvNB=ndTz*X~v -;Uq>`<)y^XImOPdju4LvQ*>c;WkGUjbZBh@0tjYxZf9v?Y-IooZf|Zzb#7;AVr*pr3{!MrbY((yX>4R= -as&YY40L&LWn@KeV{c?-asUMZ001BkQ*>c;WkYXnc4cyOZ*l|y01R|_aAjmgZewp`WpV%o0RR9X3RH4o -ZgXjLX>V=@0t9bxX=DN#{ckC{@g>lC**6;}%ie4wrTWpLzfxZ1G^f?j#teR$1pOW=(>>~JNCWGL*g;d+ -+M&*cL)Xpv6~Gz6EP87RWMy-7a&LKMWB>{R8vSo6y748@dD%A`C(GV!Bc=M$qQ6pJ?^qX=Q9=0RS=asX*kWXYB6R3=Qj%*Q}7nuz@;iFkmb;*F>vukd;=m`ygb@x#_>`RmOO$0)3Z)|!;hNTZrwV~w-1E;$H-a1RJ5%B|vt^+e; +7P&d4QEUuBY;b5{Lt$`pPIYaS!@bE(0$}-ZY7sp4NiAJYBbbge1TY24Hrj1&?q{?PL2PhnVNP{zOmAdi +b7;APe&;~0k`vnNG-Q(frCuPoqJv316u7g@bjO{C`L7Q_Y;b5{Lt$`pOmAdib7;{$48tlLt$LiSdWrZt +D89RIP6<)a+sF&_$Yh7CvfdCuY;b5{Q*B{vY)o%tVRL8;Q*?4^V{}w`aAk83011Y{iz50p(P||0m=?fQ +^Mv6fMp@;h#Lzj#&aRFSj|)~|a%o|1bWUMyWgE0u0rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~atTIh +Wo%?lVQpn3W7@xbO7ZHEAn(6`!pDiBSCZ86`=cyam?N@6JWikDr@YkEAs#9)9JJvRH +-Qc7Q2s%Kf+=VCyOABEU3kOtrQ)O*QWJFFoaz*WZZ5##rf6bm&7qffY6*N`B##bI~HzDmr7z##dWo%?q +Wo=1hQx*t>6v={gsJ=SZlTl1iF5eQ8IAl(q%E@>So406W2vm7+WlmvjWn_%h53p;7sgGx&z)8&prN#D& +cR=tS@df05SQ3Z*PZCvbZeeX@WJYOaY-Dp&Wo=1hYXqYdo~D%m7H6OD0<^0n_2##VWXRdjy=DB@qgYOj +1yf~hNo0M=LMPN>0NEy%g(UCHeUkYj{YR7-159lqXIqm$}teZO^;JC(UrZ-Ks{e+7M1*ZDnLeX=Q9= +b5mt)No1EHgR0RSPeIWLGZ_*YTjUMn3>33lep74@i%V@}#Ze4JZgp)|VRC6;+#Z*Ep$a%o|1baPW>ZAoPPfv$so3kRF1PV2}fOp_vjQ6FdFHId|c;Wkg|gVJaZyb^%Am +ddWHa4KviIG&MIR=4dgQCM`MQ0t_o8Y6(McZgXXBb9HkGI~)ojbzlK9RlMPSsRAF{u3`1{jbaG*1bWLS+VP;J4i*)JNux}oPU70Tdu0t8K($c?_!S>o~ +*oLTaD+ohnY-~(#V{3YUMz^{f^4P10B0i_1BZ+HXyoMYO`#lf0*V91r>--8+bYXO5R$**)Wr?xcYv24& +K>40oE_H6?>)2+;e*jh+U^b^tM?X0L)&)avWMz1eGT8kA;5NZv^)A=~l$Hu3;R{+3y%_^C98!aE0Z@zu +Npo{`Wtjy19xBs4>TE~@>xkGvQ`p*}&V@tQ&H5F<8Nn=iYXnblX=I-WEJ-@Z0;0Ob-P{Wzd?2rs)M&&= +&l*}G;Jw22Ix-4FZ*FvQVPkYjWV4Al&y+EOWgjT<3G&iWor^UN2TqE@U#9z`!g(#dX9+=dbZAs>Yh`Y= +tm{9}qo!Lcbf&x`)m=B!6PPbxdmBJ+ysRCuhjfe;8oWo&FgWMp#vS;NBVT;TAYsL|^P+?^W;{W$E31sqn+dpk{- +*m~XvQek&QVRT^>01828XL4m{VRUbD1O)&DZf|a7000011aog~WdH>M0sGFKbHJ&K=73;xT9e8zPrRwV +e+qg8W^KOf5Mb-Ek^%&DVQXao1pxv3&Yg3>sf*@-U~^iN$}dm6slI;-dIV-|zUvTR>#>pp0&j8v1p)#4 +&Yg3>sf*@-U~^iN$}dm6slI;-dIV-|zUvTR>#>pn`_7$nz^RMofM9c4lgckoys5r_3VH-)ZNBReVC%7x +{{>-ebyjTv1pxxLSt+!Stw+Hk(Po~~Zg)tlXc{g+3dp<|u0=7lDd*4D^W8yOb6|fgT149yr~sO2Tv2Na +_ZHTZ79ax%L5`yXL2zjX2nStW$T}qG>2$%Oag@@vMMpol0J*+&<^#2?>p#$= +rdum?r*`71Hb|_zg6yfI1@tx1ME;WCJU|FzZ*FF9a&2<}2><{B0000000000{{R30000003uI+xVRdYD +Lt$)e00aU61a5C`WdHyG0R(ezZDjxj0Ri0Lw|vJna{%YhJnSPknsk9=N+~z1q~pntg8OOz-6aNRY;R&= +Yyb)Z>7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0>g~&^g7< +u8t6o0XBgx0(F)jmyrc;VduO*=JF%lv}*bo)cWw1DVCi!sQ>@~000000RI300000000nP%Ze?Tu3Ige# +lIJ@>mw%Cdg|0Y-zbj2Rx3qrTq9O+mw%Cdg|0Y-zbj2Rx3qrTq9O+7J73 +J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0>g~&^g79000000003000000000000000000030000000000C +L2zkvLuh4VYjbsN1pxpD002M)00=>HbZKL3Wpf4t33Fv_VQzG3V{-v6x#Pn^I>)lX=EHRe6Paghwt^*k +k9ki&&;$Y0w$||jb7^M)1OfmAZf|a7000011aog~WdH>M0U^g1ZO|$}9Zg=R%ZE7et&pz}oUddU0B(<> +YerIc3k7L&b9H3`1mw(?1L1}E9EHd_BlVD&E80+f~tBjF2L +5xp4$G8|HaaRE?_3PEyoX=7|g3r=7)ofip1VQg$ubYXO51_B0cWprq7WCH1)lIJ@>mw%Cdg|0Y-zbj2R +x3qrTq9O+mw%Cdg|0Y-zbj2Rx3qrTq9O+WBLk*fW6RH_ +XPEi=Ry;9kVTK~nd#>)EJkp+4hb9<(4 +Us(8&D-dci;zs8W_%*U=u#QOwVs&Y3WMy&zL1&V2o**cr;@RA^i_^yDJVpBQO{s7F8GT|w6)bIX402(2 +LvL<&WpZ?Hasj8~b=Ol1`flL;V4R=asm5cRyk`k?kWEQ +dWrTza1nu+B|GJQ%{OSD#2Xf2lLZDzb8~fNas~qhV{c?-cmf3E%$5V;h4>tW$T}qG>2$%Oag@@vMMpol +0J*+&<^zeb+H2qZPeA#eSuS;M9;f44dg~&Q2=;?I9qH&bcwM9oixB$7nbmjxK +tm{9}qo!LcbfV=-00IbOXk}w-b9HS24rs`h%>r>-9X0IN +!p14WBr9LqgTBPo;{gj!U^Sf=2v2uzWn@8cX$A%bb7gHwWCH1)lIJ@>mw%Cdg|0Y-zbj2Rx3qrTq9O+< +MAdF9JWy){qZFQ|l>ioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^s;a%psEZDn+6V{-wsgItsAv)By!kd;ZK +Pd!7nxtnV;v+f7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0-ebyjTv1pxxLSt+!Stw+Hk(Po~~Zg)tlXc{g+3dp<|u0=7lDd*4D^W8yOb6|fgT149yr~sO2 +Tv2Na_ZHTZ79ax%L5`ygQek&PZ*F#Fa&&KU1OfmIb98cPV{}AiV{c?-00jX8>7J73J3yCzk$#1)IEB9} +O*pr-e%zuW2Pj0-ebyjTv1pxxLSt+!S +tw+Hk(Po~~Zg)tlXc{g+3dp<|u0=7lDd*4D^W8yOb6|fgT149yr~sO2Tv2Na_ZHTZ79ax%L5`ydQ)O*o +Zggp5a|Q+nc4cyNX>V=-00IYOWoBV@Y;*zm&z?vG7(!mC=1~h}ANI>At43DT^Vis5AIXv$ng?zMV|81Ch@9YYCa> +3uf#90000000030{{R3000007VQ^_oX<~B#2?DoSDYTERN5LY|W}eb+cSx&f8ZJNz$h;V?MKQD~=g&i7 +o!sA0+CHx-vZbVj7D6D}#pW3Uk@391OosFW_507X<}?;000013vO?2Ms;pyX<}?;00030 +1z~J;R&4+U0Rp#KDYTERN5LY|W}eb+cSx&f8ZJNz$h;V?MKQD~=g-#j-9cJ&V1F!HMB5jr0GerBQELnL +7S@v%AOi?Nj-w1ybYXO5LUn0uWMy&$1ONneZfSG?000mSba`-PWJPXcZ)9b100jX603Z<&ba`-PWJYOa +Y-B}lV{c?-asUMZ001EW1z~J;R&4+U0Rp#KDYTERN5LY|W}eb+cSx&f8ZJNz$h;V?MKQD~=g-#j-9cJ& +V1F!HMB5jr0GerBQELnL7S@v%AOi?Nj-w7!bYXO5LvL<&WpZ?Has&hb1a)p{bN~PV5DavAaAjmgZewp` +WpV%o0RR9X5fOBGaAjmhX=Q9=MQ&qnWMy&y1pxp6ApZqnY;{&`00jX8w^=E)kF7_+BGG1^(r$N1t7sZ7 +Knlpb7_LPzv?=G$*7My#T6183ELud{7pMT5X7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0>g~ +&^g7mb;*F>vukd;=m`yg +b@x#_>`RmOO#upFXJ>L{XJK?@WB>&L0_mQT=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1Pzi>?iz50p +(P||0m=?fQ^Mv6fMp@;h#Lzj#&aRFSj}23GVnJtTa%E>>bZ>G582|-iZ*FsR00ja9>7J73J3yCzk$#1) +IEB9}O*pr-e%zuW2Pj0mw%Cdg|0Y-zbj2Rx3qrTq9O+7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0>g~&^g77J73J3yCzk$#1)IEB9}O*pr- +e%zuW2Pj0>g~&^g7`ZdvNB=ndTz*X~v;Uq>`<)y^XImOPdju4Lp18#I^00ja9 +>7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0>g~&^g7?iz50p(P||0m=?fQ^Mv6f +Mp@;h#Lzj#&aRFSj|T^CbZA0hV`~5f0s`rtlIJ@>mw%Cdg|0Y-zbj2Rx3qrTq9O+0qXeK0Y#)KxnIwmOLf+#6k?&Zs#$uxiG|AD|W4^lb +KBEMn4QwBQ*qJ1UeL~*j5(9H}VgLmK0g>-mvBqMf3N*>l*JHlA@;;*kpbcyvf!LWOhkZic;{lQHSh2=p +qY5<1(br?Xy7E4w1fUIUAA#7JB!_)M-s2MkZFOt_1p)z)?^v0qXeK0Y#)KxnIwmO +Lf+#6k?&Zs#$uxiG|AD|W4^lbKBEMn4QwBQ*qJ1UeL~*j6a!>wb^rwe0g>-mvBqMf3N*>l*JHlA@;;*k +pbcyvf!LWOhkZic;{lQHSh2=pqY5<1(br?Xy7E4w1fUIUAA#7JB!_)M-s2Sma%F7*1p)z)?^v0qXeK0Y#)KxnIwmOLf+#6k?&Zs#$uxiG|AD|W4^lbKBEMn4QwBQ*qJ1UeL~*j76WB?Z~z4Y +0g>-mvBqMf3N*>l*JHlA@;;*kpbcyvf!LWOhkZic;{lQHSh2=pqY5<1(br?Xy7E4w1fUIUAA#7JB!_)M +-s2zzV{dhCbN~eb0_mQT=Q}``f02HLt~iCiD@{1Jw0_*8A_pi$)ov?1Pzi>?iz50p(P||0m=?fQ^Mv6f +Mp@;h#Lzj#&aRFSk0A?VZ*^{TRc>imw%Cdg|0Y-zbj2Rx3qrTq9O+7J73J3yCzk$#1)IEB9}O*pr-e%zuW +2Pj0>g~&^g77J73J3yCzk$#1) +IEB9}O*pr-e%zuW2Pj0>g~&^g7)W{ +00jX8>7J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0>g~&^g7< +u8t6oB?)a|a8@!?Wpq^l1pxx-o|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsMhQW&>`ZdvNB=ndT +z*X~v;Uq>`<)y^XImOPdju4M933GLARc?23VQ>Hi0RrislIJ@>mw%Cdg|0Y-zbj2Rx3qrTq9O+7J73J3yCzk$#1) +IEB9}O*pr-e%zuW2Pj0>g~&^g77J73J3yCzk$#1)IEB9}O*pr-e%zuW2Pj0>g~&^g7< +u8t6oGYxQZZ)8t$L}g}Sb!>D11pxx-o|5M~K$m}!eub_$g}*CJIJdNZ+@c}}C`8q6D?CsMhQW&>`ZdvN +B=ndTz*X~v;Uq>`<)y^XImOPdju4LuRB~Z%b7^#GZ*B$x1aEL@WC8@_%$5V;h4>tW$T}qG>2$%Oag@@v +MMpol0J*+&<^!1o{T?dQJ?d;o1M7&`K~vb;q0WUv*UkDBz!||TdTR+}Wpi|LZ+T^8015&G;f44d +g~&Q2=;?I9qH&bcwM9oixB$7nbmjy5rN?q$uLxQs2Fvw;u-1mw(?1L1}E +9EHd_B ^ ..0xff ImmutableApi} - , destructible {StrictTypes.VariantName -> ^ ..0xff DestructibleApi} - , aggregators {StrictTypes.VariantName -> ^ ..0xff StateAggregator} + , global {StrictTypes.VariantName -> ^ ..0xff GlobalApi} + , owned {StrictTypes.VariantName -> ^ ..0xff OwnedApi} + , aggregators {StrictTypes.VariantName -> ^ ..0xff Aggregator} , verifiers {StrictTypes.VariantName -> ^ ..0xff U16} , errors {U256 -> ^ ..0xff [Unicode ^ ..0xff]} - , reserved CommitVerify.ReservedBytes8 -@mnemonic(felix-dinner-forbid) -data ApiDescriptor : default Api - , custom {StrictTypes.TypeName -> Api} - , libs {AluVM.Lib} - , types StrictTypes.TypeSystem +@mnemonic(viva-index-tempo) +data ApisChecksum : [Byte ^ 4] + +@mnemonic(project-freddie-oasis) +data Articles : semantics Semantics , sig SigBlob? + , issue UltraSONIC.Issue -@mnemonic(sharp-section-left) -data ApiId : [Byte ^ 32] +@mnemonic(pigment-melon-smart) +data ArticlesId : contractId UltraSONIC.ContractId + , version U16 + , checksum ApisChecksum -@mnemonic(visible-kinetic-stella) -data Articles : apis ApiDescriptor, issue UltraSONIC.Issue +@mnemonic(sparta-ginger-analyze) +data CallState : method StrictTypes.VariantName, owned StrictTypes.VariantName? -@mnemonic(distant-east-ritual) -data ArticlesCommitment : contractId UltraSONIC.ContractId - , defaultApiId ApiId - , customApiIds {StrictTypes.TypeName -> ApiId} +@mnemonic(polaris-yellow-public) +data GlobalApi : semId StrictTypes.SemId + , published Std.Bool + , convertor StateConvertor + , builder StateBuilder + , rawConvertor RawConvertor + , rawBuilder RawBuilder -@mnemonic(danube-pilot-karate) -data ArticlesId : [Byte ^ 32] +@mnemonic(salon-record-hope) +data Issuer : codex UltraSONIC.Codex + , semantics Semantics + , sig SigBlob? -@mnemonic(alpha-balsa-verona) -data CallState : method StrictTypes.VariantName, destructible StrictTypes.VariantName? +@mnemonic(laser-george-europe) +data IssuerId : codexId UltraSONIC.CodexId + , version U16 + , checksum ApisChecksum -@mnemonic(career-ultra-harbor) -data DestructibleApi : semId StrictTypes.SemId +@mnemonic(history-support-manual) +data OwnedApi : semId StrictTypes.SemId , arithmetics StateArithm , convertor StateConvertor , builder StateBuilder , witnessSemId StrictTypes.SemId , witnessBuilder StateBuilder -@mnemonic(lexicon-mary-ceramic) -data ImmutableApi : semId StrictTypes.SemId - , published Std.Bool - , convertor StateConvertor - , builder StateBuilder - , rawConvertor RawConvertor - , rawBuilder RawBuilder +@mnemonic(tropic-brenda-reply) +data RawBuilder : strictEncode StrictTypes.SemId + | aluVm#255 AluVM.LibSite -@mnemonic(tomato-gordon-craft) -data RawBuilder : strictEncode StrictTypes.SemId | (|) +@mnemonic(result-right-amazon) +data RawConvertor : strictDecode StrictTypes.SemId + | aluVm#255 AluVM.LibSite -@mnemonic(tripod-guitar-bishop) -data RawConvertor : strictDecode StrictTypes.SemId | (|) +@mnemonic(senator-flower-guru) +data Semantics : version U16 + , default Api + , custom {StrictTypes.TypeName -> Api} + , codexLibs {AluVM.Lib} + , apiLibs {AluVM.Lib} + , types StrictTypes.TypeSystem @mnemonic(insect-cello-avalon) data SigBlob : [Byte ^ 1..0x1000] -@mnemonic(griffin-patrol-film) -data StateAggregator : count#1 StrictTypes.VariantName - | sumV StrictTypes.VariantName - | listV#32 StrictTypes.VariantName - | setV#34 StrictTypes.VariantName - | mapV2u#48 StrictTypes.VariantName - -@mnemonic(meteor-gondola-sweden) -data StateArithm : fungible | nonFungible - - -@mnemonic(bingo-deal-salami) -data StateBuilder : typedEncoder U256 | (|) - -@mnemonic(snake-diploma-sensor) -data StateConvertor : typedEncoder U256 | (|) - -@mnemonic(explore-locate-zoom) +@mnemonic(pablo-cotton-mirror) +data StateArithm : fungible () + | nonFungible () + | aluVm#255 AluVM.LibSite + +@mnemonic(reverse-delphi-camel) +data StateBuilder : unit () + | typedEncoder#16 U256 + | typedFieldEncoder U256 + | aluVm#255 AluVM.LibSite + +@mnemonic(beach-congo-instant) +data StateConvertor : unit () + | typedEncoder#16 U256 + | typedFieldEncoder U256 + | aluVm#255 AluVM.LibSite + +@mnemonic(benny-marina-fashion) +data StateSelector : global (StrictTypes.VariantName, Std.Bool) + | aggregated StrictTypes.VariantName + +@mnemonic(archer-metal-bison) +data SubAggregator : const (StrictTypes.SemId, [Byte ^ ..0xff]) + | theOnly StrictTypes.VariantName + | copy StrictTypes.VariantName + | unwrap StrictTypes.VariantName + | first StrictTypes.VariantName + | nth (StrictTypes.VariantName, U16) + | last StrictTypes.VariantName + | nthBack (StrictTypes.VariantName, U16) + | neg#16 StateSelector + | add (StateSelector, StateSelector) + | sub (StateSelector, StateSelector) + | mul (StateSelector, StateSelector) + | div (StateSelector, StateSelector) + | rem (StateSelector, StateSelector) + | exp (StateSelector, StateSelector) + | count#32 StrictTypes.VariantName + | countUnique StrictTypes.VariantName + | setV StrictTypes.VariantName + | mapV2u StrictTypes.VariantName + | mapV2ListU StrictTypes.VariantName + | mapV2SetU StrictTypes.VariantName + | sumUnwrap#48 StrictTypes.VariantName + | sumOrDefault StrictTypes.VariantName + | prodUnwrap StrictTypes.VariantName + | prodOrDefault StrictTypes.VariantName + +@mnemonic(weekend-street-channel) data Transition : opid UltraSONIC.Opid, destroyed {UltraSONIC.CellAddr -> UltraSONIC.StateCell} diff --git a/tests/dao.rs b/tests/dao.rs index 82da588..019fb29 100644 --- a/tests/dao.rs +++ b/tests/dao.rs @@ -28,15 +28,19 @@ extern crate amplify; #[macro_use] extern crate strict_types; +use std::convert::Infallible; use std::fs; use std::path::Path; use aluvm::{CoreConfig, LibSite}; use amplify::num::u256; -use commit_verify::{Digest, Sha256}; -use hypersonic::{Api, DestructibleApi, ImmutableApi}; +use commit_verify::{Digest, Sha256, StrictHash}; +use hypersonic::{Api, GlobalApi, OwnedApi}; use sonic_persist_fs::LedgerDir; -use sonicapi::{Issuer, RawBuilder, RawConvertor, StateAggregator, StateArithm, StateBuilder, StateConvertor}; +use sonicapi::{ + Aggregator, Issuer, RawBuilder, RawConvertor, Semantics, SigBlob, StateArithm, StateBuilder, StateConvertor, + SubAggregator, +}; use strict_types::{SemId, StrictVal}; use ultrasonic::aluvm::FIELD_ORDER_SECP; use ultrasonic::{AuthToken, CellAddr, Codex, Consensus, Identity}; @@ -49,6 +53,7 @@ fn codex() -> Codex { developer: Identity::default(), version: default!(), timestamp: 1732529307, + features: none!(), field_order: FIELD_ORDER_SECP, input_config: CoreConfig::default(), verification_config: CoreConfig::default(), @@ -66,13 +71,11 @@ fn api() -> Api { let codex = codex(); Api { - version: default!(), codex_id: codex.codex_id(), - developer: Identity::default(), - conforms: None, + conforms: none!(), default_call: None, - immutable: tiny_bmap! { - vname!("_parties") => ImmutableApi { + global: tiny_bmap! { + vname!("_parties") => GlobalApi { published: true, sem_id: types.get("DAO.PartyId"), convertor: StateConvertor::TypedEncoder(u256::ZERO), @@ -80,7 +83,7 @@ fn api() -> Api { raw_convertor: RawConvertor::StrictDecode(types.get("DAO.Party")), raw_builder: RawBuilder::StrictEncode(types.get("DAO.Party")), }, - vname!("_votings") => ImmutableApi { + vname!("_votings") => GlobalApi { published: true, sem_id: types.get("DAO.VoteId"), convertor: StateConvertor::TypedEncoder(u256::ONE), @@ -88,7 +91,7 @@ fn api() -> Api { raw_convertor: RawConvertor::StrictDecode(types.get("DAO.Voting")), raw_builder: RawBuilder::StrictEncode(types.get("DAO.Voting")), }, - vname!("_votes") => ImmutableApi { + vname!("_votes") => GlobalApi { published: true, sem_id: types.get("DAO.CastVote"), convertor: StateConvertor::TypedEncoder(u256::from(2u8)), @@ -97,8 +100,8 @@ fn api() -> Api { raw_builder: RawBuilder::StrictEncode(SemId::unit()), }, }, - destructible: tiny_bmap! { - vname!("signers") => DestructibleApi { + owned: tiny_bmap! { + vname!("signers") => OwnedApi { sem_id: types.get("DAO.PartyId"), arithmetics: StateArithm::NonFungible, convertor: StateConvertor::TypedEncoder(u256::ZERO), @@ -108,10 +111,10 @@ fn api() -> Api { } }, aggregators: tiny_bmap! { - vname!("parties") => StateAggregator::MapV2U(vname!("_parties")), - vname!("votings") => StateAggregator::MapV2U(vname!("_votings")), - vname!("votes") => StateAggregator::SetV(vname!("_votes")), - vname!("votingCount") => StateAggregator::Count(vname!("_votings")), + vname!("parties") => Aggregator::Take(SubAggregator::MapV2U(vname!("_parties"))), + vname!("votings") => Aggregator::Take(SubAggregator::MapV2U(vname!("_votings"))), + vname!("votes") => Aggregator::Take(SubAggregator::SetV(vname!("_votes"))), + vname!("votingCount") => Aggregator::Take(SubAggregator::Count(vname!("_votings"))), }, verifiers: tiny_bmap! { vname!("setup") => 0, @@ -119,23 +122,51 @@ fn api() -> Api { vname!("castVote") => 2, }, errors: Default::default(), - reserved: Default::default(), } } +#[test] fn main() { let types = stl::DaoTypes::new(); let codex = codex(); let api = api(); // Creating DAO with three participants - let issuer = Issuer::new(codex, api, [libs::success()], types.type_system()); + let semantics = Semantics { + version: 0, + default: api, + custom: none!(), + codex_libs: small_bset![libs::success()], + api_libs: none!(), + types: types.type_system(), + }; + + let sig = SigBlob::from_slice_checked(*b"me"); + fn sig_validator(_: StrictHash, _: &Identity, s: &SigBlob) -> Result<(), ()> { + if s.as_slice() == b"me" { + Ok(()) + } else { + Err(()) + } + } + let issuer = Issuer::with(codex, semantics, sig, sig_validator).unwrap(); let filename = "examples/dao/data/SimpleDAO.issuer"; fs::remove_file(filename).ok(); issuer .save(filename) .expect("unable to save an issuer to a file"); + let issuer2 = Issuer::load(filename, sig_validator).unwrap(); + assert_eq!(issuer.issuer_id(), issuer2.issuer_id()); + assert_eq!(issuer.codex_id(), issuer2.codex_id()); + assert_eq!(issuer.codex_name(), issuer2.codex_name()); + assert_eq!(issuer.codex(), issuer2.codex()); + assert_eq!(issuer.types(), issuer2.types()); + assert_eq!(issuer.semantics(), issuer2.semantics()); + assert_eq!(issuer.default_api(), issuer2.default_api()); + assert_eq!(issuer.custom_apis().collect::>(), issuer2.custom_apis().collect::>()); + assert_eq!(issuer.codex_libs().collect::>(), issuer2.codex_libs().collect::>()); + let seed = &[0xCA; 30][..]; let mut auth = Sha256::digest(seed); let mut next_auth = || -> AuthToken { @@ -164,12 +195,12 @@ fn main() { .finish("WonderlandDAO", 1732529307); let opid = articles.genesis_opid(); - let contract_path = Path::new("examples/dao/data/WonderlandDAO.contract"); + let contract_path = Path::new("tests/data/WonderlandDAO.contract"); if contract_path.exists() { fs::remove_dir_all(contract_path).expect("Unable to remove a contract file"); } fs::create_dir_all(contract_path).expect("Unable to create a contract folder"); - let mut ledger = LedgerDir::new(articles, contract_path.to_path_buf()).expect("Can't issue contract"); + let mut ledger = LedgerDir::new(articles.clone(), contract_path.to_path_buf()).expect("Can't issue contract"); // Proposing vote let votings = ledger @@ -228,14 +259,28 @@ fn main() { } // Now anybody accessing this file can figure out who is on duty today, by the decision of DAO. - let deeds_path = Path::new("examples/dao/data/voting.deeds"); + let deeds_path = Path::new("tests/data/voting.deeds"); if deeds_path.exists() { fs::remove_file(deeds_path).expect("unable to remove contract file"); } ledger - .export_to_file([alice_auth2, bob_auth2, carol_auth2], "examples/dao/data/voting.deeds") + .export_to_file([alice_auth2, bob_auth2, carol_auth2], deeds_path) .expect("unable to save deeds to a file"); + + let contract_path = Path::new("tests/data/WonderlandDAO-2.contract"); + if contract_path.exists() { + fs::remove_dir_all(contract_path).expect("Unable to remove a contract file"); + } + fs::create_dir_all(contract_path).expect("Unable to create a contract folder"); + let mut ledger2 = LedgerDir::new(articles, contract_path.to_path_buf()).expect("Can't issue contract"); + ledger2 + .accept_from_file(deeds_path, |_, _, _| Result::<_, Infallible>::Ok(())) + .unwrap(); + + let deeds_path = "tests/data/votings-all.deeds"; + fs::remove_file(deeds_path).ok(); + ledger2.export_all_to_file(deeds_path).unwrap(); } mod libs { diff --git a/tests/reorgs.rs b/tests/reorgs.rs index f2a1559..cc5bb74 100644 --- a/tests/reorgs.rs +++ b/tests/reorgs.rs @@ -35,7 +35,7 @@ use std::path::PathBuf; use aluvm::{CoreConfig, LibSite}; use amplify::num::u256; use commit_verify::{Digest, Sha256}; -use hypersonic::{Api, DestructibleApi}; +use hypersonic::{Api, OwnedApi}; use indexmap::{indexset, IndexSet}; use petgraph::dot::{Config, Dot}; use petgraph::graph::EdgeReference; @@ -44,7 +44,7 @@ use petgraph::Graph; use rand::rng; use rand::seq::SliceRandom; use sonic_persist_fs::LedgerDir; -use sonicapi::{IssueParams, Issuer, StateArithm, StateBuilder, StateConvertor}; +use sonicapi::{IssueParams, Issuer, Semantics, StateArithm, StateBuilder, StateConvertor}; use sonix::dump_ledger; use strict_types::SemId; use ultrasonic::aluvm::FIELD_ORDER_SECP; @@ -125,6 +125,7 @@ fn codex() -> Codex { developer: Identity::default(), version: default!(), timestamp: 1732529307, + features: none!(), field_order: FIELD_ORDER_SECP, input_config: CoreConfig::default(), verification_config: CoreConfig::default(), @@ -141,14 +142,12 @@ fn api() -> Api { let codex = codex(); Api { - version: default!(), codex_id: codex.codex_id(), - developer: Identity::default(), - conforms: None, + conforms: none!(), default_call: None, - immutable: none!(), - destructible: tiny_bmap! { - vname!("amount") => DestructibleApi { + global: none!(), + owned: tiny_bmap! { + vname!("amount") => OwnedApi { sem_id: types.get("Fungible.Amount"), arithmetics: StateArithm::Fungible, convertor: StateConvertor::TypedEncoder(u256::ZERO), @@ -163,7 +162,6 @@ fn api() -> Api { vname!("transfer") => 1, }, errors: Default::default(), - reserved: Default::default(), } } @@ -172,7 +170,16 @@ fn setup(name: &str) -> LedgerDir { let codex = codex(); let api = api(); - let issuer = Issuer::new(codex, api, [libs::success()], types.type_system()); + let semantics = Semantics { + version: 0, + default: api, + custom: none!(), + codex_libs: small_bset![libs::success()], + api_libs: none!(), + types: types.type_system(), + }; + let issuer = Issuer::new(codex, semantics).unwrap(); + issuer.save("tests/data/Test.issuer").ok(); let seed = &[0xCA; 30][..]; let mut auth = Sha256::digest(seed); @@ -183,7 +190,7 @@ fn setup(name: &str) -> LedgerDir { AuthToken::from(buf) }; - let mut issue = IssueParams::new_testnet("FungibleTest", Consensus::None); + let mut issue = IssueParams::new_testnet(issuer.codex_id(), "FungibleTest", Consensus::None); for _ in 0u16..10 { issue.push_owned_unlocked("amount", next_auth(), svnum!(100u64)); issue.push_owned_unlocked("amount", next_auth(), svnum!(100u64)); @@ -198,7 +205,7 @@ fn setup(name: &str) -> LedgerDir { fs::create_dir_all(&contract_path).expect("Unable to create a contract folder"); let mut ledger = LedgerDir::new(articles, contract_path).expect("Can't issue a contract"); - let owned = &ledger.state().main.destructible; + let owned = &ledger.state().main.owned; assert_eq!(owned.len(), 1); let owned = owned.get("amount").unwrap(); assert_eq!(owned.len(), 20); @@ -230,7 +237,7 @@ fn setup(name: &str) -> LedgerDir { prev = new_prev; } - let owned = &ledger.state().main.destructible; + let owned = &ledger.state().main.owned; assert_eq!(owned.len(), 1); assert_eq!(prev.len(), 20); let owned = owned.get("amount").unwrap(); @@ -320,7 +327,7 @@ fn check_rollback(ledger: LedgerDir, mut removed: IndexSet) -> IndexS } // Now we check that no outputs of the rolled-back ops participate in the valid state - let state = ledger.state().main.destructible.get("amount").unwrap(); + let state = ledger.state().main.owned.get("amount").unwrap(); eprintln!("Not rolled back outputs:"); for addr in state.keys() { assert!(!removed_opids.contains(&addr.opid));