diff --git a/Cargo.lock b/Cargo.lock index e5bc4d83..a3fdd9ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ version = 3 [[package]] name = "aluvm" version = "0.11.0-beta.9" -source = "git+https://github.com/AluVM/rust-aluvm?branch=develop#24bff9f61570ea26d14e86aa5e127937aa122440" +source = "git+https://github.com/AluVM/rust-aluvm?branch=develop#bedd86c160bab2398c07901728fd06b6bab13ddc" dependencies = [ "amplify", "ascii-armor", @@ -33,7 +33,6 @@ dependencies = [ "amplify_num", "amplify_syn", "ascii", - "rand", "serde", "stringly_conversions", "wasm-bindgen", @@ -177,12 +176,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" -[[package]] -name = "bitcoin-private" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" - [[package]] name = "bitcoin_hashes" version = "0.14.0" @@ -235,7 +228,7 @@ dependencies = [ "amplify", "chrono", "commit_verify", - "secp256k1 0.30.0", + "secp256k1", "serde", "strict_encoding", "strict_types", @@ -268,7 +261,7 @@ dependencies = [ "base85", "bp-consensus", "commit_verify", - "secp256k1 0.30.0", + "secp256k1", "serde", "strict_encoding", ] @@ -314,9 +307,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.30" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -433,12 +426,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "fast32" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35a73237400bde66c82e38387343f90d7182a2f2f22729e096a2abd57d75db9" - [[package]] name = "fluent-uri" version = "0.1.4" @@ -533,6 +520,7 @@ checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", + "serde", ] [[package]] @@ -552,9 +540,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "log" @@ -568,12 +556,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - [[package]] name = "minicov" version = "0.3.5" @@ -637,9 +619,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -686,17 +668,16 @@ dependencies = [ [[package]] name = "rgb-core" version = "0.11.0-beta.9" -source = "git+https://github.com/RGB-WG/rgb-core?branch=develop#50027495bf5e464f0e49edf65417f8caed837a39" +source = "git+https://github.com/RGB-WG/rgb-core?branch=feat/fungible-nonconf#78ee97123665b5da312336f52d56485153af1673" dependencies = [ "aluvm", "amplify", "baid64", + "base64", "bp-core", "chrono", "commit_verify", "getrandom", - "mime", - "secp256k1-zkp", "serde", "single_use_seals", "strict_encoding", @@ -712,7 +693,6 @@ dependencies = [ "baid64", "bp-core", "bp-invoice", - "fast32", "fluent-uri", "indexmap", "percent-encoding", @@ -720,7 +700,6 @@ dependencies = [ "rgb-core", "serde", "strict_encoding", - "strict_types", ] [[package]] @@ -788,17 +767,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "secp256k1" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" -dependencies = [ - "rand", - "secp256k1-sys", - "serde", -] - [[package]] name = "secp256k1" version = "0.30.0" @@ -820,29 +788,6 @@ dependencies = [ "cc", ] -[[package]] -name = "secp256k1-zkp" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a44aed3002b5ae975f8624c5df3a949cfbf00479e18778b6058fcd213b76e3" -dependencies = [ - "bitcoin-private", - "rand", - "secp256k1 0.29.1", - "secp256k1-zkp-sys", - "serde", -] - -[[package]] -name = "secp256k1-zkp-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6eea7919e0cab992510edfbf40bd9342c0a3c2bb910f2c51355c2cb2d69839" -dependencies = [ - "cc", - "secp256k1-sys", -] - [[package]] name = "serde" version = "1.0.210" @@ -865,9 +810,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "67d42a0bd4ac281beff598909bb56a86acaf979b84483e1c79c10dcaf98f8cf3" dependencies = [ "itoa", "memchr", @@ -960,9 +905,8 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f16e8855a575633815f01482ac927ebaca3d2485aec8e17226c6826de29154e" +version = "2.7.1" +source = "git+https://github.com/strict-types/strict-types?branch=develop#9a2041a9b1988b17608564725d47b39f442e5062" dependencies = [ "amplify", "ascii-armor", diff --git a/Cargo.toml b/Cargo.toml index f5b96320..3837c078 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ nonasync = "0.1.0" ascii-armor = "0.7.2" baid64 = "0.2.2" strict_encoding = "2.7.0" -strict_types = "2.7.0" +strict_types = "2.7.1" commit_verify = { version = "0.11.0-beta.9", features = ["stl"] } bp-core = { version = "0.11.0-beta.9", features = ["stl"] } bp-invoice = { version = "0.11.0-beta.9" } @@ -101,10 +101,11 @@ features = ["all"] [patch.crates-io] commit_verify = { git = "https://github.com/LNP-BP/client_side_validation", branch = "develop" } single_use_seals = { git = "https://github.com/LNP-BP/client_side_validation", branch = "develop" } +strict_types = { git = "https://github.com/strict-types/strict-types", branch = "develop" } aluvm = { git = "https://github.com/AluVM/rust-aluvm", branch = "develop" } bp-consensus = { git = "https://github.com/BP-WG/bp-core", branch = "develop" } bp-dbc = { git = "https://github.com/BP-WG/bp-core", branch = "develop" } bp-seals = { git = "https://github.com/BP-WG/bp-core", branch = "develop" } bp-core = { git = "https://github.com/BP-WG/bp-core", branch = "develop" } bp-invoice = { git = "https://github.com/BP-WG/bp-std", branch = "develop" } -rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "develop" } +rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "feat/fungible-nonconf" } diff --git a/invoice/Cargo.toml b/invoice/Cargo.toml index 05673093..60607596 100644 --- a/invoice/Cargo.toml +++ b/invoice/Cargo.toml @@ -18,9 +18,7 @@ name = "rgbinvoice" [dependencies] amplify = { workspace = true } baid64 = { workspace = true } -fast32 = "1.0.3" strict_encoding = { workspace = true } -strict_types = { workspace = true } bp-core = { workspace = true } bp-invoice = { workspace = true } rgb-core = { workspace = true } diff --git a/invoice/src/amount.rs b/invoice/src/amount.rs deleted file mode 100644 index 9007f085..00000000 --- a/invoice/src/amount.rs +++ /dev/null @@ -1,500 +0,0 @@ -// RGB wallet library for smart contracts on Bitcoin & Lightning network -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::cmp::Ordering; -use std::fmt; -use std::fmt::{Display, Formatter, Write}; -use std::iter::Sum; -use std::num::{ParseIntError, TryFromIntError}; -use std::str::FromStr; - -use bp::Sats; -use rgb::{FungibleState, RevealedValue}; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; -use strict_encoding::{StrictDeserialize, StrictSerialize, VariantError}; -use strict_types::StrictVal; - -use crate::LIB_NAME_RGB_CONTRACT; - -pub const ENC_BASE32_NODIGIT: &[u8; 32] = b"abcdefghkmnABCDEFGHKMNPQRSTVWXYZ"; -fast32::make_base32_alpha!(BASE32_NODIGIT, DEC_BASE32_NODIGIT, ENC_BASE32_NODIGIT); - -#[derive( - Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From -)] -#[wrapper(Add, Sub, Mul, Div, Rem)] -#[wrapper_mut(AddAssign, SubAssign, MulAssign, DivAssign, RemAssign)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct Amount( - #[from] - #[from(u32)] - #[from(u16)] - #[from(u8)] - #[from(Sats)] - u64, -); - -impl StrictSerialize for Amount {} -impl StrictDeserialize for Amount {} - -impl From for Amount { - fn from(value: RevealedValue) -> Self { Amount(value.value.as_u64()) } -} - -impl From for Amount { - fn from(state: FungibleState) -> Self { Amount(state.as_u64()) } -} - -impl From for FungibleState { - fn from(amount: Amount) -> Self { FungibleState::Bits64(amount.0) } -} - -impl Amount { - pub const ZERO: Self = Amount(0); - - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - value.unwrap_uint::().into() - } - - pub fn with_precision(amount: u64, precision: impl Into) -> Self { - precision.into().unchecked_convert(amount) - } - - pub fn with_precision_checked(amount: u64, precision: impl Into) -> Option { - precision.into().checked_convert(amount) - } - - pub fn value(self) -> u64 { self.0 } - - pub fn split(self, precision: impl Into) -> (u64, u64) { - let precision = precision.into(); - let int = self.floor(precision); - let fract = self.rem(precision); - (int, fract) - } - - pub fn round(&self, precision: impl Into) -> u64 { - let precision = precision.into(); - let mul = precision.multiplier(); - if self.0 == 0 { - return 0; - } - let inc = 2 * self.rem(precision) / mul; - self.0 / mul + inc - } - - pub fn ceil(&self, precision: impl Into) -> u64 { - let precision = precision.into(); - if self.0 == 0 { - return 0; - } - let inc = if self.rem(precision) > 0 { 1 } else { 0 }; - self.0 / precision.multiplier() + inc - } - - pub fn floor(&self, precision: impl Into) -> u64 { - if self.0 == 0 { - return 0; - } - self.0 / precision.into().multiplier() - } - - pub fn rem(&self, precision: impl Into) -> u64 { - self.0 % precision.into().multiplier() - } - - pub fn saturating_add(&self, other: impl Into) -> Self { - self.0.saturating_add(other.into().0).into() - } - pub fn saturating_sub(&self, other: impl Into) -> Self { - self.0.saturating_sub(other.into().0).into() - } - - pub fn saturating_add_assign(&mut self, other: impl Into) { - *self = self.0.saturating_add(other.into().0).into(); - } - pub fn saturating_sub_assign(&mut self, other: impl Into) { - *self = self.0.saturating_sub(other.into().0).into(); - } - - #[must_use] - pub fn checked_add(&self, other: impl Into) -> Option { - self.0.checked_add(other.into().0).map(Self) - } - #[must_use] - pub fn checked_sub(&self, other: impl Into) -> Option { - self.0.checked_sub(other.into().0).map(Self) - } - - #[must_use] - pub fn checked_add_assign(&mut self, other: impl Into) -> Option<()> { - *self = self.0.checked_add(other.into().0).map(Self)?; - Some(()) - } - #[must_use] - pub fn checked_sub_assign(&mut self, other: impl Into) -> Option<()> { - *self = self.0.checked_sub(other.into().0).map(Self)?; - Some(()) - } -} - -impl Sum for Amount { - fn sum>(iter: I) -> Self { - iter.fold(Amount::ZERO, |sum, value| sum.saturating_add(value)) - } -} - -impl Sum for Amount { - fn sum>(iter: I) -> Self { - iter.fold(Amount::ZERO, |sum, value| sum.saturating_add(value)) - } -} - -impl Display for Amount { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let bytes = self.0.to_le_bytes(); - let pos = bytes.iter().rposition(|b| *b != 0).unwrap_or(0) + 1; - let s = BASE32_NODIGIT.encode(&bytes[..pos]); - f.write_str(&s) - } -} - -impl FromStr for Amount { - type Err = fast32::DecodeError; - - fn from_str(s: &str) -> Result { - let amount = BASE32_NODIGIT.decode_str(s)?; - let len = amount.len(); - if len > 8 { - return Err(fast32::DecodeError::InvalidLength { - length: amount.len(), - }); - } - let mut le = [0u8; 8]; - le[..len].copy_from_slice(&amount); - Ok(Amount(u64::from_le_bytes(le))) - } -} - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default)] -#[repr(u8)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT, tags = repr, into_u8, try_from_u8)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub enum Precision { - Indivisible = 0, - Deci = 1, - Centi = 2, - Milli = 3, - DeciMilli = 4, - CentiMilli = 5, - Micro = 6, - DeciMicro = 7, - #[default] - CentiMicro = 8, - Nano = 9, - DeciNano = 10, - CentiNano = 11, - Pico = 12, - DeciPico = 13, - CentiPico = 14, - Femto = 15, - DeciFemto = 16, - CentiFemto = 17, - Atto = 18, -} -impl StrictSerialize for Precision {} -impl StrictDeserialize for Precision {} - -impl Precision { - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { value.unwrap_enum() } - pub const fn decimals(self) -> u8 { self as u8 } - - pub const fn multiplier(self) -> u64 { - match self { - Precision::Indivisible => 1, - Precision::Deci => 10, - Precision::Centi => 100, - Precision::Milli => 1000, - Precision::DeciMilli => 10_000, - Precision::CentiMilli => 100_000, - Precision::Micro => 1_000_000, - Precision::DeciMicro => 10_000_000, - Precision::CentiMicro => 100_000_000, - Precision::Nano => 1_000_000_000, - Precision::DeciNano => 10_000_000_000, - Precision::CentiNano => 100_000_000_000, - Precision::Pico => 1_000_000_000_000, - Precision::DeciPico => 10_000_000_000_000, - Precision::CentiPico => 100_000_000_000_000, - Precision::Femto => 1_000_000_000_000_000, - Precision::DeciFemto => 10_000_000_000_000_000, - Precision::CentiFemto => 100_000_000_000_000_000, - Precision::Atto => 1_000_000_000_000_000_000, - } - } - - pub fn unchecked_convert(self, amount: impl Into) -> Amount { - (amount.into() * self.multiplier()).into() - } - - pub fn checked_convert(self, amount: impl Into) -> Option { - amount - .into() - .checked_mul(self.multiplier()) - .map(Amount::from) - } - pub fn saturating_convert(self, amount: impl Into) -> Amount { - amount.into().saturating_mul(self.multiplier()).into() - } -} - -impl From for u16 { - fn from(value: Precision) -> Self { value as u8 as u16 } -} - -impl From for u32 { - fn from(value: Precision) -> Self { value as u8 as u32 } -} - -impl From for u64 { - fn from(value: Precision) -> Self { value as u8 as u64 } -} - -#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)] -#[display("invalid precision")] -pub struct PrecisionError; - -#[derive(Getters, Copy, Clone, Eq, PartialEq, Hash, Debug)] -pub struct CoinAmount { - #[getter(as_copy)] - int: u64, - #[getter(as_copy)] - fract: u64, - #[getter(as_copy)] - precision: Precision, -} - -impl CoinAmount { - pub fn new(amount: impl Into, precision: impl Into) -> Self { - let precision = precision.into(); - let amount = amount.into(); - let (int, fract) = amount.split(precision); - CoinAmount { - int, - fract, - precision, - } - } - - pub fn with( - int: u64, - fract: u64, - precision: impl Into, - ) -> Result { - let precision = precision.into(); - // 2^64 ~ 10^19 < 10^18 (18 is max value for Precision enum) - let pow = 10u64.pow(precision.decimals() as u32); - // number of decimals can't be larger than the smallest possible integer - if fract >= pow { - return Err(PrecisionError); - } - Ok(CoinAmount { - int, - fract, - precision, - }) - } - - pub(crate) fn to_amount_unchecked(self) -> Amount { - // 2^64 ~ 10^19 < 10^18 (18 is max value for Precision enum) - let pow = 10u64.pow(self.precision.decimals() as u32); - // number of decimals can't be larger than the smallest possible integer - self.int - .checked_mul(pow) - .expect("CoinAmount type garantees are broken") - .checked_add(self.fract) - .expect( - "integer has at least the same number of zeros in the lowest digits as much as \ - decimals has digits at most, so overflow is not possible", - ) - .into() - } -} - -impl Display for CoinAmount { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - if ![' ', '_'].contains(&f.fill()) { - panic!("disallowed fill character {} in coin amount formatting string", f.fill()) - } - if f.precision().is_some() { - panic!("formatting precision must not be used for coin amounts") - } - let fill = &f.fill().to_string(); - let to_chunks = |s: &str| -> String { - s.chars() - .rev() - .collect::() - .as_bytes() - .chunks(3) - .map(<[u8]>::to_owned) - .map(|mut chunk| unsafe { - chunk.reverse(); - String::from_utf8_unchecked(chunk) - }) - .rev() - .collect::>() - .join(fill) - }; - let mut int = self.int.to_string(); - if f.alternate() { - int = to_chunks(&int); - } - f.write_str(&int)?; - if self.fract > 0 || f.alternate() { - f.write_char('.')?; - let mut float = self.fract.to_string(); - let len = float.len(); - let decimals = self.precision.decimals() as usize; - match len.cmp(&decimals) { - Ordering::Less => { - float = format!("{:0>width$}{float}", "", width = decimals - len); - } - Ordering::Equal => {} - Ordering::Greater => panic!("float precision overflow for coin amount {self:?}"), - } - if f.alternate() { - float = to_chunks(&float); - } else { - float = float.trim_end_matches('0').to_string(); - } - f.write_str(&float)?; - } - if !f.alternate() { - write!(f, "~{}", self.precision.decimals())?; - } - Ok(()) - } -} - -#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] -#[display(doc_comments)] -pub enum AmountParseError { - /// invalid amount integer part - {0} - InvalidInt(ParseIntError), - /// invalid amount fractional part - {0} - InvalidFract(ParseIntError), - /// invalid amount precision - {0} - InvalidPrecision(ParseIntError), - - /// invalid amount precision exceeding 18 - #[from(TryFromIntError)] - PrecisionOverflow, - - /// invalid amount precision exceeding 18 - #[from] - UnknownPrecision(VariantError), -} - -impl FromStr for CoinAmount { - type Err = AmountParseError; - - fn from_str(s: &str) -> Result { - let s = s.replace([' ', '_'], ""); - let (int, remain) = s.split_once('.').unwrap_or_else(|| (&s, "0")); - let (fract, precision) = remain.split_once('~').unwrap_or((remain, "")); - let precision = if precision.is_empty() { - fract.len() as u64 - } else { - precision - .parse() - .map_err(AmountParseError::InvalidPrecision)? - }; - let int: u64 = int.parse().map_err(AmountParseError::InvalidInt)?; - let fract: u64 = fract.parse().map_err(AmountParseError::InvalidFract)?; - let precision = u8::try_from(precision)?; - Ok(CoinAmount { - int, - fract, - precision: Precision::try_from(precision)?, - }) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - #[allow(clippy::inconsistent_digit_grouping)] - fn int_trailing_zeros() { - let amount = CoinAmount::new(10_000__43_608_195u64, Precision::default()); - assert_eq!(amount.int(), 10_000); - assert_eq!(amount.fract(), 436_081_95); - assert_eq!(amount.precision(), Precision::default()); - assert_eq!(format!("{amount}"), "10000.43608195~8"); - assert_eq!(format!("{amount: >#}"), "10 000.43 608 195"); - } - - #[test] - #[allow(clippy::inconsistent_digit_grouping)] - fn sub_fraction() { - let amount = CoinAmount::new(10__00_008_195u64, Precision::default()); - assert_eq!(amount.int(), 10); - assert_eq!(amount.fract(), 8195); - assert_eq!(amount.precision(), Precision::default()); - assert_eq!(format!("{amount}"), "10.00008195~8"); - assert_eq!(format!("{amount:#}"), "10.00 008 195"); - } - - #[test] - #[allow(clippy::inconsistent_digit_grouping)] - fn small_fraction() { - let amount = CoinAmount::new(10__00_000_500u64, Precision::default()); - assert_eq!(amount.int(), 10); - assert_eq!(amount.fract(), 500); - assert_eq!(amount.precision(), Precision::default()); - assert_eq!(format!("{amount}"), "10.000005~8"); - assert_eq!(format!("{amount:_>#}"), "10.00_000_500"); - } - - #[test] - #[allow(clippy::inconsistent_digit_grouping)] - fn zero_fraction() { - let amount = CoinAmount::new(10__00_000_000u64, Precision::default()); - assert_eq!(amount.int(), 10); - assert_eq!(amount.fract(), 0); - assert_eq!(amount.precision(), Precision::default()); - assert_eq!(format!("{amount}"), "10~8"); - assert_eq!(format!("{amount:_>#}"), "10.00_000_000"); - } -} diff --git a/invoice/src/builder.rs b/invoice/src/builder.rs index 17f2da31..9d84fb61 100644 --- a/invoice/src/builder.rs +++ b/invoice/src/builder.rs @@ -21,11 +21,10 @@ use std::str::FromStr; -use rgb::ContractId; -use strict_encoding::{FieldName, TypeName}; +use rgb::{ContractId, StateData}; +use strict_encoding::{FieldName, SerializeError, StrictSerialize, TypeName}; -use crate::invoice::{Beneficiary, InvoiceState, RgbInvoice, RgbTransport, XChainNet}; -use crate::{Allocation, Amount, CoinAmount, NonFungible, Precision, TransportParseError}; +use crate::{Beneficiary, RgbInvoice, RgbTransport, TransportParseError, XChainNet}; #[derive(Clone, Eq, PartialEq, Debug)] pub struct RgbInvoiceBuilder(RgbInvoice); @@ -40,7 +39,7 @@ impl RgbInvoiceBuilder { operation: None, assignment: None, beneficiary: beneficiary.into(), - owned_state: InvoiceState::Void, + state: None, expiry: None, unknown_query: none!(), }) @@ -50,19 +49,13 @@ impl RgbInvoiceBuilder { Self::new(beneficiary).set_contract(contract_id) } - pub fn rgb20(contract_id: ContractId, beneficiary: impl Into>) -> Self { - Self::with(contract_id, beneficiary).set_interface("RGB20") - } - - pub fn rgb20_anything(beneficiary: impl Into>) -> Self { - Self::new(beneficiary).set_interface("RGB20") - } - pub fn set_contract(mut self, contract_id: ContractId) -> Self { self.0.contract = Some(contract_id); self } + /// Sets interface for the invoice. Interface can be a concrete interface (name or id), or a + /// name of an interface standard, like `RGB20`, `RGB21` etc. pub fn set_interface(mut self, name: impl Into) -> Self { self.0.iface = Some(name.into()); self @@ -78,49 +71,29 @@ impl RgbInvoiceBuilder { self } - pub fn set_amount_raw(mut self, amount: impl Into) -> Self { - self.0.owned_state = InvoiceState::Amount(amount.into()); + /// Add state data to the invoice. + /// + /// See also [`Self::serialize_state_data`], which adds state data by serializing them from a + /// state object. + pub fn set_state(mut self, data: StateData) -> Self { + self.0.state = Some(data); self } - pub fn set_amount( + /// Add state data to the invoice by strict-serializing the provided object. + /// + /// Use the function carefully, since the common pitfall here is to perform double serialization + /// of an already serialized data type, like `SmallBlob`. This produces an invalid state object + /// which can't be properly parsed later. See also [`Self::set_state`], which sets state data + /// directly with no serialization. + pub fn serialize_state_data( mut self, - integer: u64, - decimals: u64, - precision: Precision, - ) -> Result { - let amount = match CoinAmount::with(integer, decimals, precision) { - Ok(amount) => amount, - Err(_) => return Err(self), - } - .to_amount_unchecked(); - self.0.owned_state = InvoiceState::Amount(amount); + data: &impl StrictSerialize, + ) -> Result { + self.0.state = Some(StateData::from_serialized(data)?); Ok(self) } - pub fn set_allocation_raw(mut self, allocation: impl Into) -> Self { - self.0.owned_state = InvoiceState::Data(NonFungible::RGB21(allocation.into())); - self - } - - pub fn set_allocation(self, token_index: u32, fraction: u64) -> Result { - Ok(self.set_allocation_raw(Allocation::with(token_index, fraction))) - } - - /// # Safety - /// - /// The function may cause the loss of the information about the precise - /// amount of the asset, since f64 type doesn't provide full precision - /// required for that. - pub unsafe fn set_amount_approx(self, amount: f64, precision: Precision) -> Result { - if amount <= 0.0 { - return Err(self); - } - let coins = amount.floor(); - let cents = amount - coins; - self.set_amount(coins as u64, cents as u64, precision) - } - pub fn set_expiry_timestamp(mut self, expiry: i64) -> Self { self.0.expiry = Some(expiry); self diff --git a/invoice/src/data.rs b/invoice/src/data.rs deleted file mode 100644 index 7eaa93f7..00000000 --- a/invoice/src/data.rs +++ /dev/null @@ -1,293 +0,0 @@ -// RGB wallet library for smart contracts on Bitcoin & Lightning network -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::str::FromStr; - -use rgb::{DataState, RevealedData}; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; -use strict_encoding::{StrictDeserialize, StrictSerialize}; -use strict_types::StrictVal; - -use crate::LIB_NAME_RGB_CONTRACT; - -#[derive(Clone, Eq, PartialEq, Hash, Debug, Display)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub enum NonFungible { - #[display(inner)] - RGB21(Allocation), -} - -impl FromStr for NonFungible { - type Err = AllocationParseError; - fn from_str(s: &str) -> Result { - let allocation = Allocation::from_str(s)?; - Ok(NonFungible::RGB21(allocation)) - } -} - -#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] -#[display(inner)] -pub enum AllocationParseError { - #[display(doc_comments)] - /// invalid token index {0}. - InvalidIndex(String), - - #[display(doc_comments)] - /// invalid fraction {0}. - InvalidFraction(String), - - #[display(doc_comments)] - /// allocation must have format @. - WrongFormat, -} - -#[derive( - Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From -)] -#[wrapper(Display, FromStr, Add, Sub, Mul, Div, Rem)] -#[wrapper_mut(AddAssign, SubAssign, MulAssign, DivAssign, RemAssign)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct TokenIndex(u32); - -#[derive( - Wrapper, WrapperMut, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default, From -)] -#[wrapper(Display, FromStr, Add, Sub, Mul, Div, Rem)] -#[wrapper_mut(AddAssign, SubAssign, MulAssign, DivAssign, RemAssign)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct OwnedFraction(u64); - -impl OwnedFraction { - pub const ZERO: Self = OwnedFraction(0); - - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - value.unwrap_uint::().into() - } - - pub fn value(self) -> u64 { self.0 } - - pub fn saturating_add(&self, other: impl Into) -> Self { - self.0.saturating_add(other.into().0).into() - } - pub fn saturating_sub(&self, other: impl Into) -> Self { - self.0.saturating_sub(other.into().0).into() - } - - pub fn saturating_add_assign(&mut self, other: impl Into) { - *self = self.0.saturating_add(other.into().0).into(); - } - pub fn saturating_sub_assign(&mut self, other: impl Into) { - *self = self.0.saturating_sub(other.into().0).into(); - } - - #[must_use] - pub fn checked_add(&self, other: impl Into) -> Option { - self.0.checked_add(other.into().0).map(Self) - } - #[must_use] - pub fn checked_sub(&self, other: impl Into) -> Option { - self.0.checked_sub(other.into().0).map(Self) - } - - #[must_use] - pub fn checked_add_assign(&mut self, other: impl Into) -> Option<()> { - *self = self.0.checked_add(other.into().0).map(Self)?; - Some(()) - } - #[must_use] - pub fn checked_sub_assign(&mut self, other: impl Into) -> Option<()> { - *self = self.0.checked_sub(other.into().0).map(Self)?; - Some(()) - } -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default, Display)] -#[display("{1}@{0}")] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct Allocation(TokenIndex, OwnedFraction); - -impl Allocation { - pub fn with(index: impl Into, fraction: impl Into) -> Allocation { - Allocation(index.into(), fraction.into()) - } - - pub fn token_index(self) -> TokenIndex { self.0 } - - pub fn fraction(self) -> OwnedFraction { self.1 } -} - -impl StrictSerialize for Allocation {} -impl StrictDeserialize for Allocation {} - -impl From for Allocation { - fn from(data: RevealedData) -> Self { - Allocation::from_strict_serialized(data.value.into()).expect("invalid allocation data") - } -} - -impl From for Allocation { - fn from(state: DataState) -> Self { - Allocation::from_strict_serialized(state.into()).expect("invalid allocation data") - } -} - -impl From for DataState { - fn from(allocation: Allocation) -> Self { - DataState::from( - allocation - .to_strict_serialized() - .expect("invalid allocation data"), - ) - } -} - -impl FromStr for Allocation { - type Err = AllocationParseError; - - fn from_str(s: &str) -> Result { - if !s.contains('@') { - return Err(AllocationParseError::WrongFormat); - } - - match s.split_once('@') { - Some((fraction, token_index)) => Ok(Allocation( - token_index - .parse() - .map_err(|_| AllocationParseError::InvalidIndex(token_index.to_owned()))?, - fraction - .parse() - .map_err(|_| AllocationParseError::InvalidFraction(fraction.to_lowercase()))?, - )), - None => Err(AllocationParseError::WrongFormat), - } - } -} - -#[cfg(test)] -mod test { - use strict_types::value::StrictNum; - - use super::*; - - #[test] - fn owned_fraction_from_str() { - let owned_fraction = match OwnedFraction::from_str("1") { - Ok(value) => value, - Err(_) => OwnedFraction::ZERO, - }; - - assert_eq!(owned_fraction.value(), 1); - assert_eq!(format!("{owned_fraction}"), "1"); - } - - #[test] - fn owned_fraction_from_strict_val() { - // note that the strict number is u128 but not u64 - let owned_fraction = - OwnedFraction::from_strict_val_unchecked(&StrictVal::Number(StrictNum::Uint(1))); - - assert_eq!(owned_fraction.value(), 1); - assert_eq!(format!("{owned_fraction}"), "1"); - } - - #[test] - fn owned_fraction_add_assign() { - let mut owned_fraction = match OwnedFraction::from_str("1") { - Ok(value) => value, - Err(_) => OwnedFraction::ZERO, - }; - - let _ = owned_fraction.checked_add_assign(OwnedFraction::ZERO); - assert_eq!(owned_fraction.value(), 1); - assert_eq!(format!("{owned_fraction}"), "1"); - } - - #[test] - fn owned_fraction_add() { - let owned_fraction = match OwnedFraction::from_str("1") { - Ok(value) => value, - Err(_) => OwnedFraction::ZERO, - }; - - let owned = match owned_fraction.checked_add(OwnedFraction::ZERO) { - Some(value) => value, - None => OwnedFraction::ZERO, - }; - assert_eq!(owned.value(), 1); - assert_eq!(format!("{owned}"), "1"); - } - - #[test] - fn owned_fraction_sub() { - let owned_fraction = match OwnedFraction::from_str("1") { - Ok(value) => value, - Err(_) => OwnedFraction::ZERO, - }; - - let other_fraction = match OwnedFraction::from_str("1") { - Ok(value) => value, - Err(_) => OwnedFraction::ZERO, - }; - - let owned = match owned_fraction.checked_sub(other_fraction) { - Some(value) => value, - None => OwnedFraction::ZERO, - }; - assert_eq!(owned.value(), 0); - assert_eq!(format!("{owned}"), "0"); - } - - #[test] - fn owned_fraction_sub_assign() { - let mut owned_fraction = match OwnedFraction::from_str("1") { - Ok(value) => value, - Err(_) => OwnedFraction::ZERO, - }; - - let other_fraction = match OwnedFraction::from_str("1") { - Ok(value) => value, - Err(_) => OwnedFraction::ZERO, - }; - - let _ = owned_fraction.checked_sub_assign(other_fraction); - assert_eq!(owned_fraction.value(), 0); - assert_eq!(format!("{owned_fraction}"), "0"); - } -} diff --git a/invoice/src/invoice.rs b/invoice/src/invoice.rs index 853bd702..41f1720d 100644 --- a/invoice/src/invoice.rs +++ b/invoice/src/invoice.rs @@ -19,18 +19,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::str::FromStr; - use amplify::{ByteArray, Bytes32}; use bp::seals::txout::CloseMethod; use bp::{InvalidPubkey, OutputPk, PubkeyHash, ScriptHash, WPubkeyHash, WScriptHash}; use indexmap::IndexMap; use invoice::{AddressNetwork, AddressPayload, Network}; -use rgb::{AttachId, ContractId, Layer1, SecretSeal}; +use rgb::{ContractId, Layer1, SecretSeal, StateData}; use strict_encoding::{FieldName, TypeName}; -use crate::{Amount, NonFungible}; - #[derive(Clone, Eq, PartialEq, Hash, Debug)] #[non_exhaustive] pub enum RgbTransport { @@ -41,43 +37,6 @@ pub enum RgbTransport { UnspecifiedMeans, } -#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)] -#[display(inner)] -pub enum InvoiceStateError { - #[display(doc_comments)] - /// could not parse as amount, data, or attach: {0}. - ParseError(String), -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug, Display)] -pub enum InvoiceState { - #[display("")] - Void, - #[display("{0}")] - Amount(Amount), - #[display(inner)] - Data(NonFungible), - #[display(inner)] - Attach(AttachId), -} - -impl FromStr for InvoiceState { - type Err = InvoiceStateError; - fn from_str(s: &str) -> Result { - if s.is_empty() { - Ok(InvoiceState::Void) - } else if let Ok(amount) = Amount::from_str(s) { - Ok(InvoiceState::Amount(amount)) - } else if let Ok(data) = NonFungible::from_str(s) { - Ok(InvoiceState::Data(data)) - } else if let Ok(attach) = AttachId::from_str(s) { - Ok(InvoiceState::Attach(attach)) - } else { - Err(InvoiceStateError::ParseError(s.to_owned())) - } - } -} - #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] #[non_exhaustive] pub enum ChainNet { @@ -251,9 +210,10 @@ pub struct RgbInvoice { pub operation: Option, pub assignment: Option, pub beneficiary: XChainNet, - pub owned_state: InvoiceState, + pub state: Option, /// UTC unix timestamp pub expiry: Option, + // Attachment requirements should go here pub unknown_query: IndexMap, } diff --git a/invoice/src/lib.rs b/invoice/src/lib.rs index a798caeb..9ffe2999 100644 --- a/invoice/src/lib.rs +++ b/invoice/src/lib.rs @@ -21,8 +21,6 @@ #[macro_use] extern crate amplify; -#[macro_use] -extern crate strict_encoding; extern crate rgbcore as rgb; #[cfg(feature = "serde")] extern crate serde_crate as serde; @@ -34,17 +32,10 @@ pub use ::invoice::*; mod invoice; mod parse; mod builder; -mod amount; -mod data; -pub use amount::{Amount, AmountParseError, CoinAmount, Precision, PrecisionError}; pub use builder::RgbInvoiceBuilder; -pub use data::{Allocation, NonFungible, OwnedFraction, TokenIndex}; pub use parse::{InvoiceParseError, TransportParseError}; pub use crate::invoice::{ - Beneficiary, ChainNet, InvoiceState, Pay2Vout, Pay2VoutError, RgbInvoice, RgbTransport, - XChainNet, + Beneficiary, ChainNet, Pay2Vout, Pay2VoutError, RgbInvoice, RgbTransport, XChainNet, }; - -pub const LIB_NAME_RGB_CONTRACT: &str = "RGBContract"; diff --git a/invoice/src/parse.rs b/invoice/src/parse.rs index 08e4a37e..3ae6b546 100644 --- a/invoice/src/parse.rs +++ b/invoice/src/parse.rs @@ -30,12 +30,10 @@ use fluent_uri::Uri; use indexmap::IndexMap; use invoice::{AddressPayload, UnknownNetwork}; use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; -use rgb::{ContractId, SecretSeal}; +use rgb::{ContractId, SecretSeal, StateData, StateParseError}; use strict_encoding::{InvalidRString, TypeName}; -use crate::invoice::{ - Beneficiary, ChainNet, InvoiceState, Pay2Vout, RgbInvoice, RgbTransport, XChainNet, -}; +use crate::invoice::{Beneficiary, ChainNet, Pay2Vout, RgbInvoice, RgbTransport, XChainNet}; const OMITTED: &str = "~"; const EXPIRY: &str = "expiry"; @@ -72,8 +70,11 @@ pub enum InvoiceParseError { #[display(inner)] Uri(fluent_uri::ParseError), - /// invalid invoice. - Invalid, + /// absent invoice URI scheme name. + AbsentScheme, + + /// invalid invoice scheme {0}. + InvalidScheme(String), /// RGB invoice must not contain any URI authority data, including empty /// one. @@ -88,8 +89,9 @@ pub enum InvoiceParseError { /// assignment data is missed from the invoice. AssignmentMissed, - /// invalid invoice scheme {0}. - InvalidScheme(String), + #[from] + #[display(inner)] + InvalidState(StateParseError), /// no invoice transport has been provided. NoTransport, @@ -115,7 +117,7 @@ pub enum InvoiceParseError { #[from] #[display(inner)] - Id(baid64::Baid64ParseError), + Id(Baid64ParseError), /// can't recognize beneficiary "{0}": it should be either a bitcoin address /// or a blinded UTXO seal. @@ -125,10 +127,6 @@ pub enum InvoiceParseError { #[display(inner)] Num(ParseIntError), - /// can't recognize amount "{0}": it should be valid rgb21 allocation - /// data. - Data(String), - #[from] /// invalid interface name. IfaceName(InvalidRString), @@ -293,7 +291,7 @@ impl FromStr for XChainNet { impl Display for RgbInvoice { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let amt = self.owned_state.to_string(); + // TODO: Support attachment through invoice params if let Some(contract) = self.contract { let id = if f.alternate() { contract.to_string().replace('-', "") @@ -315,8 +313,8 @@ impl Display for RgbInvoice { if let Some(ref assignment_name) = self.assignment { write!(f, "{assignment_name}/")?; } - if !amt.is_empty() { - write!(f, "{amt}+")?; + if let Some(state) = self.state.as_ref() { + write!(f, "{state}+")?; } let beneficiary = if f.alternate() { self.beneficiary.to_string().replace('-', "") @@ -352,9 +350,10 @@ impl FromStr for RgbInvoice { type Err = InvoiceParseError; fn from_str(s: &str) -> Result { + // TODO: Support attachment through invoice params let uri = Uri::parse(s)?; - let scheme = uri.scheme().ok_or(InvoiceParseError::Invalid)?; + let scheme = uri.scheme().ok_or(InvoiceParseError::AbsentScheme)?; if scheme.as_str() != "rgb" { return Err(InvoiceParseError::InvalidScheme(scheme.to_string())); } @@ -392,18 +391,14 @@ impl FromStr for RgbInvoice { let Some(assignment) = path.next() else { return Err(InvoiceParseError::AssignmentMissed); }; - let (amount, beneficiary) = assignment + let (state, beneficiary) = assignment .as_str() .split_once('+') .map(|(a, b)| (Some(a), Some(b))) .unwrap_or((Some(assignment.as_str()), None)); - // TODO: support other state types - let (beneficiary_str, value) = match (beneficiary, amount) { - (Some(b), Some(a)) => ( - b, - InvoiceState::from_str(a).map_err(|_| InvoiceParseError::Data(a.to_string()))?, - ), - (None, Some(b)) => (b, InvoiceState::Void), + let (beneficiary_str, state) = match (beneficiary, state) { + (Some(b), Some(a)) => (b, Some(StateData::from_str(a)?)), + (None, Some(b)) => (b, None), _ => unreachable!(), }; @@ -439,7 +434,7 @@ impl FromStr for RgbInvoice { operation: None, assignment: None, beneficiary, - owned_state: value, + state, expiry, unknown_query: query_params, }) @@ -472,24 +467,27 @@ fn map_query_params(uri: &Uri<&str>) -> Result, Invoice #[cfg(test)] mod test { use super::*; - use crate::Amount; #[test] fn parse() { // rgb20/rgb25 parameters - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); - assert_eq!(invoice.owned_state, InvoiceState::Amount(Amount::from(100u64))); + assert_eq!(invoice.state, Some(StateData::from_checked(vec![100, 0, 0, 0, 0, 0, 0, 0]))); assert_eq!(invoice.to_string(), invoice_str); - assert_eq!(format!("{invoice:#}"), invoice_str.replace('-', "")); // rgb21 parameters - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB21/1@1+bc:\ - utxob:zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F"; + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB21/\ + -p----p---------+bc:utxob:\ + zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); + assert_eq!( + invoice.state, + Some(StateData::from_checked(vec![1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0])) + ); assert_eq!(invoice.to_string(), invoice_str); - assert_eq!(format!("{invoice:#}"), invoice_str.replace('-', "")); // no amount let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/bc:utxob:\ @@ -531,47 +529,51 @@ mod test { Err(InvoiceParseError::InvalidContractId(c)) if c == invalid_contract_id)); // with expiration - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ - zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?\ - expiry=1682086371"; + let invoice_str = + "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/y----------+bc:utxob:\ + zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?expiry=1682086371"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // bad expiration - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?expiry=six"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidExpiration(_)))); // with bad query parameter - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?expiry"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // with an unknown query parameter - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?unknown=new"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // with two unknown query parameters - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ - zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?unknown=new&\ - another=new"; + let invoice_str = + "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/y----------+bc:utxob:\ + zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?unknown=new&another=new"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // with expiration and an unknown query parameter - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ - zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?\ - expiry=1682086371&unknown=new"; + let invoice_str = + "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/y----------+bc:utxob:\ + zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?expiry=1682086371&unknown=new"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // with an unknown query parameter containing percent-encoded text - let invoice_base = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:\ - utxob:zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?"; + let invoice_base = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ + zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?"; let query_key_encoded = ":@-%20%23"; let query_key_decoded = ":@- #"; let query_val_encoded = "?/.%26%3D"; @@ -590,7 +592,7 @@ mod test { let invoice_str = "2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F"; let result = RgbInvoice::from_str(invoice_str); - assert!(matches!(result, Err(InvoiceParseError::Invalid))); + assert!(matches!(result, Err(InvoiceParseError::AbsentScheme))); // invalid scheme let invoice_str = "bad:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/bc:utxob:\ @@ -599,26 +601,30 @@ mod test { assert!(matches!(result, Err(InvoiceParseError::InvalidScheme(_)))); // empty transport endpoint specification - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints="; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // invalid transport endpoint specification - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=bad"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // invalid transport variant - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpca:/\ /host.example.com"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // rgb-rpc variant - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpc://\ host.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); @@ -629,7 +635,8 @@ mod test { assert_eq!(invoice.to_string(), invoice_str); // rgb-rpc variant, host containing authentication, "-" characters and port - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpcs:/\ /user:pass@host-1.ex-ample.com:1234"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); @@ -640,7 +647,8 @@ mod test { assert_eq!(invoice.to_string(), invoice_str); // rgb-rpc variant, IPv6 host - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpcs:/\ /%5B2001:db8::1%5D:1234"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); @@ -651,29 +659,30 @@ mod test { assert_eq!(invoice.to_string(), invoice_str); // rgb-rpc variant with missing host - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpc://"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // rgb-rpc variant with invalid separator - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ - zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpc/\ - host.example.com"; + let invoice_str = + "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/y----------+bc:utxob:\ + zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpc/host.example.com"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // rgb-rpc variant with invalid transport host specification - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ - zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpc://\ - ho]t"; + let invoice_str = + "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/y----------+bc:utxob:\ + zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpc://ho]t"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::Uri(_)))); // rgb+http variant let invoice_str = "rgb:\ 11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ - BF+bc:utxob:zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=https://\ + y----------+bc:utxob:zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=https://\ host.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); let transports = vec![RgbTransport::RestHttp { @@ -684,7 +693,8 @@ mod test { assert_eq!(invoice.to_string(), invoice_str); // rgb+ws variant - let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/BF+bc:utxob:\ + let invoice_str = "rgb:11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ + y----------+bc:utxob:\ zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=wss://\ host.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); @@ -700,7 +710,7 @@ mod test { // multiple transports let invoice_str = "rgb:\ 11Fa!$Dk-rUWXhy8-7H35qXm-pLGGLOo-txBWUgj-tbOaSbI/RGB20/\ - BF+bc:utxob:zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpcs://\ + y----------+bc:utxob:zlVS28Rb-amM5lih-ONXGACC-IUWD0Y$-0JXcnWZ-MQn8VEI-B39!F?endpoints=rpcs://\ host1.example.com,http://host2.example.com,ws://host3.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); let transports = vec![ diff --git a/src/containers/anchors.rs b/src/containers/anchors.rs index 2c7c1671..0a346a0c 100644 --- a/src/containers/anchors.rs +++ b/src/containers/anchors.rs @@ -36,7 +36,7 @@ use rgb::{ use strict_encoding::StrictDumb; use crate::containers::Dichotomy; -use crate::{MergeReveal, MergeRevealError, TypedAssignsExt, LIB_NAME_RGB_STD}; +use crate::{MergeReveal, MergeRevealError, LIB_NAME_RGB_STD}; #[derive(Clone, Eq, PartialEq, Debug, Display, Error)] #[display("state transition {0} is not a part of the bundle.")] diff --git a/src/containers/file.rs b/src/containers/file.rs index 4cd722c0..02a567b8 100644 --- a/src/containers/file.rs +++ b/src/containers/file.rs @@ -273,7 +273,6 @@ mod test { issuer: Default::default(), testnet: Default::default(), alt_layers1: Default::default(), - asset_tags: Default::default(), metadata: Default::default(), globals: Default::default(), assignments: Default::default(), @@ -371,7 +370,6 @@ mod test { issuer: Default::default(), testnet: Default::default(), alt_layers1: Default::default(), - asset_tags: Default::default(), metadata: Default::default(), globals: Default::default(), assignments: Default::default(), diff --git a/src/containers/seal.rs b/src/containers/seal.rs index 49dc3079..6e044604 100644 --- a/src/containers/seal.rs +++ b/src/containers/seal.rs @@ -24,7 +24,7 @@ use bp::seals::txout::{BlindSeal, CloseMethod, SealTxid}; use bp::secp256k1::rand::{thread_rng, RngCore}; use bp::Vout; -use rgb::{GraphSeal, Layer1, SecretSeal, TxoSeal, XChain}; +use rgb::{Assign, ExposedSeal, GraphSeal, Layer1, SecretSeal, State, XChain}; use crate::LIB_NAME_RGB_STD; @@ -109,7 +109,7 @@ impl From for GraphSeal { /// Seal used by operation builder which can be either revealed or concealed. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)] -pub enum BuilderSeal { +pub enum BuilderSeal { Revealed(XChain), #[from] Concealed(XChain), @@ -119,11 +119,26 @@ impl From>> for BuilderSeal> { fn from(seal: XChain>) -> Self { BuilderSeal::Revealed(seal) } } -impl BuilderSeal { +impl BuilderSeal { pub fn layer1(&self) -> Layer1 { match self { BuilderSeal::Revealed(x) => x.layer1(), BuilderSeal::Concealed(x) => x.layer1(), } } + + pub fn assignment(self, state: State) -> Assign { + match self { + BuilderSeal::Revealed(seal) => Assign::Revealed { + seal, + state, + lock: none!(), + }, + BuilderSeal::Concealed(seal) => Assign::Confidential { + seal, + state, + lock: none!(), + }, + } + } } diff --git a/src/containers/suppl.rs b/src/containers/suppl.rs index 5da0ea8b..a98aa3ed 100644 --- a/src/containers/suppl.rs +++ b/src/containers/suppl.rs @@ -221,6 +221,19 @@ impl Supplement { } } + pub fn with( + content: impl Into, + creator: impl Into, + timestamp: i64, + ) -> Self { + Supplement { + content_id: content.into(), + timestamp, + creator: creator.into(), + annotations: none!(), + } + } + pub fn get_default_opt( &self, sub: SupplSub, diff --git a/src/contract/assignments.rs b/src/contract/allocation.rs similarity index 51% rename from src/contract/assignments.rs rename to src/contract/allocation.rs index d4967520..cb3cdc64 100644 --- a/src/contract/assignments.rs +++ b/src/contract/allocation.rs @@ -24,51 +24,12 @@ use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hash; -use amplify::confinement::SmallVec; -use commit_verify::Conceal; -use invoice::Amount; use rgb::vm::WitnessOrd; -use rgb::{ - Assign, AssignAttach, AssignData, AssignFungible, AssignRights, AssignmentType, AttachState, - DataState, ExposedSeal, ExposedState, OpId, Opout, RevealedAttach, RevealedData, RevealedValue, - TypedAssigns, VoidState, XChain, XOutputSeal, XWitnessId, -}; +use rgb::{AssignmentType, ExposedSeal, OpId, Opout, State, XChain, XOutputSeal, XWitnessId}; use strict_encoding::{StrictDecode, StrictDumb, StrictEncode}; use crate::LIB_NAME_RGB_STD; -/// Trait used by contract state. Unlike [`ExposedState`] it doesn't allow -/// concealment of the state, i.e. may contain incomplete data without blinding -/// factors, asset tags etc. -pub trait KnownState: Debug + StrictDumb + StrictEncode + StrictDecode + Eq + Clone + Hash { - const IS_FUNGIBLE: bool; -} - -impl KnownState for () { - const IS_FUNGIBLE: bool = false; -} -impl KnownState for VoidState { - const IS_FUNGIBLE: bool = false; -} -impl KnownState for DataState { - const IS_FUNGIBLE: bool = false; -} -impl KnownState for Amount { - const IS_FUNGIBLE: bool = true; -} -impl KnownState for AttachState { - const IS_FUNGIBLE: bool = false; -} -impl KnownState for RevealedValue { - const IS_FUNGIBLE: bool = true; -} -impl KnownState for RevealedData { - const IS_FUNGIBLE: bool = false; -} -impl KnownState for RevealedAttach { - const IS_FUNGIBLE: bool = false; -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_STD)] @@ -82,8 +43,10 @@ pub struct WitnessInfo { pub ord: WitnessOrd, } +/// Allocation is an owned state assignment, equipped with information about the operation defining +/// the assignment and the witness id, containing the commitment to the operation. #[allow(clippy::derived_hash_with_manual_eq)] -#[derive(Copy, Clone, Eq, Hash, Debug)] +#[derive(Clone, Eq, Hash, Debug)] #[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] #[strict_type(lib = LIB_NAME_RGB_STD)] #[cfg_attr( @@ -91,14 +54,14 @@ pub struct WitnessInfo { derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "camelCase") )] -pub struct OutputAssignment { +pub struct Allocation { pub opout: Opout, pub seal: XOutputSeal, pub state: State, pub witness: Option, } -impl PartialEq for OutputAssignment { +impl PartialEq for Allocation { fn eq(&self, other: &Self) -> bool { // We ignore difference in witness transactions, state and seal definitions here // in order to support updates from the ephemeral state of the lightning @@ -113,11 +76,11 @@ impl PartialEq for OutputAssignment { } } -impl PartialOrd for OutputAssignment { +impl PartialOrd for Allocation { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for OutputAssignment { +impl Ord for Allocation { fn cmp(&self, other: &Self) -> Ordering { if self == other { return Ordering::Equal; @@ -129,7 +92,7 @@ impl Ord for OutputAssignment { } } -impl OutputAssignment { +impl Allocation { /// # Panics /// /// If the processing is done on invalid stash data, the seal is @@ -142,7 +105,7 @@ impl OutputAssignment { ty: AssignmentType, no: u16, ) -> Self { - OutputAssignment { + Allocation { opout: Opout::new(opid, ty, no), seal: seal.try_to_output_seal(witness_id).expect( "processing contract from unverified/invalid stash: witness seal chain doesn't \ @@ -164,7 +127,7 @@ impl OutputAssignment { ty: AssignmentType, no: u16, ) -> Self { - OutputAssignment { + Allocation { opout: Opout::new(opid, ty, no), seal: seal.to_output_seal().expect( "processing contract from unverified/invalid stash: seal must have txid \ @@ -175,16 +138,6 @@ impl OutputAssignment { } } - /// Transmutes output assignment from one form of state to another - pub fn transmute>(self) -> OutputAssignment { - OutputAssignment { - opout: self.opout, - seal: self.seal, - state: self.state.into(), - witness: self.witness, - } - } - pub fn check_witness(&self, filter: &HashMap) -> bool { match self.witness { None => true, @@ -194,62 +147,3 @@ impl OutputAssignment { } } } - -pub trait TypedAssignsExt { - fn reveal_seal(&mut self, seal: XChain); - - fn filter_revealed_seals(&self) -> Vec>; -} - -impl TypedAssignsExt for TypedAssigns { - fn reveal_seal(&mut self, seal: XChain) { - fn reveal( - vec: &mut SmallVec>, - revealed: XChain, - ) { - for assign in vec.iter_mut() { - match assign { - Assign::ConfidentialSeal { seal, state, lock } - if *seal == revealed.conceal() => - { - *assign = Assign::Revealed { - seal: revealed, - state: state.clone(), - lock: *lock, - } - } - Assign::Confidential { seal, state, lock } if *seal == revealed.conceal() => { - *assign = Assign::ConfidentialState { - seal: revealed, - state: *state, - lock: *lock, - } - } - _ => {} - } - } - } - - match self { - TypedAssigns::Declarative(v) => reveal(v, seal), - TypedAssigns::Fungible(v) => reveal(v, seal), - TypedAssigns::Structured(v) => reveal(v, seal), - TypedAssigns::Attachment(v) => reveal(v, seal), - } - } - - fn filter_revealed_seals(&self) -> Vec> { - match self { - TypedAssigns::Declarative(s) => { - s.iter().filter_map(AssignRights::revealed_seal).collect() - } - TypedAssigns::Fungible(s) => { - s.iter().filter_map(AssignFungible::revealed_seal).collect() - } - TypedAssigns::Structured(s) => s.iter().filter_map(AssignData::revealed_seal).collect(), - TypedAssigns::Attachment(s) => { - s.iter().filter_map(AssignAttach::revealed_seal).collect() - } - } - } -} diff --git a/src/contract/merge_reveal.rs b/src/contract/merge_reveal.rs index b662f5a5..a8975f24 100644 --- a/src/contract/merge_reveal.rs +++ b/src/contract/merge_reveal.rs @@ -21,13 +21,13 @@ use std::collections::BTreeMap; -use amplify::confinement::Confined; +use amplify::confinement::{Confined, NonEmptyVec}; use amplify::Wrapper; use bp::Txid; use commit_verify::{mpc, Conceal}; use rgb::{ - Assign, Assignments, BundleId, ExposedSeal, ExposedState, Extension, Genesis, OpId, Operation, - Transition, TransitionBundle, TypedAssigns, + Assign, Assignments, BundleId, ExposedSeal, Extension, Genesis, OpId, Operation, Transition, + TransitionBundle, TypedAssigns, }; #[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error, From)] @@ -90,7 +90,7 @@ pub trait MergeRevealContract: Sized { } */ -impl MergeReveal for Assign { +impl MergeReveal for Assign { fn merge_reveal(self, other: Self) -> Result { debug_assert_eq!(self.conceal(), other.conceal()); match (self, other) { @@ -98,102 +98,19 @@ impl MergeReveal for Assign (_, state @ Assign::Revealed { .. }) | (state @ Assign::Revealed { .. }, _) => { Ok(state) } - - // ConfidentialAmount + ConfidentialSeal = Revealed - ( - Assign::ConfidentialSeal { - state, lock: lock1, .. - }, - Assign::ConfidentialState { - seal, lock: lock2, .. - }, - ) => { - debug_assert_eq!(lock1, lock2); - Ok(Assign::Revealed { - seal, - state, - lock: lock1, - }) - } - - // ConfidentialSeal + ConfidentialAmount = Revealed - ( - Assign::ConfidentialState { - seal, lock: lock1, .. - }, - Assign::ConfidentialSeal { - state, lock: lock2, .. - }, - ) => { - debug_assert_eq!(lock1, lock2); - Ok(Assign::Revealed { - seal, - state, - lock: lock1, - }) - } - - // if self and other is of same variant return self - (state @ Assign::ConfidentialState { .. }, Assign::ConfidentialState { .. }) => { - Ok(state) - } - (state @ Assign::ConfidentialSeal { .. }, Assign::ConfidentialSeal { .. }) => Ok(state), - // Anything + Confidential = Anything - (state, Assign::Confidential { .. }) | (Assign::Confidential { .. }, state) => { - Ok(state) - } + (state, Assign::Confidential { .. }) => Ok(state), } } } impl MergeReveal for TypedAssigns { fn merge_reveal(self, other: Self) -> Result { - match (self, other) { - (TypedAssigns::Declarative(first_vec), TypedAssigns::Declarative(second_vec)) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssigns::Declarative( - Confined::try_from(result).expect("collection of the same size"), - )) - } - - (TypedAssigns::Fungible(first_vec), TypedAssigns::Fungible(second_vec)) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssigns::Fungible( - Confined::try_from(result).expect("collection of the same size"), - )) - } - - (TypedAssigns::Structured(first_vec), TypedAssigns::Structured(second_vec)) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssigns::Structured( - Confined::try_from(result).expect("collection of the same size"), - )) - } - - (TypedAssigns::Attachment(first_vec), TypedAssigns::Attachment(second_vec)) => { - let mut result = Vec::with_capacity(first_vec.len()); - for (first, second) in first_vec.into_iter().zip(second_vec.into_iter()) { - result.push(first.merge_reveal(second)?); - } - Ok(TypedAssigns::Attachment( - Confined::try_from(result).expect("collection of the same size"), - )) - } - // No other patterns possible, should not reach here - _ => { - unreachable!("Assignments::consensus_commitments is broken") - } + let mut result = Vec::with_capacity(self.len()); + for (first, second) in self.into_iter().zip(other.into_iter()) { + result.push(first.merge_reveal(second)?); } + Ok(TypedAssigns::from(NonEmptyVec::from_checked(result))) } } diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 624830ed..cc0c48f2 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -19,10 +19,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod assignments; +mod allocation; mod merge_reveal; -pub use assignments::{KnownState, OutputAssignment, TypedAssignsExt, WitnessInfo}; +pub use allocation::{Allocation, WitnessInfo}; pub use merge_reveal::{MergeReveal, MergeRevealError}; use rgb::vm::OrdOpRef; use rgb::{ExtensionType, OpId, TransitionType, XWitnessId}; diff --git a/src/interface/builder.rs b/src/interface/builder.rs index eb8a01c4..5b2f08b4 100644 --- a/src/interface/builder.rs +++ b/src/interface/builder.rs @@ -21,28 +21,23 @@ #![allow(clippy::result_large_err)] -use std::collections::{BTreeMap, HashSet}; +use std::collections::btree_map::Entry; -use amplify::confinement::{Confined, SmallOrdSet, TinyOrdMap, U16}; -use amplify::{confinement, Wrapper}; +use amplify::confinement::{self, Confined, SmallOrdSet, TinyOrdMap}; use chrono::Utc; -use invoice::{Allocation, Amount}; use rgb::validation::Scripts; use rgb::{ - validation, AltLayer1, AltLayer1Set, AssetTag, AssetTags, Assign, AssignmentType, Assignments, - AttachState, BlindingFactor, ContractId, DataState, ExposedSeal, FungibleType, Genesis, - GenesisSeal, GlobalState, GraphSeal, Identity, Input, Layer1, MetadataError, Opout, - OwnedStateSchema, RevealedAttach, RevealedData, RevealedValue, Schema, Transition, - TransitionType, TypedAssigns, XChain, XOutpoint, + validation, AltLayer1, AltLayer1Set, AssignmentType, Assignments, AttachId, ContractId, + ExposedSeal, Genesis, GenesisSeal, GlobalState, GlobalStateSchema, GlobalStateType, GraphSeal, + Identity, Input, Layer1, MetaType, Metadata, MetadataError, Opout, Schema, State, StateData, + Transition, TransitionType, TypedAssigns, ValencyType, XChain, XOutpoint, STATE_DATA_MAX_LEN, }; -use rgbcore::{GlobalStateSchema, GlobalStateType, MetaType, Metadata, ValencyType}; use strict_encoding::{FieldName, SerializeError, StrictSerialize}; -use strict_types::{decode, SemId, TypeSystem}; +use strict_types::{decode, typify, SemId, StrictVal, TypeSystem}; use crate::containers::{BuilderSeal, ContainerVer, Contract, ValidConsignment}; use crate::interface::resolver::DumbResolver; -use crate::interface::{Iface, IfaceImpl, TransitionIface}; -use crate::persistence::PersistedState; +use crate::interface::{Iface, IfaceImpl, StateCalc, StateCalcError, TransitionIface}; use crate::Outpoint; #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] @@ -64,28 +59,13 @@ pub enum BuilderError { /// assignment `{0}` is not known to the schema. AssignmentNotFound(FieldName), + /// valency `{0}` is not known to the schema. + ValencyNotFound(FieldName), + /// transition `{0}` is not known to the schema. TransitionNotFound(FieldName), - /// unknown owned state name `{0}`. - InvalidStateField(FieldName), - - /// state `{0}` provided to the builder has invalid type. - InvalidStateType(AssignmentType), - - /// asset tag for state `{0}` must be added before any fungible state of - /// the same type. - AssetTagMissed(AssignmentType), - - /// asset tag for state `{0}` was already automatically created. Please call - /// `add_asset_tag` before adding any fungible state to the builder. - AssetTagAutomatic(AssignmentType), - - /// state data for state type `{0}` are invalid: asset tag doesn't match the - /// tag defined by the contract. - AssetTagInvalid(AssignmentType), - - /// interface doesn't specifies default operation name, thus an explicit + /// interface doesn't specify default operation name, thus an explicit /// operation type must be provided with `set_operation_type` method. NoOperationSubtype, @@ -95,6 +75,10 @@ pub enum BuilderError { /// {0} is not supported by the contract genesis. InvalidLayer1(Layer1), + #[from] + #[display(inner)] + Calc(StateCalcError), + #[from] #[display(inner)] StrictEncode(SerializeError), @@ -103,6 +87,10 @@ pub enum BuilderError { #[display(inner)] Reify(decode::Error), + #[from] + #[display(inner)] + Typify(typify::Error), + #[from] #[display(inner)] Confinement(confinement::Error), @@ -164,23 +152,6 @@ impl ContractBuilder { } } - pub fn deterministic( - issuer: Identity, - iface: Iface, - schema: Schema, - iimpl: IfaceImpl, - types: TypeSystem, - scripts: Scripts, - ) -> Self { - Self { - builder: OperationBuilder::deterministic(iface, schema, iimpl, types), - testnet: true, - alt_layers1: none!(), - scripts, - issuer, - } - } - pub fn type_system(&self) -> &TypeSystem { self.builder.type_system() } pub fn set_mainnet(mut self) -> Self { @@ -209,164 +180,117 @@ impl ContractBuilder { } #[inline] - pub fn asset_tag(&self, name: impl Into) -> Result { - self.builder.asset_tag(name) + pub fn meta_type(&self, name: impl Into) -> Result { + self.builder.meta_type(name) } #[inline] - pub fn add_asset_tag( - mut self, - name: impl Into, - asset_tag: AssetTag, - ) -> Result { - self.builder = self.builder.add_asset_tag(name, asset_tag)?; - Ok(self) - } - - #[inline] - pub fn global_type(&self, name: &FieldName) -> Option { + pub fn global_type(&self, name: impl Into) -> Result { self.builder.global_type(name) } #[inline] - pub fn valency_type(&self, name: &FieldName) -> Option { + pub fn valency_type(&self, name: impl Into) -> Result { self.builder.valency_type(name) } + #[inline] + pub fn meta_name(&self, type_id: MetaType) -> &FieldName { self.builder.meta_name(type_id) } + #[inline] pub fn valency_name(&self, type_id: ValencyType) -> &FieldName { self.builder.valency_name(type_id) } - #[inline] - pub fn meta_name(&self, type_id: MetaType) -> &FieldName { self.builder.meta_name(type_id) } - - #[inline] pub fn add_metadata( mut self, name: impl Into, - value: impl StrictSerialize, + value: StrictVal, ) -> Result { self.builder = self.builder.add_metadata(name, value)?; Ok(self) } #[inline] - pub fn add_global_state( + pub fn serialize_metadata( mut self, name: impl Into, - value: impl StrictSerialize, + value: &impl StrictSerialize, ) -> Result { - self.builder = self.builder.add_global_state(name, value)?; + self.builder = self.builder.serialize_metadata(name, value)?; Ok(self) } - pub fn add_owned_state_det( - mut self, - name: impl Into, - seal: impl Into>, - state: PersistedState, - ) -> Result { - let seal = seal.into(); - self.check_layer1(seal.layer1())?; - self.builder = self.builder.add_owned_state_det(name, seal, state)?; - Ok(self) - } - - pub fn add_rights( - mut self, - name: impl Into, - seal: impl Into>, - ) -> Result { - let seal = seal.into(); - self.check_layer1(seal.layer1())?; - self.builder = self.builder.add_rights(name, seal)?; - Ok(self) - } - - pub fn add_fungible_state( + pub fn add_global_state( mut self, name: impl Into, - seal: impl Into>, - value: impl Into, + value: StrictVal, ) -> Result { - let name = name.into(); - let seal = seal.into(); - self.check_layer1(seal.layer1())?; - self.builder.init_asset_tag(name.clone())?; - self.builder = self.builder.add_fungible_state(name, seal, value)?; + self.builder = self.builder.add_global_state(name, value)?; Ok(self) } - pub fn add_fungible_state_det( + #[inline] + pub fn serialize_global_state( mut self, name: impl Into, - seal: impl Into>, - value: impl Into, - blinding: BlindingFactor, + value: &impl StrictSerialize, ) -> Result { - let name = name.into(); - let seal = seal.into(); - self.check_layer1(seal.layer1())?; - let tag = self.builder.init_asset_tag(name.clone())?; - let state = RevealedValue::with_blinding(value.into(), blinding, tag); - self.builder = self.builder.add_fungible_state_det(name, seal, state)?; + self.builder = self.builder.serialize_global_state(name, value)?; Ok(self) } - pub fn add_data( + pub fn add_owned_state_raw( mut self, - name: impl Into, + type_id: AssignmentType, seal: impl Into>, - value: impl StrictSerialize, + state: State, ) -> Result { let seal = seal.into(); self.check_layer1(seal.layer1())?; - self.builder = self.builder.add_data(name, seal, value)?; + self.builder = self.builder.add_owned_state_raw(type_id, seal, state)?; Ok(self) } - pub fn add_data_det( + pub fn add_rights( mut self, name: impl Into, seal: impl Into>, - data: RevealedData, + attach: Option, ) -> Result { - let seal = seal.into(); - self.check_layer1(seal.layer1())?; - self.builder = self.builder.add_data_det(name, seal, data)?; + self.builder = self.builder.add_rights(name, seal, attach)?; Ok(self) } - pub fn add_attachment( + pub fn add_owned_state( mut self, name: impl Into, seal: impl Into>, - attachment: AttachState, + state: StrictVal, + attach: Option, ) -> Result { let seal = seal.into(); self.check_layer1(seal.layer1())?; - self.builder = self.builder.add_attachment(name, seal, attachment)?; + self.builder = self.builder.add_owned_state(name, seal, state, attach)?; Ok(self) } - pub fn add_attachment_det( + pub fn serialize_owned_state( mut self, name: impl Into, seal: impl Into>, - attachment: RevealedAttach, + value: &impl StrictSerialize, + attach: Option, ) -> Result { let seal = seal.into(); self.check_layer1(seal.layer1())?; - self.builder = self.builder.add_attachment_det(name, seal, attachment)?; + self.builder = self + .builder + .serialize_owned_state(name, seal, value, attach)?; Ok(self) } pub fn issue_contract(self) -> Result, BuilderError> { - debug_assert!( - !self.builder.deterministic, - "for issuing deterministic contracts please use issue_contract_det method" - ); self.issue_contract_raw(Utc::now().timestamp()) } @@ -374,16 +298,11 @@ impl ContractBuilder { self, timestamp: i64, ) -> Result, BuilderError> { - debug_assert!( - self.builder.deterministic, - "for issuing deterministic contracts please use deterministic constructor" - ); self.issue_contract_raw(timestamp) } fn issue_contract_raw(self, timestamp: i64) -> Result, BuilderError> { - let (schema, iface, iimpl, global, assignments, types, asset_tags) = - self.builder.complete(None); + let (schema, iface, iimpl, global, assignments, types) = self.builder.complete(); let genesis = Genesis { ffv: none!(), @@ -392,7 +311,6 @@ impl ContractBuilder { timestamp, testnet: self.testnet, alt_layers1: self.alt_layers1, - asset_tags, metadata: empty!(), globals: global, assignments, @@ -430,13 +348,15 @@ impl ContractBuilder { } } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct TransitionBuilder { contract_id: ContractId, builder: OperationBuilder, nonce: u64, transition_type: TransitionType, - inputs: TinyOrdMap, + inputs: TinyOrdMap, + // TODO: Remove option once we have blank builder + calc: Option, } impl TransitionBuilder { @@ -447,17 +367,7 @@ impl TransitionBuilder { iimpl: IfaceImpl, types: TypeSystem, ) -> Self { - Self::with(contract_id, iface, schema, iimpl, TransitionType::BLANK, types) - } - - pub fn blank_transition_det( - contract_id: ContractId, - iface: Iface, - schema: Schema, - iimpl: IfaceImpl, - types: TypeSystem, - ) -> Self { - Self::deterministic(contract_id, iface, schema, iimpl, TransitionType::BLANK, types) + Self::with(contract_id, iface, schema, iimpl, TransitionType::BLANK, types, None) } pub fn default_transition( @@ -466,28 +376,15 @@ impl TransitionBuilder { schema: Schema, iimpl: IfaceImpl, types: TypeSystem, + scripts: Scripts, ) -> Result { let transition_type = iface .default_operation .as_ref() .and_then(|name| iimpl.transition_type(name)) .ok_or(BuilderError::NoOperationSubtype)?; - Ok(Self::with(contract_id, iface, schema, iimpl, transition_type, types)) - } - - pub fn default_transition_det( - contract_id: ContractId, - iface: Iface, - schema: Schema, - iimpl: IfaceImpl, - types: TypeSystem, - ) -> Result { - let transition_type = iface - .default_operation - .as_ref() - .and_then(|name| iimpl.transition_type(name)) - .ok_or(BuilderError::NoOperationSubtype)?; - Ok(Self::deterministic(contract_id, iface, schema, iimpl, transition_type, types)) + let calc = StateCalc::new(scripts, iimpl.state_abi); + Ok(Self::with(contract_id, iface, schema, iimpl, transition_type, types, Some(calc))) } pub fn named_transition( @@ -497,27 +394,14 @@ impl TransitionBuilder { iimpl: IfaceImpl, transition_name: impl Into, types: TypeSystem, + scripts: Scripts, ) -> Result { let transition_name = transition_name.into(); let transition_type = iimpl .transition_type(&transition_name) .ok_or(BuilderError::TransitionNotFound(transition_name))?; - Ok(Self::with(contract_id, iface, schema, iimpl, transition_type, types)) - } - - pub fn named_transition_det( - contract_id: ContractId, - iface: Iface, - schema: Schema, - iimpl: IfaceImpl, - transition_name: impl Into, - types: TypeSystem, - ) -> Result { - let transition_name = transition_name.into(); - let transition_type = iimpl - .transition_type(&transition_name) - .ok_or(BuilderError::TransitionNotFound(transition_name))?; - Ok(Self::deterministic(contract_id, iface, schema, iimpl, transition_type, types)) + let calc = StateCalc::new(scripts, iimpl.state_abi); + Ok(Self::with(contract_id, iface, schema, iimpl, transition_type, types, Some(calc))) } fn with( @@ -527,6 +411,7 @@ impl TransitionBuilder { iimpl: IfaceImpl, transition_type: TransitionType, types: TypeSystem, + calc: Option, ) -> Self { Self { contract_id, @@ -534,23 +419,7 @@ impl TransitionBuilder { nonce: u64::MAX, transition_type, inputs: none!(), - } - } - - fn deterministic( - contract_id: ContractId, - iface: Iface, - schema: Schema, - iimpl: IfaceImpl, - transition_type: TransitionType, - types: TypeSystem, - ) -> Self { - Self { - contract_id, - builder: OperationBuilder::deterministic(iface, schema, iimpl, types), - nonce: u64::MAX, - transition_type, - inputs: none!(), + calc, } } @@ -558,60 +427,30 @@ impl TransitionBuilder { pub fn transition_type(&self) -> TransitionType { self.transition_type } - pub fn set_nonce(mut self, nonce: u64) -> Self { - self.nonce = nonce; - self - } - #[inline] - pub fn asset_tag(&self, name: impl Into) -> Result { - self.builder.asset_tag(name) + pub fn global_type(&self, name: impl Into) -> Result { + self.builder.global_type(name) } #[inline] - pub fn add_asset_tag( - mut self, + pub fn assignments_type( + &self, name: impl Into, - asset_tag: AssetTag, - ) -> Result { - self.builder = self.builder.add_asset_tag(name, asset_tag)?; - Ok(self) - } - - #[inline] - pub fn add_asset_tag_raw( - mut self, - type_id: AssignmentType, - asset_tag: AssetTag, - ) -> Result { - self.builder = self.builder.add_asset_tag_raw(type_id, asset_tag)?; - Ok(self) + ) -> Result { + self.builder.assignments_type(name) } #[inline] - pub fn add_metadata( - mut self, - name: impl Into, - value: impl StrictSerialize, - ) -> Result { - self.builder = self.builder.add_metadata(name, value)?; - Ok(self) + pub fn valency_type(&self, name: impl Into) -> Result { + self.builder.valency_type(name) } #[inline] - pub fn add_global_state( - mut self, - name: impl Into, - value: impl StrictSerialize, - ) -> Result { - self.builder = self.builder.add_global_state(name, value)?; - Ok(self) + pub fn valency_name(&self, type_id: ValencyType) -> &FieldName { + self.builder.valency_name(type_id) } - pub fn add_input(mut self, opout: Opout, state: PersistedState) -> Result { - self.inputs.insert(Input::with(opout), state)?; - Ok(self) - } + pub fn meta_name(&self, type_id: MetaType) -> &FieldName { self.builder.meta_name(type_id) } pub fn default_assignment(&self) -> Result<&FieldName, BuilderError> { self.builder @@ -621,186 +460,115 @@ impl TransitionBuilder { .ok_or(BuilderError::NoDefaultAssignment) } - #[inline] - pub fn assignments_type(&self, name: &FieldName) -> Option { - self.builder.assignments_type(name) - } - - #[inline] - pub fn global_type(&self, name: &FieldName) -> Option { - self.builder.global_type(name) - } - - #[inline] - pub fn valency_type(&self, name: &FieldName) -> Option { - self.builder.valency_type(name) - } - - pub fn valency_name(&self, type_id: ValencyType) -> &FieldName { - self.builder.valency_name(type_id) - } - - pub fn meta_name(&self, type_id: MetaType) -> &FieldName { self.builder.meta_name(type_id) } - - pub fn add_owned_state_det( - mut self, - name: impl Into, - seal: impl Into>, - state: PersistedState, - ) -> Result { - self.builder = self.builder.add_owned_state_det(name, seal, state)?; - Ok(self) + pub fn set_nonce(mut self, nonce: u64) -> Self { + self.nonce = nonce; + self } - pub fn add_owned_state_raw( - mut self, - type_id: AssignmentType, - seal: impl Into>, - state: PersistedState, - ) -> Result { - if matches!(state, PersistedState::Amount(_, _, tag) if self.builder.asset_tag_raw(type_id)? != tag) - { - return Err(BuilderError::AssetTagInvalid(type_id)); + pub fn add_input(mut self, opout: Opout, state: State) -> Result { + if let Some(calc) = &mut self.calc { + calc.reg_input(opout.ty, &state)?; } - self.builder = self.builder.add_owned_state_raw(type_id, seal, state)?; + self.inputs.insert(Input::with(opout), state)?; Ok(self) } - pub fn add_rights( + pub fn add_metadata( mut self, name: impl Into, - seal: impl Into>, + value: StrictVal, ) -> Result { - self.builder = self.builder.add_rights(name, seal)?; + self.builder = self.builder.add_metadata(name, value)?; Ok(self) } - pub fn add_fungible_default_state( - self, - seal: impl Into>, - value: u64, - ) -> Result { - let assignment_name = self.default_assignment()?.clone(); - self.add_fungible_state(assignment_name, seal.into(), value) - } - - pub fn add_fungible_default_state_det( - self, - seal: impl Into>, - value: u64, - blinding: BlindingFactor, - ) -> Result { - let assignment_name = self.default_assignment()?.clone(); - self.add_fungible_state_det(assignment_name, seal.into(), value, blinding) - } - - pub fn add_fungible_state( + #[inline] + pub fn serialize_metadata( mut self, name: impl Into, - seal: impl Into>, - value: impl Into, + value: &impl StrictSerialize, ) -> Result { - self.builder = self.builder.add_fungible_state(name.into(), seal, value)?; + self.builder = self.builder.serialize_metadata(name, value)?; Ok(self) } - pub fn add_fungible_state_det( + pub fn add_global_state( mut self, name: impl Into, - seal: impl Into>, - value: impl Into, - blinding: BlindingFactor, + value: StrictVal, ) -> Result { - let name = name.into(); - let type_id = self - .builder - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name.clone()))?; - let tag = self.builder.asset_tag_raw(type_id)?; - let state = RevealedValue::with_blinding(value.into(), blinding, tag); - - self.builder = self.builder.add_fungible_state_det(name, seal, state)?; + self.builder = self.builder.add_global_state(name, value)?; Ok(self) } - pub fn add_fungible_state_raw( + #[inline] + pub fn serialize_global_state( mut self, - type_id: AssignmentType, - seal: impl Into>, - value: impl Into, - blinding: BlindingFactor, + name: impl Into, + value: &impl StrictSerialize, ) -> Result { - let tag = self.builder.asset_tag_raw(type_id)?; - let state = RevealedValue::with_blinding(value.into(), blinding, tag); - self.builder = self.builder.add_fungible_state_raw(type_id, seal, state)?; + self.builder = self.builder.serialize_global_state(name, value)?; Ok(self) } - pub fn add_data( + // TODO: We won't need this once we will have Blank Transition builder + /// NB: This does not process the state with VM + pub fn add_owned_state_blank( mut self, - name: impl Into, + type_id: AssignmentType, seal: impl Into>, - value: impl StrictSerialize, + state: State, ) -> Result { - self.builder = self.builder.add_data(name, seal, value)?; + self.builder = self.builder.add_owned_state_raw(type_id, seal, state)?; Ok(self) } - pub fn add_data_det( + pub fn add_rights( mut self, name: impl Into, seal: impl Into>, - data: RevealedData, + attach: Option, ) -> Result { - self.builder = self.builder.add_data_det(name, seal, data)?; + self.builder = self.builder.add_rights(name, seal, attach)?; Ok(self) } - pub fn add_data_raw( + pub fn fulfill_owned_state( mut self, type_id: AssignmentType, seal: impl Into>, - allocation: impl Into, - blinding: u64, - ) -> Result { - let revealed_state = RevealedData::with_salt(allocation.into(), blinding.into()); - self.builder = self.builder.add_data_raw(type_id, seal, revealed_state)?; - Ok(self) - } - - pub fn add_data_default( - self, - seal: impl Into>, - value: impl StrictSerialize, - ) -> Result { - let assignment_name = self.default_assignment()?.clone(); - self.add_data(assignment_name, seal.into(), value) - } - - pub fn add_attachment( - mut self, - name: impl Into, - seal: impl Into>, - attachment: AttachState, - ) -> Result { - self.builder = self.builder.add_attachment(name, seal, attachment)?; - Ok(self) + state: State, + ) -> Result<(Self, Option), BuilderError> { + let calc = self + .calc + .as_mut() + .expect("you must not call fulfill_owned_state for the blank transition builder"); + let state = calc.calc_output(type_id, &state)?; + self.builder = self + .builder + .add_owned_state_raw(type_id, seal, state.sufficient)?; + Ok((self, state.insufficient)) } - pub fn add_attachment_det( + pub fn add_owned_state_change( mut self, - name: impl Into, + type_id: AssignmentType, seal: impl Into>, - attachment: RevealedAttach, ) -> Result { - self.builder = self.builder.add_attachment_det(name, seal, attachment)?; + let calc = self + .calc + .as_mut() + .expect("you must not call add_owned_state_change for the blank transition builder"); + if let Some(state) = calc.calc_change(type_id)? { + self.builder = self.builder.add_owned_state_raw(type_id, seal, state)?; + } Ok(self) } pub fn has_inputs(&self) -> bool { !self.inputs.is_empty() } pub fn complete_transition(self) -> Result { - let (_, _, _, global, assignments, _, _) = self.builder.complete(Some(&self.inputs)); + let (_, _, _, global, assignments, _) = self.builder.complete(); let transition = Transition { ffv: none!(), @@ -828,17 +596,10 @@ pub struct OperationBuilder { schema: Schema, iface: Iface, iimpl: IfaceImpl, - asset_tags: AssetTags, - deterministic: bool, global: GlobalState, meta: Metadata, - rights: TinyOrdMap>, 1, U16>>, - fungible: - TinyOrdMap, RevealedValue>, 1, U16>>, - data: TinyOrdMap, RevealedData>, 1, U16>>, - attachments: - TinyOrdMap, RevealedAttach>, 1, U16>>, + assignments: Assignments, // TODO: add valencies types: TypeSystem, } @@ -849,35 +610,10 @@ impl OperationBuilder { schema, iface, iimpl, - asset_tags: none!(), - deterministic: false, global: none!(), + assignments: none!(), meta: none!(), - rights: none!(), - fungible: none!(), - attachments: none!(), - data: none!(), - - types, - } - } - - fn deterministic(iface: Iface, schema: Schema, iimpl: IfaceImpl, types: TypeSystem) -> Self { - OperationBuilder { - schema, - iface, - iimpl, - asset_tags: none!(), - deterministic: true, - - global: none!(), - meta: none!(), - rights: none!(), - fungible: none!(), - attachments: none!(), - data: none!(), - types, } } @@ -892,22 +628,36 @@ impl OperationBuilder { .expect("internal inconsistency") } - fn assignments_type(&self, name: &FieldName) -> Option { - self.iimpl.assignments_type(name) + fn assignments_type(&self, name: impl Into) -> Result { + let name = name.into(); + self.iimpl + .assignment_type(&name) + .ok_or(BuilderError::AssignmentNotFound(name)) } - fn meta_type(&self, name: &FieldName) -> Option { self.iimpl.meta_type(name) } + fn meta_type(&self, name: impl Into) -> Result { + let name = name.into(); + self.iimpl + .meta_type(&name) + .ok_or(BuilderError::MetadataNotFound(name)) + } fn meta_name(&self, ty: MetaType) -> &FieldName { self.iimpl.meta_name(ty).expect("internal inconsistency") } - fn global_type(&self, name: &FieldName) -> Option { - self.iimpl.global_type(name) + fn global_type(&self, name: impl Into) -> Result { + let name = name.into(); + self.iimpl + .global_type(&name) + .ok_or(BuilderError::GlobalNotFound(name)) } - fn valency_type(&self, name: &FieldName) -> Option { - self.iimpl.valency_type(name) + fn valency_type(&self, name: impl Into) -> Result { + let name = name.into(); + self.iimpl + .valency_type(&name) + .ok_or(BuilderError::ValencyNotFound(name)) } fn valency_name(&self, ty: ValencyType) -> &FieldName { @@ -915,16 +665,9 @@ impl OperationBuilder { } #[inline] - fn state_schema(&self, type_id: AssignmentType) -> &OwnedStateSchema { - self.schema - .owned_types - .get(&type_id) - .expect("schema should match interface: must be checked by the constructor") - } - - #[inline] - fn meta_schema(&self, type_id: MetaType) -> &SemId { - self.schema + fn meta_schema(&self, type_id: MetaType) -> SemId { + *self + .schema .meta_types .get(&type_id) .expect("schema should match interface: must be checked by the constructor") @@ -938,511 +681,154 @@ impl OperationBuilder { .expect("schema should match interface: must be checked by the constructor") } - pub fn asset_tag(&self, name: impl Into) -> Result { - let name = name.into(); - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name.clone()))?; - self.asset_tag_raw(type_id) - } - - #[inline] - fn asset_tag_raw(&self, type_id: AssignmentType) -> Result { - self.asset_tags - .get(&type_id) - .ok_or(BuilderError::AssetTagMissed(type_id)) - .copied() - } - - #[inline] - pub fn add_asset_tag( - self, + fn add_metadata( + mut self, name: impl Into, - asset_tag: AssetTag, + value: StrictVal, ) -> Result { - let name = name.into(); - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - - self.add_asset_tag_raw(type_id, asset_tag) - } + let type_id = self.meta_type(name)?; - #[inline] - pub fn add_asset_tag_raw( - mut self, - type_id: AssignmentType, - asset_tag: AssetTag, - ) -> Result { - if self.fungible.contains_key(&type_id) { - return Err(BuilderError::AssetTagAutomatic(type_id)); - } + let types = self.type_system(); + let sem_id = *self + .schema + .meta_types + .get(&type_id) + .expect("schema-interface inconsistency"); + let value = types.typify(value, sem_id)?; + let data = types.strict_serialize_value::(&value)?; - self.asset_tags.insert(type_id, asset_tag)?; + self.meta.add_value(type_id, data.into())?; Ok(self) } - pub fn init_asset_tag(&mut self, name: impl Into) -> Result { - let name = name.into(); - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - - if let Some(tag) = self.asset_tags.get(&type_id) { - Ok(*tag) - } else { - let asset_tag = AssetTag::new_random( - format!("{}/{}", self.schema.schema_id(), self.iface.iface_id()), - type_id, - ); - self.asset_tags.insert(type_id, asset_tag)?; - Ok(asset_tag) - } - } - - pub fn add_metadata( + fn serialize_metadata( mut self, name: impl Into, - value: impl StrictSerialize, + value: &impl StrictSerialize, ) -> Result { - let name = name.into(); + let type_id = self.meta_type(name)?; let serialized = value.to_strict_serialized::<{ u16::MAX as usize }>()?; + let sem_id = self.meta_schema(type_id); - let Some(type_id) = self.meta_type(&name) else { - return Err(BuilderError::MetadataNotFound(name)); - }; + #[cfg(debug_assertions)] + self.types + .strict_deserialize_type(sem_id, &serialized) + .expect("failed deserialization"); - let sem_id = self.meta_schema(type_id); - self.types.strict_deserialize_type(*sem_id, &serialized)?; self.meta.add_value(type_id, serialized.into())?; Ok(self) } - pub fn add_global_state( + fn add_global_state( mut self, name: impl Into, - value: impl StrictSerialize, + value: StrictVal, ) -> Result { - let name = name.into(); - let serialized = value.to_strict_serialized::<{ u16::MAX as usize }>()?; + let type_id = self.global_type(name)?; - // Check value matches type requirements - let Some(type_id) = self.global_type(&name) else { - return Err(BuilderError::GlobalNotFound(name)); - }; - let sem_id = self.global_schema(type_id).sem_id; - self.types.strict_deserialize_type(sem_id, &serialized)?; - - self.global.add_state(type_id, serialized.into())?; + let types = self.type_system(); + let sem_id = self + .schema + .global_types + .get(&type_id) + .expect("schema-interface inconsistency") + .sem_id; + let value = types.typify(value, sem_id)?; + let data = types.strict_serialize_value::(&value)?; + self.global.add_state(type_id, data.into())?; Ok(self) } - fn add_owned_state_det( - self, - name: impl Into, - seal: impl Into>, - state: PersistedState, - ) -> Result { - debug_assert!( - self.deterministic, - "to add owned state in deterministic way the builder has to be created using \ - deterministic constructor" - ); - let name = name.into(); - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name.clone()))?; - self.add_owned_state_raw(type_id, seal, state) - } - - fn add_owned_state_raw( - self, - type_id: AssignmentType, - seal: impl Into>, - state: PersistedState, - ) -> Result { - match state { - PersistedState::Void => self.add_rights_raw(type_id, seal), - PersistedState::Amount(value, blinding, tag) => { - if self.asset_tag_raw(type_id)? != tag { - return Err(BuilderError::AssetTagInvalid(type_id)); - } - - self.add_fungible_state_raw( - type_id, - seal, - RevealedValue::with_blinding(value, blinding, tag), - ) - } - PersistedState::Data(data, salt) => { - self.add_data_raw(type_id, seal, RevealedData::with_salt(data, salt)) - } - PersistedState::Attachment(attach, salt) => self.add_attachment_raw( - type_id, - seal, - RevealedAttach::with_salt(attach.id, attach.media_type, salt), - ), - } - } - - fn add_rights( - self, - name: impl Into, - seal: impl Into>, - ) -> Result { - let name = name.into(); - - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - - self.add_rights_raw(type_id, seal) - } - - fn add_rights_raw( + fn serialize_global_state( mut self, - type_id: AssignmentType, - seal: impl Into>, - ) -> Result { - let state_schema = self.state_schema(type_id); - if *state_schema != OwnedStateSchema::Declarative { - return Err(BuilderError::InvalidStateType(type_id)); - } - - let seal = seal.into(); - match self.rights.get_mut(&type_id) { - Some(assignments) => { - assignments.push(seal)?; - } - None => { - self.rights.insert(type_id, Confined::with(seal))?; - } - } - - Ok(self) - } - - fn add_fungible_state( - self, name: impl Into, - seal: impl Into>, - value: impl Into, + value: &impl StrictSerialize, ) -> Result { - debug_assert!( - !self.deterministic, - "for adding state to deterministic contracts you have to use add_*_det methods" - ); - - let name = name.into(); - - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - let tag = self.asset_tag_raw(type_id)?; - - let state = RevealedValue::new_random_blinding(value.into(), tag); - self.add_fungible_state_raw(type_id, seal, state) - } + let type_id = self.global_type(name)?; + let serialized = value.to_strict_serialized::<{ u16::MAX as usize }>()?; + let sem_id = self.global_schema(type_id).sem_id; - fn add_fungible_state_det( - self, - name: impl Into, - seal: impl Into>, - state: RevealedValue, - ) -> Result { - debug_assert!( - self.deterministic, - "to add owned state in deterministic way the builder has to be created using \ - deterministic constructor" - ); + #[cfg(debug_assertions)] + self.types + .strict_deserialize_type(sem_id, &serialized) + .expect("failed deserialization"); - let name = name.into(); + self.global.add_state(type_id, serialized.into())?; - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - self.add_fungible_state_raw(type_id, seal, state) + Ok(self) } - fn add_fungible_state_raw( + fn add_owned_state_raw( mut self, type_id: AssignmentType, seal: impl Into>, - state: RevealedValue, + state: State, ) -> Result { - let state_schema = self.state_schema(type_id); - if *state_schema != OwnedStateSchema::Fungible(FungibleType::Unsigned64Bit) { - return Err(BuilderError::InvalidStateType(type_id)); - } + let assignment = seal.into().assignment(state); - let seal = seal.into(); - match self.fungible.get_mut(&type_id) { - Some(assignments) => { - assignments.insert(seal, state)?; + match self.assignments.entry(type_id)? { + Entry::Vacant(entry) => { + entry.insert(TypedAssigns::with(assignment)); } - None => { - self.fungible - .insert(type_id, Confined::with((seal, state)))?; + Entry::Occupied(mut entry) => { + entry.get_mut().push(assignment)?; } } - Ok(self) } - fn add_data( - self, - name: impl Into, - seal: impl Into>, - value: impl StrictSerialize, - ) -> Result { - debug_assert!( - !self.deterministic, - "for adding state to deterministic contracts you have to use add_*_det methods" - ); - - let name = name.into(); - let serialized = value.to_strict_serialized::()?; - let state = DataState::from(serialized); - - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - - self.add_data_raw(type_id, seal, RevealedData::new_random_salt(state)) - } - - fn add_data_det( + fn add_rights( self, name: impl Into, seal: impl Into>, - state: RevealedData, - ) -> Result { - debug_assert!( - self.deterministic, - "to add owned state in deterministic way the builder has to be created using \ - deterministic constructor" - ); - - let name = name.into(); - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - - self.add_data_raw(type_id, seal, state) - } - - fn add_data_raw( - mut self, - type_id: AssignmentType, - seal: impl Into>, - state: RevealedData, + attach: Option, ) -> Result { - let state_schema = self.state_schema(type_id); - if let OwnedStateSchema::Structured(_) = *state_schema { - let seal = seal.into(); - match self.data.get_mut(&type_id) { - Some(assignments) => { - assignments.insert(seal, state)?; - } - None => { - self.data.insert(type_id, Confined::with((seal, state)))?; - } - } - } else { - return Err(BuilderError::InvalidStateType(type_id)); - } - Ok(self) + let type_id = self.assignments_type(name)?; + let mut state = State::default(); + state.attach = attach; + self.add_owned_state_raw(type_id, seal, state) } - fn add_attachment( + fn add_owned_state( self, name: impl Into, seal: impl Into>, - state: AttachState, + value: StrictVal, + attach: Option, ) -> Result { - debug_assert!( - !self.deterministic, - "for adding state to deterministic contracts you have to use add_*_det methods" - ); + let type_id = self.assignments_type(name)?; - let name = name.into(); - - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; + let types = self.type_system(); + let sem_id = self + .schema + .owned_types + .get(&type_id) + .expect("schema-interface inconsistency") + .sem_id; + let value = types.typify(value, sem_id)?; + let data = types.strict_serialize_value::(&value)?; - self.add_attachment_raw( - type_id, - seal, - RevealedAttach::new_random_salt(state.id, state.media_type), - ) + let mut state = State::from(StateData::from(data)); + state.attach = attach; + self.add_owned_state_raw(type_id, seal, state) } - fn add_attachment_det( + fn serialize_owned_state( self, name: impl Into, seal: impl Into>, - state: RevealedAttach, + value: &impl StrictSerialize, + attach: Option, ) -> Result { - debug_assert!( - self.deterministic, - "to add owned state in deterministic way the builder has to be created using \ - deterministic constructor" - ); - - let name = name.into(); + let type_id = self.assignments_type(name)?; - let type_id = self - .assignments_type(&name) - .ok_or(BuilderError::AssignmentNotFound(name))?; - - self.add_attachment_raw(type_id, seal, state) - } - - fn add_attachment_raw( - mut self, - type_id: AssignmentType, - seal: impl Into>, - state: RevealedAttach, - ) -> Result { - let state_schema = self.state_schema(type_id); - if let OwnedStateSchema::Attachment(_) = *state_schema { - let seal = seal.into(); - match self.attachments.get_mut(&type_id) { - Some(assignments) => { - assignments.insert(seal, state)?; - } - None => { - self.attachments - .insert(type_id, Confined::with((seal, state)))?; - } - } - } else { - return Err(BuilderError::InvalidStateType(type_id)); - } - Ok(self) + let mut state = State::from_serialized(value)?; + state.attach = attach; + self.add_owned_state_raw(type_id, seal, state) } - fn complete( - self, - inputs: Option<&TinyOrdMap>, - ) -> (Schema, Iface, IfaceImpl, GlobalState, Assignments, TypeSystem, AssetTags) { - let owned_state = self.fungible.into_iter().map(|(id, vec)| { - let mut blindings = Vec::with_capacity(vec.len()); - let mut vec = vec - .into_iter() - .map(|(seal, value)| { - blindings.push(value.blinding); - match seal { - BuilderSeal::Revealed(seal) => Assign::Revealed { - seal, - state: value, - lock: none!(), - }, - BuilderSeal::Concealed(seal) => Assign::ConfidentialSeal { - seal, - state: value, - lock: none!(), - }, - } - }) - .collect::>(); - if let Some(assignment) = vec.last_mut() { - blindings.pop(); - let state = assignment - .as_revealed_state_mut() - .expect("builder always operates revealed state"); - let mut inputs = inputs - .map(|i| { - i.iter() - .filter(|(out, _)| out.prev_out.ty == id) - .map(|(_, ts)| match ts { - PersistedState::Amount(_, blinding, _) => *blinding, - _ => panic!("previous state has invalid type"), - }) - .collect::>() - }) - .unwrap_or_default(); - if inputs.is_empty() { - inputs = vec![BlindingFactor::EMPTY]; - } - state.blinding = BlindingFactor::zero_balanced(inputs, blindings).expect( - "malformed set of blinding factors; probably random generator is broken", - ); - } - let state = Confined::try_from_iter(vec).expect("at least one element"); - let state = TypedAssigns::Fungible(state); - (id, state) - }); - let owned_data = self.data.into_iter().map(|(id, vec)| { - let vec_data = vec.into_iter().map(|(seal, value)| match seal { - BuilderSeal::Revealed(seal) => Assign::Revealed { - seal, - state: value, - lock: none!(), - }, - BuilderSeal::Concealed(seal) => Assign::ConfidentialSeal { - seal, - state: value, - lock: none!(), - }, - }); - let state_data = Confined::try_from_iter(vec_data).expect("at least one element"); - let state_data = TypedAssigns::Structured(state_data); - (id, state_data) - }); - let owned_rights = self.rights.into_iter().map(|(id, vec)| { - let vec_data = vec.into_iter().map(|seal| match seal { - BuilderSeal::Revealed(seal) => Assign::Revealed { - seal, - state: none!(), - lock: none!(), - }, - BuilderSeal::Concealed(seal) => Assign::ConfidentialSeal { - seal, - state: none!(), - lock: none!(), - }, - }); - let state_data = Confined::try_from_iter(vec_data).expect("at least one element"); - let state_data = TypedAssigns::Declarative(state_data); - (id, state_data) - }); - let owned_attachments = self.attachments.into_iter().map(|(id, vec)| { - let vec_data = vec.into_iter().map(|(seal, value)| match seal { - BuilderSeal::Revealed(seal) => Assign::Revealed { - seal, - state: value, - lock: none!(), - }, - BuilderSeal::Concealed(seal) => Assign::ConfidentialSeal { - seal, - state: value, - lock: none!(), - }, - }); - let state_data = Confined::try_from_iter(vec_data).expect("at least one element"); - let state_data = TypedAssigns::Attachment(state_data); - (id, state_data) - }); - - let owned_state = Confined::try_from_iter(owned_state).expect("same size"); - let owned_data = Confined::try_from_iter(owned_data).expect("same size"); - let owned_rights = Confined::try_from_iter(owned_rights).expect("same size"); - let owned_attachments = Confined::try_from_iter(owned_attachments).expect("same size"); - - let mut assignments = Assignments::from_inner(owned_state); - assignments - .extend(Assignments::from_inner(owned_data).into_inner()) - .expect("too many assignments"); - assignments - .extend(Assignments::from_inner(owned_rights).into_inner()) - .expect("too many assignments"); - assignments - .extend(Assignments::from_inner(owned_attachments).into_inner()) - .expect("too many assignments"); - - (self.schema, self.iface, self.iimpl, self.global, assignments, self.types, self.asset_tags) + fn complete(self) -> (Schema, Iface, IfaceImpl, GlobalState, Assignments, TypeSystem) { + (self.schema, self.iface, self.iimpl, self.global, self.assignments, self.types) } } diff --git a/src/interface/calc.rs b/src/interface/calc.rs new file mode 100644 index 00000000..077b2fd5 --- /dev/null +++ b/src/interface/calc.rs @@ -0,0 +1,194 @@ +// RGB standard library for working with smart contracts on Bitcoin & Lightning +// +// SPDX-License-Identifier: Apache-2.0 +// +// Written in 2019-2024 by +// Dr Maxim Orlovsky +// +// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use aluvm::data::ByteStr; +use aluvm::library::{LibId, LibSite}; +use aluvm::reg::{Reg16, Reg32, RegA, RegR}; +use amplify::num::{u256, u4}; +use amplify::{ByteArray, Wrapper}; +use rgb::validation::Scripts; +use rgb::{AssignmentType, AttachId, StateData}; + +use crate::LIB_NAME_RGB_STD; + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error)] +#[display(doc_comments)] +pub enum StateCalcError { + /// reserved byte value {0} is not 0x00 for assignment type {1}. + InvalidReserved(AssignmentType, u8), + /// error registering input state of type {0} - {1}. + InputReg(AssignmentType, String), + /// error registering output state of type {0} - {1}. + OutputReg(AssignmentType, String), + /// error computing output state of type {0} - {1}. + OutputCalc(AssignmentType, String), + /// error computing change state of type {0} - {1}. + ChangeCalc(AssignmentType, String), + /// failed script for calculating output state of type {0}; please update interface + /// implementation for the schema + InsufficientState(AssignmentType), +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] +#[strict_type(lib = LIB_NAME_RGB_STD)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate", rename_all = "camelCase") +)] +pub struct StateAbi { + pub reg_input: LibSite, + pub reg_output: LibSite, + pub calc_output: LibSite, + pub calc_change: LibSite, +} + +impl StateAbi { + pub fn lib_ids(&self) -> impl Iterator { + [self.reg_input, self.reg_output, self.calc_output, self.calc_change] + .into_iter() + .map(|site| site.lib) + } +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub struct AllocatedState { + pub sufficient: rgb::State, + pub insufficient: Option, +} + +#[derive(Clone, Debug)] +pub struct StateCalc { + vm: aluvm::Vm, + abi: StateAbi, + scripts: Scripts, +} + +impl StateCalc { + pub fn new(scripts: Scripts, abi: StateAbi) -> Self { + let vm = aluvm::Vm::new(); + Self { vm, abi, scripts } + } + + fn run(&mut self, site: LibSite) -> Result<(), String> { + if !self.vm.exec(site, |id| self.scripts.get(&id), &()) { + if let Some(err) = self.vm.registers.s16(15).cloned() { + return Err(err.to_string()); + } + } + Ok(()) + } + + fn put_state(&mut self, ty: AssignmentType, state: &rgb::State) { + self.vm + .registers + .set_n(RegA::A16, Reg32::Reg0, Some(ty.to_inner())); + assert_eq!(state.reserved, none!()); + self.vm.registers.set_n(RegA::A8, Reg32::Reg0, Some(0u8)); + self.vm.registers.set_s16(0, ByteStr::with(&state.data)); + self.vm.registers.set_n( + RegR::R256, + Reg32::Reg0, + state.attach.map(|a| u256::from_le_bytes(a.to_byte_array())), + ); + } + + fn fetch_state( + &self, + ty: AssignmentType, + idx: Reg16, + ) -> Result, StateCalcError> { + let Some(data) = self.vm.registers.s16(u4::from(idx)) else { + return Ok(None); + }; + let reserved = self + .vm + .registers + .get_n(RegA::A8, idx) + .map(|n| u8::from(n)) + .unwrap_or_default(); + let attach = self + .vm + .registers + .get_n(RegR::R256, idx) + .map(|n| AttachId::from_byte_array(u256::from(n).to_le_bytes())); + if reserved != 0x00 { + return Err(StateCalcError::InvalidReserved(ty, reserved)); + } + Ok(Some(rgb::State { + reserved: none!(), + data: StateData::from_checked(data.to_vec()), + attach, + })) + } + + pub fn reg_input( + &mut self, + ty: AssignmentType, + state: &rgb::State, + ) -> Result<(), StateCalcError> { + self.put_state(ty, state); + self.run(self.abi.reg_input) + .map_err(|err| StateCalcError::InputReg(ty, err)) + } + + pub fn reg_output( + &mut self, + ty: AssignmentType, + state: &rgb::State, + ) -> Result<(), StateCalcError> { + self.put_state(ty, state); + self.run(self.abi.reg_output) + .map_err(|err| StateCalcError::OutputReg(ty, err)) + } + + pub fn calc_output( + &mut self, + ty: AssignmentType, + state: &rgb::State, + ) -> Result { + self.put_state(ty, state); + self.run(self.abi.calc_output) + .map_err(|err| StateCalcError::OutputCalc(ty, err))?; + let Some(sufficient) = self.fetch_state(ty, Reg16::Reg0)? else { + return Err(StateCalcError::InsufficientState(ty)); + }; + let insufficient = self.fetch_state(ty, Reg16::Reg1)?; + Ok(AllocatedState { + sufficient, + insufficient, + }) + } + + pub fn calc_change( + &mut self, + ty: AssignmentType, + ) -> Result, StateCalcError> { + self.run(self.abi.calc_change) + .map_err(|err| StateCalcError::ChangeCalc(ty, err))?; + self.fetch_state(ty, Reg16::Reg0) + } + + pub fn is_sufficient_for(&self, ty: AssignmentType, state: &rgb::State) -> bool { + self.clone().calc_output(ty, state).is_ok() + } +} diff --git a/src/interface/contract.rs b/src/interface/contract.rs index 2709a054..e027b43c 100644 --- a/src/interface/contract.rs +++ b/src/interface/contract.rs @@ -22,79 +22,65 @@ use std::borrow::Borrow; use std::collections::{BTreeSet, HashMap, HashSet}; -use invoice::{Allocation, Amount}; +use amplify::confinement::SmallBlob; +use amplify::Wrapper; +use rgb::validation::Scripts; use rgb::{ - AssignmentType, AttachState, ContractId, DataState, OpId, RevealedAttach, RevealedData, - RevealedValue, Schema, VoidState, XOutpoint, XOutputSeal, XWitnessId, + AssignmentType, AttachId, ContractId, OpId, Opout, Schema, State, StateData, XOutputSeal, + XWitnessId, STATE_DATA_MAX_LEN, }; -use strict_encoding::{FieldName, StrictDecode, StrictDumb, StrictEncode}; -use strict_types::{StrictVal, TypeSystem}; +use strict_encoding::{FieldName, SerializeError, StrictDeserialize}; +use strict_types::{typify, SemId, StrictVal, TypeSystem}; -use crate::contract::{KnownState, OutputAssignment, WitnessInfo}; +use crate::contract::{Allocation, WitnessInfo}; use crate::info::ContractInfo; -use crate::interface::{AssignmentsFilter, IfaceImpl}; +use crate::interface::{AssignmentsFilter, IfaceImpl, StateCalc}; use crate::persistence::ContractStateRead; -use crate::LIB_NAME_RGB_STD; #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] #[display(doc_comments)] pub enum ContractError { /// field name {0} is unknown to the contract interface FieldNameUnknown(FieldName), + + /// the provided state object is invalid; {0} + #[from] + Typify(typify::Error), + + /// the provided state exceeds maximum allowed length when serialized. + #[from] + Strict(SerializeError), } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, From)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_STD, tags = custom)] -#[display(inner)] +/// Allocation is an owned state assignment, equipped with information about the operation defining +/// the assignment and the witness id, containing the commitment to the operation. +#[derive(Clone, PartialEq, Eq, Debug)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate", rename_all = "camelCase") )] -pub enum AllocatedState { - #[from(())] - #[from(VoidState)] - #[display("~")] - #[strict_type(tag = 0, dumb)] - Void, - - #[from] - #[from(RevealedValue)] - #[strict_type(tag = 1)] - Amount(Amount), - - #[from] - #[from(RevealedData)] - #[from(Allocation)] - #[strict_type(tag = 2)] - Data(DataState), - - #[from] - #[from(RevealedAttach)] - #[strict_type(tag = 3)] - Attachment(AttachState), -} - -impl KnownState for AllocatedState { - const IS_FUNGIBLE: bool = false; +pub struct Output { + pub opout: Opout, + pub seal: XOutputSeal, + pub state: T, + pub attach_id: Option, + pub witness: Option, } -impl AllocatedState { - fn unwrap_fungible(&self) -> Amount { - match self { - AllocatedState::Amount(amount) => *amount, - _ => panic!("unwrapping non-fungible state"), +impl From for Output { + fn from(a: Allocation) -> Self { + Output { + opout: a.opout, + seal: a.seal, + state: T::from_strict_serialized(a.state.data.to_inner()) + .expect("data in stash are not valid"), + attach_id: a.state.attach, + witness: a.witness, } } } -pub type OwnedAllocation = OutputAssignment; -pub type RightsAllocation = OutputAssignment; -pub type FungibleAllocation = OutputAssignment; -pub type DataAllocation = OutputAssignment; -pub type AttachAllocation = OutputAssignment; - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)] #[cfg_attr( feature = "serde", @@ -108,123 +94,50 @@ pub enum OpDirection { Sent, } -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Debug)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase", tag = "type") + serde(crate = "serde_crate", rename_all = "camelCase") )] pub struct ContractOp { pub direction: OpDirection, pub ty: AssignmentType, pub opids: BTreeSet, - pub state: AllocatedState, + pub state: StrictVal, + pub attach_id: Option, pub to: BTreeSet, pub witness: Option, } -fn reduce_to_ty(allocations: impl IntoIterator) -> AssignmentType { - allocations - .into_iter() - .map(|a| a.opout.ty) - .reduce(|ty1, ty2| { - assert_eq!(ty1, ty2); - ty1 - }) - .expect("empty list of allocations") -} - impl ContractOp { - fn non_fungible_genesis( - our_allocations: HashSet, - ) -> impl ExactSizeIterator { - our_allocations.into_iter().map(|a| Self { - direction: OpDirection::Issued, - ty: a.opout.ty, - opids: bset![a.opout.op], - state: a.state, - to: bset![a.seal], - witness: None, - }) - } - - fn non_fungible_sent( - witness: WitnessInfo, - ext_allocations: HashSet, - ) -> impl ExactSizeIterator { - ext_allocations.into_iter().map(move |a| Self { - direction: OpDirection::Sent, - ty: a.opout.ty, - opids: bset![a.opout.op], - state: a.state, - to: bset![a.seal], - witness: Some(witness), - }) - } - - fn non_fungible_received( - witness: WitnessInfo, - our_allocations: HashSet, - ) -> impl ExactSizeIterator { - our_allocations.into_iter().map(move |a| Self { - direction: OpDirection::Received, - ty: a.opout.ty, - opids: bset![a.opout.op], - state: a.state, - to: bset![a.seal], - witness: Some(witness), - }) - } - - fn fungible_genesis(our_allocations: HashSet) -> Self { - let to = our_allocations.iter().map(|a| a.seal).collect(); - let opids = our_allocations.iter().map(|a| a.opout.op).collect(); - let issued = our_allocations - .iter() - .map(|a| a.state.unwrap_fungible()) - .sum(); + fn new( + direction: OpDirection, + assignment: Allocation, + value: StrictVal, + witness: Option, + ) -> Self { Self { - direction: OpDirection::Issued, - ty: reduce_to_ty(our_allocations), - opids, - state: AllocatedState::Amount(issued), - to, - witness: None, + direction, + ty: assignment.opout.ty, + opids: bset![assignment.opout.op], + state: value, + attach_id: assignment.state.attach, + to: bset![assignment.seal], + witness, } } - fn fungible_sent(witness: WitnessInfo, ext_allocations: HashSet) -> Self { - let opids = ext_allocations.iter().map(|a| a.opout.op).collect(); - let to = ext_allocations.iter().map(|a| a.seal).collect(); - let amount = ext_allocations - .iter() - .map(|a| a.state.unwrap_fungible()) - .sum(); - Self { - direction: OpDirection::Sent, - ty: reduce_to_ty(ext_allocations), - opids, - state: AllocatedState::Amount(amount), - to, - witness: Some(witness), - } + fn issued(assignment: Allocation, value: StrictVal) -> Self { + Self::new(OpDirection::Issued, assignment, value, None) } - fn fungible_received(witness: WitnessInfo, our_allocations: HashSet) -> Self { - let opids = our_allocations.iter().map(|a| a.opout.op).collect(); - let to = our_allocations.iter().map(|a| a.seal).collect(); - let amount = our_allocations - .iter() - .map(|a| a.state.unwrap_fungible()) - .sum(); - Self { - direction: OpDirection::Received, - ty: reduce_to_ty(our_allocations), - opids, - state: AllocatedState::Amount(amount), - to, - witness: Some(witness), - } + fn received(assignment: Allocation, value: StrictVal, witness: WitnessInfo) -> Self { + Self::new(OpDirection::Received, assignment, value, Some(witness)) + } + + fn sent(assignment: Allocation, value: StrictVal, witness: WitnessInfo) -> Self { + Self::new(OpDirection::Sent, assignment, value, Some(witness)) } } @@ -236,16 +149,78 @@ pub struct ContractIface { pub schema: Schema, pub iface: IfaceImpl, pub types: TypeSystem, + pub scripts: Scripts, pub info: ContractInfo, } impl ContractIface { + fn assignment_type(&self, name: impl Into) -> Result { + let name = name.into(); + self.iface + .assignment_type(&name) + .ok_or(ContractError::FieldNameUnknown(name)) + } + + fn assignment_sem_id(&self, ty: AssignmentType) -> SemId { + self.schema + .owned_types + .get(&ty) + .expect("invalid contract state") + .sem_id + } + + fn allocation_to_output(&self, a: &Allocation) -> Output { + Output { + opout: a.opout, + seal: a.seal, + state: self.value_from_state_raw(a.opout.ty, &a.state), + attach_id: a.state.attach, + witness: a.witness, + } + } + + pub fn value_from_state_raw(&self, ty: AssignmentType, state: &State) -> StrictVal { + self.types + .strict_deserialize_type(self.assignment_sem_id(ty), state.data.as_slice()) + .expect("invalid contract state") + .unbox() + } + + pub fn value_from_state( + &self, + name: impl Into, + state: &State, + ) -> Result { + let type_id = self.assignment_type(name)?; + Ok(self.value_from_state_raw(type_id, state)) + } + + pub fn value_to_state_raw( + &self, + ty: AssignmentType, + value: StrictVal, + ) -> Result { + let t = self.types.typify(value, self.assignment_sem_id(ty))?; + let value = self + .types + .strict_serialize_value::(&t)?; + Ok(value.into()) + } + + pub fn value_to_state( + &self, + name: impl Into, + value: StrictVal, + ) -> Result { + let type_id = self.assignment_type(name)?; + self.value_to_state_raw(type_id, value) + } + pub fn contract_id(&self) -> ContractId { self.state.contract_id() } /// # Panics /// - /// If data are corrupted and contract schema doesn't match interface - /// implementations. + /// If data are corrupted and contract schema doesn't match interface implementations. pub fn global( &self, name: impl Into, @@ -266,154 +241,124 @@ impl ContractIface { .expect("schema doesn't match interface") .map(|data| { self.types - .strict_deserialize_type(global_schema.sem_id, data.borrow().as_slice()) + .strict_deserialize_type(global_schema.sem_id, data.borrow()) .expect("unvalidated contract data in stash") .unbox() })) } - fn extract_state<'c, A, U>( - &'c self, - state: impl IntoIterator> + 'c, - name: impl Into, - filter: impl AssignmentsFilter + 'c, - ) -> Result> + 'c, ContractError> - where - A: Clone + KnownState + 'c, - U: From + KnownState + 'c, - { - Ok(self - .extract_state_unfiltered(state, name)? - .filter(move |outp| filter.should_include(outp.seal, outp.witness))) - } - - fn extract_state_unfiltered<'c, A, U>( - &'c self, - state: impl IntoIterator> + 'c, + /// # Panics + /// + /// If data are corrupted and contract schema doesn't match interface implementations. + pub fn global_typed( + &self, name: impl Into, - ) -> Result> + 'c, ContractError> - where - A: Clone + KnownState + 'c, - U: From + KnownState + 'c, - { + ) -> Result + '_, ContractError> { let name = name.into(); let type_id = self .iface - .assignments_type(&name) + .global_type(&name) .ok_or(ContractError::FieldNameUnknown(name))?; - Ok(state - .into_iter() - .filter(move |outp| outp.opout.ty == type_id) - .cloned() - .map(OutputAssignment::::transmute)) + Ok(self + .state + .global(type_id) + .expect("schema doesn't match interface") + .map(|data| { + let data = SmallBlob::from_slice_checked(data.borrow()); + T::from_strict_serialized(data).expect("unvalidated contract data in stash") + })) } - pub fn rights<'c>( + pub fn allocations<'c>( &'c self, - name: impl Into, filter: impl AssignmentsFilter + 'c, - ) -> Result + 'c, ContractError> { - self.extract_state(self.state.rights_all(), name, filter) + ) -> impl Iterator + 'c { + self.state + .assignments() + .filter(move |a| filter.should_include(a.seal, a.witness)) } - pub fn fungible<'c>( + pub fn outputs<'c>( &'c self, - name: impl Into, filter: impl AssignmentsFilter + 'c, - ) -> Result + 'c, ContractError> { - self.extract_state(self.state.fungible_all(), name, filter) + ) -> impl Iterator + 'c { + self.allocations(filter) + .map(|a| self.allocation_to_output(a)) } - pub fn data<'c>( + pub fn outputs_by_type<'c>( &'c self, name: impl Into, filter: impl AssignmentsFilter + 'c, - ) -> Result + 'c, ContractError> { - self.extract_state(self.state.data_all(), name, filter) + ) -> Result + 'c, ContractError> { + let type_id = self.assignment_type(name)?; + Ok(self + .outputs(filter) + .filter(move |outp| outp.opout.ty == type_id)) } - pub fn attachments<'c>( + pub fn output_selection<'c, K: Ord + 'c>( &'c self, name: impl Into, filter: impl AssignmentsFilter + 'c, - ) -> Result + 'c, ContractError> { - self.extract_state(self.state.attach_all(), name, filter) + sorting: impl FnMut(&&Allocation) -> K, + state: &'c State, + ) -> Result + 'c, ContractError> { + let type_id = self.assignment_type(name)?; + let mut selected = self + .allocations(filter) + .filter(move |a| a.opout.ty == type_id) + .collect::>(); + selected.sort_by_key(sorting); + let mut calc = StateCalc::new(self.scripts.clone(), self.iface.state_abi); + Ok(selected + .into_iter() + .take_while(move |a| { + if calc.reg_input(a.opout.ty, &a.state).is_err() { + return false; + } + calc.is_sufficient_for(a.opout.ty, state) + }) + .map(|a| self.allocation_to_output(a))) } - pub fn allocations<'c>( + pub fn outputs_typed<'c, T: StrictDeserialize + 'c>( &'c self, - filter: impl AssignmentsFilter + Copy + 'c, - ) -> impl Iterator + 'c { - fn f<'a, S, U>( - filter: impl AssignmentsFilter + 'a, - state: impl IntoIterator> + 'a, - ) -> impl Iterator> + 'a - where - S: Clone + KnownState + 'a, - U: From + KnownState + 'a, - { - state - .into_iter() - .filter(move |outp| filter.should_include(outp.seal, outp.witness)) - .cloned() - .map(OutputAssignment::::transmute) - } - - f(filter, self.state.rights_all()) - .map(OwnedAllocation::from) - .chain(f(filter, self.state.fungible_all()).map(OwnedAllocation::from)) - .chain(f(filter, self.state.data_all()).map(OwnedAllocation::from)) - .chain(f(filter, self.state.attach_all()).map(OwnedAllocation::from)) - } - - pub fn outpoint_allocations( - &self, - outpoint: XOutpoint, - ) -> impl Iterator + '_ { - self.allocations(outpoint) + name: impl Into, + filter: impl AssignmentsFilter + 'c, + ) -> Result> + 'c, ContractError> { + let type_id = self.assignment_type(name)?; + Ok(self + .allocations(filter) + .filter(move |a| a.opout.ty == type_id) + .cloned() + .map(Output::from)) } pub fn history( &self, - filter_outpoints: impl AssignmentsFilter + Clone, - filter_witnesses: impl AssignmentsFilter + Clone, - ) -> Vec { - self.history_fungible(filter_outpoints.clone(), filter_witnesses.clone()) - .into_iter() - .chain(self.history_rights(filter_outpoints.clone(), filter_witnesses.clone())) - .chain(self.history_data(filter_outpoints.clone(), filter_witnesses.clone())) - .chain(self.history_attach(filter_outpoints, filter_witnesses)) - .collect() - } - - fn operations<'c, T: KnownState + 'c, I: Iterator>>( - &'c self, - state: impl Fn(&'c S) -> I, filter_outpoints: impl AssignmentsFilter, filter_witnesses: impl AssignmentsFilter, - ) -> Vec - where - AllocatedState: From, - { + ) -> Vec { // get all allocations which ever belonged to this wallet and store them by witness id - let mut allocations_our_outpoint = state(&self.state) + let mut allocations_our_outpoint = self + .state + .assignments() .filter(move |outp| filter_outpoints.should_include(outp.seal, outp.witness)) .fold(HashMap::<_, HashSet<_>>::new(), |mut map, a| { - map.entry(a.witness) - .or_default() - .insert(a.clone().transmute::()); + map.entry(a.witness).or_default().insert(a.clone()); map }); // get all allocations which has a witness transaction belonging to this wallet - let mut allocations_our_witness = state(&self.state) + let mut allocations_our_witness = self + .state + .assignments() .filter(move |outp| filter_witnesses.should_include(outp.seal, outp.witness)) .fold(HashMap::<_, HashSet<_>>::new(), |mut map, a| { let witness = a.witness.expect( "all empty witnesses must be already filtered out by wallet.filter_witness()", ); - map.entry(witness) - .or_default() - .insert(a.clone().transmute::()); + map.entry(witness).or_default().insert(a.clone()); map }); @@ -427,11 +372,10 @@ impl ContractIface { // reconstruct contract history from the wallet perspective let mut ops = Vec::with_capacity(witness_ids.len() + 1); // add allocations with no witness to the beginning of the history - if let Some(genesis_allocations) = allocations_our_outpoint.remove(&None) { - if T::IS_FUNGIBLE { - ops.push(ContractOp::fungible_genesis(genesis_allocations)); - } else { - ops.extend(ContractOp::non_fungible_genesis(genesis_allocations)); + if let Some(genesis_state) = allocations_our_outpoint.remove(&None) { + for assignment in genesis_state { + let value = self.value_from_state_raw(assignment.opout.ty, &assignment.state); + ops.push(ContractOp::issued(assignment, value)) } } for witness_id in witness_ids { @@ -444,37 +388,37 @@ impl ContractIface { // we own both allocation and witness transaction: these allocations are changes and // outgoing payments. The difference between the change and the payments are whether // a specific allocation is listed in the first tuple pattern field. - (Some(our_allocations), Some(all_allocations)) => { + (Some(our_assignments), Some(all_assignments)) => { // all_allocations - our_allocations = external payments - let ext_allocations = all_allocations - .difference(&our_allocations) + let ext_assignments = all_assignments + .difference(&our_assignments) .cloned() .collect::>(); // This was a blank state transition with no external payment - if ext_allocations.is_empty() { + if ext_assignments.is_empty() { continue; } - if T::IS_FUNGIBLE { - ops.push(ContractOp::fungible_sent(witness_info, ext_allocations)) - } else { - ops.extend(ContractOp::non_fungible_sent(witness_info, ext_allocations)) + for assignment in ext_assignments { + let value = + self.value_from_state_raw(assignment.opout.ty, &assignment.state); + ops.push(ContractOp::sent(assignment, value, witness_info)) } } // the same as above, but the payment has no change - (None, Some(ext_allocations)) => { - if T::IS_FUNGIBLE { - ops.push(ContractOp::fungible_sent(witness_info, ext_allocations)) - } else { - ops.extend(ContractOp::non_fungible_sent(witness_info, ext_allocations)) + (None, Some(ext_assignments)) => { + for assignment in ext_assignments { + let value = + self.value_from_state_raw(assignment.opout.ty, &assignment.state); + ops.push(ContractOp::sent(assignment, value, witness_info)) } } // we own allocation but the witness transaction was made by other wallet: // this is an incoming payment to us. - (Some(our_allocations), None) => { - if T::IS_FUNGIBLE { - ops.push(ContractOp::fungible_received(witness_info, our_allocations)) - } else { - ops.extend(ContractOp::non_fungible_received(witness_info, our_allocations)) + (Some(our_assignments), None) => { + for assignment in our_assignments { + let value = + self.value_from_state_raw(assignment.opout.ty, &assignment.state); + ops.push(ContractOp::received(assignment, value, witness_info)) } } // these can't get into the `witness_ids` due to the used filters @@ -485,38 +429,6 @@ impl ContractIface { ops } - pub fn history_fungible( - &self, - filter_outpoints: impl AssignmentsFilter, - filter_witnesses: impl AssignmentsFilter, - ) -> Vec { - self.operations(|state| state.fungible_all(), filter_outpoints, filter_witnesses) - } - - pub fn history_rights( - &self, - filter_outpoints: impl AssignmentsFilter, - filter_witnesses: impl AssignmentsFilter, - ) -> Vec { - self.operations(|state| state.rights_all(), filter_outpoints, filter_witnesses) - } - - pub fn history_data( - &self, - filter_outpoints: impl AssignmentsFilter, - filter_witnesses: impl AssignmentsFilter, - ) -> Vec { - self.operations(|state| state.data_all(), filter_outpoints, filter_witnesses) - } - - pub fn history_attach( - &self, - filter_outpoints: impl AssignmentsFilter, - filter_witnesses: impl AssignmentsFilter, - ) -> Vec { - self.operations(|state| state.attach_all(), filter_outpoints, filter_witnesses) - } - pub fn witness_info(&self, witness_id: XWitnessId) -> Option { let ord = self.state.witness_ord(witness_id)?; Some(WitnessInfo { diff --git a/src/interface/contractum.rs b/src/interface/contractum.rs index 01cbdbe6..0fa8b927 100644 --- a/src/interface/contractum.rs +++ b/src/interface/contractum.rs @@ -28,9 +28,7 @@ use rgb::Occurrences; use strict_encoding::{FieldName, TypeName, VariantName}; use strict_types::{SemId, SymbolicSys}; -use super::{ - ArgMap, ExtensionIface, GenesisIface, Iface, IfaceId, Modifier, OwnedIface, TransitionIface, -}; +use super::{ArgMap, ExtensionIface, GenesisIface, Iface, IfaceId, Modifier, TransitionIface}; struct ArgMapDisplay<'a>(&'a ArgMap); @@ -266,13 +264,9 @@ impl<'a> Display for IfaceDisplay<'a> { write!(f, "{fname}")?; sugar(f, a.required, a.multiple)?; f.write_str(": ")?; - match a.owned_state { - OwnedIface::Any => write!(f, "AnyType")?, - OwnedIface::Amount => write!(f, "Zk64")?, - OwnedIface::AnyData => write!(f, "Any")?, - OwnedIface::AnyAttach => write!(f, "AnyAttachment")?, - OwnedIface::Rights => write!(f, "Rights")?, - OwnedIface::Data(id) => resolve(f, self.types, id)?, + match a.state_ty { + None => write!(f, "T any => T")?, + Some(id) => resolve(f, self.types, id)?, } writeln!(f)?; } diff --git a/src/interface/iface.rs b/src/interface/iface.rs index d4a904fc..84dfec26 100644 --- a/src/interface/iface.rs +++ b/src/interface/iface.rs @@ -200,58 +200,66 @@ impl GlobalIface { serde(crate = "serde_crate", rename_all = "camelCase") )] pub struct AssignIface { - pub owned_state: OwnedIface, + pub state_ty: Option, + pub attach: Option, pub public: bool, pub required: bool, pub multiple: bool, } impl AssignIface { - pub fn public(owned_state: OwnedIface, req: Req) -> Self { + pub fn optional() -> Self { AssignIface { - owned_state, - public: true, - required: req.is_required(), - multiple: req.is_multiple(), + state_ty: None, + attach: None, + public: false, + required: false, + multiple: false, } } - - pub fn private(owned_state: OwnedIface, req: Req) -> Self { + pub fn required() -> Self { AssignIface { - owned_state, + state_ty: None, + attach: None, public: false, - required: req.is_required(), - multiple: req.is_multiple(), + required: true, + multiple: false, } } -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_STD, tags = order)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub enum OwnedIface { - #[strict_type(dumb)] - Any, - Rights, - Amount, - AnyData, - AnyAttach, - Data(SemId), -} - -impl OwnedIface { - pub fn sem_id(&self) -> Option { - if let Self::Data(id) = self { - Some(*id) - } else { - None + pub fn none_or_many() -> Self { + AssignIface { + state_ty: None, + attach: None, + public: false, + required: false, + multiple: true, + } + } + pub fn one_or_many() -> Self { + AssignIface { + state_ty: None, + attach: None, + public: false, + required: true, + multiple: true, } } + pub fn public(mut self) -> Self { + self.public = true; + self + } + pub fn rights(mut self) -> Self { + self.state_ty = Some(SemId::default()); + self + } + pub fn typed(mut self, sem_id: SemId) -> Self { + self.state_ty = Some(sem_id); + self + } + pub fn attachments(mut self, require: bool) -> Self { + self.attach = Some(require); + self + } } pub type ArgMap = TinyOrdMap; @@ -434,11 +442,7 @@ impl Iface { .values() .copied() .chain(self.global_state.values().filter_map(|i| i.sem_id)) - .chain( - self.assignments - .values() - .filter_map(|i| i.owned_state.sem_id()), - ) + .chain(self.assignments.values().filter_map(|i| i.state_ty)) } pub fn find_abstractable_impl<'a>( diff --git a/src/interface/iimpl.rs b/src/interface/iimpl.rs index 1e528ed1..5644aa36 100644 --- a/src/interface/iimpl.rs +++ b/src/interface/iimpl.rs @@ -36,7 +36,7 @@ use strict_encoding::{FieldName, StrictDumb, VariantName}; use strict_types::encoding::{StrictDecode, StrictEncode, StrictType}; use crate::interface::iface::IfaceId; -use crate::interface::{Iface, VerNo}; +use crate::interface::{Iface, StateAbi, VerNo}; use crate::{ReservedBytes, LIB_NAME_RGB_STD}; pub trait SchemaTypeIndex: @@ -228,6 +228,7 @@ pub struct IfaceImpl { pub extensions: TinyOrdSet>, pub errors: TinyOrdSet>, pub developer: Identity, + pub state_abi: StateAbi, } impl IfaceImpl { @@ -255,7 +256,7 @@ impl IfaceImpl { .map(|nt| nt.id) } - pub fn assignments_type(&self, name: &FieldName) -> Option { + pub fn assignment_type(&self, name: &FieldName) -> Option { self.assignments .iter() .find(|nt| &nt.name == name) diff --git a/src/interface/inheritance.rs b/src/interface/inheritance.rs index 518c0595..2c746494 100644 --- a/src/interface/inheritance.rs +++ b/src/interface/inheritance.rs @@ -27,7 +27,7 @@ use rgb::{ use strict_encoding::{FieldName, TypeName}; use crate::interface::{ - ExtensionIface, GenesisIface, Iface, IfaceImpl, Modifier, OpName, OwnedIface, TransitionIface, + ExtensionIface, GenesisIface, Iface, IfaceImpl, Modifier, OpName, TransitionIface, }; #[derive(Clone, PartialEq, Eq, Debug, Display, From)] @@ -273,18 +273,6 @@ pub enum ExtensionError { InheritanceOverflow, } -impl OwnedIface { - pub fn is_superset(self, other: OwnedIface) -> bool { - if self == Self::Any { - return true; - } - if self == Self::AnyData && matches!(other, Self::Data(_)) { - return true; - } - self == other - } -} - impl Modifier { pub fn is_final(self) -> bool { self == Self::Final } pub fn can_be_overridden_by(self, other: Modifier) -> bool { @@ -401,7 +389,7 @@ impl Iface { } } Some(orig) => { - if !orig.owned_state.is_superset(e.owned_state) { + if orig.state_ty.is_some() && orig.state_ty != e.state_ty { errors.push(ExtensionError::AssignmentType(name)); } else if orig.required & !e.required { errors.push(ExtensionError::AssignmentOcc(name)); diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 496ce87e..7b70ae47 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -31,17 +31,16 @@ mod filter; pub(crate) mod resolver; mod contractum; mod inheritance; +mod calc; pub use builder::{BuilderError, ContractBuilder, TransitionBuilder, TxOutpoint}; -pub use contract::{ - AllocatedState, AttachAllocation, ContractError, ContractIface, ContractOp, DataAllocation, - FungibleAllocation, OpDirection, OwnedAllocation, RightsAllocation, -}; +pub use calc::{AllocatedState, StateAbi, StateCalc, StateCalcError}; +pub use contract::{ContractError, ContractIface, ContractOp, OpDirection, Output}; pub use contractum::IfaceDisplay; pub use filter::{AssignmentsFilter, FilterExclude, FilterIncludeAll}; pub use iface::{ ArgMap, AssignIface, ExtensionIface, GenesisIface, GlobalIface, Iface, IfaceClass, IfaceId, - IfaceInconsistency, IfaceRef, IfaceWrapper, Modifier, OpName, OwnedIface, Req, TransitionIface, + IfaceInconsistency, IfaceRef, IfaceWrapper, Modifier, OpName, Req, TransitionIface, ValencyIface, }; pub use iimpl::{IfaceImpl, ImplId, NamedField, NamedType, NamedVariant, SchemaTypeIndex}; diff --git a/src/lib.rs b/src/lib.rs index d428aa06..58f9e507 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,13 +46,10 @@ mod contract; pub mod info; pub use bp::{Outpoint, Txid}; -pub use contract::{ - KnownState, MergeReveal, MergeRevealError, OutputAssignment, TypedAssignsExt, WitnessInfo, -}; -pub use invoice::{Allocation, Amount, CoinAmount, OwnedFraction, Precision, TokenIndex}; +pub use contract::{Allocation, MergeReveal, MergeRevealError, WitnessInfo}; pub use rgb::prelude::*; pub use rgb::rgbasm; -pub use stl::{LIB_NAME_RGB_CONTRACT, LIB_NAME_RGB_STD, LIB_NAME_RGB_STORAGE}; +pub use stl::{LIB_NAME_RGB_STD, LIB_NAME_RGB_STORAGE}; /// BIP32 derivation index for outputs which may contain assigned RGB state. pub const RGB_NATIVE_DERIVATION_INDEX: u32 = 9; diff --git a/src/persistence/index.rs b/src/persistence/index.rs index b07b831c..2f0ac19e 100644 --- a/src/persistence/index.rs +++ b/src/persistence/index.rs @@ -26,9 +26,8 @@ use std::fmt::Debug; use amplify::confinement; use nonasync::persistence::{CloneNoPersistence, Persisting}; use rgb::{ - Assign, AssignmentType, BundleId, ContractId, ExposedState, Extension, Genesis, GenesisSeal, - GraphSeal, OpId, Operation, Opout, TransitionBundle, TypedAssigns, XChain, XOutputSeal, - XWitnessId, + Assign, AssignmentType, BundleId, ContractId, Extension, Genesis, GenesisSeal, GraphSeal, OpId, + Operation, Opout, TransitionBundle, XChain, XOutputSeal, XWitnessId, }; use crate::containers::{ConsignmentExt, ToWitnessId, WitnessBundle}; @@ -185,25 +184,9 @@ impl Index

{ fn index_genesis(&mut self, id: ContractId, genesis: &Genesis) -> Result<(), IndexError

> { let opid = genesis.id(); - for (type_id, assign) in genesis.assignments.iter() { - match assign { - TypedAssigns::Declarative(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - TypedAssigns::Fungible(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - TypedAssigns::Structured(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - TypedAssigns::Attachment(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - } + for (type_id, assigns) in genesis.assignments.iter() { + self.provider + .index_genesis_assignments(id, assigns, opid, *type_id)?; } Ok(()) } @@ -214,25 +197,9 @@ impl Index

{ extension: &Extension, ) -> Result<(), IndexError

> { let opid = extension.id(); - for (type_id, assign) in extension.assignments.iter() { - match assign { - TypedAssigns::Declarative(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - TypedAssigns::Fungible(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - TypedAssigns::Structured(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - TypedAssigns::Attachment(vec) => { - self.provider - .index_genesis_assignments(id, vec, opid, *type_id)?; - } - } + for (type_id, assigns) in extension.assignments.iter() { + self.provider + .index_genesis_assignments(id, assigns, opid, *type_id)?; } Ok(()) } @@ -250,45 +217,14 @@ impl Index

{ for (opid, transition) in &bundle.known_transitions { self.provider.register_operation(*opid, bundle_id)?; - for (type_id, assign) in transition.assignments.iter() { - match assign { - TypedAssigns::Declarative(vec) => { - self.provider.index_transition_assignments( - contract_id, - vec, - *opid, - *type_id, - witness_id, - )?; - } - TypedAssigns::Fungible(vec) => { - self.provider.index_transition_assignments( - contract_id, - vec, - *opid, - *type_id, - witness_id, - )?; - } - TypedAssigns::Structured(vec) => { - self.provider.index_transition_assignments( - contract_id, - vec, - *opid, - *type_id, - witness_id, - )?; - } - TypedAssigns::Attachment(vec) => { - self.provider.index_transition_assignments( - contract_id, - vec, - *opid, - *type_id, - witness_id, - )?; - } - } + for (type_id, assigns) in transition.assignments.iter() { + self.provider.index_transition_assignments( + contract_id, + assigns, + *opid, + *type_id, + witness_id, + )?; } } @@ -413,18 +349,18 @@ pub trait IndexWriteProvider: StoreTransaction { bundle_id: BundleId, ) -> Result>; - fn index_genesis_assignments( + fn index_genesis_assignments( &mut self, contract_id: ContractId, - vec: &[Assign], + vec: &[Assign], opid: OpId, type_id: AssignmentType, ) -> Result<(), IndexWriteError>; - fn index_transition_assignments( + fn index_transition_assignments( &mut self, contract_id: ContractId, - vec: &[Assign], + vec: &[Assign], opid: OpId, type_id: AssignmentType, witness_id: XWitnessId, diff --git a/src/persistence/memory.rs b/src/persistence/memory.rs index 5b5d229e..81acbf70 100644 --- a/src/persistence/memory.rs +++ b/src/persistence/memory.rs @@ -42,11 +42,10 @@ use rgb::vm::{ OrdOpRef, UnknownGlobalStateType, WitnessOrd, }; use rgb::{ - Assign, AssignmentType, Assignments, AssignmentsRef, AttachId, AttachState, BundleId, - ContractId, DataState, ExposedSeal, ExposedState, Extension, FungibleState, Genesis, - GenesisSeal, GlobalStateType, GraphSeal, Identity, OpId, Operation, Opout, RevealedAttach, - RevealedData, RevealedValue, Schema, SchemaId, SecretSeal, Transition, TransitionBundle, - TypedAssigns, VoidState, XChain, XOutpoint, XOutputSeal, XWitnessId, + Assign, AssignmentType, Assignments, AssignmentsRef, AttachId, BundleId, ContractId, + ExposedSeal, Extension, Genesis, GenesisSeal, GlobalStateType, GraphSeal, Identity, OpId, + Operation, Opout, Schema, SchemaId, SecretSeal, StateData, Transition, TransitionBundle, + XChain, XOutpoint, XOutputSeal, XWitnessId, }; use strict_encoding::{StrictDeserialize, StrictSerialize}; use strict_types::TypeSystem; @@ -61,7 +60,7 @@ use super::{ use crate::containers::{ AnchorSet, ContentId, ContentRef, ContentSigs, SealWitness, SigBlob, Supplement, TrustLevel, }; -use crate::contract::{GlobalOut, KnownState, OpWitness, OutputAssignment}; +use crate::contract::{Allocation, GlobalOut, OpWitness}; use crate::interface::{Iface, IfaceClass, IfaceId, IfaceImpl, IfaceRef}; use crate::LIB_NAME_RGB_STORAGE; @@ -566,10 +565,7 @@ impl StateReadProvider for MemState { .values() .flat_map(|state| state.known.keys()) .any(|out| out.witness_id() == id) - || unfiltered.rights.iter().any(|a| a.witness == id) - || unfiltered.fungibles.iter().any(|a| a.witness == id) - || unfiltered.data.iter().any(|a| a.witness == id) - || unfiltered.attach.iter().any(|a| a.witness == id) + || unfiltered.owned.iter().any(|a| a.witness == id) }) .map(|(id, ord)| (*id, *ord)) .collect(); @@ -684,7 +680,7 @@ impl StateWriteProvider for MemState { #[strict_type(lib = LIB_NAME_RGB_STORAGE)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] pub struct MemGlobalState { - known: LargeOrdMap, + known: LargeOrdMap, limit: u24, } @@ -721,10 +717,7 @@ pub struct MemContractState { contract_id: ContractId, #[getter(skip)] global: TinyOrdMap, - rights: LargeOrdSet>, - fungibles: LargeOrdSet>, - data: LargeOrdSet>, - attach: LargeOrdSet>, + owned: LargeOrdSet, } impl MemContractState { @@ -739,10 +732,7 @@ impl MemContractState { schema_id: schema.schema_id(), contract_id, global, - rights: empty!(), - fungibles: empty!(), - data: empty!(), - attach: empty!(), + owned: empty!(), } } @@ -817,46 +807,28 @@ impl MemContractState { opid: OpId, assignments: &Assignments, ) { - fn process( - contract_state: &mut LargeOrdSet>, - assignments: &[Assign], - opid: OpId, - ty: AssignmentType, - witness_id: Option, - ) { + for (ty, assignments) in assignments.iter() { for (no, seal, state) in assignments .iter() .enumerate() - .filter_map(|(n, a)| a.to_revealed().map(|(seal, state)| (n, seal, state))) + .filter_map(|(n, a)| a.revealed_seal().map(|seal| (n, seal, a.as_state()))) { let assigned_state = match witness_id { - Some(witness_id) => { - OutputAssignment::with_witness(seal, witness_id, state, opid, ty, no as u16) - } - None => OutputAssignment::with_no_witness(seal, state, opid, ty, no as u16), + Some(witness_id) => Allocation::with_witness( + seal, + witness_id, + state.clone(), + opid, + *ty, + no as u16, + ), + None => Allocation::with_no_witness(seal, state.clone(), opid, *ty, no as u16), }; - contract_state + self.owned .push(assigned_state) .expect("contract state exceeded 2^32 items, which is unrealistic"); } } - - for (ty, assignments) in assignments.iter() { - match assignments { - TypedAssigns::Declarative(assignments) => { - process(&mut self.rights, assignments, opid, *ty, witness_id) - } - TypedAssigns::Fungible(assignments) => { - process(&mut self.fungibles, assignments, opid, *ty, witness_id) - } - TypedAssigns::Structured(assignments) => { - process(&mut self.data, assignments, opid, *ty, witness_id) - } - TypedAssigns::Attachment(assignments) => { - process(&mut self.attach, assignments, opid, *ty, witness_id) - } - } - } } } @@ -876,12 +848,12 @@ impl> ContractStateAccess for MemContract { &self, ty: GlobalStateType, ) -> Result, UnknownGlobalStateType> { - type Src<'a> = &'a BTreeMap; - type FilteredIter<'a> = Box + 'a>; + type Src<'a> = &'a BTreeMap; + type FilteredIter<'a> = Box + 'a>; struct Iter<'a> { src: Src<'a>, iter: FilteredIter<'a>, - last: Option<(GlobalOrd, &'a DataState)>, + last: Option<(GlobalOrd, &'a StateData)>, depth: u24, constructor: Box) -> FilteredIter<'a> + 'a>, } @@ -893,7 +865,7 @@ impl> ContractStateAccess for MemContract { } } impl<'a> GlobalStateIter for Iter<'a> { - type Data = &'a DataState; + type Data = &'a StateData; fn size(&mut self) -> u24 { let iter = self.swap(); // TODO: Consuming iterator just to count items is highly inefficient, but I do @@ -964,64 +936,20 @@ impl> ContractStateAccess for MemContract { Ok(GlobalContractState::new(iter)) } - fn rights(&self, outpoint: XOutpoint, ty: AssignmentType) -> u32 { - self.unfiltered - .borrow() - .rights - .iter() - .filter(|assignment| { - assignment.seal.to_outpoint() == outpoint && assignment.opout.ty == ty - }) - .filter(|assignment| assignment.check_witness(&self.filter)) - .count() as u32 - } - - fn fungible( - &self, - outpoint: XOutpoint, - ty: AssignmentType, - ) -> impl DoubleEndedIterator { - self.unfiltered - .borrow() - .fungibles - .iter() - .filter(move |assignment| { - assignment.seal.to_outpoint() == outpoint && assignment.opout.ty == ty - }) - .filter(|assignment| assignment.check_witness(&self.filter)) - .map(|assignment| assignment.state.value) - } - - fn data( - &self, - outpoint: XOutpoint, - ty: AssignmentType, - ) -> impl DoubleEndedIterator> { - self.unfiltered - .borrow() - .data - .iter() - .filter(move |assignment| { - assignment.seal.to_outpoint() == outpoint && assignment.opout.ty == ty - }) - .filter(|assignment| assignment.check_witness(&self.filter)) - .map(|assignment| &assignment.state.value) - } - - fn attach( + fn state( &self, outpoint: XOutpoint, ty: AssignmentType, - ) -> impl DoubleEndedIterator> { + ) -> impl DoubleEndedIterator> { self.unfiltered .borrow() - .attach + .owned .iter() .filter(move |assignment| { assignment.seal.to_outpoint() == outpoint && assignment.opout.ty == ty }) .filter(|assignment| assignment.check_witness(&self.filter)) - .map(|assignment| &assignment.state.file) + .map(|assignment| &assignment.state) } } @@ -1088,37 +1016,10 @@ impl> ContractStateRead for MemContract { } #[inline] - fn rights_all(&self) -> impl Iterator> { - self.unfiltered - .borrow() - .rights - .iter() - .filter(|assignment| assignment.check_witness(&self.filter)) - } - - #[inline] - fn fungible_all(&self) -> impl Iterator> { - self.unfiltered - .borrow() - .fungibles - .iter() - .filter(|assignment| assignment.check_witness(&self.filter)) - } - - #[inline] - fn data_all(&self) -> impl Iterator> { - self.unfiltered - .borrow() - .data - .iter() - .filter(|assignment| assignment.check_witness(&self.filter)) - } - - #[inline] - fn attach_all(&self) -> impl Iterator> { + fn assignments(&self) -> impl Iterator { self.unfiltered .borrow() - .attach + .owned .iter() .filter(|assignment| assignment.check_witness(&self.filter)) } @@ -1419,10 +1320,10 @@ impl IndexWriteProvider for MemIndex { Ok(!present) } - fn index_genesis_assignments( + fn index_genesis_assignments( &mut self, contract_id: ContractId, - vec: &[Assign], + assignments: &[Assign], opid: OpId, type_id: AssignmentType, ) -> Result<(), IndexWriteError> { @@ -1431,31 +1332,28 @@ impl IndexWriteProvider for MemIndex { .get_mut(&contract_id) .ok_or(IndexInconsistency::ContractAbsent(contract_id))?; - for (no, assign) in vec.iter().enumerate() { + for (no, assign) in assignments.iter().enumerate() { let opout = Opout::new(opid, type_id, no as u16); - if let Assign::ConfidentialState { seal, .. } | Assign::Revealed { seal, .. } = assign { + if let Assign::Revealed { seal, .. } = assign { let output = seal .to_output_seal() .expect("genesis seals always have outpoint"); - match index.outpoint_opouts.get_mut(&output) { - Some(opouts) => { - opouts.push(opout)?; - } - None => { - index.outpoint_opouts.insert(output, medium_bset!(opout))?; - } - } + index + .outpoint_opouts + .entry(output)? + .or_default() + .push(opout)?; } } // We need two cycles due to the borrow checker - self.extend_terminals(vec, opid, type_id) + self.extend_terminals(assignments, opid, type_id) } - fn index_transition_assignments( + fn index_transition_assignments( &mut self, contract_id: ContractId, - vec: &[Assign], + assignments: &[Assign], opid: OpId, type_id: AssignmentType, witness_id: XWitnessId, @@ -1465,44 +1363,38 @@ impl IndexWriteProvider for MemIndex { .get_mut(&contract_id) .ok_or(IndexInconsistency::ContractAbsent(contract_id))?; - for (no, assign) in vec.iter().enumerate() { + for (no, assign) in assignments.iter().enumerate() { let opout = Opout::new(opid, type_id, no as u16); - if let Assign::ConfidentialState { seal, .. } | Assign::Revealed { seal, .. } = assign { + if let Assign::Revealed { seal, .. } = assign { let output = seal.try_to_output_seal(witness_id).unwrap_or_else(|_| { panic!( - "chain mismatch between assignment vout seal ({}) and witness transaction \ - ({})", - seal, witness_id + "chain mismatch between assignment vout seal {seal} and witness \ + transaction {witness_id}", ) }); - match index.outpoint_opouts.get_mut(&output) { - Some(opouts) => { - opouts.push(opout)?; - } - None => { - index.outpoint_opouts.insert(output, medium_bset!(opout))?; - } - } + index + .outpoint_opouts + .entry(output)? + .or_default() + .push(opout)?; } } // We need two cycles due to the borrow checker - self.extend_terminals(vec, opid, type_id) + self.extend_terminals(assignments, opid, type_id) } } impl MemIndex { - fn extend_terminals( + fn extend_terminals( &mut self, - vec: &[Assign], + vec: &[Assign], opid: OpId, type_id: AssignmentType, ) -> Result<(), IndexWriteError> { for (no, assign) in vec.iter().enumerate() { let opout = Opout::new(opid, type_id, no as u16); - if let Assign::Confidential { seal, .. } | Assign::ConfidentialSeal { seal, .. } = - assign - { + if let Assign::Confidential { seal, .. } = assign { self.add_terminal(*seal, opout)?; } } diff --git a/src/persistence/mod.rs b/src/persistence/mod.rs index 321f7b14..c92c389a 100644 --- a/src/persistence/mod.rs +++ b/src/persistence/mod.rs @@ -51,8 +51,8 @@ pub use stash::{ StashInconsistency, StashProvider, StashReadProvider, StashWriteProvider, }; pub use state::{ - ContractStateRead, ContractStateWrite, PersistedState, State, StateError, StateInconsistency, - StateProvider, StateReadProvider, StateWriteProvider, + ContractStateRead, ContractStateWrite, State, StateError, StateInconsistency, StateProvider, + StateReadProvider, StateWriteProvider, }; pub use stock::{ ComposeError, ConsignError, ContractIfaceError, FasciaError, InputError as StockInputError, diff --git a/src/persistence/stash.rs b/src/persistence/stash.rs index c42764e9..a1c522d4 100644 --- a/src/persistence/stash.rs +++ b/src/persistence/stash.rs @@ -292,13 +292,34 @@ impl Stash

{ .map_err(StashError::ReadProvider) } - pub(super) fn extract<'a>( + pub(super) fn scripts<'a>( + &self, + lib_ids: impl IntoIterator, + ) -> Result> { + let mut scripts = BTreeMap::new(); + for id in lib_ids { + let lib = self.provider.lib(id)?; + scripts.insert(id, lib.clone()); + } + Ok(Scripts::from_checked(scripts)) + } + + pub(super) fn type_system(&self, iface: &Iface) -> Result> { + Ok(self + .provider + .type_system() + .map_err(StashError::ReadProvider)? + .extract(iface.types())?) + } + + pub(super) fn types_scripts<'a>( &self, schema: &Schema, ifaces: impl IntoIterator, ) -> Result<(TypeSystem, Scripts), StashError

> { let type_iter = schema .types() + .into_iter() .chain(ifaces.into_iter().flat_map(Iface::types)); let types = self .provider @@ -311,6 +332,7 @@ impl Stash

{ let lib = self.provider.lib(id)?; scripts.insert(id, lib.clone()); } + // TODO: Make sure we have all the libs including their dependencies let scripts = Scripts::try_from(scripts) .map_err(|_| StashDataError::TooManyLibs(schema.schema_id()))?; @@ -330,7 +352,7 @@ impl Stash

{ .get(iface_id) .ok_or(StashDataError::NoIfaceImpl(schema_id, iface_id))?; - let (types, scripts) = self.extract(&schema_ifaces.schema, [iface])?; + let (types, scripts) = self.types_scripts(&schema_ifaces.schema, [iface])?; let builder = ContractBuilder::with( issuer, @@ -355,11 +377,11 @@ impl Stash

{ let iimpl = schema_ifaces .get(iface.iface_id()) .ok_or(StashDataError::NoIfaceImpl(schema.schema_id(), iface.iface_id()))?; - let genesis = self.provider.genesis(contract_id)?; - let (types, _) = self.extract(&schema_ifaces.schema, [iface])?; + let types = self.type_system(iface)?; + let scripts = self.scripts(iimpl.state_abi.lib_ids())?; - let mut builder = if let Some(transition_name) = transition_name { + let builder = if let Some(transition_name) = transition_name { TransitionBuilder::named_transition( contract_id, iface.clone(), @@ -367,6 +389,7 @@ impl Stash

{ iimpl.clone(), transition_name.into(), types, + scripts, ) } else { TransitionBuilder::default_transition( @@ -375,16 +398,11 @@ impl Stash

{ schema.clone(), iimpl.clone(), types, + scripts, ) } .expect("internal inconsistency"); - for (assignment_type, asset_tag) in genesis.asset_tags.iter() { - builder = builder - .add_asset_tag_raw(*assignment_type, *asset_tag) - .expect("tags are in bset and must not repeat"); - } - Ok(builder) } @@ -399,11 +417,9 @@ impl Stash

{ if schema_ifaces.iimpls.is_empty() { return Err(StashDataError::NoIfaceImpl(schema.schema_id(), iface.iface_id()).into()); } - let genesis = self.provider.genesis(contract_id)?; + let types = self.type_system(iface)?; - let (types, _) = self.extract(&schema_ifaces.schema, [iface])?; - - let mut builder = if let Some(iimpl) = schema_ifaces.get(iface.iface_id()) { + let builder = if let Some(iimpl) = schema_ifaces.get(iface.iface_id()) { TransitionBuilder::blank_transition( contract_id, iface.clone(), @@ -424,11 +440,6 @@ impl Stash

{ types, ) }; - for (assignment_type, asset_tag) in genesis.asset_tags.iter() { - builder = builder - .add_asset_tag_raw(*assignment_type, *asset_tag) - .expect("tags are in bset and must not repeat"); - } Ok(builder) } diff --git a/src/persistence/state.rs b/src/persistence/state.rs index 4e8c21d8..216e63df 100644 --- a/src/persistence/state.rs +++ b/src/persistence/state.rs @@ -25,18 +25,16 @@ use std::error::Error; use std::fmt::Debug; use std::iter; -use invoice::Amount; use nonasync::persistence::{CloneNoPersistence, Persisting}; use rgb::validation::{ResolveWitness, WitnessResolverError}; use rgb::vm::{ContractStateAccess, WitnessOrd}; use rgb::{ - AssetTag, AttachState, BlindingFactor, ContractId, DataState, Extension, Genesis, Operation, - RevealedAttach, RevealedData, RevealedValue, Schema, SchemaId, Transition, TransitionBundle, - VoidState, XWitnessId, + ContractId, Extension, Genesis, Operation, Schema, SchemaId, Transition, TransitionBundle, + XWitnessId, }; use crate::containers::{ConsignmentExt, ToWitnessId}; -use crate::contract::OutputAssignment; +use crate::contract::Allocation; use crate::persistence::{StoreTransaction, UpdateRes}; #[derive(Debug, Display, Error, From)] @@ -74,27 +72,6 @@ pub enum StateInconsistency { AbsentWitness(XWitnessId), } -#[derive(Clone, Eq, PartialEq, Debug, Hash)] -pub enum PersistedState { - Void, - Amount(Amount, BlindingFactor, AssetTag), - // TODO: Use RevealedData - Data(DataState, u128), - // TODO: Use RevealedAttach - Attachment(AttachState, u64), -} - -impl PersistedState { - pub(crate) fn update_blinding(&mut self, blinding: BlindingFactor) { - match self { - PersistedState::Void => {} - PersistedState::Amount(_, b, _) => *b = blinding, - PersistedState::Data(_, _) => {} - PersistedState::Attachment(_, _) => {} - } - } -} - #[derive(Debug)] pub struct State { provider: P, @@ -309,10 +286,7 @@ pub trait ContractStateRead: ContractStateAccess { fn contract_id(&self) -> ContractId; fn schema_id(&self) -> SchemaId; fn witness_ord(&self, witness_id: XWitnessId) -> Option; - fn rights_all(&self) -> impl Iterator>; - fn fungible_all(&self) -> impl Iterator>; - fn data_all(&self) -> impl Iterator>; - fn attach_all(&self) -> impl Iterator>; + fn assignments(&self) -> impl Iterator; } pub trait ContractStateWrite { diff --git a/src/persistence/stock.rs b/src/persistence/stock.rs index 4b778ca1..2793c156 100644 --- a/src/persistence/stock.rs +++ b/src/persistence/stock.rs @@ -31,22 +31,22 @@ use bp::dbc::Method; use bp::seals::txout::CloseMethod; use bp::Vout; use chrono::Utc; -use invoice::{Amount, Beneficiary, InvoiceState, NonFungible, RgbInvoice}; +use invoice::{Beneficiary, RgbInvoice}; use nonasync::persistence::{CloneNoPersistence, PersistenceError, PersistenceProvider}; use rgb::validation::{DbcProof, ResolveWitness, WitnessResolverError}; use rgb::{ - validation, AssignmentType, BlindingFactor, BundleId, ContractId, DataState, GraphSeal, - Identity, OpId, Operation, Opout, SchemaId, SecretSeal, Transition, TxoSeal, XChain, XOutpoint, - XOutputSeal, XWitnessId, + validation, AssignmentType, BundleId, ContractId, GraphSeal, Identity, OpId, Operation, Opout, + SchemaId, SecretSeal, Transition, TxoSeal, XChain, XOutpoint, XOutputSeal, XWitnessId, }; use strict_encoding::FieldName; +use strict_types::TypeSystem; use super::{ ContractStateRead, Index, IndexError, IndexInconsistency, IndexProvider, IndexReadProvider, - IndexWriteProvider, MemIndex, MemStash, MemState, PersistedState, SchemaIfaces, Stash, - StashDataError, StashError, StashInconsistency, StashProvider, StashReadProvider, - StashWriteProvider, State, StateError, StateInconsistency, StateProvider, StateReadProvider, - StateWriteProvider, StoreTransaction, + IndexWriteProvider, MemIndex, MemStash, MemState, SchemaIfaces, Stash, StashDataError, + StashError, StashInconsistency, StashProvider, StashReadProvider, StashWriteProvider, State, + StateError, StateInconsistency, StateProvider, StateReadProvider, StateWriteProvider, + StoreTransaction, }; use crate::containers::{ AnchorSet, AnchoredBundleMismatch, Batch, BuilderSeal, ClientBundle, Consignment, ContainerVer, @@ -62,7 +62,7 @@ use crate::interface::{ }; use crate::MergeRevealError; -pub type ContractAssignments = HashMap>; +pub type ContractAssignments = HashMap>; #[derive(Debug, Display, Error, From)] #[display(inner)] @@ -231,6 +231,9 @@ pub enum ComposeError { /// the invoice contains no interface information. NoIface, + /// the invoice lacks specific state information. + NoInvoiceState, + /// the invoice requirements can't be fulfilled using available assets or /// smart contract state. InsufficientState, @@ -492,6 +495,9 @@ impl Stock { pub fn iface(&self, iface: impl Into) -> Result<&Iface, StockError> { Ok(self.stash.iface(iface)?) } + pub fn type_system(&self, iface: &Iface) -> Result> { + Ok(self.stash.type_system(iface)?) + } pub fn schemata(&self) -> Result + '_, StockError> { Ok(self.stash.schemata()?.map(SchemaInfo::with)) } @@ -571,12 +577,13 @@ impl Stock { let iimpl = self.stash.impl_for::(schema_ifaces)?; let iface = self.stash.iface(iimpl.iface_id)?; - let (types, _) = self.stash.extract(&schema_ifaces.schema, [iface])?; + let types = self.stash.type_system(iface)?; Ok(C::Wrapper::with(ContractIface { state, schema: schema_ifaces.schema.clone(), iface: iimpl.clone(), + scripts: self.stash.scripts(iimpl.state_abi.lib_ids())?, types, info, })) @@ -596,12 +603,13 @@ impl Stock { ContractIfaceError::NoAbstractImpl(iface_id, schema_ifaces.schema.schema_id()) })?; - let (types, _) = self.stash.extract(&schema_ifaces.schema, [iface])?; + let types = self.stash.type_system(iface)?; Ok(ContractIface { state, schema: schema_ifaces.schema.clone(), iface: iimpl.clone(), + scripts: self.stash.scripts(iimpl.state_abi.lib_ids())?, types, info, }) @@ -617,48 +625,14 @@ impl Stock { let state = self.contract_state(contract_id)?; let mut res = - HashMap::>::with_capacity(outputs.len()); + HashMap::>::with_capacity(outputs.len()); - for item in state.fungible_all() { - let outpoint = item.seal.into(); - if outputs.contains::(&outpoint) { - res.entry(item.seal).or_default().insert( - item.opout, - PersistedState::Amount( - item.state.value.into(), - item.state.blinding, - item.state.tag, - ), - ); - } - } - - for item in state.data_all() { - let outpoint = item.seal.into(); - if outputs.contains::(&outpoint) { - res.entry(item.seal).or_default().insert( - item.opout, - PersistedState::Data(item.state.value.clone(), item.state.salt), - ); - } - } - - for item in state.rights_all() { + for item in state.assignments() { let outpoint = item.seal.into(); if outputs.contains::(&outpoint) { res.entry(item.seal) .or_default() - .insert(item.opout, PersistedState::Void); - } - } - - for item in state.attach_all() { - let outpoint = item.seal.into(); - if outputs.contains::(&outpoint) { - res.entry(item.seal).or_default().insert( - item.opout, - PersistedState::Attachment(item.state.clone().into(), item.state.salt), - ); + .insert(item.opout, item.state.clone()); } } @@ -708,7 +682,9 @@ impl Stock { kit.iimpls .extend(schema_ifaces.iimpls.values().cloned()) .expect("type guarantees"); - let (types, scripts) = self.stash.extract(&schema_ifaces.schema, &kit.ifaces)?; + let (types, scripts) = self + .stash + .types_scripts(&schema_ifaces.schema, &kit.ifaces)?; kit.scripts .extend(scripts.into_values()) .expect("type guarantees"); @@ -783,7 +759,7 @@ impl Stock { // 2. Collect secret seals from terminal transitions to add to the consignment terminals for typed_assignments in transition.assignments.values() { for index in 0..typed_assignments.len_u16() { - let seal = typed_assignments.to_confidential_seals()[index as usize]; + let seal = typed_assignments.confidential_seals()[index as usize]; if secret_seal == Some(seal) { let res = terminals.insert(bundle_id, seal); assert_eq!(res, None); @@ -873,7 +849,9 @@ impl Stock { let terminals = Confined::try_from(terminals).map_err(|_| ConsignError::TooManyTerminals)?; - let (types, scripts) = self.stash.extract(&schema_ifaces.schema, ifaces.keys())?; + let (types, scripts) = self + .stash + .types_scripts(&schema_ifaces.schema, ifaces.keys())?; let scripts = Confined::from_iter_checked(scripts.into_values()); let supplements = Confined::try_from(supplements).map_err(|_| ConsignError::TooManySupplements)?; @@ -907,7 +885,7 @@ impl Stock { #[allow(clippy::result_large_err)] pub fn compose( &self, - invoice: &RgbInvoice, + invoice: RgbInvoice, prev_outputs: impl IntoIterator>, method: CloseMethod, beneficiary_vout: Option>, @@ -920,7 +898,6 @@ impl Stock { beneficiary_vout, u64::MAX, allocator, - |_, _| BlindingFactor::random(), |_, _| rand::random(), ) } @@ -931,16 +908,17 @@ impl Stock { #[allow(clippy::too_many_arguments, clippy::result_large_err)] pub fn compose_deterministic( &self, - invoice: &RgbInvoice, + invoice: RgbInvoice, prev_outputs: impl IntoIterator>, method: CloseMethod, beneficiary_vout: Option>, priority: u64, allocator: impl Fn(ContractId, AssignmentType, VelocityHint) -> Option, - pedersen_blinder: impl Fn(ContractId, AssignmentType) -> BlindingFactor, seal_blinder: impl Fn(ContractId, AssignmentType) -> u64, ) -> Result> { let layer1 = invoice.layer1(); + let state_data = invoice.state.ok_or(ComposeError::NoInvoiceState)?; + let state = rgb::State::from(state_data); // TODO: Take account attachements when they will be supported by invoices let prev_outputs = prev_outputs .into_iter() .map(|o| o.into()) @@ -989,16 +967,13 @@ impl Stock { .or_else(|| main_builder.default_assignment().ok()) .ok_or(BuilderError::NoDefaultAssignment)? .clone(); - let assignment_id = main_builder - .assignments_type(&assignment_name) - .ok_or(BuilderError::InvalidStateField(assignment_name.clone()))?; + let assignment_id = main_builder.assignments_type(assignment_name)?; // If there are inputs which are using different seal closing method from our // wallet (and thus main state transition) we need to put them aside and // allocate a different state transition spending them as a change. let mut alt_builder = self.transition_builder(contract_id, iface.clone(), invoice.operation.clone())?; - let mut alt_inputs = Vec::::new(); let layer1 = invoice.beneficiary.chain_network().layer1(); let beneficiary = match (invoice.beneficiary.into_inner(), beneficiary_vout) { @@ -1020,16 +995,7 @@ impl Stock { // 2. Prepare transition let mut main_inputs = Vec::::new(); - let mut sum_inputs = Amount::ZERO; - let mut sum_alt = Amount::ZERO; - let mut data_inputs = vec![]; - let mut data_main = true; - let lookup_state = - if let InvoiceState::Data(NonFungible::RGB21(allocation)) = &invoice.owned_state { - Some(DataState::from(*allocation)) - } else { - None - }; + let mut alt_inputs = Vec::::new(); for (output, list) in self.contract_assignments_for(contract_id, prev_outputs.iter().copied())? @@ -1039,7 +1005,7 @@ impl Stock { } else { alt_inputs.push(output) }; - for (opout, mut state) in list { + for (opout, state) in list { if output.method() == method { main_builder = main_builder.add_input(opout, state.clone())?; } else { @@ -1047,113 +1013,38 @@ impl Stock { } if opout.ty != assignment_id { let seal = output_for_assignment(contract_id, opout.ty)?; - state.update_blinding(pedersen_blinder(contract_id, assignment_id)); if output.method() == method { - main_builder = main_builder.add_owned_state_raw(opout.ty, seal, state)?; + main_builder = main_builder.add_owned_state_blank(opout.ty, seal, state)?; } else { - alt_builder = alt_builder.add_owned_state_raw(opout.ty, seal, state)?; - } - } else if let PersistedState::Amount(value, _, _) = state { - sum_inputs += value; - if output.method() != method { - sum_alt += value; + alt_builder = alt_builder.add_owned_state_blank(opout.ty, seal, state)?; } - } else if let PersistedState::Data(value, _) = state { - if lookup_state.as_ref() == Some(&value) && output.method() != method { - data_main = false; - } - data_inputs.push(value); } } } - // Add payments to beneficiary and change - match invoice.owned_state.clone() { - InvoiceState::Amount(amt) => { - // Pay beneficiary - if sum_inputs < amt { - return Err(ComposeError::InsufficientState.into()); - } - - let sum_main = sum_inputs - sum_alt; - let (paid_main, paid_alt) = - if sum_main < amt { (sum_main, amt - sum_main) } else { (amt, Amount::ZERO) }; - let blinding_beneficiary = pedersen_blinder(contract_id, assignment_id); - - if paid_main > Amount::ZERO { - main_builder = main_builder.add_fungible_state_raw( - assignment_id, - beneficiary, - paid_main, - blinding_beneficiary, - )?; - } - if paid_alt > Amount::ZERO { - alt_builder = alt_builder.add_fungible_state_raw( - assignment_id, - beneficiary, - paid_alt, - blinding_beneficiary, - )?; - } - let blinding_change = pedersen_blinder(contract_id, assignment_id); - let change_seal = output_for_assignment(contract_id, assignment_id)?; - - // Pay change - if sum_main > paid_main { - main_builder = main_builder.add_fungible_state_raw( - assignment_id, - change_seal, - sum_main - paid_main, - blinding_change, - )?; - } - if sum_alt > paid_alt { - alt_builder = alt_builder.add_fungible_state_raw( - assignment_id, - change_seal, - sum_alt - paid_alt, - blinding_change, - )?; - } - } - InvoiceState::Data(data) => match data { - NonFungible::RGB21(allocation) => { - let lookup_state = DataState::from(allocation); - if !data_inputs.into_iter().any(|x| x == lookup_state) { - return Err(ComposeError::InsufficientState.into()); - } - - let seal = seal_blinder(contract_id, assignment_id); - if data_main { - main_builder = main_builder.add_data_raw( - assignment_id, - beneficiary, - allocation, - seal, - )?; - } else { - alt_builder = alt_builder.add_data_raw( - assignment_id, - beneficiary, - allocation, - seal, - )?; - } - } - }, - _ => { - todo!( - "only PersistedState::Amount and PersistedState::Allocation are currently \ - supported" - ) + // Add payments to beneficiary + let (builder, partial_state) = + main_builder.fulfill_owned_state(assignment_id, beneficiary, state)?; + main_builder = builder; + if let Some(partial_state) = partial_state { + let (builder, remaining_state) = + alt_builder.fulfill_owned_state(assignment_id, beneficiary, partial_state)?; + alt_builder = builder; + if let Some(_) = remaining_state { + // TODO: Add information about remaining state to the error + return Err(ComposeError::InsufficientState.into()); } } + // Pay change + let change_seal = output_for_assignment(contract_id, assignment_id)?; + main_builder = main_builder.add_owned_state_change(assignment_id, change_seal)?; + alt_builder = alt_builder.add_owned_state_change(assignment_id, change_seal)?; + // 3. Prepare other transitions // Enumerate state let mut spent_state = - HashMap::>>::new(); + HashMap::>>::new(); for id in self.contracts_assigning(prev_outputs.iter().copied())? { // Skip current contract if id == contract_id { @@ -1184,12 +1075,12 @@ impl Stock { Method::TapretFirst => { blank_builder_tapret = blank_builder_tapret .add_input(opout, state.clone())? - .add_owned_state_raw(opout.ty, seal, state)? + .add_owned_state_blank(opout.ty, seal, state)? } Method::OpretFirst => { blank_builder_opret = blank_builder_opret .add_input(opout, state.clone())? - .add_owned_state_raw(opout.ty, seal, state)? + .add_owned_state_blank(opout.ty, seal, state)? } } } diff --git a/src/stl/stl.rs b/src/stl.rs similarity index 54% rename from src/stl/stl.rs rename to src/stl.rs index c0243564..d20e7c85 100644 --- a/src/stl/stl.rs +++ b/src/stl.rs @@ -19,38 +19,44 @@ // See the License for the specific language governing permissions and // limitations under the License. +use amplify::IoError; +use baid64::Baid64ParseError; pub use bp::bc::stl::bp_tx_stl; pub use bp::stl::bp_core_stl; -#[allow(unused_imports)] pub use commit_verify::stl::{commit_verify_stl, LIB_ID_COMMIT_VERIFY}; -use invoice::{Allocation, Amount}; pub use rgb::stl::{aluvm_stl, rgb_commit_stl, rgb_logic_stl, LIB_ID_RGB_COMMIT, LIB_ID_RGB_LOGIC}; use strict_types::stl::{std_stl, strict_types_stl}; -use strict_types::typesys::SystemBuilder; -use strict_types::{CompileError, LibBuilder, SemId, SymbolicSys, TypeLib, TypeSystem}; +use strict_types::{typesys, CompileError, LibBuilder, TypeLib}; -use super::{ - AssetSpec, BurnMeta, ContractSpec, ContractTerms, Error, IssueMeta, MediaType, - LIB_NAME_RGB_CONTRACT, LIB_NAME_RGB_STORAGE, -}; use crate::containers::{Contract, Kit, Transfer}; use crate::persistence::{MemIndex, MemStash, MemState}; -use crate::stl::ProofOfReserves; -use crate::LIB_NAME_RGB_STD; -/// Strict types id for the library providing standard data types which may be -/// used in RGB smart contracts. -pub const LIB_ID_RGB_STORAGE: &str = - "stl:mG$H7b6I-$T8qp18-07PSNeA-rbEBNS5-$J5X4y0-1vPxRWg#channel-vortex-bandit"; +pub const LIB_NAME_RGB_STD: &str = "RGBStd"; +pub const LIB_NAME_RGB_STORAGE: &str = "RGBStorage"; /// Strict types id for the library providing standard data types which may be /// used in RGB smart contracts. -pub const LIB_ID_RGB_CONTRACT: &str = - "stl:!r5yXt4a-v3XXv0M-E9Z6eoh-BFZweik-fxS6CB4-8AaO!MM#rover-annual-disney"; +pub const LIB_ID_RGB_STORAGE: &str = + "stl:dYzM3Ct9-SJ8PljY-C!6hB6y-VlWvDE7-DAtNg3y-zanf6hE#media-fresh-cadet"; /// Strict types id for the library representing of RGB StdLib data types. pub const LIB_ID_RGB_STD: &str = - "stl:JhUC5JgH-Kwps4cO-ZNUklUj-UP6boFp-OY!18Kx-xOSJaVQ#hair-magnum-helena"; + "stl:3QsSNDHr-YPIKTR9-5O!fLuv-xhcxKT2-0LWrO9b-pG15Nvw#mango-inside-shelf"; + +#[allow(dead_code)] +#[derive(Debug, From)] +pub enum Error { + #[from(std::io::Error)] + Io(IoError), + #[from] + Baid64(Baid64ParseError), + #[from] + Compile(CompileError), + #[from] + Link1(typesys::Error), + #[from] + Link2(Vec), +} fn _rgb_std_stl() -> Result { LibBuilder::new(libname!(LIB_NAME_RGB_STD), tiny_bset! { @@ -69,23 +75,6 @@ fn _rgb_std_stl() -> Result { .compile() } -fn _rgb_contract_stl() -> Result { - LibBuilder::new(libname!(LIB_NAME_RGB_CONTRACT), tiny_bset! { - std_stl().to_dependency(), - bp_tx_stl().to_dependency() - }) - .transpile::() - .transpile::() - .transpile::() - .transpile::() - .transpile::() - .transpile::() - .transpile::() - .transpile::() - .transpile::() - .compile() -} - fn _rgb_storage_stl() -> Result { LibBuilder::new(libname!(LIB_NAME_RGB_STORAGE), tiny_bset! { std_stl().to_dependency(), @@ -107,65 +96,16 @@ fn _rgb_storage_stl() -> Result { /// Generates strict type library representation of RGB StdLib data types. pub fn rgb_std_stl() -> TypeLib { _rgb_std_stl().expect("invalid strict type RGBStd library") } -/// Generates strict type library providing standard data types which may be -/// used in RGB smart contracts. -pub fn rgb_contract_stl() -> TypeLib { - _rgb_contract_stl().expect("invalid strict type RGBContract library") -} - /// Generates strict type library providing standard storage for state, contract /// state and index. pub fn rgb_storage_stl() -> TypeLib { _rgb_storage_stl().expect("invalid strict type RGBStorage library") } -#[derive(Debug)] -pub struct StandardTypes(SymbolicSys); - -impl Default for StandardTypes { - fn default() -> Self { StandardTypes::new() } -} - -impl StandardTypes { - pub fn new() -> Self { - Self::try_with([std_stl(), bp_tx_stl(), rgb_contract_stl()]) - .expect("error in standard RGBContract type system") - } - - pub fn with(lib: TypeLib) -> Self { - Self::try_with([std_stl(), bp_tx_stl(), rgb_contract_stl(), lib]) - .expect("error in standard RGBContract type system") - } - - #[allow(clippy::result_large_err)] - fn try_with(libs: impl IntoIterator) -> Result { - let mut builder = SystemBuilder::new(); - for lib in libs.into_iter() { - builder = builder.import(lib)?; - } - let sys = builder.finalize()?; - Ok(Self(sys)) - } - - pub fn type_system(&self) -> TypeSystem { self.0.as_types().clone() } - - pub fn get(&self, name: &'static str) -> SemId { - *self.0.resolve(name).unwrap_or_else(|| { - panic!("type '{name}' is absent in standard RGBContract type library") - }) - } -} - #[cfg(test)] mod test { use super::*; - #[test] - fn contract_lib_id() { - let lib = rgb_contract_stl(); - assert_eq!(lib.id().to_string(), LIB_ID_RGB_CONTRACT); - } - #[test] fn std_lib_id() { let lib = rgb_std_stl(); diff --git a/src/stl/chain.rs b/src/stl/chain.rs deleted file mode 100644 index b3d055c3..00000000 --- a/src/stl/chain.rs +++ /dev/null @@ -1,56 +0,0 @@ -// RGB standard library for working with smart contracts on Bitcoin & Lightning -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use amplify::confinement::SmallBlob; -use amplify::ByteArray; -use bp::{Outpoint, Txid}; -use strict_encoding::{StrictDeserialize, StrictSerialize}; -use strict_types::StrictVal; - -use super::LIB_NAME_RGB_CONTRACT; - -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT, dumb = ProofOfReserves::new(strict_dumb!(), strict_dumb!()))] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct ProofOfReserves { - pub utxo: Outpoint, - pub proof: SmallBlob, -} -impl StrictSerialize for ProofOfReserves {} -impl StrictDeserialize for ProofOfReserves {} - -impl ProofOfReserves { - pub fn new(utxo: Outpoint, proof: SmallBlob) -> ProofOfReserves { - ProofOfReserves { utxo, proof } - } - - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - let utxo = value.unwrap_struct("utxo"); - let txid = Txid::from_slice_unsafe(utxo.unwrap_struct("txid").unwrap_bytes()); - let vout: u32 = utxo.unwrap_struct("vout").unwrap_uint(); - let utxo = Outpoint::new(txid, vout); - - let proof = SmallBlob::from_checked(value.unwrap_struct("proof").unwrap_bytes().into()); - - Self { utxo, proof } - } -} diff --git a/src/stl/error.rs b/src/stl/error.rs deleted file mode 100644 index 72f9767c..00000000 --- a/src/stl/error.rs +++ /dev/null @@ -1,39 +0,0 @@ -// RGB standard library for working with smart contracts on Bitcoin & Lightning -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use amplify::IoError; -use baid64::Baid64ParseError; -use strict_types::{typesys, CompileError}; - -#[allow(dead_code)] -#[derive(Debug, From)] -pub(super) enum Error { - #[from(std::io::Error)] - Io(IoError), - #[from] - Baid64(Baid64ParseError), - #[from] - Compile(CompileError), - #[from] - Link1(typesys::Error), - #[from] - Link2(Vec), -} diff --git a/src/stl/mime.rs b/src/stl/mime.rs deleted file mode 100644 index 4f9c2188..00000000 --- a/src/stl/mime.rs +++ /dev/null @@ -1,214 +0,0 @@ -// RGB standard library for working with smart contracts on Bitcoin & Lightning -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![allow(unused_braces)] - -use std::fmt::{self, Debug}; -use std::str::FromStr; - -use strict_encoding::stl::AlphaSmall; -use strict_encoding::{ - RString, RestrictedCharSet, StrictDeserialize, StrictDumb, StrictEncode, StrictSerialize, -}; -use strict_types::StrictVal; - -use super::LIB_NAME_RGB_CONTRACT; - -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))] -pub struct MediaType { - #[strict_type(rename = "type")] - #[cfg_attr(feature = "serde", serde(rename = "type"))] - pub ty: MediaRegName, - pub subtype: Option, - pub charset: Option, -} -impl StrictDumb for MediaType { - fn strict_dumb() -> Self { MediaType::with("text/plain") } -} -impl StrictSerialize for MediaType {} -impl StrictDeserialize for MediaType {} - -impl MediaType { - /// # Safety - /// - /// Panics is the provided string is an invalid type specifier. - pub fn with(s: &'static str) -> Self { - let (ty, subty) = s.split_once('/').expect("invalid static media type string"); - MediaType { - ty: MediaRegName::from(ty), - subtype: if subty == "*" { None } else { Some(MediaRegName::from(subty)) }, - charset: None, - } - } - - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - let ty = MediaRegName::from_strict_val_unchecked(value.unwrap_struct("type")); - let subtype = value - .unwrap_struct("subtype") - .unwrap_option() - .map(MediaRegName::from_strict_val_unchecked); - let charset = value - .unwrap_struct("charset") - .unwrap_option() - .map(MediaRegName::from_strict_val_unchecked); - Self { - ty, - subtype, - charset, - } - } -} - -impl fmt::Display for MediaType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}/{}", - self.ty, - if let Some(subty) = &self.subtype { subty.to_string() } else { s!("*") } - ) - } -} - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, From)] -#[wrapper(Deref, Display, FromStr)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT, dumb = { MediaRegName::from("dumb") })] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct MediaRegName(RString); - -impl_ident_type!(MediaRegName); -impl_ident_subtype!(MediaRegName); - -impl MediaRegName { - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - MediaRegName::from_str(&value.unwrap_string()).expect("invalid media reg name") - } -} - -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT, tags = repr, into_u8, try_from_u8)] -#[display(inner)] -#[repr(u8)] -#[allow(non_camel_case_types)] -pub enum MimeChar { - #[display("!")] - Excl = b'!', - #[display("#")] - Hash = b'#', - #[display("$")] - Dollar = b'$', - #[display("&")] - Amp = b'&', - #[display("+")] - Plus = b'+', - #[display("-")] - Dash = b'-', - #[display(".")] - Dot = b'.', - #[display("0")] - Zero = b'0', - #[display("1")] - One = b'1', - #[display("2")] - Two = b'2', - #[display("3")] - Three = b'3', - #[display("4")] - Four = b'4', - #[display("5")] - Five = b'5', - #[display("6")] - Six = b'6', - #[display("7")] - Seven = b'7', - #[display("8")] - Eight = b'8', - #[display("9")] - Nine = b'9', - #[display("^")] - Caret = b'^', - #[display("_")] - Lodash = b'_', - #[strict_type(dumb)] - #[display("a")] - a = b'a', - #[display("b")] - b = b'b', - #[display("c")] - c = b'c', - #[display("d")] - d = b'd', - #[display("e")] - e = b'e', - #[display("f")] - f = b'f', - #[display("g")] - g = b'g', - #[display("h")] - h = b'h', - #[display("i")] - i = b'i', - #[display("j")] - j = b'j', - #[display("k")] - k = b'k', - #[display("l")] - l = b'l', - #[display("m")] - m = b'm', - #[display("n")] - n = b'n', - #[display("o")] - o = b'o', - #[display("p")] - p = b'p', - #[display("q")] - q = b'q', - #[display("r")] - r = b'r', - #[display("s")] - s = b's', - #[display("t")] - t = b't', - #[display("u")] - u = b'u', - #[display("v")] - v = b'v', - #[display("w")] - w = b'w', - #[display("x")] - x = b'x', - #[display("y")] - y = b'y', - #[display("z")] - z = b'z', -} - -impl RestrictedCharSet for MimeChar {} diff --git a/src/stl/mod.rs b/src/stl/mod.rs deleted file mode 100644 index d2d84c82..00000000 --- a/src/stl/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -// RGB standard library for working with smart contracts on Bitcoin & Lightning -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -mod specs; -#[allow(clippy::module_inception)] -mod stl; -mod error; -mod mime; -mod chain; - -pub use chain::ProofOfReserves; -use error::Error; -pub use invoice::LIB_NAME_RGB_CONTRACT; -pub use mime::{MediaRegName, MediaType}; -pub use specs::{ - Article, AssetSpec, Attachment, BurnMeta, ContractSpec, ContractTerms, Details, IssueMeta, - Name, RicardianContract, Ticker, -}; -pub use stl::{ - aluvm_stl, bp_core_stl, bp_tx_stl, commit_verify_stl, rgb_commit_stl, rgb_contract_stl, - rgb_logic_stl, rgb_std_stl, rgb_storage_stl, StandardTypes, LIB_ID_RGB_COMMIT, - LIB_ID_RGB_CONTRACT, LIB_ID_RGB_LOGIC, LIB_ID_RGB_STD, LIB_ID_RGB_STORAGE, -}; - -pub const LIB_NAME_RGB_STD: &str = "RGBStd"; -pub const LIB_NAME_RGB_STORAGE: &str = "RGBStorage"; diff --git a/src/stl/specs.rs b/src/stl/specs.rs deleted file mode 100644 index f51afc5d..00000000 --- a/src/stl/specs.rs +++ /dev/null @@ -1,410 +0,0 @@ -// RGB standard library for working with smart contracts on Bitcoin & Lightning -// -// SPDX-License-Identifier: Apache-2.0 -// -// Written in 2019-2024 by -// Dr Maxim Orlovsky -// -// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![allow(unused_braces)] // caused by rustc unable to understand strict_dumb - -use std::fmt::{self, Debug, Formatter}; -use std::hash::{Hash, Hasher}; -use std::str::FromStr; - -use amplify::confinement::{Confined, NonEmptyString, SmallOrdSet, SmallString, U8}; -use amplify::Bytes32; -use invoice::Precision; -use strict_encoding::stl::{Alpha, AlphaNum, AsciiPrintable}; -use strict_encoding::{ - InvalidRString, RString, StrictDeserialize, StrictDumb, StrictEncode, StrictSerialize, - StrictType, -}; -use strict_types::StrictVal; - -use super::{MediaType, ProofOfReserves, LIB_NAME_RGB_CONTRACT}; - -#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct BurnMeta { - pub burn_proofs: SmallOrdSet, -} -impl StrictSerialize for BurnMeta {} -impl StrictDeserialize for BurnMeta {} - -#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct IssueMeta { - pub reserves: SmallOrdSet, -} -impl StrictSerialize for IssueMeta {} -impl StrictDeserialize for IssueMeta {} - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, From)] -#[wrapper(Deref, Display, FromStr)] -#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT, dumb = { Article::from("DUMB") })] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct Article(RString); - -impl_ident_type!(Article); -impl_ident_subtype!(Article); - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, From)] -#[wrapper(Deref, Display, FromStr)] -#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT, dumb = { Ticker::from("DUMB") })] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct Ticker(RString); - -impl PartialEq for Ticker { - fn eq(&self, other: &Self) -> bool { - self.as_str() - .to_uppercase() - .eq(&other.as_str().to_uppercase()) - } -} - -impl Hash for Ticker { - fn hash(&self, state: &mut H) { self.as_str().to_uppercase().hash(state) } -} - -impl_ident_type!(Ticker); -impl_ident_subtype!(Ticker); - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, From)] -#[wrapper(Deref, Display, FromStr)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct Name(RString); - -impl StrictSerialize for Name {} -impl StrictDeserialize for Name {} - -impl_ident_type!(Name); -impl_ident_subtype!(Name); - -impl Name { - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - Name::from_str(&value.unwrap_string()).unwrap() - } -} - -#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, From)] -#[wrapper(Deref, Display)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct Details(NonEmptyString); -impl StrictSerialize for Details {} -impl StrictDeserialize for Details {} - -impl AsRef for Details { - #[inline] - fn as_ref(&self) -> &str { self.0.as_str() } -} - -impl Details { - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - Details::from_str(&value.unwrap_string()).unwrap() - } -} - -impl StrictDumb for Details { - fn strict_dumb() -> Self { - Self(Confined::try_from(s!("Dumb long description which is stupid and so on...")).unwrap()) - } -} - -impl FromStr for Details { - type Err = InvalidRString; - - fn from_str(s: &str) -> Result { - let s = Confined::try_from_iter(s.chars())?; - Ok(Self(s)) - } -} - -impl From<&'static str> for Details { - fn from(s: &'static str) -> Self { Self::from_str(s).expect("invalid details") } -} - -impl TryFrom for Details { - type Error = InvalidRString; - - fn try_from(name: String) -> Result { - let s = Confined::try_from(name)?; - Ok(Self(s)) - } -} - -impl Debug for Details { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_tuple("ContractDetails") - .field(&self.as_str()) - .finish() - } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct AssetSpec { - pub ticker: Ticker, - pub name: Name, - pub details: Option

, - pub precision: Precision, -} -impl StrictSerialize for AssetSpec {} -impl StrictDeserialize for AssetSpec {} - -impl AssetSpec { - pub fn new(ticker: &'static str, name: &'static str, precision: Precision) -> AssetSpec { - AssetSpec { - ticker: Ticker::from(ticker), - name: Name::from(name), - details: None, - precision, - } - } - - pub fn with( - ticker: &str, - name: &str, - precision: Precision, - details: Option<&str>, - ) -> Result { - Ok(AssetSpec { - ticker: Ticker::try_from(ticker.to_owned())?, - name: Name::try_from(name.to_owned())?, - details: details.map(Details::from_str).transpose()?, - precision, - }) - } - - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - let ticker = value.unwrap_struct("ticker").unwrap_string(); - let name = value.unwrap_struct("name").unwrap_string(); - let details = value - .unwrap_struct("details") - .unwrap_option() - .map(StrictVal::unwrap_string); - let precision = value.unwrap_struct("precision").unwrap_enum(); - Self { - ticker: Ticker::from_str(&ticker).expect("invalid asset ticker"), - name: Name::from_str(&name).expect("invalid asset name"), - details: details - .as_deref() - .map(Details::from_str) - .transpose() - .expect("invalid asset details"), - precision, - } - } - - pub fn ticker(&self) -> &str { self.ticker.as_str() } - - pub fn name(&self) -> &str { self.name.as_str() } - - pub fn details(&self) -> Option<&str> { self.details.as_ref().map(|d| d.as_str()) } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct ContractSpec { - pub article: Option
, - pub name: Name, - pub details: Option
, - pub precision: Precision, -} -impl StrictSerialize for ContractSpec {} -impl StrictDeserialize for ContractSpec {} - -impl ContractSpec { - pub fn new(name: &'static str, precision: Precision) -> ContractSpec { - ContractSpec { - article: None, - name: Name::from(name), - details: None, - precision, - } - } - - pub fn with( - article: &str, - name: &str, - precision: Precision, - details: Option<&str>, - ) -> Result { - Ok(ContractSpec { - article: Some(Article::try_from(article.to_owned())?), - name: Name::try_from(name.to_owned())?, - details: details.map(Details::from_str).transpose()?, - precision, - }) - } - - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - let article = value.unwrap_struct("article").unwrap_option(); - let name = value.unwrap_struct("name").unwrap_string(); - let details = value - .unwrap_struct("details") - .unwrap_option() - .map(StrictVal::unwrap_string); - let precision = value.unwrap_struct("precision").unwrap_enum(); - Self { - article: article.map(|val| { - Article::from_str(&val.unwrap_string()).expect("invalid contract article") - }), - name: Name::from_str(&name).expect("invalid contract name"), - details: details - .as_deref() - .map(Details::from_str) - .transpose() - .expect("invalid contract details"), - precision, - } - } - - pub fn article(&self) -> Option<&str> { self.article.as_ref().map(|a| a.as_str()) } - - pub fn name(&self) -> &str { self.name.as_str() } - - pub fn details(&self) -> Option<&str> { self.details.as_ref().map(|d| d.as_str()) } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Default)] -#[display(inner)] -#[derive(StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", transparent) -)] -pub struct RicardianContract(SmallString); -impl StrictSerialize for RicardianContract {} -impl StrictDeserialize for RicardianContract {} - -impl AsRef for RicardianContract { - #[inline] - fn as_ref(&self) -> &str { self.0.as_str() } -} - -impl FromStr for RicardianContract { - type Err = InvalidRString; - - fn from_str(s: &str) -> Result { - let s = Confined::try_from_iter(s.chars())?; - Ok(Self(s)) - } -} - -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct Attachment { - #[strict_type(rename = "type")] - #[cfg_attr(feature = "serde", serde(rename = "type"))] - pub ty: MediaType, - pub digest: Bytes32, -} -impl StrictSerialize for Attachment {} -impl StrictDeserialize for Attachment {} - -impl Attachment { - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - let ty = MediaType::from_strict_val_unchecked(value.unwrap_struct("type")); - let digest = value - .unwrap_struct("digest") - .unwrap_bytes() - .try_into() - .expect("invalid digest"); - Self { ty, digest } - } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_CONTRACT)] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -pub struct ContractTerms { - pub text: RicardianContract, - pub media: Option, -} -impl StrictSerialize for ContractTerms {} -impl StrictDeserialize for ContractTerms {} - -impl ContractTerms { - pub fn from_strict_val_unchecked(value: &StrictVal) -> Self { - let text = RicardianContract::from_str(&value.unwrap_struct("text").unwrap_string()) - .expect("invalid text"); - let media = value - .unwrap_struct("media") - .unwrap_option() - .map(Attachment::from_strict_val_unchecked); - Self { text, media } - } -} diff --git a/stl/IfaceStd.con b/stl/IfaceStd.con deleted file mode 100644 index 37380a20..00000000 --- a/stl/IfaceStd.con +++ /dev/null @@ -1,252 +0,0 @@ -@version(1) -@timestamp(1711405444) -interface NamedAsset - global spec: RGBContract.AssetSpec - global terms: RGBContract.AssetTerms - - genesis: abstract - globals: spec, terms - - -@version(1) -@timestamp(1711405444) -interface RenameableAsset - - public updateRight: Rights - - genesis: override - assigns: updateRight - - transition rename: required, final - globals: spec - assigns: updateRight(?) - default: updateRight - inputs: updateRight - - -@version(1) -@timestamp(1711405444) -interface FungibleAsset - global issuedSupply: RGBContract.Amount - - owned assetOwner(*): Zk64 - - error nonEqualAmounts - "the sum of spent assets doesn't equal to the sum of assets in outputs" - error supplyMismatch - "supply specified as a global parameter doesn't match the issued supply allocated to the asset owners" - - genesis: override - errors: insufficientReserves, invalidProof, supplyMismatch - globals: issuedSupply - assigns: assetOwner(*) - - transition transfer: required, default, abstract - errors: nonEqualAmounts - assigns: assetOwner(+) - default: assetOwner - inputs: assetOwner(+) - - -@version(1) -@timestamp(1711405444) -interface FixedAsset - - owned assetOwner(+): Zk64 - - genesis: override - errors: insufficientReserves, invalidProof, supplyMismatch - assigns: assetOwner(+) - - -@version(1) -@timestamp(1711405444) -interface BurnableAsset - global burnedSupply(*): RGBContract.Amount - - public burnRight(+): Rights - - error insufficientCoverage - "the claimed amount of burned assets is not covered by the assets in the operation inputs" - - genesis: override - assigns: burnRight(+) - - transition burn: required, final - errors: insufficientCoverage, invalidProof, supplyMismatch - meta: RGBContract.BurnMeta - globals: burnedSupply - assigns: burnRight(*) - inputs: burnRight - - -@version(1) -@timestamp(1711405444) -interface InflatableAsset - global issuedSupply(+): RGBContract.Amount - - public inflationAllowance(*): Zk64 - - error issueExceedsAllowance - "you try to issue more assets than allowed by the contract terms" - - genesis: override - assigns: inflationAllowance(+) - - transition issue: required, abstract - errors: issueExceedsAllowance, supplyMismatch - globals: issuedSupply - assigns: assetOwner(*), inflationAllowance(*) - default: assetOwner - inputs: inflationAllowance(+) - - -@version(1) -@timestamp(1711405444) -interface ReplaceableAsset - global burnedSupply(*): RGBContract.Amount - global replacedSupply(*): RGBContract.Amount - - public burnEpoch(+): Rights - public burnRight(*): Rights - - error insufficientCoverage - "the claimed amount of burned assets is not covered by the assets in the operation inputs" - - genesis: override - assigns: burnEpoch - - transition burn: required, final - errors: insufficientCoverage, invalidProof, supplyMismatch - meta: RGBContract.BurnMeta - globals: burnedSupply - assigns: burnRight(?) - inputs: burnRight - - transition openEpoch: required, final - assigns: burnEpoch(?), burnRight - default: burnRight - inputs: burnEpoch - - transition replace: required, final - errors: insufficientCoverage, invalidProof, nonEqualAmounts, supplyMismatch - meta: RGBContract.BurnMeta - globals: replacedSupply - assigns: assetOwner(*), burnRight(?) - default: assetOwner - inputs: burnRight - - -@version(1) -@timestamp(1711405444) -interface ReservableAsset - - error insufficientReserves - "reserve is insufficient to cover the issued assets" - error invalidProof - "the provided proof is invalid" - - genesis: override - errors: insufficientReserves, invalidProof - meta: RGBContract.IssueMeta - - transition issue: override - errors: insufficientReserves, invalidProof - meta: RGBContract.IssueMeta - default: assetOwner - inputs: - - -@version(1) -@timestamp(1711405444) -interface NonFungibleToken - global attachmentTypes(*): RGB21.AttachmentType - global tokens(*): RGB21.TokenData - - owned assetOwner(*): RGB21.Allocation - - error fractionOverflow - "the amount of fractional token in outputs exceeds 1" - error invalidAttachmentType - "attachment has a type which is not allowed for the token" - error nonEqualValues - "the sum of spent token fractions doesn't equal to the sum of token fractions in outputs" - error nonFractionalToken - "attempt to transfer a fraction of non-fractionable token" - - genesis: override - errors: fractionOverflow, invalidAttachmentType - globals: attachmentTypes(*), tokens(*) - assigns: assetOwner(*) - - transition transfer: required, default, final - errors: fractionOverflow, nonEqualValues, nonFractionalToken - assigns: assetOwner(+) - default: assetOwner - inputs: assetOwner(+) - - -@version(1) -@timestamp(1711405444) -interface EngravableNft - global engravings(*): RGB21.EngravingData - - error nonEngravableToken - "attempt to engrave on a token which prohibit engraving" - - genesis: override - - transition engrave: required, final - errors: fractionOverflow, nonEngravableToken, nonEqualValues, nonFractionalToken - globals: engravings - assigns: assetOwner(+) - default: assetOwner - inputs: assetOwner(+) - - -@version(1) -@timestamp(1711405444) -interface UniqueNft - global attachmentTypes: RGB21.AttachmentType - global tokens: RGB21.TokenData - - owned assetOwner(+): RGB21.Allocation - - genesis: override - globals: attachmentTypes, tokens - assigns: assetOwner(+) - - -@version(1) -@timestamp(1711405444) -interface LimitedNft - global attachmentTypes(+): RGB21.AttachmentType - global tokens(+): RGB21.TokenData - - owned assetOwner(+): RGB21.Allocation - - genesis: override - globals: attachmentTypes(+), tokens(+) - assigns: assetOwner(+) - - -@version(1) -@timestamp(1711405444) -interface IssuableNft - - public inflationAllowance(+): RGB21.ItemsCount - - error issueExceedsAllowance - "you try to issue more assets than allowed by the contract terms" - - genesis: override - assigns: inflationAllowance(+) - - transition issue: required, abstract - errors: fractionOverflow, insufficientReserves, invalidAttachmentType, invalidProof, issueExceedsAllowance - globals: attachmentTypes(*), tokens(*) - assigns: assetOwner(*), inflationAllowance(*) - default: assetOwner - inputs: inflationAllowance(+) - - diff --git a/stl/RGBContract@0.11.0.sta b/stl/RGBContract@0.11.0.sta deleted file mode 100644 index 50e247d3..00000000 --- a/stl/RGBContract@0.11.0.sta +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN STRICT TYPE LIB----- -Id: stl:!r5yXt4a-v3XXv0M-E9Z6eoh-BFZweik-fxS6CB4-8AaO!MM#rover-annual-disney -Name: RGBContract -Dependencies: - Std#ralph-blue-lucky, - Bitcoin#signal-color-cipher -Check-SHA256: 6347d5f0a4c36a074fd3b6abb98041f64798a4a233e1742a352edc330dddbf3d - -3sOfyLvL<$a$#e10?I5NZ-bfLFbqC#o>4E?M+l67UG^w8*<_XZ#%uyqCj(P-Wc6$lVk7oBr%DNv+($;q -`HHK!gIHa)*%m(-e#9sm3I{@IbYpL6ZUP5FX>?<6X>J1mA>%$n#j0HLDJN5-IKgM_J7b(p+0MPGk2Gl) -y2(Rz1Xgc#bfbbo^UK%K(4i9Ajp1M~R@C@!4#dQE#lUD;OiKi1Rs>XdX=LbXK+Rkw`Mu(V|7oQWGN(Z+ -AyvH&RuaL#N1_Q*>km07$+g7b@t4MVjY>G@u4Q3HlB(d+LiLJm-R=h;`?dxDG*c -V`*tna%paKVPb4$UtT8V#RWVYMMP0s#-L?ApehHE`!Nx1aisd$7U5G>2tjOcXkkuuZGt0!^mXvL0b>G|!UaKWaA;xq7YGF1t^|4b)vt7`JJJH?>OpeZskt`?6&l-r#0;SdL2Phn -VN-2kY-|(&3PEgaZ)0I}X>V=?0s&*k#ka7f`< -Z^7s3P_GJP!FFFM4E? -M+l67UG^w8*<_XZ#%uyqCxRn@^mXvL0b>G|!T<;Y$}AplgPGkh3_fq3 -Q7_j=2#kPT_9!;lWR>~GYywm#UtT8V#RWVYMMP0s#-L?ApehHE`!Nx1aisd$7U5G>00000000009{>OV -000002|;snWpq<;Wn%^e26Sm-Yh`i)TX!suv0v9m0LPL+_79KRH|I99{YEOV7tT#ZPWpkW1a4t%WdVR* -#k^Az$U%@qU7>2Bz={du0O&G0&#r1CLJBFZ06hm}WprU_Y;ynv0ssVVZ*FA(00035b8l^B00jX7KPz&# -#IG7-47St%2#c>Z5R>jkTb_MKDq#SE1Nsg8a>I`c#0nSFF19TD^=GS9xE -uuG0V@n0eeL3DIsV`yzV!Z000000RR600000001QKKZgg^CV{}t+Wn%^e2Vrt_X=7|<00aU61a5C`WdHyG0R(ezZDjxj0ReXZ -@I5NQHT;&p7LREnfs~VQpmrfL_JCQxeEQkVIXfYN5c23F83hGCI$$Y9m4l -DXjoK2V`Y*VQFl000aU61a5C`WdHyG0R(ezZDjxj0RcZNa<{~<8ep?nYaleMc%`0D|O6 -*W?Lsa%E#_b7^mG0bK*c7mcZoem^?%L*to!bRZoO^d~aUzM`;8jz95VA`L@tZgg^CV{}wya&2=40t9qr -cys|6%am^tlg}6qop{{FTg974FaQ3n`}K{nn9PGH_DcZ;ZDnL>VE_aI00eGtZe;)f009JZZ*64&1pxs= -s(;1y^<+=wqOM*VsgOd=>xYy=<4kft^@4w~Gv0~^L}hegX>4-^0RRX90RaF2000000RI300000000~KR -b9H4+WprT%0SIzsb7gXNWpe-t0S?j{I~j%e^V!Z000000RR60 -0000001QoKWNBeiWoJ%dZDj=k00ja9$}AplgPGkh3_fq3Q7_j=2#kPT_9!;lWR>~GYywm#`4m;t2@#H=ITLm*{QiV2NfFIf5Z%-00;p*(W0Hqt(%d1CNN)#sHFQL7%(bMbH%I*cn#*O0A6zd00000 -0000#0000000009O=VnH0sEektM3d!V}qV`yP= -b7gb@1OfmAZf|a7000011aog~WdH>M0UWS(jugTGj1K^e=F-$2o*6gc%@3Ir#hQL8;m&)Yy9iBbZDm7f -VR8d41Z8+*Y#{__VRL9B24rt+Y+-UF17U4&CIoP7b#p5OWMOk?Edyk4bS?yXWpZyY18;6+F#~jWZ!!gR -XmVv`GX!RDb#gQWW@&b1H3M^Lcs2!dWp-t5Hw9&BXJ~Xd1a4_=WjO_7VRB`3UIuJ$WMOk?UjboZ0b*hS -V`BkiWC3Mm0cK_aXJ-LuXaQ+y0cvUiYij{)YyoX;0d8&qZ*Ku`Z~<{~0djHyb8`W7bOCjB0d{r)cXt7J -cma8N0eX4_PGN0j1pxpB0s_h`9&dx0-7pM3Z=O*v*GCA9fL-<|HrZsA`NnJlR3}KjBNr;@ghiU?gEXK9 -KMDE{F?;HZBRuDVqlk6qmbd^20?I5NZ-bfLFbqC#o>4E?M+l67UG^w8*<_XZ#%uyqCrG{{7b@t4MVjY> -G@u4Q3HlB(d+LiLJm-R=h;`?dxBvhE0000004D$d0000001Z!fZe?Ufa$#e1X>V=?0RR992~cunV`+0~ -Z*Bt<3u$g-X?AIIX<}?;00d-ZV`%{eV`Xl1X#xdpX>4q10|{hhV`)ukY;0)+3S(t%bZJd#Y;0)-1#M|# -a&HC+WMyM%O=)9tZwCrvWo~q7O=)9tZwLf#VQy~;2xMhrX-;8oZwd)xWo~q7PGN3u3j}a!V{Z%yWMyM% -P-$at4GCjqZggo-X=85=1!iS!bZ-v{WMyM%MrCbuZx9M&Wo~q7MrCbuZxIAxbaZbL4^VP%Z)Q(sQe|^x -a&~2N1_A_iba-z9^=uPjBlbC`N(qzPM@Gr{imSMTSY5T*7C#t%#3&jH=xRXCTqXIv;)MTcr4cfxK`S9u -y$)6q!N22#m0-mN1#oh2Z)N}p002M$0000000030{{R300000HQfXsha%5>?ZbNTwbaG*1bOiwb2mk>9 -0000000030{{R3000006RB2;tWpV`p00ja9$}AplgPGkh3_fq3Q7_j=2#kPT_9!;lWR>~GYywm#f+K+R -b@1)9wcJs8k=}EVt)knrbu3H - Copyright (C) 2023-2024 LNP/BP Standards Association. All rights reserved. - License: Apache-2.0 --} - -@context -typelib RGBContract - -import Std#ralph-blue-lucky - use AsciiPrintable#ultra-sunset-format - use AlphaNum#window-tractor-alamo - use Alpha#citizen-bicycle-stretch - use AlphaSmall#magnum-martin-soviet - -import Bitcoin#signal-color-cipher - use Vout#brush-gloria-heroic - use Txid#shallow-light-reverse - use Outpoint#logo-alamo-madam - - -@mnemonic(blonde-slang-mobile) -data Allocation : TokenIndex, OwnedFraction - -@mnemonic(monica-tornado-page) -data Amount : U64 - -@mnemonic(infant-father-exhibit) -data Article : Std.Alpha, [Std.AlphaNum ^ ..0x1f] - -@mnemonic(alaska-archive-mailbox) -data AssetSpec : ticker Ticker - , name Name - , details Details? - , precision Precision - -@mnemonic(mono-bagel-falcon) -data Attachment : type MediaType, digest [Byte ^ 32] - -@mnemonic(ivory-speed-finish) -data BurnMeta : burnProofs {ProofOfReserves} - -@mnemonic(hawaii-winter-orca) -data ContractSpec : article Article? - , name Name - , details Details? - , precision Precision - -@mnemonic(voodoo-toga-meaning) -data ContractTerms : text RicardianContract, media Attachment? - -@mnemonic(trivial-halt-nobody) -data Details : [Unicode ^ 1..0xff] - -@mnemonic(alias-analog-icon) -data IssueMeta : reserves {ProofOfReserves} - -@mnemonic(taboo-pogo-exile) -data MediaRegName : Std.AlphaSmall, [MimeChar ^ ..0x3f] - -@mnemonic(brother-burma-book) -data MediaType : type MediaRegName - , subtype MediaRegName? - , charset MediaRegName? - -@mnemonic(amber-alarm-satire) -data MimeChar : excl#33 | hash#35 | dollar | amp#38 - | plus#43 | dash#45 | dot | zero#48 - | one | two | three | four - | five | six | seven | eight - | nine | caret#94 | lodash | a#97 - | b | c | d | e - | f | g | h | i - | j | k | l | m - | n | o | p | q - | r | s | t | u - | v | w | x | y - | z - - -@mnemonic(lexicon-monitor-madonna) -data Name : Std.AsciiPrintable, [Std.AsciiPrintable ^ ..0x27] - -@mnemonic(mission-person-armor) -data OwnedFraction : U64 - -@mnemonic(vendor-anita-british) -data Precision : indivisible | deci | centi | milli - | deciMilli | centiMilli | micro | deciMicro - | centiMicro | nano | deciNano | centiNano - | pico | deciPico | centiPico | femto - | deciFemto | centiFemto | atto - - -@mnemonic(harmony-dolby-golf) -data ProofOfReserves : utxo Bitcoin.Outpoint, proof [Byte] - -@mnemonic(bernard-right-pablo) -data RicardianContract : [Unicode] - -@mnemonic(newton-corona-aloha) -data Ticker : Std.Alpha, [Std.AlphaNum ^ ..0x7] - -@mnemonic(giraffe-correct-modest) -data TokenIndex : U32 - - diff --git a/stl/RGBStd@0.11.0.sta b/stl/RGBStd@0.11.0.sta index 5c9d924c..589d596b 100644 --- a/stl/RGBStd@0.11.0.sta +++ b/stl/RGBStd@0.11.0.sta @@ -1,20 +1,20 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:JhUC5JgH-Kwps4cO-ZNUklUj-UP6boFp-OY!18Kx-xOSJaVQ#hair-magnum-helena +Id: stl:3QsSNDHr-YPIKTR9-5O!fLuv-xhcxKT2-0LWrO9b-pG15Nvw#mango-inside-shelf Name: RGBStd Dependencies: - RGBCommit#harvest-person-orion, StrictTypes#century-comrade-chess, BPCore#austin-story-retro, AluVM#congo-archive-folio, CommitVerify#miller-pancake-elastic, + RGBCommit#trident-rover-tape, Std#ralph-blue-lucky, Bitcoin#signal-color-cipher -Check-SHA256: 6a9228bc3dd61ed396d19a0d3e71c3a3dfc999d232e57ec13c1488bb0b6eeb91 +Check-SHA256: d003c3fbc2fb3bbf7c1af3b580825dfbf43f509f0b75adb51c4f3096e33e53f5 -22w{tQ*>kpAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{j2~tNwLvL+uX>>*EqhH(h&*4NaBbD49mT$3z|G4nQgoFBhHh%l@K06L}1!AJ%| -P(yEWWnyqOe<9`Lptgpr6F_xjAC6(~TLj#*ewiHU&X!byiJ!10COKearHwcS=7M7YzYaI8*bv -hMOc?)(rkC#nUDXLvL+uX>?X)a%pCH$}AplgPGkh3_fq3Q7_j=2#kPT_9!;lWR>~GYywm#15kpMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C`}q*r3sZD*X=8L$d2nTORuk6O)Q5AKbFW;J +EQ>MoHhG*Mzd(pEtONi$rOUxc20~CnZ*pZ~a5aA+<>R2XhQO_4{AcS-HH^7AVzASV8M4NYxyCjHL2Pwa +O?m?z-)Viz@~C%8KNS}Z0aQ3s^SOqbBwN-D{wl@OCJaMwZEb0ER%LQ&W_f!)g4$;(NAWquAkw}j-|{|z +I;-FIp1Euir581u{j3R6M?ynyZEb0E$}AplgPGkh3_fq3Q7_j=2#kPT_9!;lWR>~GYywm#15DT%6aZ| SrJerP1pIOD57`7Ol|-ogQ6Pjg~y>s-v>!^VNPLfWv4Jz0xkJm$nc4yMWR2J-cc#Q6SofWC)gp7L6!Sc @@ -43,239 +43,228 @@ g#T%!5i+MiDe1kloHngE|MP04pL=vWpZ|9WI}m#WpgzCf)+{N -c)mXTm=OBn8@DNvJ^I(u7Ttc@lJ^C)`OzK@Qe|^xa&~28LV0v$b2tf7M?ynyZEb0EL;wS50?er0_e!9% +c)mXTm=OBn8@DNvJ^I(u7Ttc@lJ^C)`OzK@Qe|^xa&~28LV0v$b2tf7M?ynyZEb0EFaQH+0?er0_e!9% 6%WL6o5Q7yVM7GXa@w44CHDB`4cre!cywiMb7^mGQ)6glZD9j@leIk>g)RqK0VQ|Mwn6X+txo3vSYd;; -z)HQ~0$d0}b#7#AWl3ZSwto`e>uZ$?1z+)WysMU3t2e*FfKh32^DD>YKF13Ts`WEp!#kMM{I9mVQf}mY;|RG6eT>4P{pQ?3(@m6s4{*=wy-PiS_k>W -l|t&*Fr0fZ2~A~mVOC*mb!8QqXJpH@t3U@-^C5At>@@qQFQ2KNd+8eYXv4en`-lihZg6#UO<`~tNY&HC -T(P)^FVARS*Zg3m2dUS*m(weL9PhQe$_)h#M`dnhb7^x^V`ybEPw9I -@e~jMZwd)2j0{0+bWCA+WpXi7WppJ)biTp4ZzpWVEhda;c-OlKZN9QQ?CZI;=cI(fPVx{>cWz~5Q*>c; -Wm98lWo=<8B@PC`naz9~L0@lerBKV`$$1fC6#s{=m+2p6@mtIZL349ubW~wyb1t%_{ujV7L@=1(T$>wO -Y}Ov_b`4?P%YY`+Wb+o`y9rirX=GD$VRU6Oo>ox?`Aroor<$W|05z3@o%yggc;Wi(O`t`n9TUcD*&5hFi^PVx{q1b@^7zTcrn*%qZTXbx0zVQzD2bZKvHRC#b^Ho-KZ`k;Xmr`<4s -JYKN!!u{G5u+^j1lf!PF4>GEG3r}NXb#iiLZewM0IVbbqN^4g)WDG0#SSGl-+Q@e<+6H_!d>A}?>eT16ofolpo#8 -?XuHZHx7d=!p7E)2#$3bL349yXKrm}Zgg`(Y-w&}Q)OXnRCrKyaz^du!w4MxxaL=+DqP^k2!wz9AHH68 -xp8!<%Jqp^&I?vyY-Mg^c~p6DWk|gmZWsH8I~II?C0;dW+k!*yDqgzlqQwf$39g<|8WK=tWMy)5Wo|=n -ZEb0EZDnqBN@#iqkT|?l*=bx{^0c**fmF&H)l(b`S3$sb4!MK-5kqfoV`X7%Wn@NmZf9v?Y-Ljs%|ogz -QLxC5#{z1Bs(ImjcZKu%4y_xMoB3q3{238PY;R&=Y*Tb$bY)XxXk~3-Q>XLl0V(0al ->0fVsbCfs)I{K8&2}O8xWo~n6Z*Ei2ZB|09R9osd9G^&mV=@u*B|k@iff^?C=mvC@noA);b8~5DZc=4- -WnpY(WI=RvVPj}QY-w&}Q)OXnRCsA*T5oByCBEN9T=>W0>u%$${;`BKEO$VG0b8(5pxNmH8B}?2Wn@8f -b7^O8b3$xsZe&wsVQf@*X=GZDa|tC)BU>oS@xONigke(HCtahRyiRHf-TMdwWnpYocxhy0bsj>g6`?#s5rWnKhSeO?L~x^!;Y#eFP|P}0Z%Ez^MR;^&ZgXjGZd7@2Wo<;p^e<`! -Iztr?rsl#d#OQkEER^^L)C{HEhxT=ipb%1Jc4c8~Wn@NmZf9v?Y-Ml_We~E0fo~tTJ>?Q(lLJ=>rBY$7 -0^roXTE)+&>In@)Z*F5{VQgh&L}7Gcb>vO>-_DBy8`Vb0jGrW9$=2qSMXvL3HlVN`i= -Wp=e2Xp5rzopjE#5h98`u~h0v`BV8NkLOrpFzp4z*br25VQzD2bZKvHQ)6glZDD(|HElq4!)_b{H>!() -nCt8iM0hjp5N|z=I>OKHojw{=d2nT9L349yXKr&sY-w&}Q)OXnRCrKya)BP_mkyA>T}tj_kdvFcMGT4` -fC%jFncQ)?C=$=&Q6NEcb7^O8Qe}2!VQgh&L}7GcLTqVnWK(5fY*ctqbaH|W4XEgn0epQ -k*PX+nL>xOm%pK>soN7+Lug@XZbEEnZe&wsVQf@*X=H?P4U;TR^uxCZOKFR+hj1x=IbKf -Z0H=mhJ>?uV^xB4~9n`Dx!RtcK)nwJGn -aBp>VlfaZ*5|&qoaMx&cZSO)Ho!_*yjLvyQo1^f$X+6j;96@t)X=iR$Z)s#xbYXO5LTqVnWK(5fY*ct@ -WRz0V+XJhss8OG%_CC-Q>(otsF+cqN0Qy}ddQ=3E5C~IaXk~3-No1AC=6W7=VqesjRYGc!>wZFzp>JB4 -@xD;^wu&SY_r(NHa7kpJ2rNlD$O59e#ogQsB77jPl+h5j^*S;NLvL<$a$#e1No1ysFp)<~ -$~wYgjK`HkjV#@&#T1_fGnK3MJXK)_7bXoxb#7;AVr*qobYXO5siJyUlgOLOB};96cGdSG6&iv=7PD~j -ruGj4o;;a=21#ykb#!y8wrKJIUBJXnP(l%Y$cDDuY1Bm#?@QxYCjWldxIc>!SVL%GX>L$;VpnN&Ze??G -uZ@?{0aPfN4Did>Ze%hHN@6KPlLd+s#TneAz-EYx5L9wuZgXjLX>V>qb#7#AWwz*mh8!q$B6|*YuiTY; -OURW8#d%1{rxIXtTaY^?oCrx|Wo~q7ba}{Yf_n>Eea4XlBy!~v3=AX`3Ri2tjjmWpq?wXVr~g2n?Horiuqf0^m>2O`jNR -ziT$b7#=ya6uYYC;sr@=aCLOm?vf5kh_h+&YE#h%O8d1V_{UOl9{V;uR#^q%R5PSyeIwjVvMyte)HLS3WfgRB~Z%b7^#GZ*JDSGqJ&TQwZPkn|ZOr{h9VN -EFkRYIec?G`g2UV1s5Vgb8~5DZc=4-WnpY(WI=RvVPj}QY-w&}Q)OXnRCrKya@w0w6Id2jc94hrndMfL -ayEe1ISdA&%p{mB1!VWk)dNOmcG|`19mwqd!6t9MpF6k$l8zT&IM0)BxIjDir5zArRUtuhb7^O8Qe}2! -VQgh&R$**)WkPIeZe&wsVQf@*P;_$Jidq_i6cBYN^7xEELu$lFU37Sf$J;ty5yrmOX|)6pSVL%GX>LWpmymk!z-`g4hv-$6z_Y -xoLZ_neUP>BpbEf7FA*KKfDV^Y;R&=Y*Tb$bY;{@O*mP8`7qV21dnrCyk{{a-lF$FG0V5TNAc?Tc{K=4 -WprU=VRT{n^sESGu0eNZ)cp(*eFU-DRQ(QTUJ^TE1nY56>E%WYMs;pyX<}?;RC#b^{4_<~U(XE-|Ev|H -db$N7;9H9;8!%;3hl7uME$faw4?}NmV`X7%Wn@8gbYWv?|7c^tcv66A`G>fI&S@S1XLTY^Y?LL}v9ZWWu2|;XdXkkNP -aC1n$BNr;@ghiU?gEXK9KMDE{F?;HZBRuDVqlk6qmbeZmb;*F> -vukd;=m`ygb@x#_>`RmOO$0)3Z)|vJcxJL|x?WKK>7x;m>=zTw_)ojDN{iR+YxT1qeJQTRI%yh?{hxxA$ -L2PhnVMAeXb4+h!VRLBFJq*Jt8?Abrta^#~Iw-!oZ%zqO(A&rh^vGm~tg_w^L2PhnVN-2kY-~(#WMOk? -3sZD*X=8L$d2nTO4*&^LN2X=Q9=Q)O*QWK$LhgcQkwbf~^M){{|8P%hsRk~m~ep32F151Y4W -WC&DwaAi(mZDnMP)DN(0hN+Kdp}ZAoN($wDX8VgT7DmW3qm%zcviBmGB|7z0dgBIJ4& -sCG^VR$+2!VQzGR(<~&{!{{>E!(#o&^pB98KZhv1GEPn8Orhb4n;8ZMQ)zl>ZfBCy0{K32d-H~a`3x8b -375ImR&CF_#3#*gz1^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*Q -Wc?UbbJ9Xwr}~3wv^yxa@v}v^+kiGSR2X#8M$tG2GZIy9X>V>;VRC6_vj93RHP;Wm9=`bY*QQ01rWKV`y)3Wn@BiZe(m_a|8nc26SO?a%FS?1pxsz -U(P2B2NqiWU>yu4AB#Dm;I?Y3kL%RWN&q1Y-Ioj0tR$paB^jI0XARGCkqD_TK!-h3?(0nIicXTch2QnD}62L@rHg-X9aI? -a%FS@hd|-Wi=lHam_X!<3uvO83$-e(J0!3HH}n+hlR66r4nb~iZ**aFX>V>$VQpmv0RRO80?I5NZ-bfL -FbqC#o>4E?M+l67UG^w8*<_XZ#%uyqCnto_jB5_YJg;9E|1`d*r&;qSS3+uh`0YNLave-Im;eX@$}Apl -gPGkh3_fq3Q7_j=2#kPT_9!;lWR>~GYywm#cxiZMvTM3tQ2*(p5s~Z{6V3QiK&W#-F~+s6raGiL00000 -00000{r~^~000003qfvfZ**aFX>V?G1pxpG0WnM89|TAhYfrNblQVQ`LpZXKteHopy#|_NJkG`K5da7P -06+i$00000009600000000000000000093000000000X?b8~5DZb@cgV`T;e3U7CAWn@!yVRU5y-Vzs+ --~y(u)KQ?3g=q&>T!Ej;9TxQjc0+10Fg2)p25@y^Y-wWx$}AplgPGkh3_fq3Q7_j=2#kPT_9!;lWR>~G -Yywm#VTK~nd#>CWCF@89&dx0-7pM3Z=O*v*GCA9 -fL-<|HrZsA`NnJlR3~AEBGG%U@MZ$v=XJ?|;InIPy66cFfOYp#JM2r7_Du+Fb!>ELaBO7)$}AplgPGkh -3_fq3Q7_j=2#kPT_9!;lWR>~GYywm#VTK~nd#>0|;$!V^DH$Z)O5|10COKearHwcS=7M7YzYaI8*bvhMOc?)(rkC#nUE*(LK3V -&vL%&i(~ao9rExlGMgPx_&tqtqVlwo1}@PEWMX4ba&K>D0#*~&*VKn|nRBmPlPrrd^EP>$AHP6|FsuXs -I;G3ONJmc3T+rxDK6vW;JU&?LxLM72H?wDC1Zo}=N}D)4mj+^WZe(m_0w7l>toMja192_(UwD?W=?zm* -&IhOn$k(lG-qz;DsjrQf(E(H_nGEpD*KTAo3`$}tLz4xH6U7D0(t`--)Viz@~C%8KNS}Z0aQ3s^SOqbBwN-D{wl@OCWX;GxmM3|zUzx)^-Ue} -@Gdf&9Z>i^jdP;%w2}rc(FkN>V^DH$Z)O5k6V}(%hjW>8uUwNXi!t*yd7K}=K!`A`1OPgv%fUzwwjY>3 -8tto&d&=ez4Ev5gyU5%_yeyFzybaG*Cb7p070?I5NZ-bfLFbqC#o>4E?M+l67UG^w8 -*<_XZ#%uyqCt-#n(R;4&W&+>mb;*F>vukd;=m`ygb@x#_>`RmOO$l^ma&2jDVQg~%3IZTkC#?5~OapN( -_Fs6GvFQy{P|gRa2*}s1Y~I%9#i;{(leIk>g)RqK0VQ|Mwn6X+txo3vSYd;;z)HQ~0$c(hS0}9Zh)e@< -E%sk{ma*v#Q&7$as0hf{t!&=b=EbSoidq_i6cBYN^7xEELu$lFU37Sf$J;ty5yrmOX|)6Z0000000030 -{{R3000007XJu|>b7^w|AXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{j?6T%|znQ^KeoD%bg94CL -Cf*q;P?fLY7qq^#2NiM*3T1e7Wo~n6Z*Fq{2?8KjC#?5~OapN(_Fs6GvFQy{P|gRa2*}s1Y~I%9#i>)L -^XdU9;lkvmMR*4bh)jz;q`~Q5Z+&x=I0QQSl+6GD0000000960|Nj60000MKb#7#AWpe-t0nT^OmoUfe -VvhY+ARw!>`>M$upk~C-sV(3xjy;4dI{*Lx000000RR90{{R3000whoXk~3-0w7l>toMja192_(UwD?W -=?zm*&IhOn$k(lG-qz;DsX2RKhRF9oualB}P71SaJfwx=uHX^JIK`}#x3$o4Af`kVHyQ&~TYCSRqgWgjZ$<5FZnjcuT6B5B6)POqpHCTrHl4#QtZa;zni700000 -00000{{R30000003v+dFaBO95Wo~qH00{wOJ=2M>OG#EL&$!Mwbx&PZd -lOljoA7|k;k>s6qoa5|8f~f~{V{&P5baMa+0%CAAe<9`Lptgpr6F_xjAC6(~TLj#*ewiHWCD< -wgM1*ibOB -_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jgmDd%EKc;pw+KsVi?D}qDSkO*B!5Mb*xG|_(S5o&00;m8 -KmY&$000000RR900000000000000000RR6000000019(yXKrD1b#i5M015%()D=(>(T2L(qY0=?NR6Lh9EroO>_{O=WapR$**)WfhrcWXrXy +KnGOwA#t$mH2bG7pQ)aE=^FQF!@KkQhzLn;aCLM|VQ?5o)zidWvABmX&uCxQ{9vUAsn@)h(<^=)@3p(i +4FwHHWo~72X>(I!Xk~3-Bv(?{Wq|OU%4#DwR1!oWV0@!2f9}lj6c7M!3JEHV3_)ykOksItaxqh7bSH=1 +76q?Ln5XIuLR#_zRbAPwIB5*EnEyRWJ!fE72nR=HZe??6b15|5V&kT8y6~TWc*7|JHyCs+SQUVx5x3G3 +JW%hcW)wklb7^O8LTqVnWK(5fY*ctqbaFIO53UoI8eY9A{1GERg--GiI0S#x1is&)M%fmnGH4D|a$#@6CZd7@2Wj4Vyq57bK6Q|uUfIMEX^1}Vv6tLB!)|10-o)0prc?(ZtV|8+JWo~0-b4Kmv!w4MxxaL=+ +DqP^k2!wz9AHH68xp8!<%Jqp^&I?vyY-Mg^c~p6DWlGzRB>WS2JTsxo?J^nrEn#tWN`qbZIFMMoKp}H7 +3kyeVZ(?C=Q*>c;Wm6H&L#ixMu*i?c0&0P(dEtC_h4cCjts9h^`DC;F84*WpZ(?C=Q*>c;Wm98lWo=g0JcRyH0-^B_jy?=3vl7@|?;Iu8>aJK2Pj_x*WK(oubY)XxXk~3-WOW`wsTH9-LlJ`2|Ay5Z +(?oEikl{+~pis;@Q*TJ#4Mli#Wo~n6Z*Ek1aAjtg@YuYL)mGY=t+%+rwO5o~d+_&R+tuqk#Xfx`l28Rx +bYXO5YaRzjxhIn~dZom07UlfSoQtD~R`Oa5ClF^a?j|y47(sJ$X=iS2Wo~qHLTqVnWK(5fY*ct@WOd|C +_}|Wp0vpvv$c&#PW69R$ltr%da5t5w^x+8!q6kf8bYWC^aAkJ28)%E7`<-;ovk@YSJ+V~kNcmIwC6DJ= +V=(On#Mls2a$#@6CZc}4uWo==5A5uv7J8luQ*>c;Wkg|g +VSG;aq+M7t(|8CqhYFNGrYCJZsM!5gSQ1|R{9!*4-Wfr2b7^O8ZDnqBb3$xsZe&wsVQf@*P;_#F3=OYq +{WJl0D5$WZ$SVL%GX>LMnX>MdwWnpYocxhyWaSf9!PV~dK2uo>;u!nFd +emP_$e?^hl+JkM;eY!XZL3DIsV`xcahyLPaScq)s9KMExvw34D6J>+NwrBxfixd_%u|$Wt4ncEsX=iS2 +Wo~p-d2nTqyTa&4noi_R;$3lnz4{Zl)X|Z&ZIQtMA_g1big7g*SVL%GX>LMnX>MdwWnpYocu;h5lMuXs +u{2tXFT+?;?hj39&>gq>HOrf1lB-q;n)I5N1y68qb##h5j^*S;NLvL<$a$#e1 +No1gfw_qjpC#e%OW}_qta$#@6CZbEf#WNc-qHt(`hF}jj5^Xl;{ +(HZPSTKb&GEytIZbS*TmyWyh~L349yXKq4lX>MdwWnpYocxhy*qIy@8$eYR~OKp92)%PJ48iGR>vvBgJ +_74J{Jehz7Np5g;baSek)I|~ROXFB3|9;oFKZ_7pLug@XZcue%S7~%^Wpi_~ +b0B+_A}OcS<+P>xMf>Z^#E~58SS7t910|t=tEdzjRC#b^WI=OtX=iS8LTqVnWK(5fY*ctqbaJy5G(X-+ +WB1Zrg#;?=ldFutl!B%^|8k$(>Jc+!mLLg5cywiMb7^mGw&;L{94K`ndk%K5+?9Jv$dw7jc}U5p5@2#$ +kUJ%u2uWmRZggpMdB|&mdkb29#*qXha^)f?kI>J>8dqqbOFybHKpQ-MBMCulbWCA+WpXjhc-#ja_=m*S +BlnLKRX%|Q+#wpdF)6$++xuDj|9wvxRC#b^WI=OtX=iS8LTqVnWK(5fY*ct@WX{t-&_vWw`D^wPq`MWf +kMs^Yw9fkOkt*ANQL*Z(84O2kZ(?C=R$**)WpmYyUkD7Ff~JZGMgrhZ&rP2gYrktY!x$bpv=qCl=HdlO +Zg6#U)$WoGNrKtpQ8M_qJyiO1VIUJ=H=)@ii_5LiQKVQFqt +Wn*$>bW>$vY~6)s0B>Pr5ftu@@z<*O39}j`u&O7io3b$Is?RA$O$kloIF_owDud_0-;wW=VYU(CXh)E2Io8JwEt_I8KzGq2fE*LgU9v8ta3RH4o +ZgXjLX>V@zdQCW4e)%xftOSp9TD)g5B;KO;Krzd=y+`rt_<1!5O=WapWMOn+15cBr>9x-Cs#sheE97?nsOaXHkb)PY;b5{Lt$`pNWLQ%D(Hkon&*Qwpawq)`VKLB>Wd>h=Ype%b?272 +4ncEcX=zY$X>N33Vr*q$h9c2>uJC38-{*D7fZ(%hZo23R4S;p`Q9JBQllDynLT_(ucxiZMvTM3tQ2*(p +5s~Z{6V3QiK&W#-F~+s6raGiL3_)ygXkkuuZA4*nXnIG6r4LWFq2&q#r@H{&I!mq*@dJpi12bb5xjCg# +Yz#qcaA;veVQ_O!b#0Zyy~#}iVEJ)s5j^%uEnQ9{n2s|9Fa^ps+HG#`XS5DMY;b5{PIYZeZ)9O}Xt{%a +=RmHK6WZ%EWRm@*ULd%lgGoFTxU-Vi}-aA;vuZDDL|OmAdib7%`wbaH89bX0k8WpfVz35LOoBKkGaY9#cS7Qj{WgyAGc +S>>g~&^g7Kv@4tY;$BCg=lGO40qbyjMBe4%@A^HhWa%pX8bZK^FG5w(M*PErPQ*K8));4q9;G_%) +IzXn}g(wG03t}BM5{Lay5>;+)VQpn(MrmbiWOGwxZAoNn1fvw5rj-B|XP@r^w5ufb=C_Ju$l1`nW&GEpSWb-vQ)O*Q +WPQm(C)8p9*(R2SB=5|9lKCV3N0b-?Ol>0MdKRd5P6t+Da%o|1bb-?>B-g{}GTFmo{mAr>kexq=D7-RG +P2^0W;fb3W1_o1UdTDNFlG6hDK5~2WhJ*PG7zYWLxz$!}&%4AY&2YWlsz$Eb5KdujWn@NaWo%?~Q)O*Q +WS1d>s?i)zLD2{^84?*=6Qgx+2Ybs0Lm?xkSqB0N +LAl2~i-ZdPG(X<=@3b5mt)No4(ju7iFH2b-u)>&PZdlOljoA7|k;k>s6qoa5|8f~g8rd2nS@d2@7SZ72W_ +L2hGcZ*pa1LUnFrY-Mu<0|5qfVQ_L~bN~eb0T0xtlHy_+MpO-oA=S$!jW5-l +aB^jI00jX7!z&ZH^kdL0x{(6jWvLBXp#FHfK^@BGb=Hv9yjh=W0|sPobz*E~00sgEbYXCEWpn`#)Tff- +Vi`tM4T|KNb>ER}n*iD|-e4is%O;I4)>XI#Z*X#DbOFOF6S?$b&@8%<0^Vh*4O*c7c)LLz%I0;}kk-6e +pK1<4ZfI^CwqAYJB+ZKALhJOg5MR2m;D19&dx0-7pM3Z=O*v*GCA9fL-<|HrZsA`NnJlR3~_8cxJL| +x?WKK>7x;m>=zTw_)C`}q*rYXqYdo~D%m7H6OD0<^0n_2##VWXRdjy=DB@qgYOj24Qq`VPj|j1OfmAZf|a700001 +1aog~WdH>M0?I5NZ-bfLFbqC#o>4E?M+l67UG^w8*<_XZ#%uyqCt-#n(R;4&W&+>mb;*F>vukd;=m`yg +b@x#_>`RmOO$KmvVr*$+0?I5NZ-bfLFbqC#o>4E?M+l67UG^w8*<_XZ#%uyqCt-#n(R;4&W&+>mb;*F> +vukd;=m`ygb@x#_>`RmOO$c&jadl~OWn==%EFN!zncXl9K5w2;FV{y1jDTJCC^p$-mHEbO0#qkqh9c2> +uJC38-{*D7fZ(%hZo23R4S;p`Q9JBQllDyrZFOvPX>e?10?I5NZ-bfLFbqC#o>4E?M+l67UG^w8*<_XZ +#%uyqCt-#n(R;4&W&+>mb;*F>vukd;=m`ygb@x#_>`RmOO%_9JX=QG7LUnFrY-LYya%FT-a&K>D1_KCf +aAQz%Z*OJ-dIKHbX?@G`sCP;~6&DQwR5(-fxrUo0Thx*OcO&#*^E;5@PQ20HK +bE5LJk_Il(2xMYoP;zf?W&&0d*4NaBbD49mT$3z|G4nQgoFBhHh%l@K06L}1!AM6=&s@;xOg?z(`#e5a +?6_IYcQ>MoHhG*Mzd(pEtONi$rOUxc54IneKN{_;j(f`H9IfkFzO$PGV=;l-_zLn%tmAe68Jly{Qj?Kss0n +y)C8xzFm#1PkyMk2y}8`ZgXa3astXM9&dx0-7pM3Z=O*v*GCA9fL-<|HrZsA`NnJlR3~AEBGG%U@MZ$v +=XJ?|;InIPy66cFfOYp#JM2r7_DuKtpQ8M_qJyiO1VIUJ=H=)@ii_0000000000|Nj60000002WMq&WpinB0((A! ++Gi<8@j1mH(!M6&@;-q&tKasXxoi@p7d4yxtS5)v76q?Ln5XIuLR#_zRbAPwIB5*EnEyRWJ!fE72nuC* +bY*UHX>V?G00{znK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgb_6*NEINn`iYT!jQG>yxXDz?6cf +JO6T@+v*WBWR@TR0000000030|Ns9000007Vs&n0Y-Mu*2?0gOA09vpxUJU-a-WZ4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HLtfv$so3kRF1PV2}fOp_vjQ6FdFHId|lr&gK9B000000000400000000YNbaY{3Xl-R~baMa-0((A!+Gi<8@j1mH(!M6&@;-q&tKasX +xoi@p7d4yxtb}n5lPpg3!?y@aX^XIja4CK{WF&t@k=WXUZP9(YH~bairNa{vkf;?xyT5z&Ua+M@}mOiDpYxh>^^GknUxTJ!XL#OUcE0frb5 +ENEw7&f?o%+)B!ZpG}K!%4G?I4vp$|ttu*CMF0Q*000000RI300000001rcNZgXj8Zf#|5baZlcWd;og +c4cyNX>V=;l-_zLn%tmAe68Jly{Qj?Kss0ny)C8xzFm#1PkyMk2y}8`ZgXa3astXM9&dx0-7pM3Z=O*v +*GCA9fL-<|HrZsA`NnJlR3~AEBGG%U@MZ$v=XJ?|;InIPy66cFfOYp#JM2r7_DuKtpQ8M_qJyiO1VIUJ=H=)@ii_ +0000000000|Nj60000002WMq&WpinB0((A!+Gi<8@j1mH(!M6&@;-q&tKasXxoi@p7d4yxtS5)v76q?L +n5XIuLR#_zRbAPwIB5*EnEyRWJ!fE72nuC*bY*UHX>V?G00{znK7!h3DM#@+#URqYCg1WtfjX<-_MW+H +5~UY4oBgb_6*NEINn`iYT!jQG>yxXDz?6cfJO6T@+v*WBWR@TR0000000030|Ns9000007Vs&n0Y-Mu* +2?0gOA09vpxUJU-a-WZ4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HLtfv$so +3kRF1PV2}fOp_vjQ6FdFHId|lr&gK9B000000000400000000YNbaY{3Xl-R~ +baMa-0((A!+Gi<8@j1mH(!M6&@;-q&tKasXxoi@p7d4yxtb}n5lPpg3!?y@aX^XIja4CK{WF&t@k=WXU +ZP9(YH~bairNa{vkf;?xyT5z&Ua ++M@}mOiDpYxh>^^GknUxTJ!XL#OUcE0frb5ENEw7&f?o%+)B!ZpG}K!%4G?I4vp$|ttu*CMF0Q*00000 +0RI300000001QKKZggR3Ze?;-WpV=n0(LS22}5sgbY*UINn`{C00whoXk~3-00jX8dp?5NXDLVVImIB- +z9!%DK7l%`-}aulY!amxHJkmclv2~%1FNg3QJ<&wKF}2F)J=UcKm7gx`duV?R0NO^0S9MgZe??6a{vVa +0((A!+Gi<8@j1mH(!M6&@;-q&tKasXxoi@p7d4yxte*%hNjk^^qPoT1+zTRnAg`3vXv9d*8d@RXy~6c6 +G6Dr@W?^Gx00jX7JIcU;0|?p#+${pKVqYC0|{wnVPj=UZE$P=1pxt8$PakD +#zGc4+eY|aXXwx;YM0QXyiqR;Jsw2Z*{J&j1#@+9aBKht0Rd++hrkGM>lK-W|y2ahx3nF|Vuawki#7NH?S|Q-Q!u2{b0tIPiVPjm(ZiUQ7;QU +9z@vLsQU{;Z*FvDZgf*=XLAJs015(oK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgb|=zxYCD0L!x +4tB5Hm3vFbl?lapNXe%XU~*fKJ0+X}A;%YO&?-P3O4E?M+l67UG^w8*<_XZ#%uyqCt-#n(R;4&W&+>mb;*F>vukd; +=m`ygb@x#_>`RmOO$cpebYWy+bYTDq0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3 +ZOHs70;T-agdg$OP=xIp;K4#IcLF!~asU7T000000RI300000000(DmZ(?C=a{vkgMe3tp+xFv-0Xp&G +?S=|}9rRaeU`~uMrbA>C`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0((A!+Gi<8@j1mH +(!M6&@;-q&tKasXxoi@p7d4yxtTw?kq57bK6Q|uUfIMEX^1}Vv6tLB!)|10-o)0prc>n+a000000RI30 +0000001IJrb7^O8ZDnqBa{vkgMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C`}q*r8?;yf@?frQ$owe+ +rTo-{AMw{vgzX#P!9p!}0yp?_0((A!+Gi<8@j1mH(!M6&@;-q&tKasXxoi@p7d4yxtTw?kq57bK6Q|uU +fIMEX^1}Vv6tLB!)|10-o)0prc>n+a000000RI300000000(kqWMyS-a{vhfMe3tp+xFv-0Xp&G?S=|} +9rRaeU`~uMrbA>C`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0000000000{{R3000000 +33g#@Wo~0>Wpe-t0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-agdg$O +P=xIp;K4#IcLF!~asU7T000000RI300000000w1pa&K~T00{y`>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7 +Lu3>C`4HI&hQW&>`ZdvNB=ndTz*X~v;Uq>`<)y^XImOPdju4Lk0000000030000000000HWMyVyb!>D& +b8~5DZf#|5bN~bb00eGtZe;)f009JZZ*64&1pxv@>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~ +v{(W1V6JV*{3!yZ{M3XW@z+pZODNcTE%yi#yB_`&o2yJC_VPs)+VE_pNMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C +`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0000000000{{R30000002WM<=Vqt7^015&{ +>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+pGEG +0000000000{{R30000003t@9}X=iS2Wo~qH015&{>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~ +v{(W1V6JV*{3!yZ{M3XW@z+pGEG0000000000{{R300000033g#@Wo~0>Wpe-t0!8Yh +U)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~asU7T +000000RI300000000w1pa&K~T00{y`>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI&hQW&>`ZdvN +B=ndTz*X~v;Uq>`<)y^XImOPdju4Lk0000000030000000000BM{I9mVQfieVPjM0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*=q!&6rQG)02XJT?*g=| +B=zREie$*y(7k2+*P~cYjR +uJC38-{*D7fZ(%hZo23R4S;p`Q9JBQllDyrZFOvPX>e?10?I5NZ-bfLFbqC#o>4E?M+l67UG^w8*<_XZ +#%uyqCt-#n(R;4&W&+>mb;*F>vukd;=m`ygb@x#_>`RmOO$AA2VPjC`}q*rQx*t> +6v={gsJ=SZlTl1iF5eQ8IAl(q%E@>So406W2x)F;WpZhBa{vedJIcU;0|?p +#+${pKVqYC0000000000{{R300000033O>~Wpi|4ZEyepNC<6ZbYWy+bYTDr0!8YhU)%QMkO4aJ;_ZeC +e;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~asox_qhH(hioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^Kn000000093000000 +000YTY;R&=Y*Tb$bY%bv0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-a +gdg$OP=xIp;K4#IcLF!~askQ+=8&Hpw3LVJZG0TWlikxJMmHEDQne=0G(X}F$%Fs^000000093000000 +000YNb8~5DZf#|5baMa-0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-a +gdg$OP=xIp;K4#IcLF!~asje_AWW3G;?XQ~tKI=u-8a=qROrukTtPZ4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW +@z+pC`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0XGgC8a;P^ +F9!TQys`YZF3(w8EA1?b(;%Z(R5QEQf&c&j000000RI3000000019PzbY*UHX>V?G015&{>Z4!V_T!KN +I`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+p&VRUJ4ZU6)V00eGt +Ze;)f009JZZ*64&1pxv@>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW +@z+pn8fQnYaJ?>kL6XG(3esa0W5QyJn#ohg24a)00000 +0093000000000YTY;R&=Y*Tb$bY%bu0daC2M$y&U#EU!@hie?UNS!6hQhW-W8INxxf{Fuzg#Z8m00000 +0RI300000001IJrb7^O8ZDnqBa{vhenIb5$QI^$V6PNW$vdMt6d#0>Rmk*`=dQ)K)k7d+w0000000000 +{{R300000033g#@Wo~0>Wpe-t0ak~ln%Z2n%R^9PBgQXo1&n-R?HR4hpUd;mfGub-hyVZp000000RI30 +0000001I?-VQzD2bZKvHa{vheI6k{n`X+XC81LasyqR+($`>jwnD57lV5q8m)(2RS0000000000{{R30 +000003T1e7Wo~n6Z*Fq{2?1%uWwlwnKfCTqC!TnpV`xO%(e*mXP$JGS1-q69d*1*6000000093000000 +000JMa&m8Sa{vhe!)N7;Jv;(oC!o$&iP#xB8s<*^%!GF?$0)U9@BFJ?0000000000{{R300000031nq< +Wo&P7WpV<0K7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgb|=zxYCD0L!x4tB5Hm3vFbl?lapNXe%X +U~*fKJ0+Y5b97;JWkF(T0kye8jk+}zMj0CEc-y32_=FESDTGMdT)8q$(GFPM`UXjDaBN9r1pxpD002NB +00T>DbOs0qc4cyNX>V=;l-_zLn%tmAe68Jly{Qj?Kss0ny)C8xzFm#1PkyMk25DwtV`Xyy2?5?}PuOqD +o>SrzbQhfr-(8uQ5TW$;8TfLT9_>sbd87aU000000093000000000PcV`ybD+9a{vheLR+L0000000000{{R3000000 +3v+dFaBO95Wo~qH00{wOJ=2M>OG#EL&$!Mwbx&PZdlOljoA7|k;k>s6q +oa5|8f~f~{V{&P5baMa+0%CAAe<9`Lptgpr6F_xjAC6(~TLj#*ewiHWCD(T2L(qY0=?Nz4Ev5gyU5%_yeyFzybaG*C -b7p070?I5NZ-bfLFbqC#o>4E?M+l67UG^w8*<_XZ#%uyqCt-#n(R;4&W&+>mb;*F>vukd;=m`ygb@x#_ ->`RmOO$l^ma&2jDVQg~%3IZTkC#?5~OapN(_Fs6GvFQy{P|gRa2*}s1Y~I%9#i;{(leIk>g)RqK0VQ|M -wn6X+txo3vSYd;;z)HQ~0$c(hS0}9Zh)e@b7^w|AXg`>_lQgbaV_>=c$Ts04O39g -2dD_h*R5>c*5<{j?6T%|znQ^KeoD%bg94CLCf*q;P?fLY7qq^#2NiM*3T1e7Wo~n6Z*Fq{2?8KjC#?5~ -OapN(_Fs6GvFQy{P|gRa2*}s1Y~I%9#i>)L^XdU9;lkvmMR*4bh)jz;q`~Q5Z+&x=I0QQSl+6GD00000 -00960|Nj60000MKb#7#AWpe-t0nT^OmoUfeVvhY+ARw!>`>M$upk~C-sV(3xjy;4dI{*Lx000000RR90 -{{R3000whoXk~3-0w7l>toMja192_(UwD?W=?zm*&IhOn$k(lG-qz;DsX2RKhRF9oualB}P71SaJfwx= -uHX^JIK`}#x3$o4Af`kVHyQ&~TYCSRqgWgjZ$<5FZnj -cuT6B5B6)POqpHCTrHl4#QtZa;zni70000000000{{R30000003v+dFaBO95Wo~qH00{wOJ=2M>OG#EL -&$!Mwbx&PZdlOljoA7|k;k>s6qoa5|8f~f~{V{&P5baMa+0%CAAe<9`L -ptgpr6F_xjAC6(~TLj#*ewiHWCD_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jgmDd%EKc;p -w+KsVi?D}qDSkO*B!5Mb*xG|_(S5o&00;m8KmY&$000000RR900000000000000000RR6000000019(y -XKrD1b#i5M015%()D=(>(T2L(qY0=?N_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jp9m~TI>-W|y2ahx -3nF|Vuawki#7NH?S|Q-Q!u2{b0tIPiVPjm(ZiUQ7;QU9z@vLsQUy3b9HcVYybrT0cSFYzzA^b -6`Drj_fC5M7<0km5x1u)VS{2*yf9yYl?p>|ZggdCbW&wz1OxyEb7N>_ZD9Zf0RkXbC#?5~OapN(_Fs6G -vFQy{P|gRa2*}s1Y~I%9#i^81)7t~9tEf?*r}jS36zkMYeK9}${s8)2BzjZ?kPra}XJu|>b7^w`1pxve -S0}9Zh)e@2rNlD$O59e#ogQsB77jPl+h5j^*S;F -1!-nsV`TsZ0RcP8z<~n@;VY|KA!vt$qMEp^75#kD_Tqj3WXX=Y(#Wl3#tYybrT0anNlc)Z3! -7CPHT_+Dq|&?jn_(4)LjFAF^$MA+G=`wK&FZggdCbW>?(a|Hna3IZTkC#?5~OapN(_Fs6GvFQy{P|gRa -2*}s1Y~I%9#i_RFfQB3>bs~EXcCXx(drQcb3B`Fx$)^%va$Ar)C7b~v#}{qTDnK1gUZ=~4IPtBJuMnKC -WEcQ$kD_ZvQg;gh000000000A000000000EMR;^&ZgXjGZb@cgV`T;j2yJg~GYywm# -VTK~nd#>C`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0000000000{{R30000002WM<= -Vqt7^015&{>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+p_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jHo-KZ`k;Xmr`<4sJYKN!!u{G5u+^j1 -lf!PF4>GEG0000000000{{R30000003t@9}X=iS2Wo~qH015&{>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7 -Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+p_lQgbaV_>=c$Ts04O39g2dD_h -*R5>c*5<{jHo-KZ`k;Xmr`<4sJYKN!!u{G5u+^j1lf!PF4>GEG0000000000{{R30000002XbX(Wo2!1 -00{y`>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+pa{vhfMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C`}q*r -8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0000000000{{R300000024!+`Z*p@02?9mxqhH(h -&Z4!V_T!KN -I`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+pa{vhfMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C`}q*r8?;yf@?frQ$owe+rTo-{ -AMw{vgzX#P!9p!}0yp?_0000000000{{R300000024!+`Z*p@02?9mxqhH(hNn`*70ssVVZ*FA(00035b8l^B00jX8Me3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C -`}q*rYXqYdo~D%m7H6OD0<^0n_2##VWXRdjy=DB@qgYOj2y$g{b!l>CWCF@89&dx0-7pM3Z=O*v*GCA9 -fL-<|HrZsA`NnJlR3~AEBGG%U@MZ$v=XJ?|;InIPy66cFfOYp#JM2r7_Du+Fb!>ELaBO7)$}AplgPGkh -3_fq3Q7_j=2#kPT_9!;lWR>~GYywm#VTK~nd#>Z4!V_T!KNI`QJ|h6;Zj -^jB$MPK+?7Lu3>C`4HJt76^nC$%1sKzB<;EQA|)S-x88IWKN#S$#@T&w`gPtX>Mp`a%psP00;p)%D{mG -2;nQMTOnwNgyXhzrB~SH04;UKo5i(1Vxw^Y00000000300000000009bZKp6b97;CZ~y>E2yJC_VPs)+ -VE_sOMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!} -0yp?_0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*=q!&6rQG)02XJT?*g=|B=zREie$*y(7k2+ -*P~cYjQ{`u000000RI300000001IbqZ(?C=Q*>c;WdI5SMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C -`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0m=yGke?j1l!xqXd>q7+-P0pRHy9#PwIC -`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0ZXaKh^f@$D{A?t{IfX>#}PNp!L%7{0GY9x -pq!KXGXMYp000000RI3000000010+sY-Mg^X=QT&3IavyqhH(hb7^w{b?qhoJW!8=sKG~^&Ni^C7tcO}co=3CQC(GPVoWSC3v_Z} -ZgXjLX>V?G015&{>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+p< -?Hl01LM?X!H~4Y^Hx3&bJ$HXE2K+s|vHZ6#&ske5?JSDZAfr}PGrQJ;0000000000{{R30000003T1e7 -Wo~n6Z*Fq{3IavyqhH(hD`aAk5~bZKvH00aU61a5C`WdHyG0R(ezZDjxj0RlzpqhH(hC`}q*r35LOoBKkGaY9#cS7Qj{WgyAGcS>>g~&^g7bS0}9Zh)e@p#+${pKVqYC33O>~Wpi|4ZEyepNC<6ZbYWy+bYTDq0lk5UVp0y6#Opn49V(cQc;WdI2QadI6-(bd|-i#!&GYaF>qoh8ar -da{vheR)?jU+FZ2DLr`QR#xHIKjC^A48Li8o -%k$8HEod=_0000000000{{R30000003v_Z}ZgXjLX>V?G00{v&KD$)QXhhr5^*YH=BF-=c -yOsxg-v9sr000000RI300000000w1pa&K~T00{xZXXT7NJOW`Spw3o_*cmz+=1%_1gm*5-D79nn{HtC7 -00000000300000000009WMy_`Y;SO7asnV%C#?5~OapN(_Fs6GvFQy{P|gRa2*}s1Y~I%9#i_RFfQB3> -bs~EXcCXx(drQcb3B`Fx$)^%va$Ar)C7cFHZE$Q!WCZ~L2LJ#-AOHhPX>#x3$o4Af`kVHyQ&~TYC -SRqgV00000000300000000008b7N>_ZDDj_00{yhS0}9Zh)e@ite$I%(jAWg00000000300000000006X=!b6Y;yn!0fbj(2M`|< -m3T|4oDcSEr%ah$$XqR+hQ$77qvA$o%>V!Z000000RI300000001I<Z4!V_T!KNI`QJ|h6;Zj -^jB$MPK+?7Lu3>C`4HLtfv$so3kRF1PV2}fOp_vjQ6FdFHId|lr&gK9B00000 -0096000000000VeX=iR>bairNa{vkf;?xyT5z&Ua+M@}mOiDpYxh>^^GknUxTJ!XL#OUcE0frb5ENEw7 -&f?o%+)B!ZpG}K!%4G?I4vp$|ttu*CMF0Q*000000RI300000000>QQWNBt;WpV=p2w`G#baG*1bN~o% -c4cyMX=G&q1!ie(VQl{xPGN0jWJYOaY-B-mb7^O8ZDnqBRC#b^1_J_VWC9>pC#?5~OapN(_Fs6GvFQy{ -P|gRa2*}s1Y~I%9#i@t>;$>KfZ0H=mhJ>?uVC`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_2y$g}WpZ|9WCD5v -9p7nv%krpqNFdAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jWOW`w -sTH9-LlJ`2|Ay5Z(?oEikl{+~pis;@Q*TJ#1a4t%WdcR&qhH(he1kloHngE|MP08BSqsWn@NaWo%?eY;R&=Y*Tb$ -bY)a|aAgJq0%>FdAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{j)$WoGNrZ4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+p< +?Hl01LM?X!H~4Z0a%FR6a&~280(t`--)Viz@~C%8KNS}Z0aQ3s^SOqbBwN-D{wl@OChzJK4+YqPF=12x +aaxrgbrDxyH3K7!h3DM#@+#URqY +Cg1WtfjX<-_MW+H5~UY4oBgb0bsj>g6`?#s5rWnKhSeO?L~x^!;Y#eFP|P}0Z%Ez*ZeeX@0!8YhU)%QM +kO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~atLx|b7gXN +Wn=<+10COKearHwcS=7M7YzYaI8*bvhMOc?)(rkC#nUG5>JtwI*nu%&Q~z;Vl^%5wS6(#;{6ajG64wDP +k{-($PGN0jWJYOaY-C4lZ(?C=Q*>c;WmI`^Wd;KRX=DO>K7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4 +oBgcS?vf5kh_h+&YE#h%O8d1V_{UOl9{V;uR#^q%JtwI*nu%&Q~z;Vl^%5wS6(#;{6ajG64wDPk{-(vPGN0jWJYOaY-CMk +bYWC^aAgJq0%>Fddp?5NXDLVVImIB-z9!%DK7l%`-}aulY!amxHJkmcb>vO>-_DBy8`Vb0jGrW9$=2qS +MXvL3He1kloHngE|MP05>8=lWn@NaWo%?kWprUwd2nS00|IGe0w7l>toMja192_( -UwD?W=?zm*&IhOn$k(lG-qz;DsdeN{_}|Wp0vpvv$c&#PW69R$ltr%da5t5w^x+8!q6BVXZDj&Q>Z4!V -_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1V6JV*{3!yZ{M3XW@z+pFdAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c -*5<{jG*S<)6P6lYy(#<=BR_>s@(?%#f7ArN-=Rj?7Ns(11a4t%WdcR&qhH(he1kloHngE|MP06;5GoWn@NaWo%?t -VQgh?V|i40aAgJq0%>FdAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jM(yUq2ps*m=2xUDT;RqC -gn#@WzFu~@adfH5^@&-|1a4t%WdcR&qhH(he1kloHngE|MP04o+chWn@-ia%o|1bagle0|IGe00035ZeeX@0!8Yh -U)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*$IZhiz50p(P||0m=?fQ^Mv6fMp@;h#Lzj#&aRFSj|g&Q -b7gXNWn=<+10COKearHwcS=7M7YzYaI8*bvhMOc?)(rkC#nUG5>JtwI*nu%&Q~z;Vl^%5wS6(#;{6ajG -64wDPk{-(nPj_x*WJzXWV`T&e00Uuec>n+a0S0nuXJ~YD0000224QV)b#8P30009AVQzUuVRT^t000CD -VQzUrbaY{3XaE2J1q5VabYTDm0RlzpqhH(hioJ -pYH;+t0eX2w~A!Q+0eaZ{MVycPK^psbz)a(bZ%vHa|8ka1ax?5WB>&L0`+VYVk7oBr%DNv+($;q`HHK! -gIHa)*%m(-e#9sm3ZsHT^UK%K(4i9Ajp1M~R@C@!4#dQE#lUD;OiKi1RsjNZcmM?f0`+VYVk7oBr%DNv -+($;q`HHK!gIHa)*%m(-e#9sm3dMUNn!oosZgNI|twmNZeC(lYZa*g7-2eQ3Yy;-pL1po(RWoBV@Y;*ts009Pc +1=xWxVN?HcT9qDk5m#O{2>e1kloHngE|MP07*1hrWn@NaWo%?ra$#@6CZd7@2Wd;KRX=DO>K7!h3 +DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgabQV*^ZmKt8YDf|&5KZQ>65I6*X)C9iYp+?yjr7~y)ZeeX@ +0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~ +atLx|b7gXNWn=<+10COKearHwcS=7M7YzYaI8*bvhMOc?)(rkC#nUG5>JtwI*nu%&Q~z;Vl^%5wS6(#; +{6ajG64wDPk{-(yPGN0jWJYOaY-CnpY-Mg^c~p6DWd;KRX=DO>K7!h3DM#@+#URqYCg1WtfjX<-_MW+H +5~UY4oBgat?dHP>9R0ZFSEMRj;Km4qfBYZ5UUs>0bg9bqiCNABZeeX@0!8YhU)%QMkO4aJ;_ZeCe;xE! +X<$x_Fs4If6Z`oP*&DQ20rFt3ZOHs70;T-agdg$OP=xIp;K4#IcLF!~atLx|b7gXNWn=<+10COKearHw +cS=7M7YzYaI8*bvhMOc?)(rkC#nUG5>JtwI*nu%&Q~z;Vl^%5wS6(#;{6ajG64wDPk{-(rPGN0jWL9Bv +X<=@3bvOnC0%>Fb009JUVQpmsMe3tp+xFv-0Xp&G?S=|}9rRaeU`~uMrbA>C`}q*r35LOoBKkGaY9#cS +7Qj{WgyAGcS>>g~&^g7&L0`+VYVk7oBr%DNv ++($;q`HHK!gIHa)*%m(-e#9sm3ZsHT^UK%K(4i9Ajp1M~R@C@!4#dQE#lUD;OiKi1RsjNZcmM?f0`+VY +Vk7oBr%DNv+($;q`HHK!gIHa)*%m(-e#9sm3dMUNn!oosZgNI|twmNZeC(lYZa*g7-2eQ3Yy;-pLpZg6#U0%CAAe<9`Lptgpr6F_xjAC6(~TLj#*ewiHf`^rCgHqw;r~cW`-QaCLM7VsJHo +A?4$swuZp1Wc+9AOf`(TIbyKWjTy4WkGaM+ZSSEb;k|42*wg~2q@3^Lq|9zft}OB~jx>)hO73S(hx +V^4K-aCLM7VsJHoA?4$swuZp1Wc+9AOf`(TIbyKWjTy4WkGaM+ZSSEb;k|42*wg~2q@3^Lq|9zft} +OB~jx>)hO73S(hxV?$_RZf9izVsJHoA?4$swuZp1Wc+9AOf`(TIbyKWjTy4WkGaM+ZSSEb;k|42*w +g~2q@3^Lq|9zft}OB~jx>)hO72UB%$aBN9r1pxpD002NB00~odaByr%bY*P>1po(RWoBV@Y;*ts009Pc d2nS;ZvX`W0006J2y}UHWlmvjWdH>M0!8YhU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*;5t>gcQkw bf~^M){{|8P%hsRk~m~ep32F151Y4WWD*HxX=Q9=PGN0j00jX8Me3tp+xFv-0Xp&G?S=|}9rRaeU`~uM rbA>C`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_6AN}>a%o|1bWUMyWdH>M0!8YhU)%QM @@ -284,19 +273,19 @@ VQ>Wj015$yz}|oy`cC#6Uw2{wE+Sw~);*uMH+9Bf@aCY-RuiZDn*}0S0GmZ(?C=0tIh(Ze?Tx 2XWo~161PWnub7^O8ZDnqB1qWwkZe??6a|Q}@a$#@6CZU+fvcywiMb7^mG2nl6)V`Xr3X>V=` 3R87(aBO95Wo~o^1PNnrZggdCbV+0Z2AHk4+Bm{3x%H=p>4!*u&n~Wpi|4 -ZEyepNC#tbWnpx0asnV%C#?5~OapN(_Fs6GvFQy{P|gRa2*}s1Y~I%9#i_RFfQB3>bs~EXcCXx(drQcb +ZEyepNC#tbWnpx0asqokg4$;(NAWquAkw}j-|{|zI;-FIp1Euir581u{j9d=fQB3>bs~EXcCXx(drQcb 3B`Fx$)^%va$Ar)C7cUkZfdKHyBH|__hx_vscRWAu^w2r{b^x;wDWyGXd29 kG60)seH8)H{-R`;$q)jqasX>@6CZb@cgV`T;j 2yJg~GYywm#VTK~nd#>C`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_ 0000000000{{R30000002WM<=Vqt7^015&{>Z4!V_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HI~v{(W1 -V6JV*{3!yZ{M3XW@z+p_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jHo-KZ +V6JV*{3!yZ{M3XW@z+pGEG0000000000{{R300000025D|^b#!w83IavyqhH(ha{vhfMe3tp+xFv-0Xp&G ?S=|}9rRaeU`~uMrbA>C`}q*r8?;yf@?frQ$owe+rTo-{AMw{vgzX#P!9p!}0yp?_0000000000{{R30 0000024!+`Z*p@02?9mxqhH(huJC38-{*D7fZ(%hZo23R4S;p`Q9JBQllDyoR%LQdZvz4Xb}#?}b}<1BS7~%^Wpi^vb#7#AWd;HY -aCKr=X>@L7b8`Y9S0}9Zh)e@zVQyn+Z*pa1LUnFrY-Mu+hzwODL;*@eYE_8FVm19wjO(ZbIvDI)B0PALl`~a8 +aCKr=X>@L7b8`ZFK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgb+wrKJIUBJXnP(l%Y$cDDuY1Bm# +?@QxYCjWldxIc>zVQyn+Z*pa1LUnFrY-Mu+MB9U ^ ..0xff [Byte]} -@mnemonic(baby-infant-cake) -data AssignIface : ownedState OwnedIface +@mnemonic(optic-hippie-isabel) +data AssignIface : stateTy StrictTypes.SemId? + , attach Std.Bool? , public Std.Bool , required Std.Bool , multiple Std.Bool -@mnemonic(scoop-deluxe-action) +@mnemonic(prague-peru-under) data ClientBundleOpretProof : mpcProof CommitVerify.MerkleProof , dbcProof BPCore.OpretProof , bundle RGBCommit.TransitionBundle -@mnemonic(fame-iris-habitat) +@mnemonic(baron-liberal-burger) data ClientBundleTapretProof : mpcProof CommitVerify.MerkleProof , dbcProof BPCore.TapretProof , bundle RGBCommit.TransitionBundle -@mnemonic(tango-hotel-jamaica) +@mnemonic(jordan-episode-duet) data Consignmentfalse : version ContainerVer , transfer Std.Bool , terminals {RGBCommit.BundleId -> RGBCommit.XChainSecretSeal} @@ -201,7 +182,7 @@ data Consignmentfalse : version ContainerVer , attachments {RGBCommit.AttachId -> [Byte ^ ..0xffffff]} , signatures {ContentId -> ^ ..0xff ContentSigs} -@mnemonic(postage-canary-oxygen) +@mnemonic(gustav-people-message) data Consignmenttrue : version ContainerVer , transfer Std.Bool , terminals {RGBCommit.BundleId -> RGBCommit.XChainSecretSeal} @@ -279,7 +260,7 @@ data Iface : version VerNo @mnemonic(nova-cola-carbon) data IfaceId : [Byte ^ 32] -@mnemonic(chris-earth-pony) +@mnemonic(sphere-emotion-east) data IfaceImpl : version VerNo , schemaId RGBCommit.SchemaId , ifaceId IfaceId @@ -292,11 +273,12 @@ data IfaceImpl : version VerNo , extensions {NamedFieldExtensionType ^ ..0xff} , errors {NamedVariantu8 ^ ..0xff} , developer RGBCommit.Identity + , stateAbi StateAbi @mnemonic(seminar-data-table) data ImplId : [Byte ^ 32] -@mnemonic(sultan-dexter-lotus) +@mnemonic(polka-neptune-star) data Kit : version ContainerVer , ifaces {Iface ^ ..0xff} , schemata {RGBCommit.Schema ^ ..0xff} @@ -345,14 +327,6 @@ data NamedVariantu8 : id U8 , name StrictTypes.VariantName , reserved CommitVerify.ReservedBytes4 -@mnemonic(delphi-athlete-fresh) -data OwnedIface : any () - | rights () - | amount () - | anyData () - | anyAttach () - | data StrictTypes.SemId - @mnemonic(paper-visa-storm) data PubWitness : txid Bitcoin.Txid | tx Bitcoin.Tx @@ -360,6 +334,12 @@ data PubWitness : txid Bitcoin.Txid @mnemonic(insect-cello-avalon) data SigBlob : [Byte ^ 1..0x1000] +@mnemonic(thermos-demo-fragile) +data StateAbi : regInput AluVM.LibSite + , regOutput AluVM.LibSite + , calcOutput AluVM.LibSite + , calcChange AluVM.LibSite + @mnemonic(pilot-claudia-minute) data SupplId : [Byte ^ 32] diff --git a/stl/RGBStorage@0.11.0.sta b/stl/RGBStorage@0.11.0.sta index 3a12b1b6..f87233bf 100644 --- a/stl/RGBStorage@0.11.0.sta +++ b/stl/RGBStorage@0.11.0.sta @@ -1,24 +1,24 @@ -----BEGIN STRICT TYPE LIB----- -Id: stl:mG$H7b6I-$T8qp18-07PSNeA-rbEBNS5-$J5X4y0-1vPxRWg#channel-vortex-bandit +Id: stl:dYzM3Ct9-SJ8PljY-C!6hB6y-VlWvDE7-DAtNg3y-zanf6hE#media-fresh-cadet Name: RGBStorage Dependencies: - RGBCommit#harvest-person-orion, - RGBStd#hair-magnum-helena, + RGBLogic#leonid-melody-quick, StrictTypes#century-comrade-chess, BPCore#austin-story-retro, AluVM#congo-archive-folio, CommitVerify#miller-pancake-elastic, - RGBLogic#import-boxer-seminar, + RGBCommit#trident-rover-tape, Std#ralph-blue-lucky, + RGBStd#mango-inside-shelf, Bitcoin#signal-color-cipher -Check-SHA256: 1b751fa1bbeea231625cc17129d356fefecb85e0974f343cadf022d6c227ad17 +Check-SHA256: 9253c34c5b44ddbc699161987833ea989bcdcd22aa105c8cf57fbdc138fdbcb6 -3Q|WxQ*>`~VP|CtAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{j2~tNwLvL+uX>=wP0_2znD++Ak -!AD4^=04ZLvBczwX;cPMM?zC{WJT(uU)%QMkO4aJ;_ZeCe;xE!X<$x_Fs4If6Z`oP*$Y#2 -a%p39RC#b^b5;}9*VKn|nRBmPlPrrd^EP>$AHP6|FsuXsI;G3ONCrYsLvM0rVsJHoA?4$swuZp1Wc+9A -Of`(TIbyKWjTy4WkGaM+1wm|eR!w>X9p7nv%krpqN@X!nKLI&Lh~GYywm#15`~VP|CtE%Dq(^gpz7jp7pJ!qRo6KcERC_=qjv!(mxp;l`5z2vSEvOmAmtV@2wtU)%QMkO4aJ +;_ZeCe;xE!X<$x_Fs4If6Z`oP*$Y#2a%p39RC#b^b5;}9*VKn|nRBmPlPrrd^EP>$AHP6|FsuXsI;G3O +NCrYsLvM0rVsJHoA?4$swuZp1Wc+9AOf`(TIbyKWjTy4WkGaM+1wm|eR!w>X9p7nv%krpqN4E?M+l67UG^w8*<_XZ#%uyqCj(P-WZerAG%@R7@(N8Kc{}IJy8K~t5|i6P +)~xSaq-}XN{034-LQ`~P^=uPjBlbC`N(qzPM@Gr{imSMTSY5T*7C#t%#3&jH2SRCdV{d702?arHbyiIV 01^bJwgM1*ibOBDT%6aZ|SrJerP1pIOD57`7Ol|-ogQ6Pjg~y>s-v>!^VNPLfWv4Jz0xkJm$nc4y MWR2J-cc#Q6SofWC)gp7L6!Sc3I$AQVo7AP4Jk3r!|EoW{Zi$060oMN(jLzPuNboiNpoRS @@ -51,173 +51,149 @@ H8-hI70Bv^+*0?ef%0)>Q3WPbltNdpi4*91)SI!>2Tf&jb75y?IG#g>Clv)aMjKgwAH@`bu1x<7g|G$} _h5K%L=laq&yA1JoJ^{7>oKLkF4~iax8KK|47hp@Qe|^xa&~28LV0v$b1}=fEj#9D^K)f#Cf|Xn@L3mU 0Z2&n-dr?jcD1Ll0RawDWpib6c4cHjd30rSGT61bmh)A>-9G+(AKhLw+s!eDmlO2>&}_PPHjCBJR|r&c Wo1rpWM%K_6AuO0fiYoI|8ZKC9(55{UNs2(LOhfb*8wh)9?K3=Wpib6c4cHjd30rSH2#7XN#A(BKKz&v -`r;e6DUv<<*U}c>;b184%wsNMHUptBVZ#B!U% +`r;e6DUv<<*U}c>CH184%wsNMHUptBVZ#B!U% rHo-i1kG~VoNp!e_~i}U4@G!%Wo~n6Z*Eg#Xk~3-1ACLTJsO2B2U!6ncg?mz@CdC==Kxq?gSEg)z2E{| -2tsvkWNc+gWC^x^65s1c;WeUUgB8EM+V1n+T -F3m?Yd1DC`X&GvUv9(-1>WQHGZVX3kZ(?C=R$**)WpflIJdRMsrjHBJ^EIe4enz&iEACnc`NWk%>en!w -doT%2WprUyVQh6}6`5yb%eAXO2UPPRaj@((`=>9Tsh)f38uw_!yYu^q2uW^mb#zT(a2QC{)5Kh{xQ8## -XkXX-V5JAC*Swe0D}EgBwY$m<1r0}KZe??6b5mnzWo=<3S5nwzfbg8kY9lvP5=0XL2PtPVR>b8F;iu9B}H_;!MSfIY{o4njA(e*y9jN*vODbSxwYq{gu+hp5Knh*Wn@!yVRU6vV`yb< -VJRgJ2Em!ld>cVuZ*8Se%j3y;5n>eohpw0DA7$}d%n3nrb7gc?VP|tLvZekPz%WEGnBZKS8(M7E9_@Aw -VcyGtCevi|7U8=IR&Qx!Q*>c;Wip;tQ3m-<6)UHjqig^*m4co5us7ukl*0UQzs7w8g$YDqbYW9;VRU6Q -QV*^ZmKt8YDf|&5KZQ>65I6*X)C9iYp+?yjr7~y^RB~Z%b7^#GZ*Ek1aAh{ZG@<&SffJ|QFn~N>u=2wF -+7z(Wqt=tdZk`V^s(A}fV`Fu4a%FB~WpgMdwWnpYocu;h5IeTD+$oD|6lahT-3bSoIq=nQXM0|*v-OPCjO=V)bO0J^ce(PcW1p-OKH=(^)qT -gDk?v){Y2{bs0f(b7^O8ZDnqBb3$xsZe&wsVQf@*P;_!e?dHP>9R0ZFSEMRj;Km4qfBYZ5UUs>0bg9bq -iCNAIR$**qZew{=d2nS&y&7&8`-VFfe10WfHD}v`L+>hHy6d9F3e5?wo>3YSP-SFga&u*FLvL+uX>@I6 -Zgfg$dIyj=yj0m~TwLF91B-Lz;+I~gZmLfZ*F5{VQgh&Ms;pyX<}?;QxVNWsw`2k$dAVY -YJsYG;e2<6^ZE|08NgypNP%NA5%VQKM}UDECiLhAbd;J)AwhFi#4d2nT9L349yXKr&s -Y-w&}Q)OXnRCsA*T90!HB~2q+D9Z7_cLRiBQrIV5qn*4?Y6;!|pLWveA3<|-X=iRyWp-s@Y-MCbVRT_a -Y-w&}Q)OXnRCsA*Vd@w5&2+699UCMSB2$w)@^&J+aUCZtmJ634`nl9<7(sJ$X=iS2Wo~qHLTqVnWK(5f -Y*ct@WMp+7La7y@JVOzJ)&GXo9MeQ_qmbcB?4VH0I#X{*-VH@~bY*UHX>V>+d2nTIM8@PY!h`6Z9%SYt5l1;p48RB~Z%b7^#GZ*Eg#Xk~3-dBoUB2y8Zom7+;NN8Xgkb3WeV -)QDb*=NiflQ)(Iz225djWpXilvNdf$cEfHQ12?LRftc&;5JY%0?GSH0jXJ{5?wvjwRC#b^WI=OtX=iS8 -LTqVnWK(5fY*ctqbaH_n=a&wUzgWZ$SVL%GX>LMnX>MdwWnpYo -cxhyWaSf9!PV~dK2uo>;u!nFdemP_$e?^hl+JkM;eY!XZL3DIsV`xcag}C@DyY!@{4YR*LMYs=?Zg_*k -tx|21^lzg9sBTBv4nk~cZe(e0XGURTbZ>Hp{^Dg=h-~N_zJ`Red1EINWrM}GXaQb}6c#qIM2EQ!L349y -XKrm}Zgf<6aAk>WSS8KIkY89@$6%;X7qJ(R#b4x^L3+^xAn+qc8}SNQLug@XZd7<_WRJVT=tr7P^xB4~9 -n`Dx!RtcK)nwJGnaBp>VlfaZ*5|&qoaMx&cZSO)Ho!_*yjLvyQo1^f$X+6j;96@t)X=iR$Z)s#xbYXO5 -LTqVnWK(5fY*ct@WRz0V+XJhss8OG%_CC-Q>(otsF+cqN0Qy}ddQ=3E5C~IaXk~3-No1AC=6W7=Vqesj -RYGc!>wZFzp>JB4@xD;^wu&SY_r(NHa7kpJ2rNlD$O59e#ogQsB77jPl+h5j^*S;NLvL<$ -a$#e1No1ysFp)<~$~wYgjK`HkjV#@&#T1_fGnK3MJXK)_7bXoxb#7;AVr*qobYXO5siJyUlgOLOB};96 -cGdSG6&iv=7PD~jruGj4o;;a=21#ykb#!yDjhE2@R4ADY@XOb3WHJm&VktwD1&R~J8Qi15W{8UrRB~Z% -b7^#GZ*D?$Ze(m_w&;L{94K`ndk%K5+?9Jv$dw7jc}U5p5@2#$kUJ%u2uWmRZggpMdB|&mdkb29#*qXh -a^)f?kI>J>8dqqbOFybHKpQ-MBMCulbWCA+WpXjekD95&21^?K{bw7Oyejxis%MV9vZ(?C=Q*>c;WmI`^W!4yF%LYxT^jDrckDVwO1AtjoG6an*A`7gZ+wE6AH40R6VQzD2bZKvH -*1R*Z!FE#!-}0MzvBUkD_A@LX?C3dsb3FQUOt}RYB0+O=X=iRyWp-s@Y-MCYbaY{3XhLjhZe&wsVQf@* -P;_$In^6;37FKqUhx?i3R+Mr!fY&(;2BFL(m@EZk_srD;MrL-}#pxZ$?Eb+fZ@!;9xB`-n7hgEflW({{ -JNKm>5Mos!L349yXKqquc4c8~Wn@-iY;|QqY-w&}Q)OXnRCrKya@&ep8iEuMbtv-qj6g$b#7A9pc!|f` -I$jaRzSe2A1Q1w5Xklq?Q)OdvWpqv&8b0-V>p(oz$%022vTKaWo2z;WalM|{+CCYqok=CI6O*0D2Q5~XK8~xVetWFewK9hZ4Odpc4c8~ -Wn@8gbYWv??6T%|znQ^KeoD%bg94CLCf*q;P?fLY7qq^#2NiM*2S;UYWpinB^?FS>S$_F2)vN@Mb6UJ- -F(lri_dqerx4lR4>iBsz2u)>lVPs)+Vfpl|2xhK9cV^W63=w?=$`$i`X@y)HBPPGtNLug@XZcue%S7~%^Wpi`yAASLvLGVedrqOkAVG6;X=iRyWp-s@ -Y-MCtVQh6}LTqVnWK(5fY*ct@WC&76LQHRGX=4HaT-**L6)$-r+lRyXoI{GIo*U3CNI7Emc=xo*$N+#6 -3Rh`#Ze??GP;YZ`yF$nqQ(ZC7jQ{zx3L?h_$J($?&iPIm+b{NqZ<^r>S7~%^Wpi^+a%2WlM?zC{WGVm# -J4=$RltJLk?Nfj|sXiSdmgaJi@wPyW+dHeUQG($LP<3KgX>@L7b8`lmt+(1Z!Y#S=r-tc=NPf>PeW=$` -IKP*ssSB}HE2RoUZ*FvDZgf&*W+BHHZO|$}9Zg=R%ZE7et&pz}oUddU0B(<>YerIc3kOqaXF_amVlhkK -9|TAhYfrNblQVQ`LpZXKteHopy#|_NJkG`K5e`9aZf|s9bZKvHPGN0jHx3&bJ$HXE2K+s|vHZ6#&ske5 -?JSDZAfr}PGrQJ;4^(ntZgXjLX>V>xW?^GxI6k{n`X+XC81LasyqR+($`>jwnD57lV5q8m)(2RS7*1hr -Wn@NaWo%?ra$#@6CZd7@2WjJdtcwu66snXR_9Zdb&#xLPSG6d3U8q**F>Pta$W)4MobY*UHX>V>x -W?^GxIma44eh@g%x4xWoee18jkej%UZIDDtP|$FhF<2o`1xaRMV`V$az<~n@;VY|KA!vt$qM -Ep^75#kD_Tqj3jGW?^GxNn}22@%59@e*l9;LQD7pr}6`4EeCo&xZzHANbCVxZ$AuHVQgh?V|httVPj=J -w@A-6`Vp=cnK>{7wQSPJQFX$PK`>V6xnyyv_mEW!L2hnubYXO9Z*Fr-smO?_)Z;5^`KSD|ISj`UH_gGc -8EgQVv6`Tqlln6YL349yXKqPmVPj=XbV6p4OMBubAg=+DGK(xA?XXJF{2H^dT~zWT)b=0OBT1J2MDVb#QQO -Q*~lsKY4$``7oZ);noRy3n6DO2)Q4;H@bN5MlNj7(#BUDPjz%~b#y^6%<dWpinBNoHYVWq36o>AP`=z3=Ru;NRp0 -56I1tGJoS+I(F^t&c0kHT?s*MV`y)3Q)P67S7rwg9}|^$ORAg?_G_n1nO(?SEuMzN{%51&MrF+jNoHYV -Wl3#tY=#&RENEw7&f?o%+)B!ZpG}K!%4G?I4vp$|ttu*CMGHf3ZggdCbW>?(bB4g)fE@Zx_8VV!VgW89 -U{2OOpSL%4#$e>_yXHjFISEsBaByr%bY*Rn9PeeuXILaAA3^JIKdZ3ic!M@6PJV67bl-3#Cg!RLO>bmr -W@%+|nIb5$QI^$V6PNW$vdMt6d#0>Rmk*`=dQ)K)k7d+w7*1hrWn@NaWo%?Yb8~5DZf#|5bX0k8Wuo9& -)X}ib9i^%gOs*8bY}uR&S59aNAMwsm_ykY{pbAuSb#rt~Wp-t3y@7~gQVy8J>pg27DwvPuRhrP3QWOC! -bDKQy2TX#&5>8=lWn@NaWo%?kWprUwd2nUJXXT7NJOW`Spw3o_*cmz+=1%_1gm*5-D79nn{HtCLPGN0j -WL9BvX<=@3bvVaOk0BBjil877-n>SP^xWIoCC77|*ORF1g-x>(>`)0$a93$`Ze??G$6skVRwOM6wz9dS -Yg6i3-rmX0uFE(Y8AEY@srN=83sYrbY*%S?Ze??G$_VC=pB%K5hwN>99K@5|(<4SV7$Q=&CebuM;tt7# -3rB2kVqt7aW?^Gx(swU)=eHZcWUx8U##PM;a30K-=Jl8VtAf?Zi=Hx63{zuhWo=T!Ej;9TxQjc0+10Fg2)p -3Qu=#Wn@WaVPj?D)D=(>(T2L(qY0=?Nc;Wdl=mWC;K#gwc#^4#qsMUl{*1zNe>I^CwqAYJB+ZKALhJOg5Ma -L2PhnVMAeXb4b1;7b@t4MVjY>G@u4Q3HlB(d+LiLJm-R=h;`?dxDG*cV`*tna%paKVPb4$VTK~nd#>-Vi}-aA;vuZDDL|OmAdib7%`wbaH89bX0k8WpfVz35LOoBKkGa -Y9#cS7Qj{WgyAGcS>>g~&^g7Kv@4tY;$BCg=lGO40qbyjMBe4%@A^HhWa%pX8bZK^FG5w(M*PErP -Q*K8));4q9;G_%)IzXn}g(wG03t}BM5{Lay5>;+)VQpn(MrmbiWOGwxZAoNn1fvw5rj-B|XP@r^w5ufb=C_Ju$l1`n -W&GEpSWb-vQ)O*QWPQm(C)8p9*(R2SB=5|9lKCV3N0b-?Ol>0MdKRd5P6t+Da%o|1bb-?>B-g{}GTFmo -{mAr>kexq=D7-RGP2^0W;fb3W1_o1UdTDNFlG6hDK5~2WhJ*PG7zYWLxz$!}&%4AY&2YWlsz$Eb5Kduj -Wn@NaWo%?~Q)O*QWS1d>s?i)zLD2{^84?*=6Qgx+ -2Ybs0Lm?xkSqB0NLAl2~i-ZdPG(X<=@3b5mt)No4(ju7iFH2b-u)>&PZdlOljoA7|k;k>s6qoa5|8f~g8r -d2nS@d2@7SZ3X}hLvL<$a$#e1Np56icm@ItaCKsAX=6`tZ*_EY00{yhS0}9Zh)e@5%bR49t5yk`^qQ9d0000000030|Nj600000EZ*_EV -Z)t9HPjGK_baMa-0w7l>toMja192_(UwD?W=?zm*&IhOn$k(lG-qz;DsnKT_y+ac4_6daU{%%bk3j+fu -`A*2Y1(Gbp$uTFEssITBAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jlMuXsu{2tXFT+?;?hj39 -&>gq>HOrf1lB-q;n)I5N0000000000|Ns90000000000000000|Ns90000005KU!mLvL<$a$#e1Q*>c; -Wd;Wbb7N>_ZDC1d0w7l>toMja192_(UwD?W=?zm*&IhOn$k(lG-qz;DsgzRF+XJhss8OG%_CC-Q>(ots -F+cqN0Qy}ddQ=3E5DH^&Zgg^CV{}Pm0w7l>toMja192_(UwD?W=?zm*&IhOn$k(lG-qz;DshAD4^=04ZLvBczwX;k#6 -*Wiap5|FEe8kw!8dbCNj+WG;-FCN910OIk;E?fWr0000000960|Nj60000SQb#7;AVr*q|00{yn6$0d# -2P+C};lr6VNhMM>59zuEq~<=?!m-5UiD^{RS{k*RP>KQ|D6@UrgHD8Pn~kr<(gaR)wpptCRljin00000 -00030|Ns9000004WMOn+00{yn6$0d#2P+C};lr6VNhMM>59zuEq~<=?!m-5UiD^_|KY4$``7oZ);noRy -3n6DO2)Q4;H@bN5MlNj7(#BT+0000000030|Ns9000006VRUq1V`u;g0wxs#KG(vr#N>%-RB36-k*iEz1m@>LhD1|b9AmK%IADG&k)euf*x}6a-2eap000000RR90{{R3001i!M -ZAWZxVqt7kbYXO51_A|ZZf|#P015&o6$0d#2P+C};lr6VNhMM>59zuEq~<=?!m-5UiD^{hV;!^nQC@YX -pR0TOwJqTsbD!F2W4d9F8pxqnXBGnjAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jGM-jZ2Kh}D -E2o;HYydTtf}Q!WH{}bI!u)W*#(e~Z0000000000|NsC0000001#D?;X>toMja192_(UwD?W=?zm*&IhOn$k(lG-qz;Dsg=m)dLDIRU(}XWLTZugenOC; -Z(5k~zEJnJiX;;E#R4E#C#?5~OapN(_Fs6GvFQy{P|gRa2*}s1Y~I%9#i;{(leIk>g)RqK0VQ|Mwn6X+ -txo3vSYd;;z)HQ~0$cz90000000960{{R30000wWb#7#AWkYXnbaG*1bV+VxWq1Gz0w7l>toMja192_( -UwD?W=?zm*&IhOn$k(lG-qz;DsRMhHwLKbzE(ciwC3nrXLGTEzPUiqvVS}~6O1_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{j1ACLT -JsO2B2U!6ncg?mz@CdC==Kxq?gSEg)z2E{|00{yhS0}9Zh)e@_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jp9m~TI>-W|y2ahx3nF|V -uawki#7NH?S|Q-Q!u2{b0W8#V&bbGUt!Bq`S1yuTOW~jDcd`iI3^X_>4e9 -YQ#rfba;u!+d5tm#=h2RwFCeO0w7l>toMja192_(UwD?W=?zm*&IhOn$k(lG-qz;Dsgn@AfUz`Mi!Z}i -Qtl5;XwV(E`Zdd&WRj~^37YhpmjD0&000000RI300000000000000000RR900000000>QGZBuk%b7%$) -2y_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jlv2~%1FNg3QJ<&wKF}2F)J=Uc -Km7gx`duV?R0NO^0wxs#KG(vr#N>%-RMK}Zb?3Jmz+|vF&&E~F32+|F -mge=B|Eq%4$%~#cQ~&?~000000RI300000000wDhVPj=;015&o6$0d#2P+C};lr6VNhMM>59zuEq~<=? -!m-5UiD^_j%D{mG2;nQMTOnwNgyXhzrB~SH04;UKo5i(1Vxw^aCKUqYmH4o{!1*GOa -*TS*H2rNlD$O59e#ogQsB77jPl+h5j -^*S;FAXg`>_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{j?6T%|znQ^KeoD%bg94CLCf*q;P?fLY7qq^# -2NiM*0000000000{{R30000001#@+9aBKhy0wxs#KG(vr#N>%-R0f!> -x7s+uExGllhUte$e$Op^sMk_Bzn7+|3$axzr2q*6CKUqYmH4o{!1*GOa*TS*H_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{juZ@?{0aPfN4Did>Ze%hHN@6KP -lLd+s#TneAz-EYx0000000000|NsC0000003T1e7Wo~n6Z*Fq{3IZTkC#?5~OapN(_Fs6GvFQy{P|gRa -2*}s1Y~I%9#i^CZ=6W7=VqesjRYGc!>wZFzp>JB4@xD;^wu&SY_r(GrS0}9Zh)e@_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jiECIT&Bl;lSX#$ms8AQN7m&qYKG(vr#N>%-RL5UwIaVYs3AVDiqia*@S>E2s&92Kh -8W}@zf2sFIAOHXW000000RR90{{R3001IJsbYWv?ZDnqBa{vkgAXg`>_lQgbaV_>=c$Ts04O39g2dD_h -*R5>c*5<{jgmDd%EKc;pw+KsVi?D}qDSkO*B!5Mb*xG|_(S5o&00;m8KmY&$000000RR900000000000 -000000RR600000001I_lQgbaV_>=c$Ts04O39g2dD_h*R5>c*5<{jkGsO? -N19ILP2yc~f4%w>xYW^+v~7{W03rq(;firJ0000000000|Ns90000003UqmJWm9=`bY*PC`}q*r{eiB7ehUYis7~w1CQOqefKeZ3;Wd%uopqe!>_vj93Tb3zZggpM -X=QT&3IZTkC#?5~OapN(_Fs6GvFQy{P|gRa2*}s1Y~I%9#i_RFfQB3>bs~EXcCXx(drQcb3B`Fx$)^%v -a$Ar)C7c2#6$0d#2P+C};lr6VNhMM>59zuEq~<=?!m-5UiD^`#;91nsu+1H%suE1D6u@lRoC;S?XbB(j -&QSOSPz0a=0000000030{{R3000004Y-wV1015(Pa5aA+<>R2XhQO_4{AcS-HH^7AVzASV8M4NYxyCl9 -FjWFA`CQ2GiK9iLKbGE6DZmrA4)G`0A&^0p`%?-6VsJHoA?4$swuZp1Wc+9AOf`(TIbyKWjTy4WkGaM+ -5(KBV0uX$PL@)I=)&*`^S@`8Scoz5#{lyP)a751L0000000000|Nj60000001aoO;a{vkgCKUqYmH4o{!1*GOa*TS*H^^GknUxTJ!XL#OUcE0wxs#KG(vr#N>%-RE8K3ENEw7&f?o%+)B!ZpG}K!%4G?I4vp$|ttu*CMF0Q*00000 -0RR600000000>QGZBuk%bY%tt33q99Ze??GWpe-u0w7l>toMja192_(UwD?W=?zm*&IhOn$k(lG-qz;D -sflY?CC$c=UszhlV5m?Ru@{iVU*wrVdeH+Q@FPbX@dBEuZK_k`JKyPG=Rp7@Nbf+-FrJ*HF>i&!wTZgU -Bh_-dLdY0XT`|v$|M|2EBF6^D+OST}`A!+zFZPFTn&AKd0000000960|Nj60000SNZ*FvQVPkZ2015&i -S0}9Zh)e@2rNlD$O59e#ogQsB77jPl+h5j^*S;E -cA8SzdwhWF9dgX`>ZnjA*51^hO#z=?KV_fm3KoU?0000000000{{R3000000 +2tsvkWNc+gWE3Slj!?y>j|%qbz^!%<&Wu0B;HjDvS(4Y;;Uvd1Z1jQ)P4~huszhuS%Gw +>J36#@&i>}*{wKf47Hg5JxV=iU{?qSM`dnhb7^xaG~Qz4rf|COpMQA6DFZhcbS+pFfT9t%(h@vS@2O@K +L349yXKq4lX>MdwWnpYocu;h5G*S<)6P6lYy(#<=BR_>s@(?%#f7ArN-=Rj?7Ns(14peesZgXjLX>V>+ +d2nSm!8D=zpn(&o-7tVWUa<1Q{n`|;)uYyv!)~4rGOBqCPh(?sa&l#EV`Xzj?dHP>9R0ZFSEMRj;Km4q +fBYZ5UUs>0bg9bqiCNAIR$**qZew{=d2nS)+m9st6L>r`q08+u8T&0^adk?AUH3SUSi3+Wb21AHM{I9m +VQf=$VRU6v5zRxYEK#t?kH-RPfvS1oe0PQO`VOrdl$-fvv-}wmM{I9mVQf=$VRU6vV`ybpR6heI$}l1ygikbY*KE +2S>RllQnv!#Bdhn{LP$;qli}WS_~%;XE5$2GG`b;b8~5DZf#|5baO&%X>MdwWnpYocxhyHV>*V`yb=iRT*14O40w5C%+Pd1Z1jdmmICUpAm* +irZQ3c~xnGW`==N2!6EUgc~Rug%*0A2~%`obY(_oQ7|GShenHHQk6Kc**bJ*e3IRag>U{QO}* +5#AX=b8~5DZf#|5baO&%X>MdwWnpYocu;h5f(#9>YyC6LMnX>Mdw +WnpYocu;h5lMuXsu{2tXFT+?;?hj39&>gq>HOrf1lB-q;n)I5N1y68qb##h5j +^*S;NLvL<$a$#e1No1gfw_qjpC#e%OW}_qta$#@6CZbEf#WNc-q +Ht(`hF}jj5^Xl;{(HZPSTKb&GEytIZbS*TmyWyh~L349yXKq4lX>MdwWnpYocxhy*qIy@8$eYR~OKp92 +)%PJ48iGR>vvBgJ_74J{Jehz7Np5g;baS$EAbXV}DW}urw59q*`|HcZksRt+CA}j9C82<;s1zDhd2nT9 +L349yXKr&sY-w&}Q)OXnRCrKyaV?} +=zxYCD0L!x4tB5Hm3vFbl?lapNXe%XU~*fKJ0+Y5Nn~YibZK;X$ZLXo3tD}~kpv`i_>4e9YQ#rfba;u! ++d5tm#=h2RwFD4YLug@XZc}Ara%FT=WnpaHg=PS6VPp{$?vC--s`v@B8YHl)C#jpVFzBk!DMw8SR$**q +ZewX>bKlRYk@bh=O+>c=6@6CZuNRiI9Y!AFx9LCk8@hQXE7w+qW3^C%eTEp@#^?_H3&^*bYWy+ +bYc1yW|-Go+Jug{t-fL56H8!sY)>=$`$i`X@y)HBPPGtNLug@XZcue%S7~%^Wpi@~Qb$5eZ)a&^0svgx +4kHyWc_Q0~!}**;il?3%&@4zfV)l6Vw93c;fD#H@L7b8}E{b8@>v$QV;yG0%+u`Lqfm#|FpRuujhT +P8r)T_J?np;R;u2bZ%vHb5C+)22w{tQ*>k}00uitlB|?L;LPn)fIF!^9U_+Ia*^@2K#bcvtFTdm;R;Z7 +VpnN&Ze??G2AHk4+Bm{3x%H=p>4!*u&nHY;R&QOWz*^NEK^Ovka3nbZSF5vXHEqN2R?6nqxf9#qALeL2hnu +bYXO9Z*ERuZDltO8yY=#e=i37J-o5}w=U0FTPy7>iqjyYR#Y>))`AaIa$#@6CZb@cgV`Vr#yHxrn +c61o;;Y_@lb0o?aDlVAs$BAI5s(jW5SdbV_VQpn(MrmbiWK?otZgXjLX>V>+d2nSoYc6qMEp^75#kD_T +qj3jGW?^GxNn}22@%59@e*l9;LQD7pr}6`4EeCo&xZzHANbCVxZ$AuHVQgh?V|httVPj=Jw@A-6`Vp=c +nK>{7wQSPJQFX$PK`>V6xnyyv_mEW!L2hnubYXO9Z*Fr$2}2U%?SKESc;}_}8Q6@wJm*jqNZksOmu*x> +HAnjiNoHYVWl3#tY)o`QW|2#K;wB)k0g*C`Fwq1F!!?eFe@CD1{Hz9}!v$7la!zknhozd@T(rwWP-G*< +FKz{ld}8ext;?Uw^U#1TXfcQtPGN0jWJYOaY-CnpY-Mg^c~p6DWmd=!c)Z3!7CPHT_+Dq|&?jn_(4)Lj +FAF^$MA+G=`vysEaBN9rSoRTJ>~32(7)!VKwhueASIYDuGM{9p;;;bXCQUmt2vc=%aBNd`Vqp@I4KBh^ +1`?WeT6!q1%r17uTo3T2=}n^?e(vEz0t!KFY;R*>bZKvHV?EP}uuDl+D$lsiICW4a8e$Z2e6I7`3evG= +Yh^sO3R87(aBO95Wo~q5GKatjaO)MCM&b8PdjA-6!Qv6Orzv5BVpF^@Ux1YdQ+04~Y)NEk#AUTvyg$3{ +N++IppJQl5+tKwp$xtHBFa^7o2YcTaPGN0jWJYOaY-B}vbY*UHX>V>+d2nTMaves|)!M|1JQjy*9JxrH +CCXBK3Y-~_ZzF<=1A>JaPGN0jWJYOaY-C4lZ(?C=Q*>c;WmI`^Wp(W({yb2RgQ&qroX$3|s~68cgLoKb +6;WMPYGO<*F$_m#Ze??6b4g}lV`X=x<(>mzHseKA;9>iaucy+897BCKo})K|H41Qsl9mipV`yb?(bB4g)fE@Zx_8VV!VgW89U{2OOpSL%4#$e>_yXHjFISEsBaByr% +bY*Rn9PeeuXILaAA3^JIKdZ3ic!M@6PJV67bl-3#Cg!RLO>bmrW@%+|nIb5$QI^$V6PNW$vdMt6d#0>R +mk*`=dQ)K)k7d+w7*1hrWn@NaWo%?Yb8~5DZf#|5bX0k8Wuo9&)X}ib9i^%gOs*8bY}uR&S59aNAMwsm +_ykY{pbAuSb#rt~Wp-t3vVI^;l)2*3EOV>g0ax8O)k#$7&vslvM*4K4@C1O&3qf;pX=iRpW?^GxwYfr# +x-}I>85-$$+oWFjgbz9?gh<<5xiU@B4p`m#2vc-nbY($eX}y7nVp0y6#Opn49V(cQE2s&92Kh8W}@zf2sFIAPZAvVQg1vbZ%vHbIJ(jke?j1l!xqXd>q7+-P0pRHy9#PwISrzbQhfr +-(8uQ5TW$;8TfLT9_>sbd87qNW?^Gx;?xyT5z&Ua+M@}mOiDpYxh>^^GknUxTJ!XL#OUcE2}5sgbY*UI +No3<=9kcvVUUjCQt9$#kE#Vw>UA(Tr;j#yqcI82>cB +r>9x-Cs#sheE97?nsOaXHkb)PY;b5{Lt$`pNWLQ%D(Hkon&*Qwpawq)`VKLB>Wd>h=Ype%b?2724ncEc +X=zY$X>N33Vr*q$h9c2>uJC38-{*D7fZ(%hZo23R4S;p`Q9JBQllDynLT_(uW>|38j$F|Rkm*bpSUudI +qf?x|1Bk8zGh-IHIi*o-3_)ygXkkNPaC1&|ZI#2l$xQ-a`EhCyJoZT~T}~sI +jxz)>1`ZdvNB=ndTz*X~v;Uq>`<)y^XImOPdju4LvR$+2!VQzFzVQpm_v{(W1V6JV* +{3!yZ{M3XW@z+pX9JtzktHWiJ@1L)babHELfN$u@7k> +`Uy~SX>DnAX?A5X{h;vIo29B#Zbv)THgnzJqzni;K&ISmvLd)pN>Rl&wr9&I-v?L-&~MrmbiWK(5rNn}$N2!s^Lf^?|9I@Xg>Oi(W05|TJ%PM*ricn_PmXk-Xf +d2nS;VQpn(jMNXXYlf+hXQ9AJ%?72#_KJ5v@E-96x!ZDnLeX=Q9=b5mt)Nn~pTqZFQ| +l>ioJpYH;+t0eX2w~A!Q+0eaZ{MVycPK^aqWo=1heaS*6)M5bHCYFUH@63IY`6K;Dlo$g{Z6f4)7N~Yk +2UcNnX<=@3fzvD`*Td*C*~4P}$n=kpoj->tyfRKrOAiJKV)22*KzX>Mnd(*pTEa(nZJgZT^?2ML$C +)mClKyTm8WaJ}8CMy}crPGN0jWJYOaY-Dp&Wo=1hmm!0y(Hu`f(Fijc5*b_M4dVsY!8b|ZDhq! +3`K5rZB}7&X<=@3bC}8#qjhfwd&>tyAtR<)2LcK~xyL-@iqBUFK20Q^G*lRL(MHiY2Qv~?ZfS3BR$+2!VQzGDQ)O*QWc`7zgMJGKo2X9f$R^xB4~9n`Dx!RtcK)nwJ0o +0000000960{{R30000heb#!oVX>N2+aBp>Va{vkgdp?5NXDLVVImIB-z9!%DK7l%`-}aulY!amxHJkmc +(PtOELlW@z354$cZcQEw0|O`dPRP3jk}Sl@F(;O)00{znK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4 +oBgbl5WIk~G+K)5%bR49t5yk`^qQ9d0000000030|Nj60000000000000030|Nj60 +0000GO=WFEZ*FvQVPkYtbYXO51_TImV`ybbaG*1bV+0adp?5NXDLVVImIB-z9!%DK7l%` +-}aulY!amxHJkmcp9m~TI>-W|y2ahx3nF|Vuawki#7NH?S|Q-Q!u2{b24`$^Q-3t;lG3#LR3QZq*JLk)~ +{9$tvliNbptnXW-ZFx5QVG@xIF2Ya-5}I{ddMK{UE_TLT5AdbwO`{xs?%_iM0000000000|NsC000000 +4ozikM{I9mVQf=$VRU5%0tIVsZ+C703Ig2=5;QUEVDbu0A9*|H%ewqwa}tx=Le{MBTcmAyHvHpb9kcvV +UUjCQt9$#kE#Vwuv7J8ll0000000030|Ns9000005Y-w$2bN~PY2u)>eNp56icm@Rx +Z*W3&Ze(m_Np56icmN6ldp?5NXDLVVImIB-z9!%DK7l%`-}aulY!amxHJkmcmB{9L9(7`0)Rt93YLV-H +LXe?vTA1;^Q1`ZqBog<<0((A!+Gi<8@j1mH(!M6&@;-q&tKasXxoi@p7d4yxtOI+KwLKbzE(ciwC3nrX +LGTEzPUiqvVS}~6O1h5j^*S;EEYxz&xd)D|X2*0_E|OYH;h*YvvIyS{G&S`ex{XQ}0000000000{{R30 +000004RmF4ZE0>{Y)NipWq1Gz0((A!+Gi<8@j1mH(!M6&@;-q&tKasXxoi@p7d4yxtlNrO8iEuMbtv-q +j6g$b#7A9pc!|f`I$jaRzSe2A1ON#Fdp?5NXDLVVImIB-z9!%DK7l%`-}aulY!amxHJkmclMuXsu{2tX +FT+?;?hj39&>gq>HOrf1lB-q;n)I5N0000000000{{R30000000000000000|Ns90000002u)>eQ*>c- +Xa)@kb7N>_ZDDj_015(oK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgbmQq$W5tE;F{pQrXd&=l*` +O?@#x{Qdy?T_k!`1dtE{-3t;lG3#LR3QZq*JLk)~{9$tvliNbptnXW-ZFx5QcctZ?17J4eMOENo`;f1v +(uf>GeK($?H-j|_aE6kW0000000000{{R300000025DwtV`Xyy3Ig2=5;QUEVDbu0A9*|H%ewqwa}tx= +Le{MBTcmAyHvBuvz<~n@;VY|KA!vt$qMEp^75#kD_Tqj3V=3lcOj>tON%s+B6*|$00000000300000000007XJu|> +b7gY?3IcmRg4$;(NAWquAkw}j-|{|zI;-FIp1Euir581u{j8q|EJ-@Z0;0Ob-P{Wzd?2rs)M&&=&l*}G +;Jw22Ix+%#K7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgaOhuszhuS%Gw>J36#@&i>}*{wKf47Hg5 +JxV=iU{?qL00000000300000000005b9HcVYyb)Z-3t;lG3#LR3QZq*JLk)~{9$tvliNbptnXW-ZFx5Q +2AHk4+Bm{3x%H=p>4!*u&ntONOG#EL&$!Mwbxg)RqK0VQ|Mwn6X+ +txo3vSYd;;z)HQ~0$c)nK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgbyg|}cO^(UzlG-jhD8)*%a +i*=Phvt3dW&|$hhp0^tS0000000030|Ns900000AWq5RDZgXjGZgT(%0((A!+Gi<8@j1mH(!M6&@;-q& +tKasXxoi@p7d4yxtd+>-dLDIRU(}XWLTZugenOC;Z(5k~zEJnJiX;;E#R7Xig4$;(NAWquAkw}j-|{|z +I;-FIp1Euir581u{j9SUG(X-+WB1Zrg#;?=ldFutl!B%^|8k$(>Jc+!mLLEC0000000960|Nj60000Sh +X>@L7b8}^L015(oK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgbbYgi@C#*klFTE}3hP#3Wmki}o* +nL&Ed10e7tM;q}1-3t;lG3#LR3QZq*JLk)~{9$tvliNbptnXW-ZFx5Q$6skVRwOM6wz9dSYg6i3-rmX0 +uFE(Y8AEY@srN=80000000000|NsC0000003t@D0VPj}*Wo~qH015(oK7!h3DM#@+#URqYCg1WtfjX<- +_MW+H5~UY4oBgbWaSf9!PV~dK2uo>;u!nFdemP_$e?^hl+JkM;eY!XR2mk;;0000000000|Ns9000000 +0000000000|Nj60000003v*>-a%FT=WnpY{00{znK7!h3DM#@+#URqYCg1WtfjX<-_MW+H5~UY4oBgbh +yTa&4noi_R;$3lnz4{Zl)X|Z&ZIQtMA_g1big7gn0000000030|Nj600000Aba`-PQ+acAWo-gQ>Z4!V +_T!KNI`QJ|h6;Zj^jB$MPK+?7Lu3>C`4HLtfv$so3kRF1PV2}fOp_vjQ6FdFHId|R2XhQO_4{AcS-HH^7AVzASV8M4NY +xyCjU1gEwF5PXV6FZDLo1#Vec_~kix7WfVQ#Sd|CM9$^_0000000030{{R3000004b7^OD015)#3lcOj +>tON(T2L(qY0=?N-3t;l +G3#LR3QZq*JLk)~{9$tvliNbptnXW-ZFx5Qh8PemXlG!~;@e)_O3H?xO^a~KWeI~0jp}x-Dk@(^00000 +00000|Nj60000002u)>eQ*>c;Wd;HXcWHEPWpi_7a{vkgdp?5NXDLVVImIB-z9!%DK7l%`-}aulY!amx +HJkmciECIT&Bl;lSX#$ms8AQN7m&qY<-*c+r9YqvBlw6d-@{>9 +U*X1+0dl)S$QV;yG0%+u`Lqfm#|FpRuujhTP8r)T_J?np;Q#;t000000RR90{{R30010DnZgg^CV{~%> +3IcmRg4$;(NAWquAkw}j-|{|zI;-FIp1Euir581u{j8q|EJ-@Z0;0Ob-P{Wzd?2rs)M&&=&l*}G;Jw22 +Ix+!#bL(f8`U$>X>B)Y_u0zsDWJXxNV$=kC)4@UGUHf+c0000000030000000000 -----END STRICT TYPE LIB----- diff --git a/stl/RGBStorage@0.11.0.stl b/stl/RGBStorage@0.11.0.stl index 29e2bdda..314dabd9 100644 Binary files a/stl/RGBStorage@0.11.0.stl and b/stl/RGBStorage@0.11.0.stl differ diff --git a/stl/RGBStorage@0.11.0.sty b/stl/RGBStorage@0.11.0.sty index e6631235..529178e4 100644 --- a/stl/RGBStorage@0.11.0.sty +++ b/stl/RGBStorage@0.11.0.sty @@ -1,5 +1,5 @@ {- - Id: stl:mG$H7b6I-$T8qp18-07PSNeA-rbEBNS5-$J5X4y0-1vPxRWg#channel-vortex-bandit + Id: stl:dYzM3Ct9-SJ8PljY-C!6hB6y-VlWvDE7-DAtNg3y-zanf6hE#media-fresh-cadet Name: RGBStorage Version: 0.11.0 Description: RGB storage library @@ -11,80 +11,126 @@ @context typelib RGBStorage -import RGBCommit#harvest-person-orion +import RGBLogic#leonid-melody-quick + use WitnessPos#cliff-enrico-nominal + use WitnessOrd#frank-ohio-forum + +import StrictTypes#century-comrade-chess + use VariantName#theory-austin-before + use FieldName#present-flute-herman + use Primitive#deliver-arrow-boxer + use TySemId#popcorn-super-young + use FieldSemId#spiral-road-marco + use TypeName#edgar-carol-mystery + use UnnamedFieldsSemId#freedom-degree-gregory + use SemId#logic-absorb-hilton + use Variant#humor-regard-promise + use Sizing#courage-alien-salon + use NamedFieldsSemId#solar-salad-smoke + use EnumVariants#dispute-natasha-vega + use VariantInfoSemId#museum-edward-mirror + use UnionVariantsSemId#santana-address-pepper + use TypeSystem#adrian-boris-sponsor + +import BPCore#austin-story-retro + use TapretNodePartner#roger-member-educate + use ExplicitSealTxid#nova-roger-campus + use TapretProof#marco-border-sample + use TapretPathProof#kiwi-mirror-paris + use Method#bali-boris-plasma + use TapretRightBranch#miracle-patriot-touch + use BlindSealTxPtr#fortune-iron-salmon + use OpretProof#good-village-flex + use AnchorMerkleBlockTapretProof#ventura-palma-trumpet + use AnchorMerkleBlockOpretProof#sheriff-alex-degree + use SecretSeal#dollar-iris-wizard + use BlindSealTxid#media-judge-anita + use TxPtr#italian-july-eddie + +import AluVM#congo-archive-folio + use Lib#gate-biology-optimal + use LibSite#ultra-grace-message + use IsaName#taboo-olympic-cloud + use LibId#germany-culture-olivia + use IsaSeg#size-shake-olga + use LibSeg#lemon-philips-horse + +import CommitVerify#miller-pancake-elastic + use ProtocolId#shadow-eclipse-program + use Message#druid-blitz-rover + use MerkleHash#horse-popcorn-bundle + use MerkleBlock#pegasus-delta-eddie + use ReservedBytes1#origin-roger-relax + use ReservedBytes2#florida-libra-circus + use TreeNode#kansas-scarlet-ricardo + use ReservedBytes4#young-goblin-academy + use ReservedBytes8#rudolf-tape-adrian + +import RGBCommit#trident-rover-tape use ExtensionSchema#active-eddie-empty use BundleId#carmen-farmer-diesel - use AttachState#lady-japan-fiesta - use GlobalValues#pilot-boris-alice use MetaValue#split-package-recycle use InputMap#octavia-north-gram use GenesisSchema#iron-forbid-hamlet use AltLayer1Set#flute-flex-bottle - use OwnedStateSchema#python-snake-capsule - use AssetTags#anita-nice-deliver - use VoidState#email-snow-safari - use DataState#short-noise-postal + use Genesis#ford-acrobat-border + use AssignBlindSealTxPtr#harbor-charm-nelson use TransitionType#picture-reflex-brigade use Occurrences#source-olga-mirage - use AssignVoidStateBlindSealTxPtr#profit-granite-fuji - use Schema#vocal-hammer-logic - use MediaType#isabel-heaven-north - use AssignmentsBlindSealTxPtr#village-result-bahama use ValencyType#aloha-dublin-brush - use PedersenCommitment#pupil-scale-jerome - use ConcealedFungible#story-shrink-aloha + use GlobalState#mouse-bambino-brigade use GlobalStateSchema#silk-college-august - use Extension#ambient-greek-jackson - use AssignRevealedAttachBlindSealTxid#local-memo-modern - use TypedAssignsBlindSealTxid#garlic-project-zigzag - use AssignRevealedDataBlindSealTxid#fantasy-monica-jump - use AssignmentsBlindSealTxid#electra-bishop-helena + use OwnedStateSchema#cover-shampoo-weather use ExtensionType#apropos-scoop-viva - use RevealedFungible#origin-iris-insect - use ConcealedData#ivan-tripod-young + use State#aroma-sailor-manila + use AssignmentsBlindSealTxid#shelter-declare-chrome use MetaType#quebec-mission-quota use TransitionSchema#jumbo-matrix-normal use Layer1#camilla-basket-justin - use TypedAssignsBlindSealTxPtr#airline-video-travel - use AssignRevealedDataBlindSealTxPtr#ritual-license-arcade + use StateData#nissan-pattern-inside + use AssignmentsBlindSealTxPtr#clone-mayor-patient use XChainBlindSealTxid#dynamic-life-brown use AttachId#factor-hair-everest - use BlindingFactor#animal-plume-minus use AssignmentType#secret-penguin-limit use XChainTxid#liquid-river-absorb use XChainBlindSealTxPtr#senator-limbo-raymond use Opout#yoga-samba-karma - use AssignVoidStateBlindSealTxid#senior-beyond-cement use SchemaId#ramirez-patron-simon use OpId#picnic-single-gloria + use Schema#eternal-block-totem use ContractId#uniform-welcome-papa - use FungibleState#guide-poker-coconut + use TransitionBundle#rubber-permit-martin + use AssignBlindSealTxid#piano-baker-lola use Inputs#herman-liberal-galaxy - use TransitionBundle#mambo-anita-plate + use TypedAssignsBlindSealTxPtr#python-baboon-money + use Extension#swing-virgo-wisdom use Identity#smart-pioneer-nominal use AltLayer1#edison-survive-nitro - use AssetTag#slang-amber-club + use TypedAssignsBlindSealTxid#algebra-fresh-wedding + use GlobalValues#verona-iris-senator use XChainExplicitSealTxid#acid-nepal-melon use Input#actor-minus-multi use GlobalStateType#yoga-quick-jasmine - use Transition#tactic-arcade-manager - use AssignRevealedAttachBlindSealTxPtr#wave-comet-arnold use Ffv#pigment-career-hippie - use AssignRevealedValueBlindSealTxPtr#cuba-needle-salami use XChainSecretSeal#alex-griffin-left use Valencies#light-letter-comet - use GlobalState#stadium-barcode-bazaar use Redeemed#mile-lady-perfect - use RevealedAttach#slalom-phantom-voyage - use Genesis#round-sound-nectar + use Transition#economy-ethnic-audio use Metadata#member-nobody-imitate - use FungibleType#matrix-optimal-sinatra use XChainPubWitness#figure-gram-wave - use ConcealedAttach#meter-arizona-albino - use RevealedData#olivia-copper-stamp - use AssignRevealedValueBlindSealTxid#photo-jump-silicon -import RGBStd#hair-magnum-helena +import Std#ralph-blue-lucky + use AlphaCaps#picnic-soprano-aurora + use AsciiPrintable#ultra-sunset-format + use Bool#oxygen-complex-duet + use U5#orbit-graph-sonic + use AlphaNumDash#sponsor-snake-nice + use AlphaCapsNum#aladdin-zebra-marble + use AlphaNumLodash#percent-bingo-caesar + use AlphaCapsLodash#duet-hammer-labor + use AlphaSmallLodash#pioneer-eagle-spell + +import RGBStd#mango-inside-shelf use PubWitness#paper-visa-storm use ContentRef#polo-ramirez-parker use SigBlob#insect-cello-avalon @@ -92,107 +138,38 @@ import RGBStd#hair-magnum-helena use TransitionIface#axiom-parker-pyramid use NamedFieldTransitionType#express-brush-desire use ExtensionIface#model-ramirez-mentor - use Iface#violin-student-system use IfaceId#nova-cola-carbon use ValencyIface#buzzer-holiday-fiber use Annotations#spend-linda-romeo - use AssignIface#fractal-baker-outside + use IfaceImpl#coconut-snake-formula use VerNo#textile-next-stretch use NamedFieldValencyType#invest-apollo-inca use ImplId#seminar-data-table use SupplSub#canoe-denmark-short - use OutputAssignmentRevealedData#dinner-honey-saturn + use Allocation#water-poker-tape use Supplement#caviar-zebra-precise use SupplId#pilot-claudia-minute - use OutputAssignmentRevealedAttach#miami-diagram-mineral use NamedFieldExtensionType#tuna-archer-melon use NamedFieldGlobalStateType#museum-ohio-arizona use GenesisIface#rocket-paradox-press + use SchemaIfaces#popcorn-rider-panel use AnchorSet#pluto-plasma-diagram - use IfaceImpl#permit-learn-samba use ContentSigs#oval-sister-triton use SupplItem#jargon-orchid-forget use Modifier#saturn-escort-jordan use NamedFieldAssignmentType#origin-caramel-flipper use TrustLevel#cobra-script-albino + use AssignIface#optic-hippie-isabel + use StateAbi#thermos-demo-fragile use NamedFieldMetaType#prefix-carmen-artist use NamedVariantu8#star-pilgrim-pilgrim use OpWitness#valid-toronto-gibson use SealWitness#cotton-lopez-isabel use GlobalIface#concert-combat-charm - use SchemaIfaces#fossil-nepal-airline - use OutputAssignmentRevealedValue#aspect-caramel-diana use SupplMap#sailor-observe-bundle - use OwnedIface#delphi-athlete-fresh + use Iface#citizen-oxford-norway use ContentId#scarlet-portal-office use GlobalOut#capital-agatha-bruno - use OutputAssignmentVoidState#mars-alabama-public - -import StrictTypes#century-comrade-chess - use VariantName#theory-austin-before - use FieldName#present-flute-herman - use Primitive#deliver-arrow-boxer - use TySemId#popcorn-super-young - use FieldSemId#spiral-road-marco - use TypeName#edgar-carol-mystery - use UnnamedFieldsSemId#freedom-degree-gregory - use SemId#logic-absorb-hilton - use Variant#humor-regard-promise - use Sizing#courage-alien-salon - use NamedFieldsSemId#solar-salad-smoke - use EnumVariants#dispute-natasha-vega - use VariantInfoSemId#museum-edward-mirror - use UnionVariantsSemId#santana-address-pepper - use TypeSystem#adrian-boris-sponsor - -import BPCore#austin-story-retro - use TapretNodePartner#roger-member-educate - use ExplicitSealTxid#nova-roger-campus - use TapretProof#marco-border-sample - use TapretPathProof#kiwi-mirror-paris - use Method#bali-boris-plasma - use TapretRightBranch#miracle-patriot-touch - use BlindSealTxPtr#fortune-iron-salmon - use OpretProof#good-village-flex - use AnchorMerkleBlockTapretProof#ventura-palma-trumpet - use AnchorMerkleBlockOpretProof#sheriff-alex-degree - use SecretSeal#dollar-iris-wizard - use BlindSealTxid#media-judge-anita - use TxPtr#italian-july-eddie - -import AluVM#congo-archive-folio - use Lib#gate-biology-optimal - use LibSite#ultra-grace-message - use IsaName#taboo-olympic-cloud - use LibId#germany-culture-olivia - use IsaSeg#size-shake-olga - use LibSeg#lemon-philips-horse - -import CommitVerify#miller-pancake-elastic - use ProtocolId#shadow-eclipse-program - use Message#druid-blitz-rover - use MerkleHash#horse-popcorn-bundle - use MerkleBlock#pegasus-delta-eddie - use ReservedBytes1#origin-roger-relax - use ReservedBytes2#florida-libra-circus - use TreeNode#kansas-scarlet-ricardo - use ReservedBytes4#young-goblin-academy - use ReservedBytes8#rudolf-tape-adrian - -import RGBLogic#import-boxer-seminar - use WitnessPos#cliff-enrico-nominal - use WitnessOrd#frank-ohio-forum - -import Std#ralph-blue-lucky - use AlphaCaps#picnic-soprano-aurora - use AsciiPrintable#ultra-sunset-format - use Bool#oxygen-complex-duet - use U5#orbit-graph-sonic - use AlphaNumDash#sponsor-snake-nice - use AlphaCapsNum#aladdin-zebra-marble - use AlphaNumLodash#percent-bingo-caesar - use AlphaCapsLodash#duet-hammer-labor - use AlphaSmallLodash#pioneer-eagle-spell import Bitcoin#signal-color-cipher use SeqNo#copper-verbal-ingrid @@ -220,17 +197,14 @@ import Bitcoin#signal-color-cipher @mnemonic(carol-salute-aroma) data ContractIndex : publicOpouts {RGBCommit.Opout ^ ..0xffffff}, outpointOpouts {RGBCommit.XChainExplicitSealTxid -> ^ ..0xffffff {RGBCommit.Opout ^ ..0xffffff}} -@mnemonic(shake-square-wizard) +@mnemonic(fire-domingo-monaco) data MemContractState : schemaId RGBCommit.SchemaId , contractId RGBCommit.ContractId , global {RGBCommit.GlobalStateType -> ^ ..0xff MemGlobalState} - , rights {RGBStd.OutputAssignmentVoidState ^ ..0xffffffff} - , fungibles {RGBStd.OutputAssignmentRevealedValue ^ ..0xffffffff} - , data {RGBStd.OutputAssignmentRevealedData ^ ..0xffffffff} - , attach {RGBStd.OutputAssignmentRevealedAttach ^ ..0xffffffff} + , owned {RGBStd.Allocation ^ ..0xffffffff} -@mnemonic(gilbert-torpedo-digital) -data MemGlobalState : known {RGBStd.GlobalOut -> ^ ..0xffffffff RGBCommit.DataState}, limit U24 +@mnemonic(mary-mineral-frame) +data MemGlobalState : known {RGBStd.GlobalOut -> ^ ..0xffffffff RGBCommit.StateData}, limit U24 @mnemonic(savage-joshua-clone) data MemIndex : opBundleIndex {RGBCommit.OpId -> ^ ..0xffffff RGBCommit.BundleId} @@ -239,7 +213,7 @@ data MemIndex : opBundleIndex {RGBCommit.OpId -> ^ ..0xffffff RGBCommit , contractIndex {RGBCommit.ContractId -> ^ ..0xff ContractIndex} , terminalIndex {RGBCommit.XChainSecretSeal -> ^ ..0xffffff {RGBCommit.Opout ^ ..0xff}} -@mnemonic(level-open-morph) +@mnemonic(summer-sardine-disney) data MemStash : schemata {RGBCommit.SchemaId -> ^ ..0xff RGBStd.SchemaIfaces} , ifaces {RGBStd.IfaceId -> ^ ..0xff RGBStd.Iface} , geneses {RGBCommit.ContractId -> ^ ..0xff RGBCommit.Genesis} diff --git a/stl/Transfer.vesper b/stl/Transfer.vesper index ca6ac774..08cfaa9f 100644 --- a/stl/Transfer.vesper +++ b/stl/Transfer.vesper @@ -48,211 +48,43 @@ Consignmenttrue rec testnet enum Bool false=0 true=1 altLayers1 set len=0..MAX8 aka=AltLayer1Set AltLayer1 enum liquid=1 - assetTags map len=0..MAX8 aka=AssetTags - key is U16 aka=AssignmentType - value bytes len=32 aka=AssetTag metadata map len=0..MAX8 aka=Metadata key is U16 aka=MetaType value bytes len=0..MAX16 aka=MetaValue globals map len=0..MAX8 aka=GlobalState key is U16 aka=GlobalStateType value list len=1..MAX16 aka=GlobalValues - element bytes len=0..MAX16 aka=DataState + element bytes len=0..MAX16 aka=StateData assignments map len=0..MAX8 aka=AssignmentsBlindSealTxid key is U16 aka=AssignmentType - value union TypedAssignsBlindSealTxid - declarative list len=0..MAX16 wrapped tag=0 - AssignVoidStateBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - fungible list len=0..MAX16 wrapped tag=1 - AssignRevealedValueBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - structured list len=0..MAX16 wrapped tag=2 - AssignRevealedDataBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - attachment list len=0..MAX16 wrapped tag=3 - AssignRevealedAttachBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 + value list len=1..MAX16 aka=TypedAssignsBlindSealTxid + AssignBlindSealTxid union + confidential rec tag=0 + seal union XChainSecretSeal + bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 + liquid bytes len=32 wrapped aka=SecretSeal tag=1 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 + revealed rec tag=1 + seal union XChainBlindSealTxid + bitcoin rec BlindSealTxid wrapped tag=0 + method enum Method opretFirst=0 tapretFirst=1 + txid bytes len=32 aka=Txid + vout is U32 aka=Vout + blinding is U64 + liquid rec BlindSealTxid wrapped tag=1 + method enum Method opretFirst=0 tapretFirst=1 + txid bytes len=32 aka=Txid + vout is U32 aka=Vout + blinding is U64 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 valencies set len=0..MAX8 aka=Valencies element is U16 aka=ValencyType validator bytes len=1 aka=ReservedBytes1 @@ -268,202 +100,37 @@ Consignmenttrue rec globals map len=0..MAX8 aka=GlobalState key is U16 aka=GlobalStateType value list len=1..MAX16 aka=GlobalValues - element bytes len=0..MAX16 aka=DataState + element bytes len=0..MAX16 aka=StateData assignments map len=0..MAX8 aka=AssignmentsBlindSealTxid key is U16 aka=AssignmentType - value union TypedAssignsBlindSealTxid - declarative list len=0..MAX16 wrapped tag=0 - AssignVoidStateBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - fungible list len=0..MAX16 wrapped tag=1 - AssignRevealedValueBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - structured list len=0..MAX16 wrapped tag=2 - AssignRevealedDataBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - attachment list len=0..MAX16 wrapped tag=3 - AssignRevealedAttachBlindSealTxid union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxid - bitcoin rec BlindSealTxid wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxid wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid bytes len=32 aka=Txid - vout is U32 aka=Vout - blinding is U64 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 + value list len=1..MAX16 aka=TypedAssignsBlindSealTxid + AssignBlindSealTxid union + confidential rec tag=0 + seal union XChainSecretSeal + bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 + liquid bytes len=32 wrapped aka=SecretSeal tag=1 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 + revealed rec tag=1 + seal union XChainBlindSealTxid + bitcoin rec BlindSealTxid wrapped tag=0 + method enum Method opretFirst=0 tapretFirst=1 + txid bytes len=32 aka=Txid + vout is U32 aka=Vout + blinding is U64 + liquid rec BlindSealTxid wrapped tag=1 + method enum Method opretFirst=0 tapretFirst=1 + txid bytes len=32 aka=Txid + vout is U32 aka=Vout + blinding is U64 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 redeemed map len=0..MAX8 aka=Redeemed key is U16 aka=ValencyType value bytes len=32 aka=OpId @@ -473,271 +140,78 @@ Consignmenttrue rec witness bytes len=2 aka=ReservedBytes2 bundles set len=0..MAX32 WitnessBundle rec - anchoredBundles union AnchoredBundles - tapret rec ClientBundleTapretProof wrapped tag=0 - mpcProof rec MerkleProof - pos is U32 - cofactor is U16 - path list len=0..32 - element bytes len=32 aka=MerkleHash - dbcProof rec TapretProof - pathProof rec TapretPathProof - some union TapretNodePartner option wrapped tag=1 - rightBranch rec TapretRightBranch wrapped tag=2 - nonce is U8 - bundle rec TransitionBundle - closeMethod enum Method opretFirst=0 tapretFirst=1 - inputMap map len=1..MAX16 aka=InputMap - key is U32 aka=Vout - value bytes len=32 aka=OpId - knownTransitions map len=1..MAX16 - key bytes len=32 aka=OpId - value rec Transition - ffv is U16 aka=Ffv - contractId bytes len=32 aka=ContractId - nonce is U64 - transitionType is U16 aka=TransitionType - metadata map len=0..MAX8 aka=Metadata - key is U16 aka=MetaType - value bytes len=0..MAX16 aka=MetaValue - globals map len=0..MAX8 aka=GlobalState - key is U16 aka=GlobalStateType - value list len=1..MAX16 aka=GlobalValues - element bytes len=0..MAX16 aka=DataState - inputs set len=0..MAX16 aka=Inputs - Input rec - prevOut rec Opout - op bytes len=32 aka=OpId - ty is U16 aka=AssignmentType - no is U16 - reserved bytes len=2 aka=ReservedBytes2 - assignments map len=0..MAX8 aka=AssignmentsBlindSealTxPtr - key is U16 aka=AssignmentType - value union TypedAssignsBlindSealTxPtr - declarative list len=0..MAX16 wrapped tag=0 - AssignVoidStateBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - fungible list len=0..MAX16 wrapped tag=1 - AssignRevealedValueBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - structured list len=0..MAX16 wrapped tag=2 - AssignRevealedDataBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - attachment list len=0..MAX16 wrapped tag=3 - AssignRevealedAttachBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 + anchoredBundles union AnchoredBundles + tapret rec ClientBundleTapretProof wrapped tag=0 + mpcProof rec MerkleProof + pos is U32 + cofactor is U16 + path list len=0..32 + element bytes len=32 aka=MerkleHash + dbcProof rec TapretProof + pathProof rec TapretPathProof + some union TapretNodePartner option wrapped tag=1 + rightBranch rec TapretRightBranch wrapped tag=2 + nonce is U8 + bundle rec TransitionBundle + closeMethod enum Method opretFirst=0 tapretFirst=1 + inputMap map len=1..MAX16 aka=InputMap + key is U32 aka=Vout + value bytes len=32 aka=OpId + knownTransitions map len=1..MAX16 + key bytes len=32 aka=OpId + value rec Transition + ffv is U16 aka=Ffv + contractId bytes len=32 aka=ContractId + nonce is U64 + transitionType is U16 aka=TransitionType + metadata map len=0..MAX8 aka=Metadata + key is U16 aka=MetaType + value bytes len=0..MAX16 aka=MetaValue + globals map len=0..MAX8 aka=GlobalState + key is U16 aka=GlobalStateType + value list len=1..MAX16 aka=GlobalValues + element bytes len=0..MAX16 aka=StateData + inputs set len=0..MAX16 aka=Inputs + Input rec + prevOut rec Opout + op bytes len=32 aka=OpId + ty is U16 aka=AssignmentType + no is U16 + reserved bytes len=2 aka=ReservedBytes2 + assignments map len=0..MAX8 aka=AssignmentsBlindSealTxPtr + key is U16 aka=AssignmentType + value list len=1..MAX16 aka=TypedAssignsBlindSealTxPtr + AssignBlindSealTxPtr union + confidential rec tag=0 + seal union XChainSecretSeal + bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 + liquid bytes len=32 wrapped aka=SecretSeal tag=1 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 + revealed rec tag=1 + seal union XChainBlindSealTxPtr + bitcoin rec BlindSealTxPtr wrapped tag=0 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + liquid rec BlindSealTxPtr wrapped tag=1 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 valencies set len=0..MAX8 aka=Valencies element is U16 aka=ValencyType validator bytes len=1 aka=ReservedBytes1 @@ -767,7 +241,7 @@ Consignmenttrue rec globals map len=0..MAX8 aka=GlobalState key is U16 aka=GlobalStateType value list len=1..MAX16 aka=GlobalValues - element bytes len=0..MAX16 aka=DataState + element bytes len=0..MAX16 aka=StateData inputs set len=0..MAX16 aka=Inputs Input rec prevOut rec Opout @@ -777,231 +251,38 @@ Consignmenttrue rec reserved bytes len=2 aka=ReservedBytes2 assignments map len=0..MAX8 aka=AssignmentsBlindSealTxPtr key is U16 aka=AssignmentType - value union TypedAssignsBlindSealTxPtr - declarative list len=0..MAX16 wrapped tag=0 - AssignVoidStateBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - fungible list len=0..MAX16 wrapped tag=1 - AssignRevealedValueBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - structured list len=0..MAX16 wrapped tag=2 - AssignRevealedDataBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - attachment list len=0..MAX16 wrapped tag=3 - AssignRevealedAttachBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 + value list len=1..MAX16 aka=TypedAssignsBlindSealTxPtr + AssignBlindSealTxPtr union + confidential rec tag=0 + seal union XChainSecretSeal + bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 + liquid bytes len=32 wrapped aka=SecretSeal tag=1 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 + revealed rec tag=1 + seal union XChainBlindSealTxPtr + bitcoin rec BlindSealTxPtr wrapped tag=0 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + liquid rec BlindSealTxPtr wrapped tag=1 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 valencies set len=0..MAX8 aka=Valencies element is U16 aka=ValencyType validator bytes len=1 aka=ReservedBytes1 @@ -1036,7 +317,7 @@ Consignmenttrue rec globals map len=0..MAX8 aka=GlobalState key is U16 aka=GlobalStateType value list len=1..MAX16 aka=GlobalValues - element bytes len=0..MAX16 aka=DataState + element bytes len=0..MAX16 aka=StateData inputs set len=0..MAX16 aka=Inputs Input rec prevOut rec Opout @@ -1046,231 +327,38 @@ Consignmenttrue rec reserved bytes len=2 aka=ReservedBytes2 assignments map len=0..MAX8 aka=AssignmentsBlindSealTxPtr key is U16 aka=AssignmentType - value union TypedAssignsBlindSealTxPtr - declarative list len=0..MAX16 wrapped tag=0 - AssignVoidStateBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - fungible list len=0..MAX16 wrapped tag=1 - AssignRevealedValueBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - structured list len=0..MAX16 wrapped tag=2 - AssignRevealedDataBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - attachment list len=0..MAX16 wrapped tag=3 - AssignRevealedAttachBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 + value list len=1..MAX16 aka=TypedAssignsBlindSealTxPtr + AssignBlindSealTxPtr union + confidential rec tag=0 + seal union XChainSecretSeal + bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 + liquid bytes len=32 wrapped aka=SecretSeal tag=1 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 + revealed rec tag=1 + seal union XChainBlindSealTxPtr + bitcoin rec BlindSealTxPtr wrapped tag=0 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + liquid rec BlindSealTxPtr wrapped tag=1 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 valencies set len=0..MAX8 aka=Valencies element is U16 aka=ValencyType validator bytes len=1 aka=ReservedBytes1 @@ -1300,7 +388,7 @@ Consignmenttrue rec globals map len=0..MAX8 aka=GlobalState key is U16 aka=GlobalStateType value list len=1..MAX16 aka=GlobalValues - element bytes len=0..MAX16 aka=DataState + element bytes len=0..MAX16 aka=StateData inputs set len=0..MAX16 aka=Inputs Input rec prevOut rec Opout @@ -1310,231 +398,38 @@ Consignmenttrue rec reserved bytes len=2 aka=ReservedBytes2 assignments map len=0..MAX8 aka=AssignmentsBlindSealTxPtr key is U16 aka=AssignmentType - value union TypedAssignsBlindSealTxPtr - declarative list len=0..MAX16 wrapped tag=0 - AssignVoidStateBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state is Unit aka=VoidState - lock bytes len=2 aka=ReservedBytes2 - fungible list len=0..MAX16 wrapped tag=1 - AssignRevealedValueBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec ConcealedFungible - commitment bytes len=33 aka=PedersenCommitment - rangeProof bytes len=33 aka=PedersenCommitment - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedFungible - value union FungibleState - bits64 is U64 wrapped tag=0 - blinding bytes len=32 aka=BlindingFactor - tag bytes len=32 aka=AssetTag - lock bytes len=2 aka=ReservedBytes2 - structured list len=0..MAX16 wrapped tag=2 - AssignRevealedDataBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedData - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedData - value bytes len=0..MAX16 aka=DataState - salt is U128 - lock bytes len=2 aka=ReservedBytes2 - attachment list len=0..MAX16 wrapped tag=3 - AssignRevealedAttachBlindSealTxPtr union - confidential rec tag=0 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialState rec tag=1 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state bytes len=32 aka=ConcealedAttach - lock bytes len=2 aka=ReservedBytes2 - confidentialSeal rec tag=2 - seal union XChainSecretSeal - bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 - liquid bytes len=32 wrapped aka=SecretSeal tag=1 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 - revealed rec tag=3 - seal union XChainBlindSealTxPtr - bitcoin rec BlindSealTxPtr wrapped tag=0 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - liquid rec BlindSealTxPtr wrapped tag=1 - method enum Method opretFirst=0 tapretFirst=1 - txid union TxPtr - witnessTx is Unit tag=0 - txid bytes len=32 wrapped aka=Txid tag=1 - vout is U32 aka=Vout - blinding is U64 - state rec RevealedAttach - file rec AttachState - id bytes len=32 aka=AttachId - mediaType enum MediaType any=255 - salt is U64 - lock bytes len=2 aka=ReservedBytes2 + value list len=1..MAX16 aka=TypedAssignsBlindSealTxPtr + AssignBlindSealTxPtr union + confidential rec tag=0 + seal union XChainSecretSeal + bitcoin bytes len=32 wrapped aka=SecretSeal tag=0 + liquid bytes len=32 wrapped aka=SecretSeal tag=1 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 + revealed rec tag=1 + seal union XChainBlindSealTxPtr + bitcoin rec BlindSealTxPtr wrapped tag=0 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + liquid rec BlindSealTxPtr wrapped tag=1 + method enum Method opretFirst=0 tapretFirst=1 + txid union TxPtr + witnessTx is Unit tag=0 + txid bytes len=32 wrapped aka=Txid tag=1 + vout is U32 aka=Vout + blinding is U64 + state rec State + reserved bytes len=1 aka=ReservedBytes1 + data bytes len=0..MAX16 aka=StateData + some bytes len=32 option wrapped aka=AttachId tag=1 + lock bytes len=2 aka=ReservedBytes2 valencies set len=0..MAX8 aka=Valencies element is U16 aka=ValencyType validator bytes len=1 aka=ReservedBytes1 @@ -1556,11 +451,9 @@ Consignmenttrue rec maxItems is U24 ownedTypes map len=0..MAX8 key is U16 aka=AssignmentType - value union OwnedStateSchema - declarative is Unit tag=0 - fungible enum FungibleType wrapped unsigned64Bit=8 tag=1 - structured bytes len=32 wrapped aka=SemId tag=2 - attachment enum MediaType wrapped any=255 tag=3 + value rec OwnedStateSchema + reserved bytes len=1 aka=ReservedBytes1 + semId bytes len=32 aka=SemId valencyTypes set len=0..MAX8 element is U16 aka=ValencyType genesis rec GenesisSchema @@ -1647,13 +540,8 @@ Consignmenttrue rec assignments map len=0..MAX8 key ascii aka=FieldName first=AlphaSmallLodash rest=AlphaNumLodash len=1..100 value rec AssignIface - ownedState union OwnedIface - any is Unit tag=0 - rights is Unit tag=1 - amount is Unit tag=2 - anyData is Unit tag=3 - anyAttach is Unit tag=4 - data bytes len=32 wrapped aka=SemId tag=5 + some bytes len=32 option wrapped aka=SemId tag=1 + some enum Bool option wrapped false=0 true=1 tag=1 public enum Bool false=0 true=1 required enum Bool false=0 true=1 multiple enum Bool false=0 true=1 @@ -1776,6 +664,19 @@ Consignmenttrue rec name ascii aka=VariantName first=AlphaSmallLodash rest=AlphaNumLodash len=1..100 reserved bytes len=4 aka=ReservedBytes4 developer ascii aka=Identity first=AsciiPrintable rest=AsciiPrintable len=1..4096 + stateAbi rec StateAbi + regInput rec LibSite + lib bytes len=32 aka=LibId + pos is U16 + regOutput rec LibSite + lib bytes len=32 aka=LibId + pos is U16 + calcOutput rec LibSite + lib bytes len=32 aka=LibId + pos is U16 + calcChange rec LibSite + lib bytes len=32 aka=LibId + pos is U16 supplements set len=0..MAX8 Supplement rec contentId union ContentRef diff --git a/stl/src/main.rs b/stl/src/main.rs index 3cf24119..f41e32da 100644 --- a/stl/src/main.rs +++ b/stl/src/main.rs @@ -26,8 +26,8 @@ use std::io::Write; use commit_verify::CommitmentLayout; use rgbstd::containers::Transfer; use rgbstd::stl::{ - aluvm_stl, bp_core_stl, bp_tx_stl, commit_verify_stl, rgb_commit_stl, rgb_contract_stl, - rgb_logic_stl, rgb_std_stl, rgb_storage_stl, + aluvm_stl, bp_core_stl, bp_tx_stl, commit_verify_stl, rgb_commit_stl, rgb_logic_stl, + rgb_std_stl, rgb_storage_stl, }; use strict_types::stl::{std_stl, strict_types_stl}; use strict_types::{parse_args, StlFormat, SystemBuilder}; @@ -36,28 +36,6 @@ fn main() { let (_, dir) = parse_args(); let dir = dir.unwrap_or_else(|| "./stl".to_owned()); - let contract_stl = rgb_contract_stl(); - contract_stl - .serialize(StlFormat::Binary, Some(&dir), "0.11.0", None) - .expect("unable to write to the file"); - contract_stl - .serialize(StlFormat::Armored, Some(&dir), "0.11.0", None) - .expect("unable to write to the file"); - contract_stl - .serialize( - StlFormat::Source, - Some(&dir), - "0.11.0", - Some( - " - Description: Types for writing RGB contracts and interfaces - Author: Dr Maxim Orlovsky - Copyright (C) 2023-2024 LNP/BP Standards Association. All rights reserved. - License: Apache-2.0", - ), - ) - .expect("unable to write to the file"); - let rgb_std = rgb_std_stl(); rgb_std .serialize(StlFormat::Binary, Some(&dir), "0.11.0", None)