From 1d6118d8a5e7ff3aed948a5dfb889f85873d49b3 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 5 Jan 2025 12:32:36 +0100 Subject: [PATCH 01/90] update submodules to v0.12 branch --- .gitmodules | 9 + Cargo.lock | 416 ++++++++++++++--------------------------- Cargo.toml | 28 +-- amplify-nonasync | 2 +- amplify-num | 2 +- ascii-armor | 1 - bp-core | 2 +- bp-electrum-client | 2 +- bp-esplora-client | 2 +- bp-std | 2 +- bp-wallet | 2 +- client_side_validation | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-interfaces | 1 - rgb-schemata | 1 - rgb-std | 2 +- rust-aluvm | 2 +- rust-amplify | 2 +- rust-baid64 | 2 +- sonic | 1 + strict-encoding | 2 +- strict-types | 2 +- ultrasonic | 1 + zk-aluvm | 1 + 25 files changed, 173 insertions(+), 318 deletions(-) delete mode 160000 ascii-armor delete mode 160000 rgb-interfaces delete mode 160000 rgb-schemata create mode 160000 sonic create mode 160000 ultrasonic create mode 160000 zk-aluvm diff --git a/.gitmodules b/.gitmodules index 7b781f5..5798a64 100644 --- a/.gitmodules +++ b/.gitmodules @@ -61,3 +61,12 @@ [submodule "amplify-nonasync"] path = amplify-nonasync url = https://github.com/rust-amplify/amplify-nonasync.git +[submodule "zk-aluvm"] + path = zk-aluvm + url = https://github.com/AluVM/zk-aluvm +[submodule "ultrasonic"] + path = ultrasonic + url = https://github.com/AluVM/ultrasonic +[submodule "sonic"] + path = sonic + url = https://github.com/AluVM/sonic diff --git a/Cargo.lock b/Cargo.lock index 923c3be..ee0f266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,47 +28,31 @@ dependencies = [ [[package]] name = "aluvm" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", - "ascii-armor", "baid64", - "blake3", + "commit_verify", "getrandom", - "half", "paste", - "ripemd", "serde", - "sha2", "strict_encoding", - "strict_types", "wasm-bindgen", ] [[package]] name = "amplify" -version = "4.7.0" +version = "4.8.0" dependencies = [ - "amplify_apfloat", "amplify_derive", "amplify_num", "amplify_syn", "ascii", - "rand", "serde", "stringly_conversions", "wasm-bindgen", ] -[[package]] -name = "amplify_apfloat" -version = "0.3.1" -dependencies = [ - "amplify_num", - "bitflags 2.5.0", - "wasm-bindgen", -] - [[package]] name = "amplify_derive" version = "4.0.1" @@ -111,12 +95,6 @@ dependencies = [ "libc", ] -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - [[package]] name = "arrayvec" version = "0.7.4" @@ -132,17 +110,6 @@ dependencies = [ "serde", ] -[[package]] -name = "ascii-armor" -version = "0.7.2" -dependencies = [ - "amplify", - "baid64", - "base85", - "sha2", - "strict_encoding", -] - [[package]] name = "autocfg" version = "1.2.0" @@ -193,7 +160,7 @@ dependencies = [ [[package]] name = "baid64" -version = "0.2.2" +version = "0.4.1" dependencies = [ "amplify", "base64", @@ -241,7 +208,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.95", "which", ] @@ -251,12 +218,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" @@ -279,19 +240,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" -[[package]] -name = "blake3" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -303,20 +251,19 @@ dependencies = [ [[package]] name = "bp-consensus" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", "chrono", "commit_verify", - "secp256k1 0.30.0", + "secp256k1", "serde", "strict_encoding", - "strict_types", ] [[package]] name = "bp-core" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-consensus", @@ -327,40 +274,39 @@ dependencies = [ "serde", "single_use_seals", "strict_encoding", - "strict_types", "wasm-bindgen", ] [[package]] name = "bp-dbc" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", "base85", "bp-consensus", "commit_verify", - "secp256k1 0.30.0", + "secp256k1", "serde", "strict_encoding", ] [[package]] name = "bp-derive" -version = "0.11.0-beta.9.1" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-consensus", "bp-invoice", "commit_verify", "hmac", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "sha2", ] [[package]] name = "bp-electrum" -version = "0.11.0-beta.9.3" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-std", @@ -377,7 +323,7 @@ dependencies = [ [[package]] name = "bp-esplora" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-std", @@ -391,7 +337,7 @@ dependencies = [ [[package]] name = "bp-invoice" -version = "0.11.0-beta.9.1" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bech32", @@ -402,7 +348,7 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", "baid64", @@ -417,7 +363,7 @@ dependencies = [ [[package]] name = "bp-std" -version = "0.11.0-beta.9.1" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-consensus", @@ -427,14 +373,14 @@ dependencies = [ "descriptors", "getrandom", "psbt", - "secp256k1 0.30.0", + "secp256k1", "serde", "wasm-bindgen", ] [[package]] name = "bp-wallet" -version = "0.11.0-beta.9.1" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-electrum", @@ -498,9 +444,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -533,7 +479,7 @@ dependencies = [ [[package]] name = "commit_encoding_derive" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", "amplify_syn", @@ -544,7 +490,7 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", "commit_encoding_derive", @@ -557,12 +503,6 @@ dependencies = [ "vesper-lang", ] -[[package]] -name = "constant_time_eq" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" - [[package]] name = "core-foundation" version = "0.9.4" @@ -597,12 +537,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - [[package]] name = "crypto-common" version = "0.1.6" @@ -634,7 +568,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -645,7 +579,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -660,11 +594,11 @@ dependencies = [ [[package]] name = "descriptors" -version = "0.11.0-beta.9.1" +version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-derive", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", ] @@ -707,12 +641,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "fast32" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35a73237400bde66c82e38387343f90d7182a2f2f22729e096a2abd57d75db9" - [[package]] name = "fastrand" version = "2.0.2" @@ -735,15 +663,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "fluent-uri" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "fnv" version = "1.0.7" @@ -836,7 +755,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -910,16 +829,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1072,6 +981,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "hypersonic" +version = "0.12.0-beta.4" +dependencies = [ + "aluvm", + "amplify", + "commit_verify", + "getrandom", + "indexmap 2.7.0", + "serde", + "serde_yaml", + "sonic-api", + "strict_encoding", + "strict_types", + "ultrasonic", + "wasm-bindgen", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1124,9 +1051,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.0", @@ -1302,10 +1229,9 @@ dependencies = [ [[package]] name = "nonasync" -version = "0.1.2" +version = "0.1.3" dependencies = [ "amplify", - "log", ] [[package]] @@ -1361,7 +1287,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -1434,7 +1360,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -1474,30 +1400,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "psbt" -version = "0.11.0-beta.9.1" +version = "0.12.0-beta.4" dependencies = [ "amplify", "base64", "bp-core", "bp-derive", - "chrono", "commit_verify", "descriptors", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "strict_encoding", ] @@ -1627,135 +1552,59 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ - "aluvm", "amplify", - "baid64", "bp-core", - "chrono", "commit_verify", "getrandom", - "mime", - "secp256k1-zkp", "serde", "single_use_seals", "strict_encoding", - "strict_types", - "wasm-bindgen", -] - -[[package]] -name = "rgb-interfaces" -version = "0.11.0-beta.9" -dependencies = [ - "aluvm", - "amplify", - "bp-core", - "chrono", - "getrandom", - "rgb-std", - "serde_json", - "sha2", - "strict_encoding", - "strict_types", + "ultrasonic", "wasm-bindgen", ] -[[package]] -name = "rgb-invoice" -version = "0.11.0-beta.9.1" -dependencies = [ - "amplify", - "baid64", - "bp-core", - "bp-invoice", - "fast32", - "fluent-uri", - "indexmap 2.6.0", - "percent-encoding", - "rand", - "rgb-core", - "serde", - "strict_encoding", - "strict_types", -] - [[package]] name = "rgb-psbt" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", - "baid64", - "bp-core", "bp-std", "commit_verify", - "getrandom", "rgb-std", - "strict_encoding", - "wasm-bindgen", ] [[package]] name = "rgb-runtime" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ "amplify", - "baid64", - "bp-core", - "bp-electrum", - "bp-esplora", "bp-std", "bp-wallet", - "chrono", "commit_verify", "getrandom", - "indexmap 2.6.0", + "indexmap 2.7.0", "nonasync", - "rgb-psbt", "rgb-std", "serde", "serde_yaml", - "strict_types", "wasm-bindgen", ] -[[package]] -name = "rgb-schemata" -version = "0.11.0-beta.9" -dependencies = [ - "aluvm", - "amplify", - "bp-core", - "chrono", - "rgb-interfaces", - "rgb-std", - "serde", - "serde_json", - "sha2", - "strict_encoding", - "strict_types", -] - [[package]] name = "rgb-std" -version = "0.11.0-beta.9.1" +version = "0.12.0-beta.4" dependencies = [ - "aluvm", "amplify", - "ascii-armor", - "baid64", - "base85", "bp-core", "chrono", "commit_verify", "getrandom", - "indexmap 2.6.0", - "nonasync", - "rand", + "hypersonic", "rgb-core", - "rgb-invoice", "serde", + "single_use_seals", "strict_encoding", "strict_types", "wasm-bindgen", @@ -1778,10 +1627,8 @@ dependencies = [ "once_cell", "psbt", "rand", - "rgb-interfaces", "rgb-psbt", "rgb-runtime", - "rgb-schemata", "rgb-std", "rstest", "rstest_reuse", @@ -1843,7 +1690,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.66", + "syn 2.0.95", "unicode-ident", ] @@ -1856,7 +1703,7 @@ dependencies = [ "quote", "rand", "rustc_version", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -1979,17 +1826,6 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478f121bb72bbf63c52c93011ea1791dca40140dfe13f8336c4c5ac952c33aa9" -[[package]] -name = "secp256k1" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" -dependencies = [ - "rand", - "secp256k1-sys", - "serde", -] - [[package]] name = "secp256k1" version = "0.30.0" @@ -2011,29 +1847,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.0", - "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 = "security-framework" version = "2.10.0" @@ -2065,22 +1878,22 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -2135,7 +1948,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -2152,7 +1965,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -2161,7 +1974,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "itoa", "ryu", "serde", @@ -2190,7 +2003,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -2212,9 +2025,10 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "single_use_seals" -version = "0.11.0-beta.9" +version = "0.12.0-beta.4" dependencies = [ - "amplify_derive", + "serde", + "strict_encoding", ] [[package]] @@ -2253,6 +2067,23 @@ dependencies = [ "winapi", ] +[[package]] +name = "sonic-api" +version = "0.12.0-beta.4" +dependencies = [ + "aluvm", + "amplify", + "baid64", + "chrono", + "commit_verify", + "getrandom", + "serde", + "strict_encoding", + "strict_types", + "ultrasonic", + "wasm-bindgen", +] + [[package]] name = "spin" version = "0.9.8" @@ -2261,10 +2092,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "strict_encoding" -version = "2.7.0" +version = "2.8.1" dependencies = [ "amplify", - "half", "serde", "strict_encoding_derive", "wasm-bindgen", @@ -2272,7 +2102,7 @@ dependencies = [ [[package]] name = "strict_encoding_derive" -version = "2.7.0" +version = "2.8.1" dependencies = [ "amplify_syn", "heck 0.5.0", @@ -2283,13 +2113,11 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.7.2" +version = "2.8.1" dependencies = [ "amplify", - "ascii-armor", "baid64", - "half", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_json", "serde_yaml", @@ -2335,7 +2163,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -2357,9 +2185,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", @@ -2404,7 +2232,7 @@ checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", ] [[package]] @@ -2517,7 +2345,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -2582,6 +2410,20 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ultrasonic" +version = "0.12.0-beta.4" +dependencies = [ + "amplify", + "baid64", + "commit_verify", + "getrandom", + "serde", + "strict_encoding", + "wasm-bindgen", + "zk-aluvm", +] + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -2659,7 +2501,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vesper-lang" -version = "0.1.0" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd2b7e3e27aeb0524204e58042f6e4531a720745d1b1a3978d3a084f1885f63d" dependencies = [ "amplify", "strict_encoding", @@ -2701,7 +2545,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", "wasm-bindgen-shared", ] @@ -2735,7 +2579,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3003,5 +2847,17 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.95", +] + +[[package]] +name = "zk-aluvm" +version = "0.12.0-beta.4" +dependencies = [ + "aluvm", + "amplify", + "getrandom", + "serde", + "strict_encoding", + "wasm-bindgen", ] diff --git a/Cargo.toml b/Cargo.toml index 7140ef0..fc04ff9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,16 +46,12 @@ bp-wallet = { path = "./bp-wallet", features = [ ] } ## rgb rgb-runtime = { path = "./rgb", features = [ - "electrum_blocking", - "esplora_blocking", + # "electrum_blocking", + # "esplora_blocking", "fs", "serde", ] } -rgb-psbt = { path = "./rgb/psbt" } -## rgb-interfaces -rgb-interfaces = { path = "./rgb-interfaces" } -## rgb-schemata -rgb-schemata = { path = "./rgb-schemata" } +rgb-psbt = { path = "./rgb/psbt", features = ["bp"] } ## rgb-std rgb-std = { path = "./rgb-std", features = ["fs"] } ## rust-amplify @@ -67,16 +63,15 @@ strict_types = { path = "./strict-types" } [patch.crates-io] # patching all RGB-related deps, to measure code coverage +## rust-amplify +amplify = { path = "./rust-amplify" } ## amplify-derive amplify_derive = { path = "./amplify-derive" } amplify_syn = { path = "./amplify-derive/syn" } ## amplify-nonasync nonasync = { path = "./amplify-nonasync" } ## amplify-num -amplify_apfloat = { path = "./amplify-num/apfloat" } amplify_num = { path = "./amplify-num/num" } -## ascii-armor -ascii-armor = { path = "./ascii-armor" } ## baid64 baid64 = { path = "./rust-baid64" } ## bp-core @@ -105,21 +100,16 @@ rgb-runtime = { path = "./rgb" } rgb-psbt = { path = "./rgb/psbt" } ## rgb-core rgb-core = { path = "./rgb-core" } -## rgb-interfaces -rgb-interfaces = { path = "./rgb-interfaces" } -## rgb-schemata -rgb-schemata = { path = "./rgb-schemata" } ## rgb-std rgb-std = { path = "./rgb-std" } -rgb-invoice = { path = "./rgb-std/invoice" } ## rust-aluvm aluvm = { path = "./rust-aluvm" } -## rust-amplify -amplify = { path = "./rust-amplify" } +zk-aluvm = { path = "./zk-aluvm" } +## SONIC +ultrasonic = { path = "./ultrasonic" } +hypersonic = { path = "./sonic" } ## strict-encoding strict_encoding = { path = "./strict-encoding/rust" } strict_encoding_derive = { path = "./strict-encoding/rust/derive" } ## strict-types strict_types = { path = "./strict-types" } -## vesper -vesper-lang = { path = "./vesper" } diff --git a/amplify-nonasync b/amplify-nonasync index 1a5ecbf..9f4f586 160000 --- a/amplify-nonasync +++ b/amplify-nonasync @@ -1 +1 @@ -Subproject commit 1a5ecbf8d9eb8616cf0c091ceee6ff2fcc941780 +Subproject commit 9f4f5861d0fe314c2928a3e0f516f69c7377c2d3 diff --git a/amplify-num b/amplify-num index be035c1..98cda24 160000 --- a/amplify-num +++ b/amplify-num @@ -1 +1 @@ -Subproject commit be035c1ed260313217bd799bd47cbc9bdfdf27ec +Subproject commit 98cda24f2ed2d19ffaba743f59f9ad34464bb492 diff --git a/ascii-armor b/ascii-armor deleted file mode 160000 index 3d8b4cb..0000000 --- a/ascii-armor +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3d8b4cb5a20c6ec5ec41fae4d88f3f0004917072 diff --git a/bp-core b/bp-core index a928721..38939b3 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit a9287214102c70be45f05dec1aba3decb62d3173 +Subproject commit 38939b3b33e68045fdf1a4b78c13ea5ca9e8ec02 diff --git a/bp-electrum-client b/bp-electrum-client index a660268..1d2b08a 160000 --- a/bp-electrum-client +++ b/bp-electrum-client @@ -1 +1 @@ -Subproject commit a66026874b948479b14aa5f01629c677ae005abc +Subproject commit 1d2b08ada85b742d8a0f7548ed6bb5a760aef51e diff --git a/bp-esplora-client b/bp-esplora-client index 87e487e..ed54091 160000 --- a/bp-esplora-client +++ b/bp-esplora-client @@ -1 +1 @@ -Subproject commit 87e487e1aa8547833253f951929769a646e9387f +Subproject commit ed54091c5f72af0e7a8b63932a6eb8a1aa12d041 diff --git a/bp-std b/bp-std index f81848a..091ac1e 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit f81848a0751e073c92881c2d6c9c06c87e7a58bd +Subproject commit 091ac1ebd7d59b4b7ba01e00d1dd14c5fb32c14d diff --git a/bp-wallet b/bp-wallet index 429c853..1787494 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 429c853ad424d0d4e08b6b496b35fe8a4b64a321 +Subproject commit 1787494ca47d72bb35cdf848295b24c92db188bf diff --git a/client_side_validation b/client_side_validation index 7215fb5..6746486 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit 7215fb50a7ef56f090a051dffe23a3c318bb8351 +Subproject commit 67464863d8dae8aaf52807cc0b07a198232ac5b2 diff --git a/rgb b/rgb index 55a814a..e6adad0 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 55a814a6ff37677934e764790e4e0b31a5d0f18b +Subproject commit e6adad01a73a81434368984ddc21f0a43d92c552 diff --git a/rgb-core b/rgb-core index 52592c6..5dbad49 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 52592c62f9f0ba32b3deab69725f2fd6cd6784c4 +Subproject commit 5dbad491d06d616c69ae2e84b3a0c9b8065ff38b diff --git a/rgb-interfaces b/rgb-interfaces deleted file mode 160000 index 70b5528..0000000 --- a/rgb-interfaces +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 70b5528cb2b93dae57796373fd9ef81506cae352 diff --git a/rgb-schemata b/rgb-schemata deleted file mode 160000 index 7a66a9b..0000000 --- a/rgb-schemata +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7a66a9b02a3a36d3f121cbc5833fe876caf9f1f2 diff --git a/rgb-std b/rgb-std index b374468..fe00f28 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit b3744689e7ff2603b7093afdea09db50d032c5ca +Subproject commit fe00f2820c2bc05df16080e499b24496f0456e4d diff --git a/rust-aluvm b/rust-aluvm index b671b88..c1a9225 160000 --- a/rust-aluvm +++ b/rust-aluvm @@ -1 +1 @@ -Subproject commit b671b8803c0b843881c017c759d7c0dc1ef816ea +Subproject commit c1a9225398db4b912161bff40890fde86404d76e diff --git a/rust-amplify b/rust-amplify index d01b9f5..cc510c3 160000 --- a/rust-amplify +++ b/rust-amplify @@ -1 +1 @@ -Subproject commit d01b9f52c23e839c6620f68d1bf9099152178f6d +Subproject commit cc510c350e2fcc2d1f7bf7de47a59e7f4a7520a2 diff --git a/rust-baid64 b/rust-baid64 index 983854a..7e6a7c3 160000 --- a/rust-baid64 +++ b/rust-baid64 @@ -1 +1 @@ -Subproject commit 983854a1b9be7c2cd7d98b00ab4df3e633be393a +Subproject commit 7e6a7c36013b30df597c85e6c3f3464d928e4563 diff --git a/sonic b/sonic new file mode 160000 index 0000000..7abeadb --- /dev/null +++ b/sonic @@ -0,0 +1 @@ +Subproject commit 7abeadb9af079b066c1b420aeaaa7a9fc778eb95 diff --git a/strict-encoding b/strict-encoding index b11845c..f7be0a7 160000 --- a/strict-encoding +++ b/strict-encoding @@ -1 +1 @@ -Subproject commit b11845c2d811d87c69a597b6602914141ca31227 +Subproject commit f7be0a7a046fe97289bda5f0b13bd57d7108b61e diff --git a/strict-types b/strict-types index b353f5d..0292feb 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit b353f5dbc0076dae918ac14175d347a3cc1aad0c +Subproject commit 0292feb72ffa51dccbaaabc4e6e0ba9ad9a5ebbc diff --git a/ultrasonic b/ultrasonic new file mode 160000 index 0000000..cb63461 --- /dev/null +++ b/ultrasonic @@ -0,0 +1 @@ +Subproject commit cb634619676a319b818a36604ce2a317c0a3c447 diff --git a/zk-aluvm b/zk-aluvm new file mode 160000 index 0000000..08bf763 --- /dev/null +++ b/zk-aluvm @@ -0,0 +1 @@ +Subproject commit 08bf763f88f84a2c6a6c0f2b72fbab365d649754 From ff1d881c8e2614f8e8c66f76846e2a8c18a4a222 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Feb 2025 21:31:27 +0800 Subject: [PATCH 02/90] chore(test): upgrade rgb-test infra with bitlight's local-env images Signed-off-by: will-bitlightlabs --- tests/.env | 21 ++ tests/docker/.env | 21 ++ tests/docker/docker-compose.yml | 291 ++++++++++++++++++++++++ tests/docker/start_services.sh | 384 ++++++++++++++++++++++++++++++++ 4 files changed, 717 insertions(+) create mode 100644 tests/.env create mode 100644 tests/docker/.env create mode 100644 tests/docker/docker-compose.yml create mode 100755 tests/docker/start_services.sh diff --git a/tests/.env b/tests/.env new file mode 100644 index 0000000..92ae4c2 --- /dev/null +++ b/tests/.env @@ -0,0 +1,21 @@ +# RPC NAME AND PASSWORD +RPC_USER=bitcoin +RPC_PASSWORD=bitcoin +# Bitcoin Core RPC Port +BITCOIN_RPC_PORT_1=18443 +BITCOIN_RPC_PORT_2=18444 +BITCOIN_RPC_PORT_3=18445 +# Electrum RPC Port +ELECTRUM_PORT_1=50001 +ELECTRUM_PORT_2=50002 +ELECTRUM_PORT_3=50003 +# Electrs HTTP API Port +API_PORT_1=3001 +API_PORT_2=3002 +API_PORT_3=3003 +# Esplora UI Port +EXPLORE_UI_PORT_1=5005 +EXPLORE_UI_PORT_2=5006 +EXPLORE_UI_PORT_3=5007 + + diff --git a/tests/docker/.env b/tests/docker/.env new file mode 100644 index 0000000..92ae4c2 --- /dev/null +++ b/tests/docker/.env @@ -0,0 +1,21 @@ +# RPC NAME AND PASSWORD +RPC_USER=bitcoin +RPC_PASSWORD=bitcoin +# Bitcoin Core RPC Port +BITCOIN_RPC_PORT_1=18443 +BITCOIN_RPC_PORT_2=18444 +BITCOIN_RPC_PORT_3=18445 +# Electrum RPC Port +ELECTRUM_PORT_1=50001 +ELECTRUM_PORT_2=50002 +ELECTRUM_PORT_3=50003 +# Electrs HTTP API Port +API_PORT_1=3001 +API_PORT_2=3002 +API_PORT_3=3003 +# Esplora UI Port +EXPLORE_UI_PORT_1=5005 +EXPLORE_UI_PORT_2=5006 +EXPLORE_UI_PORT_3=5007 + + diff --git a/tests/docker/docker-compose.yml b/tests/docker/docker-compose.yml new file mode 100644 index 0000000..9559e32 --- /dev/null +++ b/tests/docker/docker-compose.yml @@ -0,0 +1,291 @@ +volumes: + bitcoin-data-1: + bitcoin-data-2: + bitcoin-data-3: + +networks: + rgb-tests-1: + driver: bridge + ipam: + config: + - subnet: 172.30.1.0/24 + rgb-tests-2: + driver: bridge + ipam: + config: + - subnet: 172.30.2.0/24 + +services: + # Node 1 services (isolated network) + init-1: + networks: + - rgb-tests-1 + image: bitlightlabs/bitcoind:v27.0 + restart: "no" + entrypoint: /bin/sh + volumes: + - bitcoin-data-1:/data/.bitcoin + command: + - -c + - | + echo "Initializing bitcoind configuration for node 1" + echo "# Global settings" > /data/.bitcoin/bitcoin.conf + echo "server=1" >> /data/.bitcoin/bitcoin.conf + echo "discover=0" >> /data/.bitcoin/bitcoin.conf + echo "dns=0" >> /data/.bitcoin/bitcoin.conf + echo "dnsseed=0" >> /data/.bitcoin/bitcoin.conf + echo "upnp=0" >> /data/.bitcoin/bitcoin.conf + echo "natpmp=0" >> /data/.bitcoin/bitcoin.conf + echo "rpcuser=${RPC_USER}" >> /data/.bitcoin/bitcoin.conf + echo "rpcpassword=${RPC_PASSWORD}" >> /data/.bitcoin/bitcoin.conf + echo "rpcallowip=0.0.0.0/0" >> /data/.bitcoin/bitcoin.conf + echo "changetype=bech32" >> /data/.bitcoin/bitcoin.conf + echo "fallbackfee=0.0002" >> /data/.bitcoin/bitcoin.conf + echo "zmqpubrawblock=tcp://0.0.0.0:28332" >> /data/.bitcoin/bitcoin.conf + echo "zmqpubrawtx=tcp://0.0.0.0:28333" >> /data/.bitcoin/bitcoin.conf + echo "" >> /data/.bitcoin/bitcoin.conf + echo "# Regtest settings" >> /data/.bitcoin/bitcoin.conf + echo "[regtest]" >> /data/.bitcoin/bitcoin.conf + echo "regtest=1" >> /data/.bitcoin/bitcoin.conf + echo "listen=1" >> /data/.bitcoin/bitcoin.conf + echo "bind=0.0.0.0" >> /data/.bitcoin/bitcoin.conf + echo "port=18444" >> /data/.bitcoin/bitcoin.conf + echo "rpcbind=0.0.0.0" >> /data/.bitcoin/bitcoin.conf + echo "rpcport=18443" >> /data/.bitcoin/bitcoin.conf + echo "taproot=1" >> /data/.bitcoin/bitcoin.conf + + bitcoin-core-1: + networks: + rgb-tests-1: + ipv4_address: 172.30.1.205 + image: bitlightlabs/bitcoind:v27.0 + restart: on-failure + depends_on: + - init-1 + volumes: + - bitcoin-data-1:/data/.bitcoin + entrypoint: /bin/sh + ports: + - "${BITCOIN_RPC_PORT_1:-18443}:18443" + command: + - -c + - | + while [ ! -f /data/.bitcoin/bitcoin.conf ]; do sleep 1; done + bitcoind -regtest -rpcbind=0.0.0.0 -listenonion=0 + + esplora-api-1: + networks: + - rgb-tests-1 + image: bitlightlabs/esplora-api:latest + volumes: + - bitcoin-data-1:/data/.bitcoin + depends_on: + - bitcoin-core-1 + command: + - -vvvv + - --network + - regtest + - --daemon-dir + - /data/.bitcoin + - --daemon-rpc-addr + - 172.30.1.205:18443 + - --cors + - "*" + - --cookie + - "${RPC_USER:-bitcoin}:${RPC_PASSWORD:-bitcoin}" + - --http-addr + - "0.0.0.0:3000" + - --electrum-rpc-addr + - 0.0.0.0:50001 + ports: + - "${ELECTRUM_PORT_1:-50001}:50001" + - "${API_PORT_1:-3001}:3000" + + # Node 2 & 3 services (shared network) + init-2: + networks: + - rgb-tests-2 + image: bitlightlabs/bitcoind:v27.0 + restart: "no" + entrypoint: /bin/sh + volumes: + - bitcoin-data-2:/data/.bitcoin + command: + - -c + - | + echo "Initializing bitcoind configuration for node 2" + echo "# Global settings" > /data/.bitcoin/bitcoin.conf + echo "server=1" >> /data/.bitcoin/bitcoin.conf + echo "discover=0" >> /data/.bitcoin/bitcoin.conf + echo "dns=0" >> /data/.bitcoin/bitcoin.conf + echo "dnsseed=0" >> /data/.bitcoin/bitcoin.conf + echo "upnp=0" >> /data/.bitcoin/bitcoin.conf + echo "natpmp=0" >> /data/.bitcoin/bitcoin.conf + echo "rpcuser=${RPC_USER}" >> /data/.bitcoin/bitcoin.conf + echo "rpcpassword=${RPC_PASSWORD}" >> /data/.bitcoin/bitcoin.conf + echo "rpcallowip=0.0.0.0/0" >> /data/.bitcoin/bitcoin.conf + echo "changetype=bech32" >> /data/.bitcoin/bitcoin.conf + echo "fallbackfee=0.0002" >> /data/.bitcoin/bitcoin.conf + echo "zmqpubrawblock=tcp://0.0.0.0:28332" >> /data/.bitcoin/bitcoin.conf + echo "zmqpubrawtx=tcp://0.0.0.0:28333" >> /data/.bitcoin/bitcoin.conf + echo "" >> /data/.bitcoin/bitcoin.conf + echo "# Regtest settings" >> /data/.bitcoin/bitcoin.conf + echo "[regtest]" >> /data/.bitcoin/bitcoin.conf + echo "regtest=1" >> /data/.bitcoin/bitcoin.conf + echo "listen=1" >> /data/.bitcoin/bitcoin.conf + echo "bind=0.0.0.0" >> /data/.bitcoin/bitcoin.conf + echo "port=18444" >> /data/.bitcoin/bitcoin.conf + echo "rpcbind=0.0.0.0" >> /data/.bitcoin/bitcoin.conf + echo "rpcport=18443" >> /data/.bitcoin/bitcoin.conf + echo "taproot=1" >> /data/.bitcoin/bitcoin.conf + + init-3: + networks: + - rgb-tests-2 + image: bitlightlabs/bitcoind:v27.0 + restart: "no" + entrypoint: /bin/sh + volumes: + - bitcoin-data-3:/data/.bitcoin + command: + - -c + - | + echo "Initializing bitcoind configuration for node 3" + echo "# Global settings" > /data/.bitcoin/bitcoin.conf + echo "server=1" >> /data/.bitcoin/bitcoin.conf + echo "discover=0" >> /data/.bitcoin/bitcoin.conf + echo "dns=0" >> /data/.bitcoin/bitcoin.conf + echo "dnsseed=0" >> /data/.bitcoin/bitcoin.conf + echo "upnp=0" >> /data/.bitcoin/bitcoin.conf + echo "natpmp=0" >> /data/.bitcoin/bitcoin.conf + echo "rpcuser=${RPC_USER}" >> /data/.bitcoin/bitcoin.conf + echo "rpcpassword=${RPC_PASSWORD}" >> /data/.bitcoin/bitcoin.conf + echo "rpcallowip=0.0.0.0/0" >> /data/.bitcoin/bitcoin.conf + echo "changetype=bech32" >> /data/.bitcoin/bitcoin.conf + echo "fallbackfee=0.0002" >> /data/.bitcoin/bitcoin.conf + echo "zmqpubrawblock=tcp://0.0.0.0:28332" >> /data/.bitcoin/bitcoin.conf + echo "zmqpubrawtx=tcp://0.0.0.0:28333" >> /data/.bitcoin/bitcoin.conf + echo "" >> /data/.bitcoin/bitcoin.conf + echo "# Regtest settings" >> /data/.bitcoin/bitcoin.conf + echo "[regtest]" >> /data/.bitcoin/bitcoin.conf + echo "regtest=1" >> /data/.bitcoin/bitcoin.conf + echo "listen=1" >> /data/.bitcoin/bitcoin.conf + echo "bind=0.0.0.0" >> /data/.bitcoin/bitcoin.conf + echo "port=18444" >> /data/.bitcoin/bitcoin.conf + echo "rpcbind=0.0.0.0" >> /data/.bitcoin/bitcoin.conf + echo "rpcport=18443" >> /data/.bitcoin/bitcoin.conf + echo "taproot=1" >> /data/.bitcoin/bitcoin.conf + + bitcoin-core-2: + networks: + rgb-tests-2: + ipv4_address: 172.30.2.205 + image: bitlightlabs/bitcoind:v27.0 + restart: on-failure + depends_on: + - init-2 + volumes: + - bitcoin-data-2:/data/.bitcoin + entrypoint: /bin/sh + ports: + - "${BITCOIN_RPC_PORT_2:-18444}:18443" + - "28444:18444" + command: + - -c + - | + while [ ! -f /data/.bitcoin/bitcoin.conf ]; do sleep 1; done + bitcoind -regtest -rpcbind=0.0.0.0 -listenonion=0 -discover=0 -dns=0 + + bitcoin-core-3: + networks: + rgb-tests-2: + ipv4_address: 172.30.2.206 + image: bitlightlabs/bitcoind:v27.0 + restart: on-failure + depends_on: + - init-3 + volumes: + - bitcoin-data-3:/data/.bitcoin + entrypoint: /bin/sh + ports: + - "${BITCOIN_RPC_PORT_3:-18445}:18443" + - "28445:18444" + command: + - -c + - | + while [ ! -f /data/.bitcoin/bitcoin.conf ]; do sleep 1; done + bitcoind -regtest -rpcbind=0.0.0.0 -listenonion=0 -discover=0 -dns=0 + + esplora-api-2: + networks: + - rgb-tests-2 + image: bitlightlabs/esplora-api:latest + volumes: + - bitcoin-data-2:/data/.bitcoin + depends_on: + - bitcoin-core-2 + command: + - -vvvv + - --network + - regtest + - --daemon-dir + - /data/.bitcoin + - --daemon-rpc-addr + - 172.30.2.205:18443 + - --cors + - "*" + - --cookie + - "${RPC_USER:-bitcoin}:${RPC_PASSWORD:-bitcoin}" + - --http-addr + - "0.0.0.0:3000" + - --electrum-rpc-addr + - 0.0.0.0:50001 + ports: + - "${ELECTRUM_PORT_2:-50002}:50001" + - "${API_PORT_2:-3002}:3000" + + esplora-api-3: + networks: + - rgb-tests-2 + image: bitlightlabs/esplora-api:latest + volumes: + - bitcoin-data-3:/data/.bitcoin + depends_on: + - bitcoin-core-3 + command: + - -vvvv + - --network + - regtest + - --daemon-dir + - /data/.bitcoin + - --daemon-rpc-addr + - 172.30.2.206:18443 + - --cors + - "*" + - --cookie + - "${RPC_USER:-bitcoin}:${RPC_PASSWORD:-bitcoin}" + - --http-addr + - "0.0.0.0:3000" + - --electrum-rpc-addr + - 0.0.0.0:50001 + ports: + - "${ELECTRUM_PORT_3:-50003}:50001" + - "${API_PORT_3:-3003}:3000" + esplora-1: + image: bitlightlabs/esplora:latest + environment: + - API_URL=http://127.0.0.1:${API_PORT_1} + ports: + - "${EXPLORE_UI_PORT_1:-5005}:5000" + esplora-2: + image: bitlightlabs/esplora:latest + environment: + - API_URL=http://127.0.0.1:${API_PORT_2} + ports: + - "${EXPLORE_UI_PORT_2:-5006}:5000" + esplora-3: + image: bitlightlabs/esplora:latest + environment: + - API_URL=http://127.0.0.1:${API_PORT_3} + ports: + - "${EXPLORE_UI_PORT_3:-5007}:5000" diff --git a/tests/docker/start_services.sh b/tests/docker/start_services.sh new file mode 100755 index 0000000..eda3e9c --- /dev/null +++ b/tests/docker/start_services.sh @@ -0,0 +1,384 @@ +#!/usr/bin/env bash +# +# utility script to run and command regtest services +# + +name="./$(basename "$0")" + +COMPOSE="docker compose" +if ! $COMPOSE >/dev/null; then + echo "could not call docker compose (hint: install docker compose plugin)" + exit 1 +fi + +# Bitcoin CLI commands for each node +BITCOIN_CLI_1="$COMPOSE exec bitcoin-core-1 bitcoin-cli -regtest" +BITCOIN_CLI_2="$COMPOSE exec bitcoin-core-2 bitcoin-cli -regtest" +BITCOIN_CLI_3="$COMPOSE exec bitcoin-core-3 bitcoin-cli -regtest" + +# Node IP addresses +NODE2_IP="172.30.2.205" +NODE3_IP="172.30.2.206" + +INITIAL_BLOCKS=103 +WALLET_NAME="miner" + +# Load environment variables from .env file +if [ -f .env ]; then + export $(grep -v '^#' .env | xargs) +else + echo "ERR: .env file not found" + exit 1 +fi + +_die () { + echo "ERR: $*" + exit 1 +} + +_create_or_load_wallet() { + local cli_cmd=$1 + local node_num=$2 + + echo "Setting up wallet for node $node_num..." + + # Check if wallet is already loaded + if $cli_cmd listwallets 2>/dev/null | grep -q "\"$WALLET_NAME\""; then + echo "Wallet already loaded for node $node_num" + return 0 + fi + + # Check if wallet file exists + if $cli_cmd listwalletdir 2>/dev/null | grep -q "\"$WALLET_NAME\""; then + echo "Loading existing wallet for node $node_num" + if $cli_cmd loadwallet "$WALLET_NAME" 2>/dev/null; then + echo "Successfully loaded wallet for node $node_num" + return 0 + fi + else + echo "Creating new wallet for node $node_num" + if $cli_cmd createwallet "$WALLET_NAME" 2>/dev/null; then + echo "Successfully created wallet for node $node_num" + return 0 + fi + fi + + echo "Failed to create or load wallet for node $node_num" + return 1 +} + +# Function to check if a port is in use +_check_port_in_use() { + local port=$1 + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + if [ -n "$(netstat -an | grep LISTEN | grep ".$port")" ]; then + return 0 + else + return 1 + fi + else + # Linux + if [ -n "$(ss -HOlnt "sport = :$port")" ]; then + return 0 + else + return 1 + fi + fi +} + +_connect_nodes() { + # Ensure nodes 2 and 3 are connected to each other + echo "Establishing connection between nodes..." + + # Wait for nodes to be fully started and listening + sleep 5 + + # Clear existing connections + $BITCOIN_CLI_2 clearbanned + $BITCOIN_CLI_3 clearbanned + + # Use 'add' instead of 'onetry' for persistent connections + echo "Adding peer connections..." + $BITCOIN_CLI_2 addnode "$NODE3_IP:18444" "add" + $BITCOIN_CLI_3 addnode "$NODE2_IP:18444" "add" + + # Wait for connections to be established + local max_attempts=30 + local attempt=1 + + while [ $attempt -le $max_attempts ]; do + echo "Checking node connections (attempt $attempt/$max_attempts)..." + + # Get connection information + local peers_2=$($BITCOIN_CLI_2 getpeerinfo) + local peers_3=$($BITCOIN_CLI_3 getpeerinfo) + + # Check node 2's connections + local connected_2=$(echo "$peers_2" | grep -c "$NODE3_IP") + # Check node 3's connections + local connected_3=$(echo "$peers_3" | grep -c "$NODE2_IP") + + if [ "$connected_2" -gt 0 ] && [ "$connected_3" -gt 0 ]; then + echo "Nodes successfully connected" + + # Display detailed connection information + echo "Node 2 connections:" + $BITCOIN_CLI_2 getpeerinfo | grep "addr\|subver\|banscore" + echo "Node 3 connections:" + $BITCOIN_CLI_3 getpeerinfo | grep "addr\|subver\|banscore" + + return 0 + fi + + echo "Waiting for connections to establish..." + sleep 2 + attempt=$((attempt + 1)) + + # If near the last few attempts, try adding nodes again + if [ $attempt -eq $((max_attempts - 5)) ]; then + echo "Retrying node connections..." + $BITCOIN_CLI_2 addnode "$NODE3_IP:18444" "add" + $BITCOIN_CLI_3 addnode "$NODE2_IP:18444" "add" + fi + done + + echo "Failed to establish connections after $max_attempts attempts" + return 1 +} + +_wait_for_sync() { + echo "Waiting for block synchronization..." + local max_attempts=30 + local attempt=1 + + while [ $attempt -le $max_attempts ]; do + local height_2=$($BITCOIN_CLI_2 getblockcount) + local height_3=$($BITCOIN_CLI_3 getblockcount) + + if [ "$height_2" = "$height_3" ]; then + echo "Nodes synchronized at height $height_2" + return 0 + fi + + echo "Attempt $attempt: Node 2 height: $height_2, Node 3 height: $height_3" + sleep 2 + attempt=$((attempt + 1)) + done + + echo "Warning: Synchronization failed after $max_attempts attempts" + return 1 +} + +_check_network_status() { + echo "Checking network status..." + + # Check node 2's network information + echo "Node 2 connections:" + $BITCOIN_CLI_2 getpeerinfo | grep "addr\|subver" + + # Check node 3's network information + echo "Node 3 connections:" + $BITCOIN_CLI_3 getpeerinfo | grep "addr\|subver" +} + +_wait_for_bitcoin_ready() { + local cli_cmd=$1 + local node_num=$2 + local max_attempts=30 + local attempt=1 + + echo "Waiting for node $node_num to be ready..." + while [ $attempt -le $max_attempts ]; do + if $cli_cmd getblockchaininfo >/dev/null 2>&1; then + # Wait a bit more to ensure wallet system is also ready + sleep 2 + echo "Node $node_num is ready" + return 0 + fi + echo "Waiting for node $node_num... (attempt $attempt/$max_attempts)" + sleep 2 + attempt=$((attempt + 1)) + done + + echo "Timeout waiting for node $node_num" + return 1 +} + +_start_services() { + _stop_services + + # Check exposed ports + EXPOSED_PORTS=( + $BITCOIN_RPC_PORT_1 $ELECTRUM_PORT_1 $API_PORT_1 + $BITCOIN_RPC_PORT_2 $ELECTRUM_PORT_2 $API_PORT_2 + $BITCOIN_RPC_PORT_3 $ELECTRUM_PORT_3 $API_PORT_3 + ) + for port in "${EXPOSED_PORTS[@]}"; do + if _check_port_in_use "$port"; then + _die "port $port is already bound, services can't be started" + fi + done + + echo "Starting services..." + $COMPOSE up -d + + echo "Waiting for services to start..." + sleep 10 + + # Wait for all nodes to be ready + _wait_for_bitcoin_ready "$BITCOIN_CLI_1" "1" || _die "Node 1 failed to start" + _wait_for_bitcoin_ready "$BITCOIN_CLI_2" "2" || _die "Node 2 failed to start" + _wait_for_bitcoin_ready "$BITCOIN_CLI_3" "3" || _die "Node 3 failed to start" + + # Create or load wallets + echo "Setting up wallets..." + _create_or_load_wallet "$BITCOIN_CLI_1" "1" || _die "Failed to setup wallet for node 1" + _create_or_load_wallet "$BITCOIN_CLI_2" "2" || _die "Failed to setup wallet for node 2" + _create_or_load_wallet "$BITCOIN_CLI_3" "3" || _die "Failed to setup wallet for node 3" + + # Node 1 (isolated network) + echo "Generating initial blocks for node 1..." + $BITCOIN_CLI_1 -rpcwallet="$WALLET_NAME" -generate $INITIAL_BLOCKS > /dev/null + + # Node 2 & 3 (shared network) + # Establish and verify node connections + _connect_nodes + + # Generate blocks on node 2 + echo "Generating blocks on node 2..." + $BITCOIN_CLI_2 -rpcwallet="$WALLET_NAME" -generate $INITIAL_BLOCKS > /dev/null + + # Wait for synchronization + _wait_for_sync + + # Verify block heights are the same for nodes 2 and 3 + HEIGHT_2=$($BITCOIN_CLI_2 getblockcount) + HEIGHT_3=$($BITCOIN_CLI_3 getblockcount) + + if [ "$HEIGHT_2" = "$HEIGHT_3" ]; then + echo "Node 2 and Node 3 are synchronized at height $HEIGHT_2" + else + echo "Warning: Node 2 ($HEIGHT_2) and Node 3 ($HEIGHT_3) heights differ" + fi + + # Wait for Esplora services to start + echo "Waiting for Esplora services to start..." + sleep 10 + + echo "Setup completed successfully" +} + +_stop_services() { + echo "Stopping services..." + $COMPOSE down +} + +_clean_environment() { + echo "Cleaning up environment..." + # Stop all services + $COMPOSE down --remove-orphans + + # Remove all related docker volumes + echo "Removing volumes..." + docker volume ls -q | grep "rgb-tests" | xargs -r docker volume rm + + # Remove related docker networks + echo "Removing networks..." + docker network ls --filter name=rgb-tests -q | xargs -r docker network rm + + # Remove wallet data directory + echo "Removing wallet data..." + rm -rf data{core,index,ldk0,ldk1,ldk2} + + echo "Environment cleaned successfully" +} + +_mine() { + local node=$1 + local blocks=$2 + case $node in + 1) + $BITCOIN_CLI_1 -rpcwallet="$WALLET_NAME" -generate $blocks > /dev/null + ;; + 2) + $BITCOIN_CLI_2 -rpcwallet="$WALLET_NAME" -generate $blocks > /dev/null + ;; + 3) + $BITCOIN_CLI_3 -rpcwallet="$WALLET_NAME" -generate $blocks > /dev/null + ;; + *) + _die "Invalid node number: $node" + ;; + esac +} + +_help() { + echo "$name [-h|--help]" + echo " show this help message" + echo + echo "$name start" + echo " stop services, clean up, start services," + echo " create bitcoind wallets and generate initial blocks" + echo + echo "$name stop" + echo " stop services (preserving data)" + echo + echo "$name clean" + echo " clean up environment (remove volumes, networks)" + echo + echo "$name status" + echo " check network connection status" + echo + echo "$name mine " + echo " mine the requested number of blocks on specified node (1, 2, or 3)" +} + +# cmdline arguments +[ -z "$1" ] && _help +while [ -n "$1" ]; do + case $1 in + -h|--help) + _help + exit 0 + ;; + start) + start=1 + ;; + stop) + stop=1 + ;; + clean) + clean=1 + ;; + status) + _check_network_status + ;; + mine) + [ -n "$2" ] || _die "node number is required" + [ -n "$3" ] || _die "num blocks is required" + NODE_NUM="$2" + NUM_BLOCKS="$3" + mine=1 + shift 2 + ;; + *) + _die "unsupported argument \"$1\"" + ;; + esac + shift +done + +# start services if requested +[ "$start" = "1" ] && _start_services + +# stop services if requested +[ "$stop" = "1" ] && _stop_services + +# clean environment if requested +[ "$clean" = "1" ] && _clean_environment + +# mine blocks if requested +[ "$mine" = "1" ] && _mine $NODE_NUM $NUM_BLOCKS + +exit 0 From edd13e3c2d116f06eab127607b15b0e7b6a12e49 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Feb 2025 23:41:39 +0800 Subject: [PATCH 03/90] refactor: enhance RGB test infrastructure with improved Docker configuration Signed-off-by: will-bitlightlabs --- tests/.env => .env | 0 tests/docker/docker-compose.yml | 14 +++++ tests/docker/start_services.sh | 8 ++- tests/utils/chain.rs | 100 +++++++++++++++++++++++--------- tests/utils/mod.rs | 6 +- 5 files changed, 97 insertions(+), 31 deletions(-) rename tests/.env => .env (100%) diff --git a/tests/.env b/.env similarity index 100% rename from tests/.env rename to .env diff --git a/tests/docker/docker-compose.yml b/tests/docker/docker-compose.yml index 9559e32..8193ecf 100644 --- a/tests/docker/docker-compose.yml +++ b/tests/docker/docker-compose.yml @@ -1,3 +1,5 @@ +# Project name: rgb-tests +# Use with: docker compose -p rgb-tests volumes: bitcoin-data-1: bitcoin-data-2: @@ -18,6 +20,7 @@ networks: services: # Node 1 services (isolated network) init-1: + container_name: bitcoin-init-1 networks: - rgb-tests-1 image: bitlightlabs/bitcoind:v27.0 @@ -55,6 +58,7 @@ services: echo "taproot=1" >> /data/.bitcoin/bitcoin.conf bitcoin-core-1: + container_name: bitcoin-core-1 networks: rgb-tests-1: ipv4_address: 172.30.1.205 @@ -74,6 +78,7 @@ services: bitcoind -regtest -rpcbind=0.0.0.0 -listenonion=0 esplora-api-1: + container_name: esplora-api-1 networks: - rgb-tests-1 image: bitlightlabs/esplora-api:latest @@ -103,6 +108,7 @@ services: # Node 2 & 3 services (shared network) init-2: + container_name: bitcoin-init-2 networks: - rgb-tests-2 image: bitlightlabs/bitcoind:v27.0 @@ -140,6 +146,7 @@ services: echo "taproot=1" >> /data/.bitcoin/bitcoin.conf init-3: + container_name: bitcoin-init-3 networks: - rgb-tests-2 image: bitlightlabs/bitcoind:v27.0 @@ -177,6 +184,7 @@ services: echo "taproot=1" >> /data/.bitcoin/bitcoin.conf bitcoin-core-2: + container_name: bitcoin-core-2 networks: rgb-tests-2: ipv4_address: 172.30.2.205 @@ -197,6 +205,7 @@ services: bitcoind -regtest -rpcbind=0.0.0.0 -listenonion=0 -discover=0 -dns=0 bitcoin-core-3: + container_name: bitcoin-core-3 networks: rgb-tests-2: ipv4_address: 172.30.2.206 @@ -217,6 +226,7 @@ services: bitcoind -regtest -rpcbind=0.0.0.0 -listenonion=0 -discover=0 -dns=0 esplora-api-2: + container_name: esplora-api-2 networks: - rgb-tests-2 image: bitlightlabs/esplora-api:latest @@ -245,6 +255,7 @@ services: - "${API_PORT_2:-3002}:3000" esplora-api-3: + container_name: esplora-api-3 networks: - rgb-tests-2 image: bitlightlabs/esplora-api:latest @@ -272,18 +283,21 @@ services: - "${ELECTRUM_PORT_3:-50003}:50001" - "${API_PORT_3:-3003}:3000" esplora-1: + container_name: esplora-1 image: bitlightlabs/esplora:latest environment: - API_URL=http://127.0.0.1:${API_PORT_1} ports: - "${EXPLORE_UI_PORT_1:-5005}:5000" esplora-2: + container_name: esplora-2 image: bitlightlabs/esplora:latest environment: - API_URL=http://127.0.0.1:${API_PORT_2} ports: - "${EXPLORE_UI_PORT_2:-5006}:5000" esplora-3: + container_name: esplora-3 image: bitlightlabs/esplora:latest environment: - API_URL=http://127.0.0.1:${API_PORT_3} diff --git a/tests/docker/start_services.sh b/tests/docker/start_services.sh index eda3e9c..bf176fe 100755 --- a/tests/docker/start_services.sh +++ b/tests/docker/start_services.sh @@ -3,10 +3,14 @@ # utility script to run and command regtest services # +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + name="./$(basename "$0")" -COMPOSE="docker compose" -if ! $COMPOSE >/dev/null; then +COMPOSE="docker compose -p rgb-tests" +if ! docker compose version >/dev/null; then echo "could not call docker compose (hint: install docker compose plugin)" exit 1 fi diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 5b0b276..a2c35d8 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -27,21 +27,48 @@ pub fn initialize() { panic!("invalid indexer. possible values: `esplora` (default), `electrum`") } }); + if std::env::var("SKIP_INIT").is_ok() { println!("skipping services initialization"); return; } - let start_services_file = PathBuf::from("tests").join("start_services.sh"); + + let start_services_file = PathBuf::from("tests").join("docker").join("start_services.sh"); println!("starting test services..."); - let output = Command::new(start_services_file) - .env("PROFILE", INDEXER.get().unwrap().to_string()) + + let start_output = Command::new(&start_services_file) + .arg("start") .output() .expect("failed to start test services"); - if !output.status.success() { - println!("{output:?}"); + + if !start_output.status.success() { + println!("stdout: {}", String::from_utf8_lossy(&start_output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&start_output.stderr)); panic!("failed to start test services"); } - (INSTANCE_1..=INSTANCE_3).for_each(_wait_indexer_sync); + + // Wait for all nodes to be ready + for instance in INSTANCE_1..=INSTANCE_3 { + let mut attempts = 0; + let max_attempts = 30; + + loop { + if attempts >= max_attempts { + panic!("Node {instance} failed to start after {max_attempts} attempts"); + } + + let result = _bitcoin_cli_cmd(instance, vec!["getblockchaininfo"]); + if !result.is_empty() { + break; + } + + attempts += 1; + std::thread::sleep(Duration::from_secs(1)); + } + + // Wait for indexer sync + _wait_indexer_sync(instance); + } }); } @@ -61,35 +88,36 @@ fn _service_base_name() -> String { } fn _bitcoin_cli_cmd(instance: u8, args: Vec<&str>) -> String { - let compose_file = PathBuf::from("tests").join("docker-compose.yml"); + let compose_file = PathBuf::from("tests").join("docker").join("docker-compose.yml"); let mut bitcoin_cli = vec![ + s!("-p"), + s!("rgb-tests"), s!("-f"), compose_file.to_string_lossy().to_string(), s!("exec"), s!("-T"), ]; - let service_name = format!("{}_{instance}", _service_base_name()); - match INDEXER.get().unwrap() { - Indexer::Electrum => bitcoin_cli.extend(vec![ - "-u".to_string(), - "blits".to_string(), - service_name, - "bitcoin-cli".to_string(), - "-regtest".to_string(), - ]), - Indexer::Esplora => bitcoin_cli.extend(vec![service_name, "cli".to_string()]), - }; + + let service_name = format!("bitcoin-core-{instance}"); + bitcoin_cli.extend(vec![ + service_name, + "bitcoin-cli".to_string(), + "-regtest".to_string(), + ]); + let output = Command::new("docker") .stdin(Stdio::null()) .stderr(Stdio::null()) + .current_dir(PathBuf::from("tests").join("docker")) .arg("compose") .args(bitcoin_cli) .args(&args) .output() .unwrap_or_else(|_| panic!("failed to call bitcoind with args {args:?}")); + if !output.status.success() { println!("{output:?}"); - panic!("failed to get succesful output with args {args:?}"); + panic!("failed to get successful output with args {args:?}"); } String::from_utf8(output.stdout).unwrap().trim().to_string() } @@ -191,27 +219,47 @@ pub fn resume_mining() { } fn _get_connection_tuple() -> Vec<(u8, String)> { - let serive_base_name = _service_base_name(); vec![ - (INSTANCE_3, format!("{serive_base_name}_{INSTANCE_2}:18444")), - (INSTANCE_2, format!("{serive_base_name}_{INSTANCE_3}:18444")), + (INSTANCE_3, format!("172.30.2.205:18444")), // Node 2's IP and port + (INSTANCE_2, format!("172.30.2.206:18444")), // Node 3's IP and port ] } pub fn connect_reorg_nodes() { for (instance, node_addr) in _get_connection_tuple() { - _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "onetry"]); + _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "add"]); } + let t_0 = OffsetDateTime::now_utc(); + let mut attempt = 1; + let max_attempts = 30; + loop { - if (OffsetDateTime::now_utc() - t_0).as_seconds_f32() > 20.0 { - panic!("nodes are not syncing with each other") + if (OffsetDateTime::now_utc() - t_0).as_seconds_f32() > 60.0 { + panic!("nodes failed to sync after 60 seconds"); } + let height_2 = get_height_custom(INSTANCE_2); let height_3 = get_height_custom(INSTANCE_3); + if height_2 == height_3 { - break; + // Verify connections are established + let peers_2 = _bitcoin_cli_cmd(INSTANCE_2, vec!["getpeerinfo"]); + let peers_3 = _bitcoin_cli_cmd(INSTANCE_3, vec!["getpeerinfo"]); + + if peers_2.contains("172.30.2.206") && peers_3.contains("172.30.2.205") { + break; + } + } + + if attempt == max_attempts - 5 { + // Retry connections if near max attempts + for (instance, node_addr) in _get_connection_tuple() { + _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "add"]); + } } + + attempt += 1; std::thread::sleep(Duration::from_millis(500)); } } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 256c139..aaad430 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -9,9 +9,9 @@ pub const ELECTRUM_1_REGTEST_URL: &str = "127.0.0.1:50001"; pub const ELECTRUM_2_REGTEST_URL: &str = "127.0.0.1:50002"; pub const ELECTRUM_3_REGTEST_URL: &str = "127.0.0.1:50003"; pub const ELECTRUM_MAINNET_URL: &str = "ssl://electrum.iriswallet.com:50003"; -pub const ESPLORA_1_REGTEST_URL: &str = "http://127.0.0.1:8094/regtest/api"; -pub const ESPLORA_2_REGTEST_URL: &str = "http://127.0.0.1:8095/regtest/api"; -pub const ESPLORA_3_REGTEST_URL: &str = "http://127.0.0.1:8096/regtest/api"; +pub const ESPLORA_1_REGTEST_URL: &str = "http://127.0.0.1:3001"; +pub const ESPLORA_2_REGTEST_URL: &str = "http://127.0.0.1:3002"; +pub const ESPLORA_3_REGTEST_URL: &str = "http://127.0.0.1:3003"; pub const ESPLORA_MAINNET_URL: &str = "https://blockstream.info/api"; pub const FAKE_TXID: &str = "e5a3e577309df31bd606f48049049d2e1e02b048206ba232944fcc053a176ccb:0"; pub const UDA_FIXED_INDEX: u32 = 0; From b99378f207877a9528ab2cfb0b9ddf31404e538e Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 12 Feb 2025 16:30:06 +0800 Subject: [PATCH 04/90] chore: update submodules to v0.12 branch heads Signed-off-by: will-bitlightlabs --- bp-core | 2 +- bp-esplora-client | 2 +- bp-std | 2 +- bp-wallet | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-std | 2 +- rust-aluvm | 2 +- tests-dev-log/submodule-0212-update.log | 79 +++++++++++++++++++ .../submodules-0212-older-status.bak | 21 +++++ .../submodules-0212-updated-status.bak | 21 +++++ 11 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 tests-dev-log/submodule-0212-update.log create mode 100644 tests-dev-log/submodules-0212-older-status.bak create mode 100644 tests-dev-log/submodules-0212-updated-status.bak diff --git a/bp-core b/bp-core index 38939b3..6fbc7f1 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit 38939b3b33e68045fdf1a4b78c13ea5ca9e8ec02 +Subproject commit 6fbc7f16d028d12d6d1336a9aa7752ea8ae06e15 diff --git a/bp-esplora-client b/bp-esplora-client index ed54091..056891e 160000 --- a/bp-esplora-client +++ b/bp-esplora-client @@ -1 +1 @@ -Subproject commit ed54091c5f72af0e7a8b63932a6eb8a1aa12d041 +Subproject commit 056891e5f86aa3dac80628541e4e44fee0479507 diff --git a/bp-std b/bp-std index 091ac1e..91aaf51 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit 091ac1ebd7d59b4b7ba01e00d1dd14c5fb32c14d +Subproject commit 91aaf51498126f6a514f0d9af80888465e5dbfee diff --git a/bp-wallet b/bp-wallet index 1787494..5546f0a 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 1787494ca47d72bb35cdf848295b24c92db188bf +Subproject commit 5546f0ad5d7aee3d8d92d4a5604095cf2ec834fe diff --git a/rgb b/rgb index e6adad0..bc2b889 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit e6adad01a73a81434368984ddc21f0a43d92c552 +Subproject commit bc2b88921e8886238f0ac0d00ed9a43edf3289c2 diff --git a/rgb-core b/rgb-core index 5dbad49..4a020e0 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 5dbad491d06d616c69ae2e84b3a0c9b8065ff38b +Subproject commit 4a020e09dcf4e30edc41432e3c9f92f3c13ad0ac diff --git a/rgb-std b/rgb-std index fe00f28..a368811 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit fe00f2820c2bc05df16080e499b24496f0456e4d +Subproject commit a368811a2fbaf8385d8da6de7bf5a2ce3d01e8af diff --git a/rust-aluvm b/rust-aluvm index c1a9225..8b009cd 160000 --- a/rust-aluvm +++ b/rust-aluvm @@ -1 +1 @@ -Subproject commit c1a9225398db4b912161bff40890fde86404d76e +Subproject commit 8b009cde66a210e35b7db6b2cb36ab2bc2fa60cd diff --git a/tests-dev-log/submodule-0212-update.log b/tests-dev-log/submodule-0212-update.log new file mode 100644 index 0000000..2d71204 --- /dev/null +++ b/tests-dev-log/submodule-0212-update.log @@ -0,0 +1,79 @@ +---- submodule: rgb-std +Previous HEAD position was fe00f28 chore: fix clippy lints +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: rust-aluvm +Previous HEAD position was c1a9225 Merge branch 'v0.12' +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: rgb-interfaces +Previous HEAD position was 70b5528 chore: release v0.11.0-beta.9 +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: client_side_validation +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: bp-core +Previous HEAD position was 38939b3 chore: update dependnecies +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: rgb-core +Previous HEAD position was 5dbad491 release v0.12.0-beta.4 +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: bp-std +Previous HEAD position was 091ac1e chore: fix clippy lints +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: rgb-schemata +WARNING: branch "v0.12" not found +---- submodule: strict-types +WARNING: branch "v0.12" not found +---- submodule: strict-encoding +WARNING: branch "v0.12" not found +---- submodule: bp-electrum-client +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: rust-amplify +WARNING: branch "v0.12" not found +---- submodule: rgb +Previous HEAD position was e6adad0 chore: add description to rgb-wallet crate +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: bp-wallet +Previous HEAD position was 1787494 chore: update dependencies in convert crate +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: amplify-num +WARNING: branch "v0.12" not found +---- submodule: amplify-derive +WARNING: branch "v0.12" not found +---- submodule: ascii-armor +WARNING: branch "v0.12" not found +---- submodule: bp-esplora-client +Previous HEAD position was ed54091 chore: release v0.12.0-beta.4 +branch 'v0.12' set up to track 'origin/v0.12'. +Switched to a new branch 'v0.12' +Already up to date. +---- submodule: vesper +WARNING: branch "v0.12" not found +---- submodule: rust-baid64 +WARNING: branch "v0.12" not found +---- submodule: amplify-nonasync +WARNING: branch "v0.12" not found +---- submodule: zk-aluvm +WARNING: branch "v0.12" not found +---- submodule: ultrasonic +WARNING: branch "v0.12" not found +---- submodule: sonic +WARNING: branch "v0.12" not found \ No newline at end of file diff --git a/tests-dev-log/submodules-0212-older-status.bak b/tests-dev-log/submodules-0212-older-status.bak new file mode 100644 index 0000000..e26a642 --- /dev/null +++ b/tests-dev-log/submodules-0212-older-status.bak @@ -0,0 +1,21 @@ + bb36a490d68ccf7d574b5926bfc7f8b9509776f2 amplify-derive tags/v4.0.1) + 9f4f5861d0fe314c2928a3e0f516f69c7377c2d3 amplify-nonasync tags/v0.1.3) + 98cda24f2ed2d19ffaba743f59f9ad34464bb492 amplify-num tags/v0.5.3) + 38939b3b33e68045fdf1a4b78c13ea5ca9e8ec02 bp-core tags/v0.12.0-beta.4) + 1d2b08ada85b742d8a0f7548ed6bb5a760aef51e bp-electrum-client tags/v0.12.0-beta.4) + ed54091c5f72af0e7a8b63932a6eb8a1aa12d041 bp-esplora-client tags/v0.12.0-beta.4) + 091ac1ebd7d59b4b7ba01e00d1dd14c5fb32c14d bp-std tags/v0.12.0-beta.4) + 1787494ca47d72bb35cdf848295b24c92db188bf bp-wallet tags/v0.12.0-beta.4) + 67464863d8dae8aaf52807cc0b07a198232ac5b2 client_side_validation tags/v0.12.0-beta.4) + e6adad01a73a81434368984ddc21f0a43d92c552 rgb tags/v0.12.0-beta.4) + 5dbad491d06d616c69ae2e84b3a0c9b8065ff38b rgb-core tags/v0.12.0-beta.4) + fe00f2820c2bc05df16080e499b24496f0456e4d rgb-std tags/v0.12.0-beta.4) + c1a9225398db4b912161bff40890fde86404d76e rust-aluvm tags/v0.12.0-beta.4) + cc510c350e2fcc2d1f7bf7de47a59e7f4a7520a2 rust-amplify tags/v4.8.0) + 7e6a7c36013b30df597c85e6c3f3464d928e4563 rust-baid64 tags/v0.4.1) + 7abeadb9af079b066c1b420aeaaa7a9fc778eb95 sonic tags/v0.12.0-beta.4) + f7be0a7a046fe97289bda5f0b13bd57d7108b61e strict-encoding tags/v2.8.1) + 0292feb72ffa51dccbaaabc4e6e0ba9ad9a5ebbc strict-types tags/v2.8.1) + cb634619676a319b818a36604ce2a317c0a3c447 ultrasonic tags/v0.12.0-beta.4) + 6e1c889e9b951ac709d7db0e57d02dc427446527 vesper tags/v0.1.0) + 08bf763f88f84a2c6a6c0f2b72fbab365d649754 zk-aluvm tags/v0.12.0-beta.4) diff --git a/tests-dev-log/submodules-0212-updated-status.bak b/tests-dev-log/submodules-0212-updated-status.bak new file mode 100644 index 0000000..c3ab064 --- /dev/null +++ b/tests-dev-log/submodules-0212-updated-status.bak @@ -0,0 +1,21 @@ + bb36a490d68ccf7d574b5926bfc7f8b9509776f2 amplify-derive tags/v4.0.1) + 9f4f5861d0fe314c2928a3e0f516f69c7377c2d3 amplify-nonasync tags/v0.1.3) + 98cda24f2ed2d19ffaba743f59f9ad34464bb492 amplify-num tags/v0.5.3) + 6fbc7f16d028d12d6d1336a9aa7752ea8ae06e15 bp-core heads/v0.12) + 1d2b08ada85b742d8a0f7548ed6bb5a760aef51e bp-electrum-client tags/v0.12.0-beta.4) + 056891e5f86aa3dac80628541e4e44fee0479507 bp-esplora-client heads/v0.12) + 91aaf51498126f6a514f0d9af80888465e5dbfee bp-std heads/v0.12) + 5546f0ad5d7aee3d8d92d4a5604095cf2ec834fe bp-wallet heads/v0.12) + 67464863d8dae8aaf52807cc0b07a198232ac5b2 client_side_validation tags/v0.12.0-beta.4) + bc2b88921e8886238f0ac0d00ed9a43edf3289c2 rgb heads/v0.12) + 4a020e09dcf4e30edc41432e3c9f92f3c13ad0ac rgb-core heads/v0.12) + a368811a2fbaf8385d8da6de7bf5a2ce3d01e8af rgb-std heads/v0.12) + 8b009cde66a210e35b7db6b2cb36ab2bc2fa60cd rust-aluvm heads/v0.12) + cc510c350e2fcc2d1f7bf7de47a59e7f4a7520a2 rust-amplify tags/v4.8.0) + 7e6a7c36013b30df597c85e6c3f3464d928e4563 rust-baid64 tags/v0.4.1) + 7abeadb9af079b066c1b420aeaaa7a9fc778eb95 sonic tags/v0.12.0-beta.4) + f7be0a7a046fe97289bda5f0b13bd57d7108b61e strict-encoding tags/v2.8.1) + 0292feb72ffa51dccbaaabc4e6e0ba9ad9a5ebbc strict-types tags/v2.8.1) + cb634619676a319b818a36604ce2a317c0a3c447 ultrasonic tags/v0.12.0-beta.4) + 6e1c889e9b951ac709d7db0e57d02dc427446527 vesper tags/v0.1.0) + 08bf763f88f84a2c6a6c0f2b72fbab365d649754 zk-aluvm tags/v0.12.0-beta.4) From 45c450b27d13a4484ea18b7117365f90af7023b0 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 13 Feb 2025 11:20:48 +0800 Subject: [PATCH 05/90] chore: keep complex project organizations compiling properly Signed-off-by: will-bitlightlabs --- Cargo.lock | 220 ++++++--- Cargo.toml | 1 + sonic | 2 +- tests/DemoToken.yaml | 21 + tests/issuance.rs | 521 ++++++++++----------- tests/{stress.rs => stress.rs.bak} | 0 tests/{transfers.rs => transfers.rs.bak} | 0 tests/utils/mod.rs | 84 ++-- tests/{validation.rs => validation.rs.bak} | 0 ultrasonic | 2 +- 10 files changed, 485 insertions(+), 366 deletions(-) create mode 100644 tests/DemoToken.yaml rename tests/{stress.rs => stress.rs.bak} (100%) rename tests/{transfers.rs => transfers.rs.bak} (100%) rename tests/{validation.rs => validation.rs.bak} (100%) diff --git a/Cargo.lock b/Cargo.lock index ee0f266..829147f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,11 +163,17 @@ name = "baid64" version = "0.4.1" dependencies = [ "amplify", - "base64", + "base64 0.22.1", "mnemonic", "sha2", ] +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "base64" version = "0.22.1" @@ -249,6 +255,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "borrow-or-share" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" + [[package]] name = "bp-consensus" version = "0.12.0-beta.4" @@ -328,11 +340,12 @@ dependencies = [ "amplify", "bp-std", "log", + "minreq", "reqwest", "serde", - "serde_with", + "serde_with 3.11.0", "sha2", - "ureq", + "tokio", ] [[package]] @@ -344,6 +357,7 @@ dependencies = [ "bp-consensus", "commit_verify", "serde", + "strict_encoding", ] [[package]] @@ -387,7 +401,6 @@ dependencies = [ "bp-esplora", "bp-std", "descriptors", - "log", "nonasync", "psbt", "serde", @@ -528,15 +541,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" -dependencies = [ - "cfg-if", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -547,14 +551,38 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + [[package]] name = "darling" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.8", + "darling_macro 0.20.8", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -571,13 +599,24 @@ dependencies = [ "syn 2.0.95", ] +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core", + "darling_core 0.20.8", "quote", "syn 2.0.95", ] @@ -654,13 +693,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ffe3a660c3a1b10e96f304a9413d673b2118d62e4520f7ddf4a4faccfe8b9b9" [[package]] -name = "flate2" -version = "1.0.28" +name = "fluent-uri" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "1918b65d96df47d3591bed19c5cca17e3fa5d0707318e4b5ef2eae01764df7e5" dependencies = [ - "crc32fast", - "miniz_oxide", + "borrow-or-share", + "ref-cast", ] [[package]] @@ -989,10 +1028,9 @@ dependencies = [ "amplify", "commit_verify", "getrandom", - "indexmap 2.7.0", "serde", - "serde_yaml", "sonic-api", + "sonic-callreq", "strict_encoding", "strict_types", "ultrasonic", @@ -1176,6 +1214,18 @@ dependencies = [ "adler", ] +[[package]] +name = "minreq" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0c420feb01b9fb5061f8c8f452534361dd783756dcf38ec45191ce55e7a161" +dependencies = [ + "base64 0.12.3", + "log", + "serde", + "serde_json", +] + [[package]] name = "mio" version = "0.8.11" @@ -1417,7 +1467,7 @@ name = "psbt" version = "0.12.0-beta.4" dependencies = [ "amplify", - "base64", + "base64 0.22.1", "bp-core", "bp-derive", "commit_verify", @@ -1475,6 +1525,26 @@ dependencies = [ "bitflags 2.5.0", ] +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "regex" version = "1.10.4" @@ -1516,7 +1586,7 @@ version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-core", "futures-util", @@ -1565,13 +1635,29 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "rgb-invoice" +version = "0.12.0-beta.4" +dependencies = [ + "amplify", + "baid64", + "bp-core", + "bp-invoice", + "commit_verify", + "hypersonic", + "rgb-core", + "serde", + "sonic-callreq", + "strict_encoding", +] + [[package]] name = "rgb-psbt" version = "0.12.0-beta.4" dependencies = [ "amplify", + "bp-core", "bp-std", - "commit_verify", "rgb-std", ] @@ -1586,9 +1672,11 @@ dependencies = [ "getrandom", "indexmap 2.7.0", "nonasync", + "rgb-psbt", "rgb-std", "serde", "serde_yaml", + "strict_types", "wasm-bindgen", ] @@ -1598,12 +1686,15 @@ version = "0.12.0-beta.4" dependencies = [ "amplify", "bp-core", + "bp-invoice", "chrono", "commit_verify", "getrandom", "hypersonic", "rgb-core", + "rgb-invoice", "serde", + "serde_with 1.14.0", "single_use_seals", "strict_encoding", "strict_types", @@ -1749,7 +1840,6 @@ dependencies = [ "aws-lc-rs", "log", "once_cell", - "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1762,7 +1852,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] @@ -1938,13 +2028,23 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros 1.5.2", +] + [[package]] name = "serde_with" version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -1952,17 +2052,29 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serde_with_macros", + "serde_with_macros 3.11.0", "time", ] +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling 0.13.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_with_macros" version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ - "darling", + "darling 0.20.8", "proc-macro2", "quote", "syn 2.0.95", @@ -2056,17 +2168,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "socks" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" -dependencies = [ - "byteorder", - "libc", - "winapi", -] - [[package]] name = "sonic-api" version = "0.12.0-beta.4" @@ -2078,12 +2179,28 @@ dependencies = [ "commit_verify", "getrandom", "serde", + "sonic-callreq", "strict_encoding", "strict_types", "ultrasonic", "wasm-bindgen", ] +[[package]] +name = "sonic-callreq" +version = "0.12.0-beta.4" +dependencies = [ + "amplify", + "baid64", + "chrono", + "fluent-uri", + "indexmap 2.7.0", + "serde", + "strict_encoding", + "strict_types", + "ultrasonic", +] + [[package]] name = "spin" version = "0.9.8" @@ -2457,25 +2574,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" -dependencies = [ - "base64", - "flate2", - "log", - "once_cell", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "socks", - "url", - "webpki-roots", -] - [[package]] name = "url" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index fc04ff9..880c024 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,6 +108,7 @@ zk-aluvm = { path = "./zk-aluvm" } ## SONIC ultrasonic = { path = "./ultrasonic" } hypersonic = { path = "./sonic" } +sonic-callreq = { path = "./sonic/callreq" } ## strict-encoding strict_encoding = { path = "./strict-encoding/rust" } strict_encoding_derive = { path = "./strict-encoding/rust/derive" } diff --git a/sonic b/sonic index 7abeadb..debfacf 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 7abeadb9af079b066c1b420aeaaa7a9fc778eb95 +Subproject commit debfacf6ca53977abcdaa5c64450b0eb51049503 diff --git a/tests/DemoToken.yaml b/tests/DemoToken.yaml new file mode 100644 index 0000000..0a3582c --- /dev/null +++ b/tests/DemoToken.yaml @@ -0,0 +1,21 @@ +consensus: bitcoin +testnet: true +codexId: znwQGVhW-rfRa8el-pNaAsUW-UWxXsB_-4UlC~Tf-TERhBm4#mirage-queen-delphi +name: DemoToken +method: issue +timestamp: "2024-12-18T10:32:00-02:00" + +global: + - name: name + verified: Demo Token + - name: ticker + verified: DEMO + - name: precision + verified: centiMilli + - name: circulating + verified: 10000 + +owned: + - name: owned + seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 + data: 10000 diff --git a/tests/issuance.rs b/tests/issuance.rs index 16a7bdf..c3693d7 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -5,264 +5,263 @@ use utils::*; const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; -#[template] -#[rstest] -#[case(DescriptorType::Wpkh, CloseMethod::OpretFirst)] -#[case(DescriptorType::Wpkh, CloseMethod::TapretFirst)] -#[case(DescriptorType::Tr, CloseMethod::OpretFirst)] -#[case(DescriptorType::Tr, CloseMethod::TapretFirst)] -fn descriptor_and_close_method( - #[case] wallet_desc: DescriptorType, - #[case] close_method: CloseMethod, -) { -} - -#[apply(descriptor_and_close_method)] -fn issue_nia(wallet_desc: DescriptorType, close_method: CloseMethod) { - println!("wallet_desc {wallet_desc:?} close_method {close_method:?}"); - - initialize(); - - let mut wallet = get_wallet(&wallet_desc); - - let issued_supply = 999; - let ticker = "TCKR"; - let name = "asset name"; - let precision = 2; - let details = Some("some details"); - let terms_text = "Ricardian contract"; - let terms_media_fpath = Some(MEDIA_FPATH); - let asset_info = AssetInfo::nia( - ticker, - name, - precision, - details, - terms_text, - terms_media_fpath, - vec![issued_supply], - ); - let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); - - let contract = wallet.contract_iface_class::(contract_id); - let spec = contract.spec(); - assert_eq!(spec.ticker.to_string(), ticker.to_string()); - assert_eq!(spec.name.to_string(), name.to_string()); - assert_eq!(spec.precision.decimals(), precision); - let terms = contract.contract_terms(); - assert_eq!(terms.text.to_string(), terms_text.to_string()); - let terms_media = terms.media.unwrap(); - assert_eq!(terms_media.ty.to_string(), "image/jpeg"); - assert_eq!( - terms_media.digest.to_string(), - "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" - ); - assert_eq!(contract.total_issued_supply().value(), issued_supply); - - let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); - assert_eq!(allocations.len(), 1); - let allocation = allocations[0]; - assert_eq!(allocation.seal.method(), close_method); - assert_eq!(allocation.state, Amount::from(issued_supply)); -} - -#[apply(descriptor_and_close_method)] -fn issue_uda(wallet_desc: DescriptorType, close_method: CloseMethod) { - println!("wallet_desc {wallet_desc:?} close_method {close_method:?}"); - - initialize(); - - let mut wallet = get_wallet(&wallet_desc); - - let ticker = "TCKR"; - let name = "asset name"; - let details = Some("some details"); - let terms_text = "Ricardian contract"; - let terms_media_fpath = Some(MEDIA_FPATH); - let data = vec![1u8, 3u8, 9u8]; - let preview_ty = "image/jpeg"; - let token_data_preview = EmbeddedMedia { - ty: MediaType::with(preview_ty), - data: Confined::try_from(data.clone()).unwrap(), - }; - let proof = vec![2u8, 4u8, 6u8, 10u8]; - let token_data_reserves = ProofOfReserves { - utxo: Outpoint::from_str(FAKE_TXID).unwrap(), - proof: Confined::try_from(proof.clone()).unwrap(), - }; - let token_data_ticker = "TDTCKR"; - let token_data_name = "token data name"; - let token_data_details = "token data details"; - let token_data_attachment = attachment_from_fpath(MEDIA_FPATH); - let mut token_data_attachments = BTreeMap::new(); - for (idx, attachment_fpath) in ["README.md", "Cargo.toml"].iter().enumerate() { - token_data_attachments.insert(idx as u8, attachment_from_fpath(attachment_fpath)); - } - let token_data = uda_token_data( - token_data_ticker, - token_data_name, - token_data_details, - token_data_preview.clone(), - token_data_attachment.clone(), - token_data_attachments.clone(), - token_data_reserves.clone(), - ); - let asset_info = AssetInfo::uda( - ticker, - name, - details, - terms_text, - terms_media_fpath, - token_data, - ); - let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); - - let contract = wallet.contract_iface_class::(contract_id); - let spec = contract.spec(); - assert_eq!(spec.ticker.to_string(), ticker.to_string()); - assert_eq!(spec.name.to_string(), name.to_string()); - assert_eq!(spec.precision.decimals(), 0); - let terms = contract.contract_terms(); - assert_eq!(terms.text.to_string(), terms_text.to_string()); - let terms_media = terms.media.unwrap(); - assert_eq!(terms_media.ty.to_string(), "image/jpeg"); - assert_eq!( - terms_media.digest.to_string(), - "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" - ); - let token_data = contract.token_data(); - assert_eq!(token_data.index, TokenIndex::from(0)); - assert_eq!(token_data.ticker.unwrap().to_string(), token_data_ticker); - assert_eq!(token_data.name.unwrap().to_string(), token_data_name); - assert_eq!(token_data.details.unwrap().to_string(), token_data_details); - assert_eq!(token_data.preview.unwrap(), token_data_preview); - assert_eq!(token_data.media.unwrap(), token_data_attachment); - assert_eq!( - token_data.attachments.to_unconfined(), - token_data_attachments - ); - assert_eq!(token_data.reserves.unwrap(), token_data_reserves); - - let allocations = wallet.contract_data_allocations(contract_id, &iface_type_name); - assert_eq!(allocations.len(), 1); - let allocation = &allocations[0]; - assert_eq!(allocation.seal.method(), close_method); - assert_eq!(allocation.state.to_string(), "000000000100000000000000"); -} - -#[apply(descriptor_and_close_method)] -fn issue_cfa(wallet_desc: DescriptorType, close_method: CloseMethod) { - println!("wallet_desc {wallet_desc:?} close_method {close_method:?}"); - - initialize(); - - let mut wallet = get_wallet(&wallet_desc); - - let issued_supply = 999; - let name = "asset name"; - let precision = 2; - let details = Some("some details"); - let terms_text = "Ricardian contract"; - let terms_media_fpath = Some(MEDIA_FPATH); - let asset_info = AssetInfo::cfa( - name, - precision, - details, - terms_text, - terms_media_fpath, - vec![issued_supply], - ); - let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); - - let contract = wallet.contract_iface_class::(contract_id); - assert_eq!(contract.name().to_string(), name.to_string()); - assert_eq!( - contract.details().map(|d| d.to_string()), - details.map(|d| d.to_string()) - ); - assert_eq!(contract.precision().decimals(), precision); - let terms = contract.contract_terms(); - assert_eq!(terms.text.to_string(), terms_text.to_string()); - let terms_media = terms.media.unwrap(); - assert_eq!(terms_media.ty.to_string(), "image/jpeg"); - assert_eq!( - terms_media.digest.to_string(), - "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" - ); - assert_eq!(contract.total_issued_supply().value(), issued_supply); - - let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); - assert_eq!(allocations.len(), 1); - let allocation = allocations[0]; - assert_eq!(allocation.seal.method(), close_method); - assert_eq!(allocation.state, Amount::from(issued_supply)); -} - -#[apply(descriptor_and_close_method)] -fn issue_nia_multiple_utxos(wallet_desc: DescriptorType, close_method: CloseMethod) { - println!("wallet_desc {wallet_desc:?} close_method {close_method:?}"); - - initialize(); - - let mut wallet = get_wallet(&wallet_desc); - - let amounts = vec![222, 444, 333]; - let outpoints: Vec<_> = (0..amounts.len()) - .map(|_| Some(wallet.get_utxo(None))) - .collect(); - let asset_info = AssetInfo::default_nia(amounts.clone()); - let (contract_id, iface_type_name) = - wallet.issue_with_info(asset_info, close_method, outpoints.clone()); - - let contract = wallet.contract_iface_class::(contract_id); - assert_eq!( - contract.total_issued_supply().value(), - amounts.iter().sum::() - ); - - let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); - assert_eq!(allocations.len(), amounts.len()); - for (amt, outpoint) in amounts.iter().zip(outpoints.into_iter()) { - assert!(allocations.iter().any(|a| a.state == Amount::from(*amt) - && a.seal - == XChain::Bitcoin(ExplicitSeal { - method: close_method, - txid: outpoint.unwrap().txid, - vout: outpoint.unwrap().vout - }))) - } -} - -#[apply(descriptor_and_close_method)] -fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType, close_method: CloseMethod) { - println!("wallet_desc {wallet_desc:?} close_method {close_method:?}"); - - initialize(); - - let mut wallet = get_wallet(&wallet_desc); - - let amounts = vec![222, 444, 333]; - let outpoints: Vec<_> = (0..amounts.len()) - .map(|_| Some(wallet.get_utxo(None))) - .collect(); - let asset_info = AssetInfo::default_cfa(amounts.clone()); - let (contract_id, iface_type_name) = - wallet.issue_with_info(asset_info, close_method, outpoints.clone()); - - let contract = wallet.contract_iface_class::(contract_id); - assert_eq!( - contract.total_issued_supply().value(), - amounts.iter().sum::() - ); - - let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); - assert_eq!(allocations.len(), amounts.len()); - for (amt, outpoint) in amounts.iter().zip(outpoints.into_iter()) { - assert!(allocations.iter().any(|a| a.state == Amount::from(*amt) - && a.seal - == XChain::Bitcoin(ExplicitSeal { - method: close_method, - txid: outpoint.unwrap().txid, - vout: outpoint.unwrap().vout - }))) - } -} +// #[template] +// #[rstest] +// #[case(DescriptorType::Wpkh)] +// #[case(DescriptorType::Wpkh)] +// #[case(DescriptorType::Tr)] +// #[case(DescriptorType::Tr)] +// fn descriptor_and_close_method( +// #[case] wallet_desc: DescriptorType, +// ) { +// } + +// #[apply(descriptor_and_close_method)] +// fn issue_nia(wallet_desc: DescriptorType) { +// println!("wallet_desc {wallet_desc:?} "); + +// initialize(); + +// let mut wallet = get_wallet(&wallet_desc); + +// let issued_supply = 999; +// let ticker = "TCKR"; +// let name = "asset name"; +// let precision = 2; +// let details = Some("some details"); +// let terms_text = "Ricardian contract"; +// let terms_media_fpath = Some(MEDIA_FPATH); +// let asset_info = AssetInfo::nia( +// ticker, +// name, +// precision, +// details, +// terms_text, +// terms_media_fpath, +// vec![issued_supply], +// ); +// let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); + +// let contract = wallet.contract_iface_class::(contract_id); +// let spec = contract.spec(); +// assert_eq!(spec.ticker.to_string(), ticker.to_string()); +// assert_eq!(spec.name.to_string(), name.to_string()); +// assert_eq!(spec.precision.decimals(), precision); +// let terms = contract.contract_terms(); +// assert_eq!(terms.text.to_string(), terms_text.to_string()); +// let terms_media = terms.media.unwrap(); +// assert_eq!(terms_media.ty.to_string(), "image/jpeg"); +// assert_eq!( +// terms_media.digest.to_string(), +// "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" +// ); +// assert_eq!(contract.total_issued_supply().value(), issued_supply); + +// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); +// assert_eq!(allocations.len(), 1); +// let allocation = allocations[0]; +// // assert_eq!(allocation.seal.method(), close_method); +// assert_eq!(allocation.state, Amount::from(issued_supply)); +// } + +// #[apply(descriptor_and_close_method)] +// fn issue_uda(wallet_desc: DescriptorType) { +// println!("wallet_desc {wallet_desc:?} "); + +// initialize(); + +// let mut wallet = get_wallet(&wallet_desc); + +// let ticker = "TCKR"; +// let name = "asset name"; +// let details = Some("some details"); +// let terms_text = "Ricardian contract"; +// let terms_media_fpath = Some(MEDIA_FPATH); +// let data = vec![1u8, 3u8, 9u8]; +// let preview_ty = "image/jpeg"; +// let token_data_preview = EmbeddedMedia { +// ty: MediaType::with(preview_ty), +// data: Confined::try_from(data.clone()).unwrap(), +// }; +// let proof = vec![2u8, 4u8, 6u8, 10u8]; +// let token_data_reserves = ProofOfReserves { +// utxo: Outpoint::from_str(FAKE_TXID).unwrap(), +// proof: Confined::try_from(proof.clone()).unwrap(), +// }; +// let token_data_ticker = "TDTCKR"; +// let token_data_name = "token data name"; +// let token_data_details = "token data details"; +// let token_data_attachment = attachment_from_fpath(MEDIA_FPATH); +// let mut token_data_attachments = BTreeMap::new(); +// for (idx, attachment_fpath) in ["README.md", "Cargo.toml"].iter().enumerate() { +// token_data_attachments.insert(idx as u8, attachment_from_fpath(attachment_fpath)); +// } +// let token_data = uda_token_data( +// token_data_ticker, +// token_data_name, +// token_data_details, +// token_data_preview.clone(), +// token_data_attachment.clone(), +// token_data_attachments.clone(), +// token_data_reserves.clone(), +// ); +// let asset_info = AssetInfo::uda( +// ticker, +// name, +// details, +// terms_text, +// terms_media_fpath, +// token_data, +// ); +// let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); + +// let contract = wallet.contract_iface_class::(contract_id); +// let spec = contract.spec(); +// assert_eq!(spec.ticker.to_string(), ticker.to_string()); +// assert_eq!(spec.name.to_string(), name.to_string()); +// assert_eq!(spec.precision.decimals(), 0); +// let terms = contract.contract_terms(); +// assert_eq!(terms.text.to_string(), terms_text.to_string()); +// let terms_media = terms.media.unwrap(); +// assert_eq!(terms_media.ty.to_string(), "image/jpeg"); +// assert_eq!( +// terms_media.digest.to_string(), +// "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" +// ); +// let token_data = contract.token_data(); +// assert_eq!(token_data.index, TokenIndex::from(0)); +// assert_eq!(token_data.ticker.unwrap().to_string(), token_data_ticker); +// assert_eq!(token_data.name.unwrap().to_string(), token_data_name); +// assert_eq!(token_data.details.unwrap().to_string(), token_data_details); +// assert_eq!(token_data.preview.unwrap(), token_data_preview); +// assert_eq!(token_data.media.unwrap(), token_data_attachment); +// assert_eq!( +// token_data.attachments.to_unconfined(), +// token_data_attachments +// ); +// assert_eq!(token_data.reserves.unwrap(), token_data_reserves); + +// let allocations = wallet.contract_data_allocations(contract_id, &iface_type_name); +// assert_eq!(allocations.len(), 1); +// let allocation = &allocations[0]; +// assert_eq!(allocation.seal.method(), close_method); +// assert_eq!(allocation.state.to_string(), "000000000100000000000000"); +// } + +// #[apply(descriptor_and_close_method)] +// fn issue_cfa(wallet_desc: DescriptorType) { +// println!("wallet_desc {wallet_desc:?} "); + +// initialize(); + +// let mut wallet = get_wallet(&wallet_desc); + +// let issued_supply = 999; +// let name = "asset name"; +// let precision = 2; +// let details = Some("some details"); +// let terms_text = "Ricardian contract"; +// let terms_media_fpath = Some(MEDIA_FPATH); +// let asset_info = AssetInfo::cfa( +// name, +// precision, +// details, +// terms_text, +// terms_media_fpath, +// vec![issued_supply], +// ); +// let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); + +// let contract = wallet.contract_iface_class::(contract_id); +// assert_eq!(contract.name().to_string(), name.to_string()); +// assert_eq!( +// contract.details().map(|d| d.to_string()), +// details.map(|d| d.to_string()) +// ); +// assert_eq!(contract.precision().decimals(), precision); +// let terms = contract.contract_terms(); +// assert_eq!(terms.text.to_string(), terms_text.to_string()); +// let terms_media = terms.media.unwrap(); +// assert_eq!(terms_media.ty.to_string(), "image/jpeg"); +// assert_eq!( +// terms_media.digest.to_string(), +// "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" +// ); +// assert_eq!(contract.total_issued_supply().value(), issued_supply); + +// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); +// assert_eq!(allocations.len(), 1); +// let allocation = allocations[0]; +// assert_eq!(allocation.seal.method(), close_method); +// assert_eq!(allocation.state, Amount::from(issued_supply)); +// } + +// #[apply(descriptor_and_close_method)] +// fn issue_nia_multiple_utxos(wallet_desc: DescriptorType) { +// println!("wallet_desc {wallet_desc:?} "); + +// initialize(); + +// let mut wallet = get_wallet(&wallet_desc); + +// let amounts = vec![222, 444, 333]; +// let outpoints: Vec<_> = (0..amounts.len()) +// .map(|_| Some(wallet.get_utxo(None))) +// .collect(); +// let asset_info = AssetInfo::default_nia(amounts.clone()); +// let (contract_id, iface_type_name) = +// wallet.issue_with_info(asset_info, close_method, outpoints.clone()); + +// let contract = wallet.contract_iface_class::(contract_id); +// assert_eq!( +// contract.total_issued_supply().value(), +// amounts.iter().sum::() +// ); + +// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); +// assert_eq!(allocations.len(), amounts.len()); +// for (amt, outpoint) in amounts.iter().zip(outpoints.into_iter()) { +// assert!(allocations.iter().any(|a| a.state == Amount::from(*amt) +// && a.seal +// == XChain::Bitcoin(ExplicitSeal { +// method: close_method, +// txid: outpoint.unwrap().txid, +// vout: outpoint.unwrap().vout +// }))) +// } +// } + +// #[apply(descriptor_and_close_method)] +// fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { +// println!("wallet_desc {wallet_desc:?} "); + +// initialize(); + +// let mut wallet = get_wallet(&wallet_desc); + +// let amounts = vec![222, 444, 333]; +// let outpoints: Vec<_> = (0..amounts.len()) +// .map(|_| Some(wallet.get_utxo(None))) +// .collect(); +// let asset_info = AssetInfo::default_cfa(amounts.clone()); +// let (contract_id, iface_type_name) = +// wallet.issue_with_info(asset_info, close_method, outpoints.clone()); + +// let contract = wallet.contract_iface_class::(contract_id); +// assert_eq!( +// contract.total_issued_supply().value(), +// amounts.iter().sum::() +// ); + +// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); +// assert_eq!(allocations.len(), amounts.len()); +// for (amt, outpoint) in amounts.iter().zip(outpoints.into_iter()) { +// assert!(allocations.iter().any(|a| a.state == Amount::from(*amt) +// && a.seal +// == XChain::Bitcoin(ExplicitSeal { +// method: close_method, +// txid: outpoint.unwrap().txid, +// vout: outpoint.unwrap().vout +// }))) +// } +// } diff --git a/tests/stress.rs b/tests/stress.rs.bak similarity index 100% rename from tests/stress.rs rename to tests/stress.rs.bak diff --git a/tests/transfers.rs b/tests/transfers.rs.bak similarity index 100% rename from tests/transfers.rs rename to tests/transfers.rs.bak diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index aaad430..e34a931 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -1,5 +1,5 @@ -pub mod chain; -pub mod helpers; +// pub mod chain; +// pub mod helpers; pub const TEST_DATA_DIR: &str = "test-data"; pub const INTEGRATION_DATA_DIR: &str = "integration"; @@ -44,7 +44,7 @@ pub use amplify::{ }; use bitcoin_hashes::{sha256, Hash}; pub use bp::{ - seals::txout::{BlindSeal, CloseMethod, ExplicitSeal}, + // seals::txout::{BlindSeal, CloseMethod, ExplicitSeal}, ConsensusDecode, Outpoint, Sats, ScriptPubkey, SeqNo, Tx, Txid, Vout, }; pub use bpstd::{ @@ -59,49 +59,49 @@ pub use bpwallet::{ pub use descriptors::Wpkh; pub use electrum::{Client as ElectrumClient, ElectrumApi, Param}; pub use file_format::FileFormat; -pub use ifaces::{ - rgb20, rgb21, - rgb21::{EmbeddedMedia, TokenData}, - rgb25, IssuerWrapper, Rgb20, Rgb21, Rgb25, -}; +// pub use ifaces::{ +// rgb20, rgb21, +// rgb21::{EmbeddedMedia, TokenData}, +// rgb25, IssuerWrapper, Rgb20, Rgb21, Rgb25, +// }; pub use once_cell::sync::Lazy; pub use psbt::{ Beneficiary as PsbtBeneficiary, Payment, Prevout, Psbt, PsbtConstructor, PsbtMeta, PsbtVer, }; -pub use psrgbt::{RgbExt, RgbInExt, RgbPsbt, TxParams}; -pub use rand::RngCore; -pub use rgb::{ - info::ContractInfo, - interface::{AllocatedState, AssignmentsFilter, ContractOp, OpDirection}, - invoice::Pay2Vout, - persistence::{MemContract, MemContractState, Stock}, - resolvers::AnyResolver, - stl::ContractTerms, - validation::{Failure, ResolveWitness, Scripts, Validity, WitnessResolverError}, - vm::{WitnessOrd, WitnessPos, XWitnessTx}, - BlindingFactor, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, - RgbWallet, TapretKey, TransferParams, Transition, WalletProvider, XOutpoint, XWitnessId, -}; -pub use rgbstd::{ - containers::{ - BuilderSeal, ConsignmentExt, Fascia, FileContent, IndexedConsignment, Kit, Transfer, - ValidKit, - }, - interface::{ - ContractBuilder, ContractIface, DataAllocation, FilterExclude, FungibleAllocation, Iface, - IfaceClass, IfaceId, IfaceImpl, NamedField, - }, - invoice::{Beneficiary, RgbInvoice, RgbInvoiceBuilder, XChainNet}, - persistence::{fs::FsBinStore, PersistedState, SchemaIfaces, StashReadProvider}, - schema::SchemaId, - stl::{ - AssetSpec, Attachment, Details, MediaType, Name, ProofOfReserves, RicardianContract, Ticker, - }, - Allocation, Amount, ContractId, GlobalStateType, KnownState, Layer1, Operation, - OutputAssignment, OwnedFraction, Precision, Schema, TokenIndex, TxoSeal, XChain, -}; +// pub use psrgbt::{RgbExt, RgbInExt, RgbPsbt, TxParams}; +// pub use rand::RngCore; +// pub use rgb::{ +// info::ContractInfo, +// interface::{AllocatedState, AssignmentsFilter, ContractOp, OpDirection}, +// invoice::Pay2Vout, +// persistence::{MemContract, MemContractState, Stock}, +// resolvers::AnyResolver, +// stl::ContractTerms, +// validation::{Failure, ResolveWitness, Scripts, Validity, WitnessResolverError}, +// vm::{WitnessOrd, WitnessPos, XWitnessTx}, +// BlindingFactor, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, +// RgbWallet, TapretKey, TransferParams, Transition, WalletProvider, XOutpoint, XWitnessId, +// }; +// pub use rgbstd::{ +// containers::{ +// BuilderSeal, ConsignmentExt, Fascia, FileContent, IndexedConsignment, Kit, Transfer, +// ValidKit, +// }, +// interface::{ +// ContractBuilder, ContractIface, DataAllocation, FilterExclude, FungibleAllocation, Iface, +// IfaceClass, IfaceId, IfaceImpl, NamedField, +// }, +// invoice::{Beneficiary, RgbInvoice, RgbInvoiceBuilder, XChainNet}, +// persistence::{fs::FsBinStore, PersistedState, SchemaIfaces, StashReadProvider}, +// schema::SchemaId, +// stl::{ +// AssetSpec, Attachment, Details, MediaType, Name, ProofOfReserves, RicardianContract, Ticker, +// }, +// Allocation, Amount, ContractId, GlobalStateType, KnownState, Layer1, Operation, +// OutputAssignment, OwnedFraction, Precision, Schema, TokenIndex, TxoSeal, XChain, +// }; pub use rstest::rstest; -pub use schemata::{CollectibleFungibleAsset, NonInflatableAsset, UniqueDigitalAsset}; +// pub use schemata::{CollectibleFungibleAsset, NonInflatableAsset, UniqueDigitalAsset}; pub use serial_test::serial; pub use strict_encoding::{fname, tn, FieldName, StrictSerialize, TypeName}; pub use strict_types::{StrictVal, TypeSystem}; @@ -109,4 +109,4 @@ pub use strum::IntoEnumIterator; pub use strum_macros::EnumIter; pub use time::OffsetDateTime; -pub use crate::utils::{chain::*, helpers::*}; +// pub use crate::utils::{chain::*, helpers::*}; diff --git a/tests/validation.rs b/tests/validation.rs.bak similarity index 100% rename from tests/validation.rs rename to tests/validation.rs.bak diff --git a/ultrasonic b/ultrasonic index cb63461..2bb7be9 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit cb634619676a319b818a36604ce2a317c0a3c447 +Subproject commit 2bb7be96e316746363ff3e4f1f2ccb1c8496a94a From ff667b70324787d267632bce0719d37e18d99213 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 13 Feb 2025 13:44:11 +0800 Subject: [PATCH 06/90] feat(tests): add summary report for RGB v11 baseline test execution Signed-off-by: will-bitlightlabs --- tests/dev-log/first-test.log | 210 ++++++++++++++++++++++++++++++++++ tests/dev-log/test-summary.md | 57 +++++++++ tests/utils/chain.rs | 24 +++- 3 files changed, 287 insertions(+), 4 deletions(-) create mode 100644 tests/dev-log/first-test.log create mode 100644 tests/dev-log/test-summary.md diff --git a/tests/dev-log/first-test.log b/tests/dev-log/first-test.log new file mode 100644 index 0000000..d688062 --- /dev/null +++ b/tests/dev-log/first-test.log @@ -0,0 +1,210 @@ +$ SKIP_INIT=true cargo test +zsh: correct 'test' to 'tests' [nyae]? n + Compiling rgb-tests v0.1.0 (/Users/bincheng_paopao/project/repo/rust/myself/well/rgb-tests) + Building [=======================> ] 308/310: validation(... + Finished `test` profile [unoptimized + debuginfo] target(s) in 7.58s + Running tests/issuance.rs (target/debug/deps/issuance-e9f8eff5ebec6da9) + +running 20 tests +test issue_cfa::case_2 ... ok +test issue_cfa::case_1 ... ok +test issue_cfa::case_4 ... ok +test issue_cfa::case_3 ... ok +test issue_nia::case_1 ... ok +test issue_nia::case_2 ... ok +test issue_nia::case_3 ... ok +test issue_nia::case_4 ... ok +test issue_cfa_multiple_utxos::case_1 ... ok +test issue_cfa_multiple_utxos::case_2 ... ok +test issue_cfa_multiple_utxos::case_3 ... ok +test issue_cfa_multiple_utxos::case_4 ... ok +test issue_uda::case_1 ... ok +test issue_uda::case_2 ... ok +test issue_uda::case_4 ... ok +test issue_uda::case_3 ... ok +test issue_nia_multiple_utxos::case_2 ... ok +test issue_nia_multiple_utxos::case_1 ... ok +test issue_nia_multiple_utxos::case_4 ... ok +test issue_nia_multiple_utxos::case_3 ... ok + +test result: ok. 20 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 24.75s + + Running tests/stress.rs (target/debug/deps/stress-643c591558ebdbe5) + +running 6 tests +test back_and_forth::case_1 ... ignored, run a single case if desired +test back_and_forth::case_2 ... ignored, run a single case if desired +test back_and_forth::case_3 ... ignored, run a single case if desired +test back_and_forth::case_4 ... ignored, run a single case if desired +test back_and_forth::case_5 ... ignored, run a single case if desired +test back_and_forth::case_6 ... ignored, run a single case if desired + +test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out; finished in 0.00s + + Running tests/transfers.rs (target/debug/deps/transfers-cce5ca197e08de6d) + +running 101 tests +test blank_tapret_opret::case_1 ... ignored, fix needed +test blank_tapret_opret::case_3 ... ignored, fix needed +test blank_tapret_opret::case_4 ... ignored, fix needed +test invoice_reuse::case_1 ... ignored, probably not a bug, but still unexpected +test ln_transfers::case_2 ... ignored, fix needed +test mainnet_wlt_receiving_test_asset ... ok +test accept_0conf ... ok +test reorg_history::case_1 ... FAILED +test reorg_history::case_2 ... ignored, fix needed +test reorg_history::case_3 ... FAILED +test reorg_history::case_4 ... ignored, fix needed +test reorg_history::case_5 ... FAILED +test reorg_history::case_6 ... ignored, fix needed +test revert_genesis::case_1 ... ignored, fix needed +test revert_genesis::case_2 ... ignored, fix needed +test same_transfer_twice_no_update_witnesses::case_1 ... ignored, fix needed +test check_fungible_history ... ok +test same_transfer_twice_update_witnesses::case_1 ... ignored, fix needed +test invoice_reuse::case_2 ... ok +test ln_transfers::case_1 ... ok +test sync_mainnet_wlt ... ignored, fix needed +test same_transfer_twice_no_update_witnesses::case_2 - should panic ... ok +test rbf_transfer ... ok +test collaborative_transfer ... ok +test send_to_oneself ... ok +test blank_tapret_opret::case_2 ... ok +test same_transfer_twice_update_witnesses::case_2 ... ok +test receive_from_unbroadcasted_transfer_to_blinded ... ok +test tapret_wlt_receiving_opret ... ok +test transfer_loop::case_01 has been running for over 60 seconds +test transfer_loop::case_02 has been running for over 60 seconds +test transfer_loop::case_03 has been running for over 60 seconds +test transfer_loop::case_04 has been running for over 60 seconds +test transfer_loop::case_05 has been running for over 60 seconds +test transfer_loop::case_06 has been running for over 60 seconds +test transfer_loop::case_07 has been running for over 60 seconds +test transfer_loop::case_01 ... ok +test transfer_loop::case_02 ... ok +test transfer_loop::case_03 ... ok +test transfer_loop::case_05 ... ok +test transfer_loop::case_04 ... ok +test transfer_loop::case_06 ... ok +test transfer_loop::case_07 ... ok +test transfer_loop::case_08 has been running for over 60 seconds +test transfer_loop::case_08 ... ok +test transfer_loop::case_09 has been running for over 60 seconds +test transfer_loop::case_10 has been running for over 60 seconds +test transfer_loop::case_11 has been running for over 60 seconds +test transfer_loop::case_12 has been running for over 60 seconds +test transfer_loop::case_13 has been running for over 60 seconds +test transfer_loop::case_14 has been running for over 60 seconds +test transfer_loop::case_15 has been running for over 60 seconds +test transfer_loop::case_09 ... ok +test transfer_loop::case_11 ... ok +test transfer_loop::case_10 ... ok +test transfer_loop::case_13 ... ok +test transfer_loop::case_12 ... ok +test transfer_loop::case_14 ... ok +test transfer_loop::case_15 ... ok +test transfer_loop::case_16 has been running for over 60 seconds +test transfer_loop::case_16 ... ok +test transfer_loop::case_17 has been running for over 60 seconds +test transfer_loop::case_18 has been running for over 60 seconds +test transfer_loop::case_19 has been running for over 60 seconds +test transfer_loop::case_20 has been running for over 60 seconds +test transfer_loop::case_21 has been running for over 60 seconds +test transfer_loop::case_22 has been running for over 60 seconds +test transfer_loop::case_23 has been running for over 60 seconds +test transfer_loop::case_17 ... ok +test transfer_loop::case_19 ... ok +test transfer_loop::case_18 ... ok +test transfer_loop::case_21 ... ok +test transfer_loop::case_20 ... ok +test transfer_loop::case_22 ... ok +test transfer_loop::case_23 ... ok +test transfer_loop::case_24 has been running for over 60 seconds +test transfer_loop::case_24 ... ok +test transfer_loop::case_25 has been running for over 60 seconds +test transfer_loop::case_26 has been running for over 60 seconds +test transfer_loop::case_27 has been running for over 60 seconds +test transfer_loop::case_28 has been running for over 60 seconds +test transfer_loop::case_29 has been running for over 60 seconds +test transfer_loop::case_25 ... ok +test transfer_loop::case_27 ... ok +test transfer_loop::case_26 ... ok +test transfer_loop::case_30 has been running for over 60 seconds +test transfer_loop::case_28 ... ok +test transfer_loop::case_29 ... ok +test transfer_loop::case_31 has been running for over 60 seconds +test transfer_loop::case_30 ... ok +test transfer_loop::case_31 ... ok +test transfer_loop::case_32 has been running for over 60 seconds +test transfer_loop::case_37 ... ok +test transfer_loop::case_32 ... ok +test transfer_loop::case_38 ... ok +test transfer_loop::case_39 ... ok +test transfer_loop::case_33 has been running for over 60 seconds +test transfer_loop::case_34 has been running for over 60 seconds +test transfer_loop::case_35 has been running for over 60 seconds +test transfer_loop::case_36 has been running for over 60 seconds +test transfer_loop::case_33 ... ok +test transfer_loop::case_34 ... ok +test transfer_loop::case_35 ... ok +test transfer_loop::case_36 ... ok +test transfer_loop::case_41 ... ok +test transfer_loop::case_40 ... ok +test transfer_loop::case_42 ... ok +test transfer_loop::case_43 ... ok +test transfer_loop::case_45 ... ok +test transfer_loop::case_46 ... ok +test transfer_loop::case_44 ... ok +test transfer_loop::case_47 ... ok +test transfer_loop::case_49 ... ok +test transfer_loop::case_48 ... ok +test transfer_loop::case_50 ... ok +test transfer_loop::case_51 ... ok +test transfer_loop::case_53 ... ok +test transfer_loop::case_54 ... ok +test transfer_loop::case_52 ... ok +test transfer_loop::case_55 ... ok +test transfer_loop::case_57 ... ok +test transfer_loop::case_58 ... ok +test transfer_loop::case_56 ... ok +test transfer_loop::case_59 ... ok +test transfer_loop::case_61 ... ok +test transfer_loop::case_63 ... ok +test transfer_loop::case_62 ... ok +test transfer_loop::case_60 ... ok +test transfer_loop::case_65 ... ok +test transfer_loop::case_66 ... ok +test transfer_loop::case_64 ... ok +test transfer_loop::case_67 ... ok +test transfer_loop::case_70 ... ok +test transfer_loop::case_69 ... ok +test transfer_loop::case_68 ... ok +test transfer_loop::case_71 ... ok +test transfer_loop::case_72 ... ok + +failures: + +---- reorg_history::case_1 stdout ---- +history_type Linear reorg_type ChangeOrder +Output { status: ExitStatus(unix_wait_status(5888)), stdout: "", stderr: "" } +thread 'reorg_history::case_1' panicked at tests/utils/chain.rs:120:9: +failed to get successful output with args ["addnode", "172.30.2.205:18444", "add"] +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +---- reorg_history::case_3 stdout ---- +history_type Branching reorg_type ChangeOrder +Output { status: ExitStatus(unix_wait_status(5888)), stdout: "", stderr: "" } +thread 'reorg_history::case_3' panicked at tests/utils/chain.rs:120:9: +failed to get successful output with args ["addnode", "172.30.2.205:18444", "add"] + +---- reorg_history::case_5 stdout ---- +history_type Merging reorg_type ChangeOrder +Output { status: ExitStatus(unix_wait_status(5888)), stdout: "", stderr: "" } +thread 'reorg_history::case_5' panicked at tests/utils/chain.rs:120:9: +failed to get successful output with args ["addnode", "172.30.2.205:18444", "add"] + + +failures: + reorg_history::case_1 + reorg_history::case_3 + reorg_history::case_5 \ No newline at end of file diff --git a/tests/dev-log/test-summary.md b/tests/dev-log/test-summary.md new file mode 100644 index 0000000..681a3be --- /dev/null +++ b/tests/dev-log/test-summary.md @@ -0,0 +1,57 @@ +# RGB v11 基线测试执行情况汇总 + +## 测试执行概览 + +| 测试类型 | 总数 | 通过 | 失败 | 忽略 | +| ------------ | ---- | ---- | ---- | ---- | +| issuance.rs | 20 | 20 | 0 | 0 | +| stress.rs | 6 | 0 | 0 | 6 | +| transfers.rs | 101 | 86 | 3 | 12 | +| 总计 | 127 | 106 | 3 | 18 | + +## 详细测试状态 + +### V11遗留问题 (ignored, 需要在V12验证是否修复) +1. blank_tapret_opret::case_1 +2. blank_tapret_opret::case_3 +3. blank_tapret_opret::case_4 +4. invoice_reuse::case_1 (可能不是bug,但行为异常) +5. ln_transfers::case_2 +6. reorg_history::case_2 +7. reorg_history::case_4 +8. reorg_history::case_6 +9. revert_genesis::case_1 +10. revert_genesis::case_2 +11. same_transfer_twice_no_update_witnesses::case_1 +12. same_transfer_twice_update_witnesses::case_1 +13. sync_mainnet_wlt + +### BitLight改动引入的问题 (FAILED, 可能跟部署修改有关, 不影响主线) +1. reorg_history::case_1 (错误: addnode命令失败) +2. reorg_history::case_3 (错误: addnode命令失败) +3. reorg_history::case_5 (错误: addnode命令失败) + +### 正常通过的关键测试 (ok) +1. mainnet_wlt_receiving_test_asset +2. accept_0conf +3. check_fungible_history +4. invoice_reuse::case_2 +5. ln_transfers::case_1 +6. rbf_transfer +7. collaborative_transfer +8. send_to_oneself +9. receive_from_unbroadcasted_transfer_to_blinded +10. tapret_wlt_receiving_opret +11. transfer_loop::case_01 - case_72 (所有72个transfer_loop测试) + +## 分析总结 + +1. **成功率**: 83.5% (106/127) +2. **主要问题**: + - 旧版遗留主要集中在特殊交易场景, 需要后续在V12验证是否修复 + - BitLight改动引入的问题集中在重组历史相关的功能, 可能跟部署修改有关, 不影响主线 + +3. **稳定性评估**: + - 基本功能测试(issuance.rs)全部通过,表明核心功能稳定 + - 压力测试(stress.rs)全部被忽略,需要单独评估 + - 转账相关测试(transfers.rs)大部分通过,但存在一些特定场景的问题 \ No newline at end of file diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index a2c35d8..0f270fd 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -4,6 +4,12 @@ static INIT: Once = Once::new(); pub static INDEXER: OnceLock = OnceLock::new(); +// Node addresses +const NODE2_ADDR: &str = "172.30.2.205:18444"; +const NODE3_ADDR: &str = "172.30.2.206:18444"; +const NODE2_IP: &str = "172.30.2.205"; +const NODE3_IP: &str = "172.30.2.206"; + #[derive(Clone, Default, PartialEq, Eq, Debug)] pub enum Indexer { Electrum, @@ -220,14 +226,18 @@ pub fn resume_mining() { fn _get_connection_tuple() -> Vec<(u8, String)> { vec![ - (INSTANCE_3, format!("172.30.2.205:18444")), // Node 2's IP and port - (INSTANCE_2, format!("172.30.2.206:18444")), // Node 3's IP and port + (INSTANCE_3, NODE2_ADDR.to_string()), // Node 2's address + (INSTANCE_2, NODE3_ADDR.to_string()), // Node 3's address ] } pub fn connect_reorg_nodes() { for (instance, node_addr) in _get_connection_tuple() { - _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "add"]); + let peers = _bitcoin_cli_cmd(instance, vec!["getpeerinfo"]); + // println!("connect_reorg_nodes:instance:{} peers: {}", instance, peers); + if !peers.contains(&node_addr) { + _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "add"]); + } } let t_0 = OffsetDateTime::now_utc(); @@ -247,7 +257,7 @@ pub fn connect_reorg_nodes() { let peers_2 = _bitcoin_cli_cmd(INSTANCE_2, vec!["getpeerinfo"]); let peers_3 = _bitcoin_cli_cmd(INSTANCE_3, vec!["getpeerinfo"]); - if peers_2.contains("172.30.2.206") && peers_3.contains("172.30.2.205") { + if peers_2.contains(NODE3_IP) && peers_3.contains(NODE2_IP) { break; } } @@ -268,6 +278,12 @@ pub fn disconnect_reorg_nodes() { for (instance, node_addr) in _get_connection_tuple() { _bitcoin_cli_cmd(instance, vec!["disconnectnode", &node_addr]); } + + for (instance, _) in _get_connection_tuple() { + // dump peer info + let peers = _bitcoin_cli_cmd(instance, vec!["getpeerinfo"]); + println!("disconnect_reorg_nodes:instance:{} peers: {}", instance, peers); + } } pub fn get_height() -> u32 { From 3efb1d3901a92995257d2c1520bb9c38b6f7845e Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 13 Feb 2025 16:31:26 +0800 Subject: [PATCH 07/90] fix(tests): resolve node connection and reorg test issues Signed-off-by: will-bitlightlabs --- tests/dev-log/test-summary.md | 34 +-- .../{first-test.log => v11-first-test.log} | 0 tests/dev-log/v11-second-test.log | 196 ++++++++++++++++++ tests/docker-compose.yml | 76 ------- tests/docker/start_services.sh | 47 +---- tests/start_services.sh | 129 ------------ tests/utils/chain.rs | 73 +++---- 7 files changed, 248 insertions(+), 307 deletions(-) rename tests/dev-log/{first-test.log => v11-first-test.log} (100%) create mode 100644 tests/dev-log/v11-second-test.log delete mode 100644 tests/docker-compose.yml delete mode 100755 tests/start_services.sh diff --git a/tests/dev-log/test-summary.md b/tests/dev-log/test-summary.md index 681a3be..baa687e 100644 --- a/tests/dev-log/test-summary.md +++ b/tests/dev-log/test-summary.md @@ -2,12 +2,13 @@ ## 测试执行概览 -| 测试类型 | 总数 | 通过 | 失败 | 忽略 | -| ------------ | ---- | ---- | ---- | ---- | -| issuance.rs | 20 | 20 | 0 | 0 | -| stress.rs | 6 | 0 | 0 | 6 | -| transfers.rs | 101 | 86 | 3 | 12 | -| 总计 | 127 | 106 | 3 | 18 | +| 测试类型 | 总数 | 通过 | 失败 | 忽略 | +| ------------- | ---- | ---- | ---- | ---- | +| issuance.rs | 20 | 20 | 0 | 0 | +| stress.rs | 6 | 0 | 0 | 6 | +| transfers.rs | 101 | 88 | 0 | 13 | +| validation.rs | 6 | 5 | 0 | 1 | +| 总计 | 133 | 113 | 0 | 20 | ## 详细测试状态 @@ -25,11 +26,7 @@ 11. same_transfer_twice_no_update_witnesses::case_1 12. same_transfer_twice_update_witnesses::case_1 13. sync_mainnet_wlt - -### BitLight改动引入的问题 (FAILED, 可能跟部署修改有关, 不影响主线) -1. reorg_history::case_1 (错误: addnode命令失败) -2. reorg_history::case_3 (错误: addnode命令失败) -3. reorg_history::case_5 (错误: addnode命令失败) +14. validate_consignment_generate (one-shot) ### 正常通过的关键测试 (ok) 1. mainnet_wlt_receiving_test_asset @@ -43,15 +40,24 @@ 9. receive_from_unbroadcasted_transfer_to_blinded 10. tapret_wlt_receiving_opret 11. transfer_loop::case_01 - case_72 (所有72个transfer_loop测试) +12. reorg_history::case_1 +13. reorg_history::case_3 +14. reorg_history::case_5 +15. validate_consignment_chain_fail +16. validate_consignment_bundles_fail +17. validate_consignment_genesis_fail +18. validate_consignment_resolver_error +19. validate_consignment_success ## 分析总结 -1. **成功率**: 83.5% (106/127) +1. **成功率**: 85% (113/133) 2. **主要问题**: - 旧版遗留主要集中在特殊交易场景, 需要后续在V12验证是否修复 - - BitLight改动引入的问题集中在重组历史相关的功能, 可能跟部署修改有关, 不影响主线 + - 之前的节点连接问题已经解决,所有reorg_history测试都通过了 3. **稳定性评估**: - 基本功能测试(issuance.rs)全部通过,表明核心功能稳定 - 压力测试(stress.rs)全部被忽略,需要单独评估 - - 转账相关测试(transfers.rs)大部分通过,但存在一些特定场景的问题 \ No newline at end of file + - 转账相关测试(transfers.rs)大部分通过,剩余问题都是已知的V11遗留问题 + - 验证相关测试(validation.rs)表现良好,只有一个测试被忽略 \ No newline at end of file diff --git a/tests/dev-log/first-test.log b/tests/dev-log/v11-first-test.log similarity index 100% rename from tests/dev-log/first-test.log rename to tests/dev-log/v11-first-test.log diff --git a/tests/dev-log/v11-second-test.log b/tests/dev-log/v11-second-test.log new file mode 100644 index 0000000..f69d44b --- /dev/null +++ b/tests/dev-log/v11-second-test.log @@ -0,0 +1,196 @@ + Finished `test` profile [unoptimized + debuginfo] target(s) in 0.58s + Running tests/issuance.rs (target/debug/deps/issuance-e9f8eff5ebec6da9) + +running 20 tests +test issue_cfa::case_2 ... ok +test issue_cfa::case_1 ... ok +test issue_cfa::case_3 ... ok +test issue_cfa::case_4 ... ok +test issue_nia::case_1 ... ok +test issue_nia::case_4 ... ok +test issue_nia::case_3 ... ok +test issue_nia::case_2 ... ok +test issue_cfa_multiple_utxos::case_2 ... ok +test issue_cfa_multiple_utxos::case_3 ... ok +test issue_cfa_multiple_utxos::case_4 ... ok +test issue_cfa_multiple_utxos::case_1 ... ok +test issue_uda::case_4 ... ok +test issue_uda::case_2 ... ok +test issue_uda::case_3 ... ok +test issue_uda::case_1 ... ok +test issue_nia_multiple_utxos::case_1 ... ok +test issue_nia_multiple_utxos::case_2 ... ok +test issue_nia_multiple_utxos::case_3 ... ok +test issue_nia_multiple_utxos::case_4 ... ok + +test result: ok. 20 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 25.28s + + Running tests/stress.rs (target/debug/deps/stress-643c591558ebdbe5) + +running 6 tests +test back_and_forth::case_1 ... ignored, run a single case if desired +test back_and_forth::case_2 ... ignored, run a single case if desired +test back_and_forth::case_3 ... ignored, run a single case if desired +test back_and_forth::case_4 ... ignored, run a single case if desired +test back_and_forth::case_5 ... ignored, run a single case if desired +test back_and_forth::case_6 ... ignored, run a single case if desired + +test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out; finished in 0.00s + + Running tests/transfers.rs (target/debug/deps/transfers-cce5ca197e08de6d) + +running 101 tests +test blank_tapret_opret::case_1 ... ignored, fix needed +test blank_tapret_opret::case_3 ... ignored, fix needed +test blank_tapret_opret::case_4 ... ignored, fix needed +test invoice_reuse::case_1 ... ignored, probably not a bug, but still unexpected +test ln_transfers::case_2 ... ignored, fix needed +test mainnet_wlt_receiving_test_asset ... ok +test accept_0conf ... ok +test check_fungible_history ... ok +test reorg_history::case_2 ... ignored, fix needed +test invoice_reuse::case_2 ... ok +test reorg_history::case_4 ... ignored, fix needed +test ln_transfers::case_1 ... ok +test reorg_history::case_6 ... ignored, fix needed +test revert_genesis::case_1 ... ignored, fix needed +test revert_genesis::case_2 ... ignored, fix needed +test same_transfer_twice_no_update_witnesses::case_1 ... ignored, fix needed +test rbf_transfer ... ok +test same_transfer_twice_update_witnesses::case_1 ... ignored, fix needed +test collaborative_transfer ... ok +test blank_tapret_opret::case_2 ... ok +test sync_mainnet_wlt ... ignored, fix needed +test send_to_oneself ... ok +test same_transfer_twice_no_update_witnesses::case_2 - should panic ... ok +test receive_from_unbroadcasted_transfer_to_blinded ... ok +test same_transfer_twice_update_witnesses::case_2 ... ok +test reorg_history::case_1 has been running for over 60 seconds +test reorg_history::case_3 has been running for over 60 seconds +test reorg_history::case_5 has been running for over 60 seconds +test tapret_wlt_receiving_opret ... ok +test reorg_history::case_1 ... ok +test transfer_loop::case_01 has been running for over 60 seconds +test transfer_loop::case_02 has been running for over 60 seconds +test transfer_loop::case_03 has been running for over 60 seconds +test transfer_loop::case_04 has been running for over 60 seconds +test transfer_loop::case_01 ... ok +test transfer_loop::case_02 ... ok +test transfer_loop::case_03 ... ok +test transfer_loop::case_04 ... ok +test transfer_loop::case_05 has been running for over 60 seconds +test transfer_loop::case_06 has been running for over 60 seconds +test transfer_loop::case_05 ... ok +test reorg_history::case_3 ... ok +test transfer_loop::case_06 ... ok +test transfer_loop::case_07 has been running for over 60 seconds +test transfer_loop::case_08 has been running for over 60 seconds +test transfer_loop::case_09 has been running for over 60 seconds +test transfer_loop::case_10 has been running for over 60 seconds +test transfer_loop::case_08 ... ok +test transfer_loop::case_07 ... ok +test transfer_loop::case_09 ... ok +test transfer_loop::case_10 ... ok +test transfer_loop::case_11 has been running for over 60 seconds +test transfer_loop::case_12 has been running for over 60 seconds +test transfer_loop::case_13 has been running for over 60 seconds +test transfer_loop::case_11 ... ok +test transfer_loop::case_12 ... ok +test transfer_loop::case_13 ... ok +test reorg_history::case_5 ... ok +test transfer_loop::case_14 has been running for over 60 seconds +test transfer_loop::case_15 has been running for over 60 seconds +test transfer_loop::case_16 has been running for over 60 seconds +test transfer_loop::case_17 has been running for over 60 seconds +test transfer_loop::case_14 ... ok +test transfer_loop::case_15 ... ok +test transfer_loop::case_16 ... ok +test transfer_loop::case_17 ... ok +test transfer_loop::case_18 has been running for over 60 seconds +test transfer_loop::case_19 has been running for over 60 seconds +test transfer_loop::case_20 has been running for over 60 seconds +test transfer_loop::case_21 has been running for over 60 seconds +test transfer_loop::case_18 ... ok +test transfer_loop::case_19 ... ok +test transfer_loop::case_20 ... ok +test transfer_loop::case_21 ... ok +test transfer_loop::case_22 has been running for over 60 seconds +test transfer_loop::case_23 has been running for over 60 seconds +test transfer_loop::case_24 has been running for over 60 seconds +test transfer_loop::case_25 has been running for over 60 seconds +test transfer_loop::case_25 ... ok +test transfer_loop::case_22 ... ok +test transfer_loop::case_23 ... ok +test transfer_loop::case_24 ... ok +test transfer_loop::case_26 has been running for over 60 seconds +test transfer_loop::case_26 ... ok +test transfer_loop::case_27 has been running for over 60 seconds +test transfer_loop::case_28 has been running for over 60 seconds +test transfer_loop::case_29 has been running for over 60 seconds +test transfer_loop::case_27 ... ok +test transfer_loop::case_28 ... ok +test transfer_loop::case_29 ... ok +test transfer_loop::case_30 has been running for over 60 seconds +test transfer_loop::case_31 has been running for over 60 seconds +test transfer_loop::case_32 has been running for over 60 seconds +test transfer_loop::case_33 has been running for over 60 seconds +test transfer_loop::case_30 ... ok +test transfer_loop::case_33 ... ok +test transfer_loop::case_32 ... ok +test transfer_loop::case_31 ... ok +test transfer_loop::case_37 ... ok +test transfer_loop::case_34 has been running for over 60 seconds +test transfer_loop::case_34 ... ok +test transfer_loop::case_35 has been running for over 60 seconds +test transfer_loop::case_36 has been running for over 60 seconds +test transfer_loop::case_35 ... ok +test transfer_loop::case_36 ... ok +test transfer_loop::case_38 ... ok +test transfer_loop::case_41 ... ok +test transfer_loop::case_39 ... ok +test transfer_loop::case_40 ... ok +test transfer_loop::case_42 ... ok +test transfer_loop::case_43 ... ok +test transfer_loop::case_44 ... ok +test transfer_loop::case_45 ... ok +test transfer_loop::case_46 ... ok +test transfer_loop::case_47 ... ok +test transfer_loop::case_48 ... ok +test transfer_loop::case_49 ... ok +test transfer_loop::case_50 ... ok +test transfer_loop::case_51 ... ok +test transfer_loop::case_53 ... ok +test transfer_loop::case_54 ... ok +test transfer_loop::case_52 ... ok +test transfer_loop::case_55 ... ok +test transfer_loop::case_57 ... ok +test transfer_loop::case_56 ... ok +test transfer_loop::case_58 ... ok +test transfer_loop::case_59 ... ok +test transfer_loop::case_61 ... ok +test transfer_loop::case_62 ... ok +test transfer_loop::case_63 ... ok +test transfer_loop::case_60 ... ok +test transfer_loop::case_65 ... ok +test transfer_loop::case_64 ... ok +test transfer_loop::case_66 ... ok +test transfer_loop::case_67 ... ok +test transfer_loop::case_69 ... ok +test transfer_loop::case_68 ... ok +test transfer_loop::case_70 ... ok +test transfer_loop::case_71 ... ok +test transfer_loop::case_72 ... ok + +test result: ok. 88 passed; 0 failed; 13 ignored; 0 measured; 0 filtered out; finished in 623.16s + + Running tests/validation.rs (target/debug/deps/validation-7513d6bfd30f0852) + +running 6 tests +test validate_consignment_generate ... ignored, one-shot +test validate_consignment_chain_fail ... ok +test validate_consignment_bundles_fail ... ok +test validate_consignment_genesis_fail ... ok +test validate_consignment_resolver_error ... ok +test validate_consignment_success ... ok + +test result: ok. 5 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.36s \ No newline at end of file diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml deleted file mode 100644 index 037f580..0000000 --- a/tests/docker-compose.yml +++ /dev/null @@ -1,76 +0,0 @@ -services: - bitcoind_1: - image: registry.gitlab.com/hashbeam/docker/bitcoind:25.0 - profiles: [electrum] - command: "-fallbackfee=0.0002" - bitcoind_2: - image: registry.gitlab.com/hashbeam/docker/bitcoind:25.0 - profiles: [electrum] - command: "-fallbackfee=0.0002" - bitcoind_3: - image: registry.gitlab.com/hashbeam/docker/bitcoind:25.0 - profiles: [electrum] - command: "-fallbackfee=0.0002" - electrs_1: - image: registry.gitlab.com/hashbeam/docker/electrs:0.9.14 - profiles: [electrum] - environment: - BTCHOST: bitcoind_1 - ports: - - 50001:50001 - depends_on: - - bitcoind_1 - electrs_2: - image: registry.gitlab.com/hashbeam/docker/electrs:0.9.14 - profiles: [electrum] - environment: - BTCHOST: bitcoind_2 - ports: - - 50002:50001 - depends_on: - - bitcoind_2 - electrs_3: - image: registry.gitlab.com/hashbeam/docker/electrs:0.9.14 - profiles: [electrum] - environment: - BTCHOST: bitcoind_3 - ports: - - 50003:50001 - depends_on: - - bitcoind_3 - esplora_1: - image: blockstream/esplora:956c74f42eb6ad803d8aedc272ba83d3aa6dcf5c - profiles: [esplora] - command: /srv/explorer/run.sh bitcoin-regtest explorer - environment: - DEBUG: verbose - NO_PRECACHE: 1 - NO_ADDRESS_SEARCH: 1 - NO_REGTEST_MINING: 1 - ports: - - 50004:50001 - - 8094:80 - esplora_2: - image: blockstream/esplora:956c74f42eb6ad803d8aedc272ba83d3aa6dcf5c - profiles: [esplora] - command: /srv/explorer/run.sh bitcoin-regtest explorer - environment: - DEBUG: verbose - NO_PRECACHE: 1 - NO_ADDRESS_SEARCH: 1 - NO_REGTEST_MINING: 1 - ports: - - 50005:50001 - - 8095:80 - esplora_3: - image: blockstream/esplora:956c74f42eb6ad803d8aedc272ba83d3aa6dcf5c - profiles: [esplora] - command: /srv/explorer/run.sh bitcoin-regtest explorer - environment: - DEBUG: verbose - NO_PRECACHE: 1 - NO_ADDRESS_SEARCH: 1 - NO_REGTEST_MINING: 1 - ports: - - 50006:50001 - - 8096:80 diff --git a/tests/docker/start_services.sh b/tests/docker/start_services.sh index bf176fe..6f0fb3b 100755 --- a/tests/docker/start_services.sh +++ b/tests/docker/start_services.sh @@ -104,51 +104,8 @@ _connect_nodes() { # Use 'add' instead of 'onetry' for persistent connections echo "Adding peer connections..." - $BITCOIN_CLI_2 addnode "$NODE3_IP:18444" "add" - $BITCOIN_CLI_3 addnode "$NODE2_IP:18444" "add" - - # Wait for connections to be established - local max_attempts=30 - local attempt=1 - - while [ $attempt -le $max_attempts ]; do - echo "Checking node connections (attempt $attempt/$max_attempts)..." - - # Get connection information - local peers_2=$($BITCOIN_CLI_2 getpeerinfo) - local peers_3=$($BITCOIN_CLI_3 getpeerinfo) - - # Check node 2's connections - local connected_2=$(echo "$peers_2" | grep -c "$NODE3_IP") - # Check node 3's connections - local connected_3=$(echo "$peers_3" | grep -c "$NODE2_IP") - - if [ "$connected_2" -gt 0 ] && [ "$connected_3" -gt 0 ]; then - echo "Nodes successfully connected" - - # Display detailed connection information - echo "Node 2 connections:" - $BITCOIN_CLI_2 getpeerinfo | grep "addr\|subver\|banscore" - echo "Node 3 connections:" - $BITCOIN_CLI_3 getpeerinfo | grep "addr\|subver\|banscore" - - return 0 - fi - - echo "Waiting for connections to establish..." - sleep 2 - attempt=$((attempt + 1)) - - # If near the last few attempts, try adding nodes again - if [ $attempt -eq $((max_attempts - 5)) ]; then - echo "Retrying node connections..." - $BITCOIN_CLI_2 addnode "$NODE3_IP:18444" "add" - $BITCOIN_CLI_3 addnode "$NODE2_IP:18444" "add" - fi - done - - echo "Failed to establish connections after $max_attempts attempts" - return 1 + $BITCOIN_CLI_2 addnode "$NODE3_IP:18444" "onetry" + $BITCOIN_CLI_3 addnode "$NODE2_IP:18444" "onetry" } _wait_for_sync() { diff --git a/tests/start_services.sh b/tests/start_services.sh deleted file mode 100755 index ff32e6c..0000000 --- a/tests/start_services.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash -set -eu - -_die () { - echo "ERR: $*" >&2 - exit 1 -} - -_prepare_bitcoin_nodes() { - $BCLI_1 createwallet miner - $BCLI_2 createwallet miner - $BCLI_3 createwallet miner - $BCLI_1 -rpcwallet=miner -generate 103 - $BCLI_2 -rpcwallet=miner -generate 103 - # connect the 2 bitcoin services for the reorg - if [ "$PROFILE" == "esplora" ]; then - $BCLI_2 addnode "esplora_3:18444" "onetry" - $BCLI_3 addnode "esplora_2:18444" "onetry" - elif [ "$PROFILE" == "electrum" ]; then - $BCLI_2 addnode "bitcoind_3:18444" "onetry" - $BCLI_3 addnode "bitcoind_2:18444" "onetry" - fi -} - -_wait_for_bitcoind() { - # wait for bitcoind to be up - bitcoind_service_name="$1" - until $COMPOSE logs $bitcoind_service_name |grep -q 'Bound to'; do - sleep 1 - done -} - -_wait_for_electrs() { - # wait for electrs to have completed startup - electrs_service_name="$1" - until $COMPOSE logs $electrs_service_name |grep -q 'finished full compaction'; do - sleep 1 - done -} - -_wait_for_esplora() { - # wait for esplora to have completed startup - esplora_service_name="$1" - until $COMPOSE logs $esplora_service_name |grep -q 'run: nginx:'; do - sleep 1 - done -} - -_stop_esplora() { - # stop an esplora sub service - esplora_service_name="$1" - esplora_sub_service_name="${2:-electrs}" - if $COMPOSE ps |grep -q $esplora_service_name; then - for SRV in socat $esplora_sub_service_name; do - $COMPOSE exec $esplora_service_name bash -c "sv -w 60 force-stop /etc/service/$SRV" - done - fi -} - -_stop_services() { - if [ "$PROFILE" == "esplora" ]; then - _stop_esplora esplora_1 - _stop_esplora esplora_2 - _stop_esplora esplora_3 - fi - # bring all services down - $COMPOSE --profile '*' down -v --remove-orphans -} - -_start_services() { - _stop_services - mkdir -p $TEST_DATA_DIR - for port in "${EXPOSED_PORTS[@]}"; do - if [ -n "$(ss -HOlnt "sport = :$port")" ];then - _die "port $port is already bound, services can't be started" - fi - done - $COMPOSE up -d -} - -COMPOSE="docker compose" -if ! $COMPOSE >/dev/null; then - _die "could not call docker compose (hint: install docker compose plugin)" -fi -COMPOSE="$COMPOSE -f tests/docker-compose.yml" -PROFILE=${PROFILE:-"esplora"} -COMPOSE="$COMPOSE --profile $PROFILE" -TEST_DATA_DIR="./test-data" - -# see docker-compose.yml for the exposed ports -if [ "$PROFILE" == "esplora" ]; then - BCLI_1="$COMPOSE exec -T esplora_1 cli" - BCLI_2="$COMPOSE exec -T esplora_2 cli" - BCLI_3="$COMPOSE exec -T esplora_3 cli" - EXPOSED_PORTS=(8094 8095 8096 50004 50005 50006) -elif [ "$PROFILE" == "electrum" ]; then - BCLI_1="$COMPOSE exec -T -u blits bitcoind_1 bitcoin-cli -regtest" - BCLI_2="$COMPOSE exec -T -u blits bitcoind_2 bitcoin-cli -regtest" - BCLI_3="$COMPOSE exec -T -u blits bitcoind_3 bitcoin-cli -regtest" - EXPOSED_PORTS=(50001 50002 50003) -else - _die "invalid profile" -fi - -# restart services (down + up) checking for ports availability -_start_services - -# wait for services (pre-mining) -if [ "$PROFILE" == "esplora" ]; then - _wait_for_esplora esplora_1 - _wait_for_esplora esplora_2 - _wait_for_esplora esplora_3 - _stop_esplora esplora_1 tor - _stop_esplora esplora_2 tor - _stop_esplora esplora_3 tor -elif [ "$PROFILE" == "electrum" ]; then - _wait_for_bitcoind bitcoind_1 - _wait_for_bitcoind bitcoind_2 - _wait_for_bitcoind bitcoind_3 -fi - -_prepare_bitcoin_nodes - -# wait for services (post-mining) -if [ "$PROFILE" == "electrum" ]; then - _wait_for_electrs electrs_1 - _wait_for_electrs electrs_2 - _wait_for_electrs electrs_3 -fi diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 0f270fd..18a8604 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -33,45 +33,47 @@ pub fn initialize() { panic!("invalid indexer. possible values: `esplora` (default), `electrum`") } }); - + if std::env::var("SKIP_INIT").is_ok() { println!("skipping services initialization"); return; } - - let start_services_file = PathBuf::from("tests").join("docker").join("start_services.sh"); + + let start_services_file = PathBuf::from("tests") + .join("docker") + .join("start_services.sh"); println!("starting test services..."); - + let start_output = Command::new(&start_services_file) .arg("start") .output() .expect("failed to start test services"); - + if !start_output.status.success() { println!("stdout: {}", String::from_utf8_lossy(&start_output.stdout)); println!("stderr: {}", String::from_utf8_lossy(&start_output.stderr)); panic!("failed to start test services"); } - + // Wait for all nodes to be ready for instance in INSTANCE_1..=INSTANCE_3 { let mut attempts = 0; let max_attempts = 30; - + loop { if attempts >= max_attempts { panic!("Node {instance} failed to start after {max_attempts} attempts"); } - + let result = _bitcoin_cli_cmd(instance, vec!["getblockchaininfo"]); if !result.is_empty() { break; } - + attempts += 1; std::thread::sleep(Duration::from_secs(1)); } - + // Wait for indexer sync _wait_indexer_sync(instance); } @@ -94,7 +96,9 @@ fn _service_base_name() -> String { } fn _bitcoin_cli_cmd(instance: u8, args: Vec<&str>) -> String { - let compose_file = PathBuf::from("tests").join("docker").join("docker-compose.yml"); + let compose_file = PathBuf::from("tests") + .join("docker") + .join("docker-compose.yml"); let mut bitcoin_cli = vec![ s!("-p"), s!("rgb-tests"), @@ -103,7 +107,7 @@ fn _bitcoin_cli_cmd(instance: u8, args: Vec<&str>) -> String { s!("exec"), s!("-T"), ]; - + let service_name = format!("bitcoin-core-{instance}"); bitcoin_cli.extend(vec![ service_name, @@ -120,7 +124,7 @@ fn _bitcoin_cli_cmd(instance: u8, args: Vec<&str>) -> String { .args(&args) .output() .unwrap_or_else(|_| panic!("failed to call bitcoind with args {args:?}")); - + if !output.status.success() { println!("{output:?}"); panic!("failed to get successful output with args {args:?}"); @@ -226,50 +230,30 @@ pub fn resume_mining() { fn _get_connection_tuple() -> Vec<(u8, String)> { vec![ - (INSTANCE_3, NODE2_ADDR.to_string()), // Node 2's address - (INSTANCE_2, NODE3_ADDR.to_string()), // Node 3's address + (INSTANCE_3, NODE2_ADDR.to_string()), // Node 2's address + (INSTANCE_2, NODE3_ADDR.to_string()), // Node 3's address ] } pub fn connect_reorg_nodes() { for (instance, node_addr) in _get_connection_tuple() { - let peers = _bitcoin_cli_cmd(instance, vec!["getpeerinfo"]); - // println!("connect_reorg_nodes:instance:{} peers: {}", instance, peers); - if !peers.contains(&node_addr) { - _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "add"]); - } + _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "onetry"]); } - + let t_0 = OffsetDateTime::now_utc(); - let mut attempt = 1; - let max_attempts = 30; - + loop { if (OffsetDateTime::now_utc() - t_0).as_seconds_f32() > 60.0 { panic!("nodes failed to sync after 60 seconds"); } - + let height_2 = get_height_custom(INSTANCE_2); let height_3 = get_height_custom(INSTANCE_3); - + if height_2 == height_3 { - // Verify connections are established - let peers_2 = _bitcoin_cli_cmd(INSTANCE_2, vec!["getpeerinfo"]); - let peers_3 = _bitcoin_cli_cmd(INSTANCE_3, vec!["getpeerinfo"]); - - if peers_2.contains(NODE3_IP) && peers_3.contains(NODE2_IP) { - break; - } - } - - if attempt == max_attempts - 5 { - // Retry connections if near max attempts - for (instance, node_addr) in _get_connection_tuple() { - _bitcoin_cli_cmd(instance, vec!["addnode", &node_addr, "add"]); - } + break; } - - attempt += 1; + std::thread::sleep(Duration::from_millis(500)); } } @@ -282,7 +266,10 @@ pub fn disconnect_reorg_nodes() { for (instance, _) in _get_connection_tuple() { // dump peer info let peers = _bitcoin_cli_cmd(instance, vec!["getpeerinfo"]); - println!("disconnect_reorg_nodes:instance:{} peers: {}", instance, peers); + println!( + "disconnect_reorg_nodes:instance:{} peers: {}", + instance, peers + ); } } From e326654d2f05e89494c37b2b824814d972291a92 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 14 Feb 2025 00:42:53 +0800 Subject: [PATCH 08/90] feat: (WIP) refactoring utils from rgb V0.11 to V0.12 Signed-off-by: will-bitlightlabs --- tests/utils/helpers.rs | 873 +++++++++++++++++++++-------------------- tests/utils/mod.rs | 21 +- 2 files changed, 463 insertions(+), 431 deletions(-) diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index f949a1c..fe44de3 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1,4 +1,13 @@ -use super::*; +use std::fs::File; + +use rand::RngCore; + +use crate::utils::chain::fund_wallet; + +use super::{ + chain::{indexer_url, mine_custom, Indexer, INDEXER}, + *, +}; pub struct TestWallet { wallet: RgbWallet>, @@ -157,326 +166,326 @@ impl fmt::Display for AssetSchema { } impl AssetSchema { - fn iface_type_name(&self) -> TypeName { - tn!(match self { - Self::Nia => "RGB20Fixed", - Self::Uda => "RGB21Unique", - Self::Cfa => "RGB25Base", - }) - } - - fn schema(&self) -> Schema { - match self { - Self::Nia => NonInflatableAsset::schema(), - Self::Uda => UniqueDigitalAsset::schema(), - Self::Cfa => CollectibleFungibleAsset::schema(), - } - } - - fn issue_impl(&self) -> IfaceImpl { - match self { - Self::Nia => NonInflatableAsset::issue_impl(), - Self::Uda => UniqueDigitalAsset::issue_impl(), - Self::Cfa => CollectibleFungibleAsset::issue_impl(), - } - } - - fn scripts(&self) -> Scripts { - match self { - Self::Nia => NonInflatableAsset::scripts(), - Self::Uda => UniqueDigitalAsset::scripts(), - Self::Cfa => CollectibleFungibleAsset::scripts(), - } - } - - fn types(&self) -> TypeSystem { - match self { - Self::Nia => NonInflatableAsset::types(), - Self::Uda => UniqueDigitalAsset::types(), - Self::Cfa => CollectibleFungibleAsset::types(), - } - } - - fn iface(&self) -> Iface { - match self { - Self::Nia => Rgb20::iface(&Rgb20::FIXED), - Self::Uda => Rgb21::iface(&Rgb21::NONE), - Self::Cfa => Rgb25::iface(&Rgb25::NONE), - } - } - - fn get_valid_kit(&self) -> ValidKit { - let mut kit = Kit::default(); - kit.schemata.push(self.schema()).unwrap(); - kit.ifaces.push(self.iface()).unwrap(); - kit.iimpls.push(self.issue_impl()).unwrap(); - kit.scripts.extend(self.scripts().into_values()).unwrap(); - kit.types = self.types(); - kit.validate().unwrap() - } -} - -#[derive(Debug)] -pub enum AssetInfo { - Nia { - spec: AssetSpec, - terms: ContractTerms, - issue_amounts: Vec, - }, - Uda { - spec: AssetSpec, - terms: ContractTerms, - token_data: TokenData, - }, - Cfa { - name: Name, - precision: Precision, - details: Option
, - terms: ContractTerms, - issue_amounts: Vec, - }, + // fn iface_type_name(&self) -> TypeName { + // tn!(match self { + // Self::Nia => "RGB20Fixed", + // Self::Uda => "RGB21Unique", + // Self::Cfa => "RGB25Base", + // }) + // } + + // fn schema(&self) -> Schema { + // match self { + // Self::Nia => NonInflatableAsset::schema(), + // Self::Uda => UniqueDigitalAsset::schema(), + // Self::Cfa => CollectibleFungibleAsset::schema(), + // } + // } + + // fn issue_impl(&self) -> IfaceImpl { + // match self { + // Self::Nia => NonInflatableAsset::issue_impl(), + // Self::Uda => UniqueDigitalAsset::issue_impl(), + // Self::Cfa => CollectibleFungibleAsset::issue_impl(), + // } + // } + + // fn scripts(&self) -> Scripts { + // match self { + // Self::Nia => NonInflatableAsset::scripts(), + // Self::Uda => UniqueDigitalAsset::scripts(), + // Self::Cfa => CollectibleFungibleAsset::scripts(), + // } + // } + + // fn types(&self) -> TypeSystem { + // match self { + // Self::Nia => NonInflatableAsset::types(), + // Self::Uda => UniqueDigitalAsset::types(), + // Self::Cfa => CollectibleFungibleAsset::types(), + // } + // } + + // fn iface(&self) -> Iface { + // match self { + // Self::Nia => Rgb20::iface(&Rgb20::FIXED), + // Self::Uda => Rgb21::iface(&Rgb21::NONE), + // Self::Cfa => Rgb25::iface(&Rgb25::NONE), + // } + // } + + // fn get_valid_kit(&self) -> ValidKit { + // let mut kit = Kit::default(); + // kit.schemata.push(self.schema()).unwrap(); + // kit.ifaces.push(self.iface()).unwrap(); + // kit.iimpls.push(self.issue_impl()).unwrap(); + // kit.scripts.extend(self.scripts().into_values()).unwrap(); + // kit.types = self.types(); + // kit.validate().unwrap() + // } } -impl AssetInfo { - fn asset_schema(&self) -> AssetSchema { - match self { - Self::Nia { .. } => AssetSchema::Nia, - Self::Uda { .. } => AssetSchema::Uda, - Self::Cfa { .. } => AssetSchema::Cfa, - } - } - - fn iface_type_name(&self) -> TypeName { - self.asset_schema().iface_type_name() - } - - fn schema(&self) -> Schema { - self.asset_schema().schema() - } - - fn issue_impl(&self) -> IfaceImpl { - self.asset_schema().issue_impl() - } - - fn scripts(&self) -> Scripts { - self.asset_schema().scripts() - } - - fn types(&self) -> TypeSystem { - self.asset_schema().types() - } - - fn iface(&self) -> Iface { - self.asset_schema().iface() - } - - pub fn default_cfa(issue_amounts: Vec) -> Self { - AssetInfo::cfa("CFA asset name", 0, None, "CFA terms", None, issue_amounts) - } - - pub fn default_nia(issue_amounts: Vec) -> Self { - AssetInfo::nia( - "NIATCKR", - "NIA asset name", - 2, - None, - "NIA terms", - None, - issue_amounts, - ) - } - - pub fn default_uda() -> Self { - AssetInfo::uda( - "UDATCKR", - "UDA asset name", - None, - "NIA terms", - None, - uda_token_data_minimal(), - ) - } - - pub fn nia( - ticker: &str, - name: &str, - precision: u8, - details: Option<&str>, - terms_text: &str, - terms_media_fpath: Option<&str>, - issue_amounts: Vec, - ) -> Self { - let spec = AssetSpec::with( - ticker, - name, - Precision::try_from(precision).unwrap(), - details, - ) - .unwrap(); - let text = RicardianContract::from_str(terms_text).unwrap(); - let attachment = terms_media_fpath.map(attachment_from_fpath); - let terms = ContractTerms { - text, - media: attachment, - }; - Self::Nia { - spec, - terms, - issue_amounts, - } - } - - pub fn uda( - ticker: &str, - name: &str, - details: Option<&str>, - terms_text: &str, - terms_media_fpath: Option<&str>, - token_data: TokenData, - ) -> AssetInfo { - let spec = AssetSpec::with(ticker, name, Precision::try_from(0).unwrap(), details).unwrap(); - let text = RicardianContract::from_str(terms_text).unwrap(); - let attachment = terms_media_fpath.map(attachment_from_fpath); - let terms = ContractTerms { - text, - media: attachment.clone(), - }; - Self::Uda { - spec, - terms, - token_data, - } - } - - pub fn cfa( - name: &str, - precision: u8, - details: Option<&str>, - terms_text: &str, - terms_media_fpath: Option<&str>, - issue_amounts: Vec, - ) -> AssetInfo { - let text = RicardianContract::from_str(terms_text).unwrap(); - let attachment = terms_media_fpath.map(attachment_from_fpath); - let terms = ContractTerms { - text, - media: attachment, - }; - Self::Cfa { - name: Name::try_from(name.to_owned()).unwrap(), - precision: Precision::try_from(precision).unwrap(), - details: details.map(|d| Details::try_from(d.to_owned()).unwrap()), - terms, - issue_amounts, - } - } - - fn add_global_state(&self, mut builder: ContractBuilder) -> ContractBuilder { - match self { - Self::Nia { - spec, - terms, - issue_amounts, - } => builder - .add_global_state("spec", spec.clone()) - .unwrap() - .add_global_state("terms", terms.clone()) - .unwrap() - .add_global_state( - "issuedSupply", - Amount::from(issue_amounts.iter().sum::()), - ) - .unwrap(), - Self::Uda { - spec, - terms, - token_data, - } => builder - .add_global_state("spec", spec.clone()) - .unwrap() - .add_global_state("terms", terms.clone()) - .unwrap() - .add_global_state("tokens", token_data.clone()) - .unwrap(), - Self::Cfa { - name, - precision, - details, - terms, - issue_amounts: issued_supply, - } => { - builder = builder - .add_global_state("name", name.clone()) - .unwrap() - .add_global_state("precision", *precision) - .unwrap() - .add_global_state("terms", terms.clone()) - .unwrap() - .add_global_state( - "issuedSupply", - Amount::from(issued_supply.iter().sum::()), - ) - .unwrap(); - if let Some(details) = details { - builder = builder - .add_global_state("details", details.clone()) - .unwrap() - } - builder - } - } - } - - fn add_asset_owner( - &self, - mut builder: ContractBuilder, - close_method: CloseMethod, - outpoints: Vec, - ) -> ContractBuilder { - fn get_genesis_seal( - close_method: CloseMethod, - outpoint: Outpoint, - ) -> BuilderSeal> { - let blind_seal = match close_method { - CloseMethod::TapretFirst => { - BlindSeal::tapret_first_rand(outpoint.txid, outpoint.vout) - } - CloseMethod::OpretFirst => { - BlindSeal::opret_first_rand(outpoint.txid, outpoint.vout) - } - }; - let genesis_seal = GenesisSeal::from(blind_seal); - let seal: XChain> = XChain::with(Layer1::Bitcoin, genesis_seal); - BuilderSeal::from(seal) - } - - match self { - Self::Nia { issue_amounts, .. } | Self::Cfa { issue_amounts, .. } => { - for (amt, outpoint) in issue_amounts.iter().zip(outpoints.iter().cycle()) { - builder = builder - .add_fungible_state( - "assetOwner", - get_genesis_seal(close_method, *outpoint), - *amt, - ) - .unwrap(); - } - builder - } - Self::Uda { token_data, .. } => { - let fraction = OwnedFraction::from(1); - let allocation = Allocation::with(token_data.index, fraction); - builder - .add_data( - "assetOwner", - get_genesis_seal(close_method, outpoints[0]), - allocation, - ) - .unwrap() - } - } - } -} +// #[derive(Debug)] +// pub enum AssetInfo { +// Nia { +// spec: AssetSpec, +// terms: ContractTerms, +// issue_amounts: Vec, +// }, +// Uda { +// spec: AssetSpec, +// terms: ContractTerms, +// token_data: TokenData, +// }, +// Cfa { +// name: Name, +// precision: Precision, +// details: Option
, +// terms: ContractTerms, +// issue_amounts: Vec, +// }, +// } + +// impl AssetInfo { +// fn asset_schema(&self) -> AssetSchema { +// match self { +// Self::Nia { .. } => AssetSchema::Nia, +// Self::Uda { .. } => AssetSchema::Uda, +// Self::Cfa { .. } => AssetSchema::Cfa, +// } +// } + +// fn iface_type_name(&self) -> TypeName { +// self.asset_schema().iface_type_name() +// } + +// fn schema(&self) -> Schema { +// self.asset_schema().schema() +// } + +// fn issue_impl(&self) -> IfaceImpl { +// self.asset_schema().issue_impl() +// } + +// fn scripts(&self) -> Scripts { +// self.asset_schema().scripts() +// } + +// fn types(&self) -> TypeSystem { +// self.asset_schema().types() +// } + +// fn iface(&self) -> Iface { +// self.asset_schema().iface() +// } + +// pub fn default_cfa(issue_amounts: Vec) -> Self { +// AssetInfo::cfa("CFA asset name", 0, None, "CFA terms", None, issue_amounts) +// } + +// pub fn default_nia(issue_amounts: Vec) -> Self { +// AssetInfo::nia( +// "NIATCKR", +// "NIA asset name", +// 2, +// None, +// "NIA terms", +// None, +// issue_amounts, +// ) +// } + +// pub fn default_uda() -> Self { +// AssetInfo::uda( +// "UDATCKR", +// "UDA asset name", +// None, +// "NIA terms", +// None, +// uda_token_data_minimal(), +// ) +// } + +// pub fn nia( +// ticker: &str, +// name: &str, +// precision: u8, +// details: Option<&str>, +// terms_text: &str, +// terms_media_fpath: Option<&str>, +// issue_amounts: Vec, +// ) -> Self { +// let spec = AssetSpec::with( +// ticker, +// name, +// Precision::try_from(precision).unwrap(), +// details, +// ) +// .unwrap(); +// let text = RicardianContract::from_str(terms_text).unwrap(); +// let attachment = terms_media_fpath.map(attachment_from_fpath); +// let terms = ContractTerms { +// text, +// media: attachment, +// }; +// Self::Nia { +// spec, +// terms, +// issue_amounts, +// } +// } + +// pub fn uda( +// ticker: &str, +// name: &str, +// details: Option<&str>, +// terms_text: &str, +// terms_media_fpath: Option<&str>, +// token_data: TokenData, +// ) -> AssetInfo { +// let spec = AssetSpec::with(ticker, name, Precision::try_from(0).unwrap(), details).unwrap(); +// let text = RicardianContract::from_str(terms_text).unwrap(); +// let attachment = terms_media_fpath.map(attachment_from_fpath); +// let terms = ContractTerms { +// text, +// media: attachment.clone(), +// }; +// Self::Uda { +// spec, +// terms, +// token_data, +// } +// } + +// pub fn cfa( +// name: &str, +// precision: u8, +// details: Option<&str>, +// terms_text: &str, +// terms_media_fpath: Option<&str>, +// issue_amounts: Vec, +// ) -> AssetInfo { +// let text = RicardianContract::from_str(terms_text).unwrap(); +// let attachment = terms_media_fpath.map(attachment_from_fpath); +// let terms = ContractTerms { +// text, +// media: attachment, +// }; +// Self::Cfa { +// name: Name::try_from(name.to_owned()).unwrap(), +// precision: Precision::try_from(precision).unwrap(), +// details: details.map(|d| Details::try_from(d.to_owned()).unwrap()), +// terms, +// issue_amounts, +// } +// } + +// fn add_global_state(&self, mut builder: ContractBuilder) -> ContractBuilder { +// match self { +// Self::Nia { +// spec, +// terms, +// issue_amounts, +// } => builder +// .add_global_state("spec", spec.clone()) +// .unwrap() +// .add_global_state("terms", terms.clone()) +// .unwrap() +// .add_global_state( +// "issuedSupply", +// Amount::from(issue_amounts.iter().sum::()), +// ) +// .unwrap(), +// Self::Uda { +// spec, +// terms, +// token_data, +// } => builder +// .add_global_state("spec", spec.clone()) +// .unwrap() +// .add_global_state("terms", terms.clone()) +// .unwrap() +// .add_global_state("tokens", token_data.clone()) +// .unwrap(), +// Self::Cfa { +// name, +// precision, +// details, +// terms, +// issue_amounts: issued_supply, +// } => { +// builder = builder +// .add_global_state("name", name.clone()) +// .unwrap() +// .add_global_state("precision", *precision) +// .unwrap() +// .add_global_state("terms", terms.clone()) +// .unwrap() +// .add_global_state( +// "issuedSupply", +// Amount::from(issued_supply.iter().sum::()), +// ) +// .unwrap(); +// if let Some(details) = details { +// builder = builder +// .add_global_state("details", details.clone()) +// .unwrap() +// } +// builder +// } +// } +// } + +// fn add_asset_owner( +// &self, +// mut builder: ContractBuilder, +// close_method: CloseMethod, +// outpoints: Vec, +// ) -> ContractBuilder { +// fn get_genesis_seal( +// close_method: CloseMethod, +// outpoint: Outpoint, +// ) -> BuilderSeal> { +// let blind_seal = match close_method { +// CloseMethod::TapretFirst => { +// BlindSeal::tapret_first_rand(outpoint.txid, outpoint.vout) +// } +// CloseMethod::OpretFirst => { +// BlindSeal::opret_first_rand(outpoint.txid, outpoint.vout) +// } +// }; +// let genesis_seal = GenesisSeal::from(blind_seal); +// let seal: XChain> = XChain::with(Layer1::Bitcoin, genesis_seal); +// BuilderSeal::from(seal) +// } + +// match self { +// Self::Nia { issue_amounts, .. } | Self::Cfa { issue_amounts, .. } => { +// for (amt, outpoint) in issue_amounts.iter().zip(outpoints.iter().cycle()) { +// builder = builder +// .add_fungible_state( +// "assetOwner", +// get_genesis_seal(close_method, *outpoint), +// *amt, +// ) +// .unwrap(); +// } +// builder +// } +// Self::Uda { token_data, .. } => { +// let fraction = OwnedFraction::from(1); +// let allocation = Allocation::with(token_data.index, fraction); +// builder +// .add_data( +// "assetOwner", +// get_genesis_seal(close_method, outpoints[0]), +// allocation, +// ) +// .unwrap() +// } +// } +// } +// } pub struct Report { pub report_path: PathBuf, @@ -529,41 +538,35 @@ fn _get_wallet( const OPRET_KEYCHAINS: [Keychain; 3] = [ Keychain::INNER, Keychain::OUTER, - Keychain::with(RgbKeychain::Rgb as u8), + Keychain::with(KEY_CHAIN_RGB), ]; const TAPRET_KEYCHAINS: [Keychain; 4] = [ Keychain::INNER, Keychain::OUTER, - Keychain::with(RgbKeychain::Rgb as u8), - Keychain::with(RgbKeychain::Tapret as u8), + Keychain::with(KEY_CHAIN_RGB), + Keychain::with(KEY_CHAIN_TAPRET), ]; let keychains: &[Keychain] = match *descriptor_type { DescriptorType::Tr => &TAPRET_KEYCHAINS[..], DescriptorType::Wpkh => &OPRET_KEYCHAINS[..], }; let xpub_derivable = XpubDerivable::with(xpub_account.clone(), keychains); + let noise = xpub_derivable.xpub().chain_code().to_byte_array(); let descriptor = match descriptor_type { - DescriptorType::Wpkh => RgbDescr::Wpkh(Wpkh::from(xpub_derivable)), - DescriptorType::Tr => RgbDescr::TapretKey(TapretKey::from(xpub_derivable)), + DescriptorType::Wpkh => RgbDescr::new_unfunded(Wpkh::from(xpub_derivable), noise), + DescriptorType::Tr => RgbDescr::key_only_unfunded(xpub_derivable, noise), }; let name = "bp_wallet_name"; - let mut bp_wallet = Wallet::new_layer1(descriptor.clone(), network); - bp_wallet.set_name(name.to_string()); - let bp_dir = wallet_dir.join(name); - let bp_wallet_provider = FsTextStore::new(bp_dir).unwrap(); - bp_wallet.make_persistent(bp_wallet_provider, true).unwrap(); + let provider = FsTextStore::new(wallet_dir.join(name)).unwrap(); + let wallet = RgbWallet::create(provider, descriptor.clone(), network, true) + .expect("Unable to create wallet"); - let stock_provider = FsBinStore::new(wallet_dir.clone()).unwrap(); - let mut stock = Stock::in_memory(); - stock.make_persistent(stock_provider, true).unwrap(); - let mut wallet = RgbWallet::new(stock, bp_wallet); - - for asset_schema in AssetSchema::iter() { - let valid_kit = asset_schema.get_valid_kit(); - wallet.stock_mut().import_kit(valid_kit).unwrap(); - } + // for asset_schema in AssetSchema::iter() { + // let valid_kit = asset_schema.get_valid_kit(); + // wallet.stock_mut().import_kit(valid_kit).unwrap(); + // } let signer = match wallet_account { WalletAccount::Private(xpriv_account) => Some(TestnetSigner::new(xpriv_account)), @@ -652,7 +655,7 @@ fn broadcast_tx(tx: &Tx, indexer_url: &str) { inner.transaction_broadcast(tx).unwrap(); } AnyIndexer::Esplora(inner) => { - inner.publish(tx).unwrap(); + inner.broadcast(tx).unwrap(); } _ => unreachable!("unsupported indexer"), } @@ -663,65 +666,65 @@ pub fn broadcast_tx_and_mine(tx: &Tx, instance: u8) { mine_custom(false, instance, 1); } -pub fn attachment_from_fpath(fpath: &str) -> Attachment { - let file_bytes = std::fs::read(fpath).unwrap(); - let file_hash: sha256::Hash = Hash::hash(&file_bytes[..]); - let digest = file_hash.to_byte_array().into(); - let mime = FileFormat::from_file(fpath) - .unwrap() - .media_type() - .to_string(); - let media_ty: &'static str = Box::leak(mime.clone().into_boxed_str()); - let media_type = MediaType::with(media_ty); - Attachment { - ty: media_type, - digest, - } -} - -fn uda_token_data_minimal() -> TokenData { - TokenData { - index: TokenIndex::from(UDA_FIXED_INDEX), - ..Default::default() - } -} - -pub fn uda_token_data( - ticker: &str, - name: &str, - details: &str, - preview: EmbeddedMedia, - media: Attachment, - attachments: BTreeMap, - reserves: ProofOfReserves, -) -> TokenData { - let mut token_data = uda_token_data_minimal(); - token_data.preview = Some(preview); - token_data.media = Some(media); - token_data.attachments = Confined::try_from(attachments.clone()).unwrap(); - token_data.reserves = Some(reserves); - token_data.ticker = Some(Ticker::try_from(ticker.to_string()).unwrap()); - token_data.name = Some(Name::try_from(name.to_string()).unwrap()); - token_data.details = Some(Details::try_from(details.to_string()).unwrap()); - token_data -} +// pub fn attachment_from_fpath(fpath: &str) -> Attachment { +// let file_bytes = std::fs::read(fpath).unwrap(); +// let file_hash: sha256::Hash = Hash::hash(&file_bytes[..]); +// let digest = file_hash.to_byte_array().into(); +// let mime = FileFormat::from_file(fpath) +// .unwrap() +// .media_type() +// .to_string(); +// let media_ty: &'static str = Box::leak(mime.clone().into_boxed_str()); +// let media_type = MediaType::with(media_ty); +// Attachment { +// ty: media_type, +// digest, +// } +// } + +// fn uda_token_data_minimal() -> TokenData { +// TokenData { +// index: TokenIndex::from(UDA_FIXED_INDEX), +// ..Default::default() +// } +// } + +// pub fn uda_token_data( +// ticker: &str, +// name: &str, +// details: &str, +// preview: EmbeddedMedia, +// media: Attachment, +// attachments: BTreeMap, +// reserves: ProofOfReserves, +// ) -> TokenData { +// let mut token_data = uda_token_data_minimal(); +// token_data.preview = Some(preview); +// token_data.media = Some(media); +// token_data.attachments = Confined::try_from(attachments.clone()).unwrap(); +// token_data.reserves = Some(reserves); +// token_data.ticker = Some(Ticker::try_from(ticker.to_string()).unwrap()); +// token_data.name = Some(Name::try_from(name.to_string()).unwrap()); +// token_data.details = Some(Details::try_from(details.to_string()).unwrap()); +// token_data +// } impl TestWallet { pub fn network(&self) -> Network { - self.wallet.wallet().network() + self.wallet.network() } pub fn testnet(&self) -> bool { self.network().is_testnet() } - pub fn keychain(&self) -> RgbKeychain { - RgbKeychain::for_method(self.close_method()) + pub fn keychain(&self) -> Keychain { + // RgbKeychain::for_method(self.close_method()) + todo!() } pub fn get_derived_address(&self) -> DerivedAddr { self.wallet - .wallet() .addresses(self.keychain()) .next() .expect("no addresses left") @@ -736,7 +739,7 @@ impl TestWallet { let txid = Txid::from_str(&fund_wallet(address.to_string(), sats, self.instance)).unwrap(); self.sync(); let mut vout = None; - let coins = self.wallet.wallet().address_coins(); + let coins = self.wallet.address_coins(); assert!(!coins.is_empty()); for (_derived_addr, utxos) in coins { for utxo in utxos { @@ -796,16 +799,12 @@ impl TestWallet { pub fn sync(&mut self) { let indexer = self.get_indexer(); - self.wallet - .wallet_mut() - .update(&indexer) - .into_result() - .unwrap(); + self.wallet.update(&indexer).into_result().unwrap(); } - pub fn close_method(&self) -> CloseMethod { - self.wallet.wallet().seal_close_method() - } + // pub fn close_method(&self) -> CloseMethod { + // self.wallet.wallet().seal_close_method() + // } pub fn mine_tx(&self, txid: &Txid, resume: bool) { let mut attempts = 10; @@ -821,42 +820,60 @@ impl TestWallet { } } - pub fn issue_with_info( - &mut self, - asset_info: AssetInfo, - close_method: CloseMethod, - outpoints: Vec>, - ) -> (ContractId, TypeName) { - let outpoints = if outpoints.is_empty() { - vec![self.get_utxo(None)] - } else { - outpoints - .into_iter() - .map(|o| o.unwrap_or_else(|| self.get_utxo(None))) - .collect() - }; - - let mut builder = ContractBuilder::with( - Identity::default(), - asset_info.iface(), - asset_info.schema(), - asset_info.issue_impl(), - asset_info.types(), - asset_info.scripts(), - ); - - builder = asset_info.add_global_state(builder); - - builder = asset_info.add_asset_owner(builder, close_method, outpoints); + pub fn runtime(&self) -> RgbDirRuntime { + let wallet = self.wallet.clone(); + let mut runtime = RgbDirRuntime::from(DirBarrow::with(wallet, self.mound())); + runtime + } - let contract = builder.issue_contract().expect("failure issuing contract"); - let resolver = self.get_resolver(); - self.wallet - .stock_mut() - .import_contract(contract.clone(), resolver) - .unwrap(); + pub fn mound(&self) -> BpDirMound { + if !self.network().is_testnet() { + panic!("Non-testnet networks are not yet supported"); + } + BpDirMound::load_testnet(Consensus::Bitcoin, &self.wallet_dir, false) + } - (contract.contract_id(), asset_info.iface_type_name()) + pub fn issue_with_info( + &mut self, + // asset_info: AssetInfo, + params: Option, + // close_method: CloseMethod, + // outpoints: Vec>, + ) -> ContractId { + let mut runtime = self.runtime(); + let file = File::open(params).expect("Unable to open parameters file"); + let params = serde_yaml::from_reader::<_, CreateParams>(file)?; + let contract_id = runtime.issue_to_file(params)?; + println!("A new contract issued with ID {contract_id}"); + contract_id + // let outpoints = if outpoints.is_empty() { + // vec![self.get_utxo(None)] + // } else { + // outpoints + // .into_iter() + // .map(|o| o.unwrap_or_else(|| self.get_utxo(None))) + // .collect() + // }; + + // let mut builder = ContractBuilder::with( + // Identity::default(), + // asset_info.iface(), + // asset_info.schema(), + // asset_info.issue_impl(), + // asset_info.types(), + // asset_info.scripts(), + // ); + + // builder = asset_info.add_global_state(builder); + + // builder = asset_info.add_asset_owner(builder, close_method, outpoints); + + // let contract = builder.issue_contract().expect("failure issuing contract"); + // let resolver = self.get_resolver(); + // self.wallet + // .stock_mut() + // .import_contract(contract.clone(), resolver) + // .unwrap(); } pub fn issue_nia( diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index e34a931..57d70c2 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -1,5 +1,5 @@ -// pub mod chain; -// pub mod helpers; +pub mod chain; +pub mod helpers; pub const TEST_DATA_DIR: &str = "test-data"; pub const INTEGRATION_DATA_DIR: &str = "integration"; @@ -45,7 +45,14 @@ pub use amplify::{ use bitcoin_hashes::{sha256, Hash}; pub use bp::{ // seals::txout::{BlindSeal, CloseMethod, ExplicitSeal}, - ConsensusDecode, Outpoint, Sats, ScriptPubkey, SeqNo, Tx, Txid, Vout, + ConsensusDecode, + Outpoint, + Sats, + ScriptPubkey, + SeqNo, + Tx, + Txid, + Vout, }; pub use bpstd::{ h, signers::TestnetSigner, Address, DerivationPath, DerivationSeg, DerivedAddr, Descriptor, @@ -82,6 +89,11 @@ pub use psbt::{ // BlindingFactor, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, // RgbWallet, TapretKey, TransferParams, Transition, WalletProvider, XOutpoint, XWitnessId, // }; +use rgb::popls::bp::file::{BpDirMound, DirBarrow}; +use rgb::Consensus; +use rgb::{CallScope, ContractId, CreateParams}; +use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbRuntime, RgbWallet}; + // pub use rgbstd::{ // containers::{ // BuilderSeal, ConsignmentExt, Fascia, FileContent, IndexedConsignment, Kit, Transfer, @@ -110,3 +122,6 @@ pub use strum_macros::EnumIter; pub use time::OffsetDateTime; // pub use crate::utils::{chain::*, helpers::*}; + +pub const KEY_CHAIN_RGB: u8 = 9; +pub const KEY_CHAIN_TAPRET: u8 = 10; From f3656963f95ee33d7f53604e98d1dbddca473530 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 14 Feb 2025 13:44:47 +0800 Subject: [PATCH 09/90] feat: (WIP) build utils scaffolding for V0.12 Signed-off-by: will-bitlightlabs --- tests/NonInflatableAsset.issuer | Bin 0 -> 2945 bytes tests/issuance.rs | 117 +- tests/utils/helpers.rs | 1765 ++++++++++++++++--------------- tests/utils/mod.rs | 3 +- 4 files changed, 979 insertions(+), 906 deletions(-) create mode 100644 tests/NonInflatableAsset.issuer diff --git a/tests/NonInflatableAsset.issuer b/tests/NonInflatableAsset.issuer new file mode 100644 index 0000000000000000000000000000000000000000..58c9fe00a03ff0679abb6f3ba8598c75a1ec2abc GIT binary patch literal 2945 zcmdT`c}x^%6rbTT*ukjZ`qOAncX=!yrb5G z7KPS|;ziZiYNXnr@d(9wm6&2}t+kaZ3YJ){x7b#p&{>4~Ps=oE)1)ui*FLA6FautX=V4 zMAh{X-5L+Fzk1d8`{lO>RCQsADX9F`y&aVkHwABFfs&&x1?MO`3jA_a0e<{WN}p3P z8AH2&ytjPD)?Uc-?sj`r%#wR6YpC%Nl>Ky{28Ij>RljgKv;hwdNBSIfX-Pp89 zGW7Ln3K(_1YR7@;Ya6<=D3p|g>-V=gnXe(@|_>5)w`nfd?<60~C*RMIYaojhxd7W2l>i}x)Lx9tv zi?$uDfcfItb*4-8`|u~9e;qmT)2d2$uOqr1*!qiV)gr)2%BOLALusz3_HNZ~zjfiu z3$E(6?CkzS?17}8GmDSqPOTc~H}uC9F{L+`hm>g}^v^tl7TkVoVA#!NJ6Fp$HyqKB zgy^7XWWZ4#&H8JdGA|)<0B)m1+d!>_XIV;k)y;tf8gbGfJ!My*sEnq;?v#TUC4qO? zP=L-XP)c)2aj$iv`@ zAF1Iv6r_=I`B8*q6A%iTb6(*Q{QHWrf8ra^N0bV$a zE!Rt(3n&Vh&48wX#R3olRx8NL0yZ097%*=h$j$~V3+#5lae(K6!vUO5AP7Jdfg}N0 z201w(Hy7mPf&6?hf4-jXyvPFF!8p*uKMs-?5fZ~%(Bk+o(}|jAqn|FhRJI|vZ`{`oKCm)#O-ey20n{GI?Du2SOpPJ;iYsoEjXZq+;<>}6ReN3@;oW~s`oU^{ z&;FQBZOUo7doY}Z$x%k4vJElZqD)6XxLS{aO6RaFqtUz0;$0ATZztL@p|G^TYdcs4 zx^=P&)+y7RMO9Nm!9x;=S5!PIf`>=Qi81 z4^BxE?@P`Z+<1lvdnG2?nE6>5nou^>t++YJ$L`$q>~hcgl$o0Ff70InRipm9&9-dd z(kA)A-Ghg&81swk#G>*Y-&e?iaax;kFQDOulbVqKXIyGKjR0ydKy6wRP%U>)ThS-G zTk(contract_id); -// let spec = contract.spec(); -// assert_eq!(spec.ticker.to_string(), ticker.to_string()); -// assert_eq!(spec.name.to_string(), name.to_string()); -// assert_eq!(spec.precision.decimals(), precision); -// let terms = contract.contract_terms(); -// assert_eq!(terms.text.to_string(), terms_text.to_string()); -// let terms_media = terms.media.unwrap(); -// assert_eq!(terms_media.ty.to_string(), "image/jpeg"); -// assert_eq!( -// terms_media.digest.to_string(), -// "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" -// ); -// assert_eq!(contract.total_issued_supply().value(), issued_supply); - -// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); -// assert_eq!(allocations.len(), 1); -// let allocation = allocations[0]; -// // assert_eq!(allocation.seal.method(), close_method); -// assert_eq!(allocation.state, Amount::from(issued_supply)); -// } +#[template] +#[rstest] +#[case(DescriptorType::Wpkh)] +#[case(DescriptorType::Wpkh)] +#[case(DescriptorType::Tr)] +#[case(DescriptorType::Tr)] +fn descriptor_and_close_method(#[case] wallet_desc: DescriptorType) {} + +#[apply(descriptor_and_close_method)] +fn issue_nia(wallet_desc: DescriptorType) { + println!("wallet_desc {wallet_desc:?} "); + + initialize(); + + let mut wallet = get_wallet(&wallet_desc); + + // temporary comment out custom parameters, temporarily read from file + // let issued_supply = 999; + // let ticker = "TCKR"; + // let name = "asset name"; + // let precision = 2; + // let details = Some("some details"); + // let terms_text = "Ricardian contract"; + // let terms_media_fpath = Some(MEDIA_FPATH); + // let asset_info = AssetInfo::nia( + // ticker, + // name, + // precision, + // details, + // terms_text, + // terms_media_fpath, + // vec![issued_supply], + // ); + // let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); + let contract_id = wallet.issue_nia(PathBuf::from("./tests/DemoToken.yaml")); + wallet.contract_states(Some(contract_id)); + // let contract = wallet.contract_iface_class::(contract_id); + // let spec = contract.spec(); + // assert_eq!(spec.ticker.to_string(), ticker.to_string()); + // assert_eq!(spec.name.to_string(), name.to_string()); + // assert_eq!(spec.precision.decimals(), precision); + // let terms = contract.contract_terms(); + // assert_eq!(terms.text.to_string(), terms_text.to_string()); + // let terms_media = terms.media.unwrap(); + // assert_eq!(terms_media.ty.to_string(), "image/jpeg"); + // assert_eq!( + // terms_media.digest.to_string(), + // "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" + // ); + // assert_eq!(contract.total_issued_supply().value(), issued_supply); + + // let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); + // assert_eq!(allocations.len(), 1); + // let allocation = allocations[0]; + // // assert_eq!(allocation.seal.method(), close_method); + // assert_eq!(allocation.state, Amount::from(issued_supply)); +} // #[apply(descriptor_and_close_method)] // fn issue_uda(wallet_desc: DescriptorType) { diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index fe44de3..6be01ce 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1,6 +1,8 @@ use std::fs::File; +use bp::seals::WTxoSeal; use rand::RngCore; +use rgb::{ContractInfo, ContractRef, FilePile, FileSupply, Stockpile}; use crate::utils::chain::fund_wallet; @@ -10,7 +12,7 @@ use super::{ }; pub struct TestWallet { - wallet: RgbWallet>, + wallet: RgbWallet, descriptor: RgbDescr, signer: Option, wallet_dir: PathBuf, @@ -29,50 +31,50 @@ pub enum AllocationFilter { WalletTentative, } -enum Filter<'w> { - NoWallet, - Wallet(&'w RgbWallet>), - WalletAll(&'w RgbWallet>), - WalletTentative(&'w RgbWallet>), -} +// enum Filter<'w> { +// NoWallet, +// Wallet(&'w RgbWallet>), +// WalletAll(&'w RgbWallet>), +// WalletTentative(&'w RgbWallet>), +// } -impl AssignmentsFilter for Filter<'_> { - fn should_include(&self, outpoint: impl Into, id: Option) -> bool { - match self { - Filter::Wallet(wallet) => wallet - .wallet() - .filter_unspent() - .should_include(outpoint, id), - Filter::WalletTentative(wallet) => wallet - .wallet() - .filter_outpoints() - .should_include(outpoint, id), - _ => true, - } - } -} -impl Filter<'_> { - fn comment(&self, outpoint: XOutpoint) -> &'static str { - let outpoint = outpoint - .into_bp() - .into_bitcoin() - .expect("liquid is not yet supported"); - match self { - Filter::Wallet(rgb) if rgb.wallet().is_unspent(outpoint) => "", - Filter::WalletAll(rgb) | Filter::WalletTentative(rgb) - if rgb.wallet().is_unspent(outpoint) => - { - "-- unspent" - } - Filter::WalletAll(rgb) | Filter::WalletTentative(rgb) - if rgb.wallet().has_outpoint(outpoint) => - { - "-- spent" - } - _ => "-- third-party", - } - } -} +// impl AssignmentsFilter for Filter<'_> { +// fn should_include(&self, outpoint: impl Into, id: Option) -> bool { +// match self { +// Filter::Wallet(wallet) => wallet +// .wallet() +// .filter_unspent() +// .should_include(outpoint, id), +// Filter::WalletTentative(wallet) => wallet +// .wallet() +// .filter_outpoints() +// .should_include(outpoint, id), +// _ => true, +// } +// } +// } +// impl Filter<'_> { +// fn comment(&self, outpoint: XOutpoint) -> &'static str { +// let outpoint = outpoint +// .into_bp() +// .into_bitcoin() +// .expect("liquid is not yet supported"); +// match self { +// Filter::Wallet(rgb) if rgb.wallet().is_unspent(outpoint) => "", +// Filter::WalletAll(rgb) | Filter::WalletTentative(rgb) +// if rgb.wallet().is_unspent(outpoint) => +// { +// "-- unspent" +// } +// Filter::WalletAll(rgb) | Filter::WalletTentative(rgb) +// if rgb.wallet().has_outpoint(outpoint) => +// { +// "-- spent" +// } +// _ => "-- third-party", +// } +// } +// } #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum DescriptorType { @@ -111,6 +113,7 @@ impl fmt::Display for TransferType { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum InvoiceType { Blinded(Option), Witness, @@ -150,7 +153,7 @@ pub struct ColoringInfo { } /// Map of contract ID and list of its beneficiaries -pub type AssetBeneficiariesMap = BTreeMap>>; +// pub type AssetBeneficiariesMap = BTreeMap>>; #[derive(Debug, EnumIter, Copy, Clone, PartialEq)] pub enum AssetSchema { @@ -642,12 +645,12 @@ fn get_indexer(indexer_url: &str) -> AnyIndexer { } } -fn get_resolver(indexer_url: &str) -> AnyResolver { - match INDEXER.get().unwrap() { - Indexer::Electrum => AnyResolver::electrum_blocking(indexer_url, None).unwrap(), - Indexer::Esplora => AnyResolver::esplora_blocking(indexer_url, None).unwrap(), - } -} +// fn get_resolver(indexer_url: &str) -> AnyResolver { +// match INDEXER.get().unwrap() { +// Indexer::Electrum => AnyResolver::electrum_blocking(indexer_url, None).unwrap(), +// Indexer::Esplora => AnyResolver::esplora_blocking(indexer_url, None).unwrap(), +// } +// } fn broadcast_tx(tx: &Tx, indexer_url: &str) { match get_indexer(indexer_url) { @@ -758,14 +761,14 @@ impl TestWallet { self.instance = instance; } - pub fn sync_and_update_witnesses(&mut self, after_height: Option) { - self.sync(); - self.update_witnesses(after_height.unwrap_or(1)); - } + // pub fn sync_and_update_witnesses(&mut self, after_height: Option) { + // self.sync(); + // self.update_witnesses(after_height.unwrap_or(1)); + // } pub fn switch_to_instance(&mut self, instance: u8) { self.change_instance(instance); - self.sync_and_update_witnesses(None); + // self.sync_and_update_witnesses(None); } pub fn indexer_url(&self) -> String { @@ -776,26 +779,26 @@ impl TestWallet { get_indexer(&self.indexer_url()) } - pub fn get_resolver(&self) -> AnyResolver { - get_resolver(&self.indexer_url()) - } + // pub fn get_resolver(&self) -> AnyResolver { + // get_resolver(&self.indexer_url()) + // } pub fn broadcast_tx(&self, tx: &Tx) { broadcast_tx(tx, &self.indexer_url()); } - pub fn get_witness_ord(&self, txid: &Txid) -> WitnessOrd { - self.get_resolver() - .resolve_pub_witness_ord(XWitnessId::Bitcoin(*txid)) - .unwrap() - } + // pub fn get_witness_ord(&self, txid: &Txid) -> WitnessOrd { + // self.get_resolver() + // .resolve_pub_witness_ord(XWitnessId::Bitcoin(*txid)) + // .unwrap() + // } - pub fn get_tx_height(&self, txid: &Txid) -> Option { - match self.get_witness_ord(txid) { - WitnessOrd::Mined(witness_pos) => Some(witness_pos.height().get()), - _ => None, - } - } + // pub fn get_tx_height(&self, txid: &Txid) -> Option { + // match self.get_witness_ord(txid) { + // WitnessOrd::Mined(witness_pos) => Some(witness_pos.height().get()), + // _ => None, + // } + // } pub fn sync(&mut self) { let indexer = self.get_indexer(); @@ -806,23 +809,36 @@ impl TestWallet { // self.wallet.wallet().seal_close_method() // } - pub fn mine_tx(&self, txid: &Txid, resume: bool) { - let mut attempts = 10; - loop { - mine_custom(resume, self.instance, 1); - if self.get_tx_height(txid).is_some() { - break; - } - attempts -= 1; - if attempts == 0 { - panic!("TX is not getting mined"); - } - } + // pub fn mine_tx(&self, txid: &Txid, resume: bool) { + // let mut attempts = 10; + // loop { + // mine_custom(resume, self.instance, 1); + // if self.get_tx_height(txid).is_some() { + // break; + // } + // attempts -= 1; + // if attempts == 0 { + // panic!("TX is not getting mined"); + // } + // } + // } + pub fn wallet_provider(&self) -> FsTextStore { + FsTextStore::new(self.wallet_dir.clone()).expect("Broken directory structure") + } + + pub fn wallet(&self) -> RgbWallet { + let provider = self.wallet_provider(); + RgbWallet::load(provider, true).unwrap_or_else(|_| { + panic!( + "Error: unable to load wallet from path `{}`", + self.wallet_dir.display() + ) + }) } pub fn runtime(&self) -> RgbDirRuntime { - let wallet = self.wallet.clone(); - let mut runtime = RgbDirRuntime::from(DirBarrow::with(wallet, self.mound())); + let wallet = self.wallet(); + let runtime = RgbDirRuntime::from(DirBarrow::with(wallet, self.mound())); runtime } @@ -833,17 +849,41 @@ impl TestWallet { BpDirMound::load_testnet(Consensus::Bitcoin, &self.wallet_dir, false) } + pub fn contracts_info(&self) -> Vec { + self.mound().contracts_info().collect() + } + + // FIXME: + // returns a value referencing data owned by the current function + // | temporary value created here + // pub fn contracts(&self) -> Vec<(ContractId, &Stockpile>)> { + // self.mound().contracts().collect() + // } + + pub fn contract_states( + &self, + contract_id: Option, + // TODO: cannot use type `ContractState`, because it mod is private and not exported + // ) -> Vec<(ContractId, ContractState)> { + ) { + let mut runtime = self.runtime(); + let contract_states = runtime.state_all(contract_id).collect::>(); + dbg!(contract_states); + todo!() + } + pub fn issue_with_info( &mut self, // asset_info: AssetInfo, - params: Option, + params: CreateParams, // close_method: CloseMethod, // outpoints: Vec>, ) -> ContractId { let mut runtime = self.runtime(); - let file = File::open(params).expect("Unable to open parameters file"); - let params = serde_yaml::from_reader::<_, CreateParams>(file)?; - let contract_id = runtime.issue_to_file(params)?; + + let contract_id = runtime + .issue_to_file(params) + .expect("failed to issue contract"); println!("A new contract issued with ID {contract_id}"); contract_id // let outpoints = if outpoints.is_empty() { @@ -878,81 +918,114 @@ impl TestWallet { pub fn issue_nia( &mut self, - issued_supply: u64, - close_method: CloseMethod, - outpoint: Option<&Outpoint>, - ) -> (ContractId, TypeName) { - let asset_info = AssetInfo::default_nia(vec![issued_supply]); - self.issue_with_info(asset_info, close_method, vec![outpoint.copied()]) + params: PathBuf, + // issued_supply: u64, + // close_method: CloseMethod, + // outpoint: Option<&Outpoint>, + ) -> ContractId { + let file = File::open(params).expect("Unable to open parameters file"); + let params: CreateParams = + serde_yaml::from_reader::<_, CreateParams>(file).expect(""); + // let asset_info = AssetInfo::default_nia(vec![issued_supply]); + self.issue_with_info(params) } pub fn issue_uda( &mut self, - close_method: CloseMethod, + // close_method: CloseMethod, outpoint: Option<&Outpoint>, ) -> (ContractId, TypeName) { - let asset_info = AssetInfo::default_uda(); - self.issue_with_info(asset_info, close_method, vec![outpoint.copied()]) + todo!() + // let asset_info = AssetInfo::default_uda(); + // self.issue_with_info(asset_info, close_method, vec![outpoint.copied()]) } pub fn issue_cfa( &mut self, issued_supply: u64, - close_method: CloseMethod, + // close_method: CloseMethod, outpoint: Option<&Outpoint>, ) -> (ContractId, TypeName) { - let asset_info = AssetInfo::default_cfa(vec![issued_supply]); - self.issue_with_info(asset_info, close_method, vec![outpoint.copied()]) + todo!() + // let asset_info = AssetInfo::default_cfa(vec![issued_supply]); + // self.issue_with_info(asset_info, close_method, vec![outpoint.copied()]) } pub fn invoice( &mut self, contract_id: ContractId, - iface_type_name: &TypeName, + // iface_type_name: &TypeName, amount: u64, - close_method: CloseMethod, + // close_method: CloseMethod, invoice_type: InvoiceType, ) -> RgbInvoice { - let network = self.wallet.wallet().network(); - let beneficiary = match invoice_type { - InvoiceType::Blinded(outpoint) => { - let outpoint = if let Some(outpoint) = outpoint { - outpoint - } else { - self.get_utxo(None) - }; - let seal = XChain::Bitcoin(GraphSeal::new_random( - close_method, - outpoint.txid, - outpoint.vout, - )); - self.wallet.stock_mut().store_secret_seal(seal).unwrap(); - Beneficiary::BlindedSeal(*seal.to_secret_seal().as_reduced_unsafe()) - } - InvoiceType::Witness => { - let address = self.get_address(); - Beneficiary::WitnessVout(Pay2Vout { - address: address.payload, - method: close_method, - }) - } + // let network = self.wallet.network(); + let mut runtime = self.runtime(); + let beneficiary = if invoice_type == InvoiceType::Witness { + let wout = runtime.wout(None); + RgbBeneficiary::WitnessOut(wout) + } else { + let auth = runtime.auth_token(None).expect( + "Wallet has no unspent outputs; try `fund` first, or use `-w` flag to \ + generate a witness output-based seal", + ); + RgbBeneficiary::Token(auth) }; - let mut builder = RgbInvoiceBuilder::new(XChainNet::bitcoin(network, beneficiary)) - .set_contract(contract_id) - .set_interface(iface_type_name.clone()); - if *iface_type_name == AssetSchema::Uda.iface_type_name() { - if amount != 1 { - panic!("UDA amount must be 1"); - } - builder = builder - .clone() - .set_allocation(UDA_FIXED_INDEX, amount) - .unwrap(); - } else { - builder = builder.clone().set_amount_raw(amount); - } - builder.finish() + let contract_id = CallScope::ContractId(contract_id); + + let value = StrictVal::num(amount); + let mut invoice = RgbInvoice::new(contract_id, beneficiary, Some(value)); + // if let Some(api) = api { + // invoice = invoice.use_api(api.clone()); + // } + // if let Some(method) = method { + // invoice = invoice.use_method(method.clone()); + // } + // if let Some(state) = state { + // invoice = invoice.use_state(state.clone()); + // } + + invoice + // let beneficiary = match invoice_type { + // InvoiceType::Blinded(outpoint) => { + // let outpoint = if let Some(outpoint) = outpoint { + // outpoint + // } else { + // self.get_utxo(None) + // }; + // let seal = XChain::Bitcoin(GraphSeal::new_random( + // close_method, + // outpoint.txid, + // outpoint.vout, + // )); + // self.wallet.stock_mut().store_secret_seal(seal).unwrap(); + // Beneficiary::BlindedSeal(*seal.to_secret_seal().as_reduced_unsafe()) + // } + // InvoiceType::Witness => { + // let address = self.get_address(); + // Beneficiary::WitnessVout(Pay2Vout { + // address: address.payload, + // method: close_method, + // }) + // } + // }; + + // let mut builder = RgbInvoiceBuilder::new(XChainNet::bitcoin(network, beneficiary)) + // .set_contract(contract_id) + // .set_interface(iface_type_name.clone()); + // if *iface_type_name == AssetSchema::Uda.iface_type_name() { + // if amount != 1 { + // panic!("UDA amount must be 1"); + // } + // builder = builder + // .clone() + // .set_allocation(UDA_FIXED_INDEX, amount) + // .unwrap(); + // } else { + // builder = builder.clone().set_amount_raw(amount); + // } + // builder.finish() } pub fn sign_finalize(&self, psbt: &mut Psbt) { @@ -965,491 +1038,491 @@ impl TestWallet { psbt.extract().unwrap() } - pub fn transfer( - &mut self, - invoice: RgbInvoice, - sats: Option, - fee: Option, - broadcast: bool, - report: Option<&Report>, - ) -> (Transfer, Tx) { - self.sync(); - - let fee = Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS)); - let sats = Sats::from_sats(sats.unwrap_or(2000)); - let params = TransferParams::with(fee, sats); - let pay_start = Instant::now(); - let (mut psbt, _psbt_meta, consignment) = self.wallet.pay(&invoice, params).unwrap(); - let pay_duration = pay_start.elapsed(); - if let Some(report) = report { - report.write_duration(pay_duration); - } - - let mut cs_path = self.wallet_dir.join("consignments"); - std::fs::create_dir_all(&cs_path).unwrap(); - let consignment_id = consignment.consignment_id(); - cs_path.push(consignment_id.to_string()); - cs_path.set_extension("yaml"); - let mut file = std::fs::File::options() - .read(true) - .write(true) - .create_new(true) - .open(cs_path) - .unwrap(); - serde_yaml::to_writer(&mut file, &consignment).unwrap(); - - let tx = self.sign_finalize_extract(&mut psbt); - - let txid = tx.txid().to_string(); - println!("transfer txid: {txid}, consignment: {consignment_id}"); - - let mut tx_path = self.wallet_dir.join("transactions"); - std::fs::create_dir_all(&tx_path).unwrap(); - tx_path.push(&txid); - tx_path.set_extension("yaml"); - let mut file = std::fs::File::options() - .read(true) - .write(true) - .create_new(true) - .open(tx_path) - .unwrap(); - serde_yaml::to_writer(&mut file, &tx).unwrap(); - writeln!(file, "\n---\n").unwrap(); - serde_yaml::to_writer(&mut file, &psbt).unwrap(); - - if broadcast { - self.broadcast_tx(&tx); - } - - (consignment, tx) - } - - pub fn accept_transfer(&mut self, consignment: Transfer, report: Option<&Report>) { - let mut resolver = self.get_resolver(); - resolver.add_terminals(&consignment); - self.accept_transfer_custom_resolver(consignment, report, &resolver); - } + // pub fn transfer( + // &mut self, + // invoice: RgbInvoice, + // sats: Option, + // fee: Option, + // broadcast: bool, + // report: Option<&Report>, + // ) -> (Transfer, Tx) { + // self.sync(); + + // let fee = Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS)); + // let sats = Sats::from_sats(sats.unwrap_or(2000)); + // let params = TransferParams::with(fee, sats); + // let pay_start = Instant::now(); + // let (mut psbt, _psbt_meta, consignment) = self.wallet.pay(&invoice, params).unwrap(); + // let pay_duration = pay_start.elapsed(); + // if let Some(report) = report { + // report.write_duration(pay_duration); + // } - pub fn accept_transfer_custom_resolver( - &mut self, - consignment: Transfer, - report: Option<&Report>, - resolver: &impl ResolveWitness, - ) { - self.sync(); - let validate_start = Instant::now(); - let validated_consignment = consignment - .validate(&resolver, self.testnet()) - .map_err(|(status, _)| status) - .unwrap(); - let validate_duration = validate_start.elapsed(); - if let Some(report) = report { - report.write_duration(validate_duration); - } + // let mut cs_path = self.wallet_dir.join("consignments"); + // std::fs::create_dir_all(&cs_path).unwrap(); + // let consignment_id = consignment.consignment_id(); + // cs_path.push(consignment_id.to_string()); + // cs_path.set_extension("yaml"); + // let mut file = std::fs::File::options() + // .read(true) + // .write(true) + // .create_new(true) + // .open(cs_path) + // .unwrap(); + // serde_yaml::to_writer(&mut file, &consignment).unwrap(); + + // let tx = self.sign_finalize_extract(&mut psbt); + + // let txid = tx.txid().to_string(); + // println!("transfer txid: {txid}, consignment: {consignment_id}"); + + // let mut tx_path = self.wallet_dir.join("transactions"); + // std::fs::create_dir_all(&tx_path).unwrap(); + // tx_path.push(&txid); + // tx_path.set_extension("yaml"); + // let mut file = std::fs::File::options() + // .read(true) + // .write(true) + // .create_new(true) + // .open(tx_path) + // .unwrap(); + // serde_yaml::to_writer(&mut file, &tx).unwrap(); + // writeln!(file, "\n---\n").unwrap(); + // serde_yaml::to_writer(&mut file, &psbt).unwrap(); + + // if broadcast { + // self.broadcast_tx(&tx); + // } - let validation_status = validated_consignment.clone().into_validation_status(); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Valid); - let accept_start = Instant::now(); - self.wallet - .stock_mut() - .accept_transfer(validated_consignment.clone(), &resolver) - .unwrap(); - let accept_duration = accept_start.elapsed(); - if let Some(report) = report { - report.write_duration(accept_duration); - } - } + // (consignment, tx) + // } - pub fn contract_iface( - &self, - contract_id: ContractId, - iface_type_name: &TypeName, - ) -> ContractIface> { - self.wallet - .stock() - .contract_iface(contract_id, iface_type_name.clone()) - .unwrap() - } + // pub fn accept_transfer(&mut self, consignment: Transfer, report: Option<&Report>) { + // let mut resolver = self.get_resolver(); + // resolver.add_terminals(&consignment); + // self.accept_transfer_custom_resolver(consignment, report, &resolver); + // } - pub fn contract_iface_class( - &self, - contract_id: ContractId, - ) -> C::Wrapper> { - self.wallet - .stock() - .contract_iface_class::(contract_id) - .unwrap() - } + // pub fn accept_transfer_custom_resolver( + // &mut self, + // consignment: Transfer, + // report: Option<&Report>, + // resolver: &impl ResolveWitness, + // ) { + // self.sync(); + // let validate_start = Instant::now(); + // let validated_consignment = consignment + // .validate(&resolver, self.testnet()) + // .map_err(|(status, _)| status) + // .unwrap(); + // let validate_duration = validate_start.elapsed(); + // if let Some(report) = report { + // report.write_duration(validate_duration); + // } - pub fn contract_fungible_allocations( - &self, - contract_id: ContractId, - iface_type_name: &TypeName, - show_tentative: bool, - ) -> Vec { - let filter = if show_tentative { - Filter::WalletTentative(&self.wallet) - } else { - Filter::Wallet(&self.wallet) - }; - self.contract_iface(contract_id, iface_type_name) - .fungible(fname!("assetOwner"), filter) - .unwrap() - .collect() - } + // let validation_status = validated_consignment.clone().into_validation_status(); + // let validity = validation_status.validity(); + // assert_eq!(validity, Validity::Valid); + // let accept_start = Instant::now(); + // self.wallet + // .stock_mut() + // .accept_transfer(validated_consignment.clone(), &resolver) + // .unwrap(); + // let accept_duration = accept_start.elapsed(); + // if let Some(report) = report { + // report.write_duration(accept_duration); + // } + // } - pub fn contract_data_allocations( - &self, - contract_id: ContractId, - iface_type_name: &TypeName, - ) -> Vec { - self.contract_iface(contract_id, iface_type_name) - .data(fname!("assetOwner"), Filter::Wallet(&self.wallet)) - .unwrap() - .collect() - } + // pub fn contract_iface( + // &self, + // contract_id: ContractId, + // iface_type_name: &TypeName, + // ) -> ContractIface> { + // self.wallet + // .stock() + // .contract_iface(contract_id, iface_type_name.clone()) + // .unwrap() + // } - pub fn history(&self, contract_id: ContractId, iface_type_name: &TypeName) -> Vec { - self.wallet - .history(contract_id, iface_type_name.clone()) - .unwrap() - } + // pub fn contract_iface_class( + // &self, + // contract_id: ContractId, + // ) -> C::Wrapper> { + // self.wallet + // .stock() + // .contract_iface_class::(contract_id) + // .unwrap() + // } - pub fn list_contracts(&self) -> Vec { - self.wallet.stock().contracts().unwrap().collect() - } + // pub fn contract_fungible_allocations( + // &self, + // contract_id: ContractId, + // iface_type_name: &TypeName, + // show_tentative: bool, + // ) -> Vec { + // let filter = if show_tentative { + // Filter::WalletTentative(&self.wallet) + // } else { + // Filter::Wallet(&self.wallet) + // }; + // self.contract_iface(contract_id, iface_type_name) + // .fungible(fname!("assetOwner"), filter) + // .unwrap() + // .collect() + // } - pub fn debug_contracts(&self) { - println!("Contracts:"); - for info in self.list_contracts() { - println!("{}", info.to_string().replace("\n", "\t")); - } - } + // pub fn contract_data_allocations( + // &self, + // contract_id: ContractId, + // iface_type_name: &TypeName, + // ) -> Vec { + // self.contract_iface(contract_id, iface_type_name) + // .data(fname!("assetOwner"), Filter::Wallet(&self.wallet)) + // .unwrap() + // .collect() + // } - pub fn debug_logs( - &self, - contract_id: ContractId, - iface_type_name: &TypeName, - filter: AllocationFilter, - ) { - let filter = match filter { - AllocationFilter::WalletAll => Filter::WalletAll(&self.wallet), - AllocationFilter::WalletTentative => Filter::WalletTentative(&self.wallet), - AllocationFilter::Wallet => Filter::Wallet(&self.wallet), - AllocationFilter::Stock => Filter::NoWallet, - }; + // pub fn history(&self, contract_id: ContractId, iface_type_name: &TypeName) -> Vec { + // self.wallet + // .history(contract_id, iface_type_name.clone()) + // .unwrap() + // } - let contract = self.contract_iface(contract_id, iface_type_name); + // pub fn list_contracts(&self) -> Vec { + // self.wallet.stock().contracts().unwrap().collect() + // } - println!("Global:"); - for global in &contract.iface.global_state { - if let Ok(values) = contract.global(global.name.clone()) { - for val in values { - println!(" {} := {}", global.name, val); - } - } - } + // pub fn debug_contracts(&self) { + // println!("Contracts:"); + // for info in self.list_contracts() { + // println!("{}", info.to_string().replace("\n", "\t")); + // } + // } - println!("\nOwned:"); - fn witness( - allocation: &OutputAssignment, - contract: &ContractIface>, - ) -> String { - allocation - .witness - .and_then(|w| contract.witness_info(w)) - .map(|info| format!("{} ({})", info.id, info.ord)) - .unwrap_or_else(|| s!("~")) - } - for owned in &contract.iface.assignments { - println!(" State \t{:78}\tWitness", "Seal"); - println!(" {}:", owned.name); - if let Ok(allocations) = contract.fungible(owned.name.clone(), &filter) { - for allocation in allocations { - println!( - " {: >9}\t{}\t{} {}", - allocation.state.value(), - allocation.seal, - witness(&allocation, &contract), - filter.comment(allocation.seal.to_outpoint()) - ); - } - } - if let Ok(allocations) = contract.data(owned.name.clone(), &filter) { - for allocation in allocations { - println!( - " {: >9}\t{}\t{} {}", - allocation.state, - allocation.seal, - witness(&allocation, &contract), - filter.comment(allocation.seal.to_outpoint()) - ); - } - } - if let Ok(allocations) = contract.attachments(owned.name.clone(), &filter) { - for allocation in allocations { - println!( - " {: >9}\t{}\t{} {}", - allocation.state, - allocation.seal, - witness(&allocation, &contract), - filter.comment(allocation.seal.to_outpoint()) - ); - } - } - if let Ok(allocations) = contract.rights(owned.name.clone(), &filter) { - for allocation in allocations { - println!( - " {: >9}\t{}\t{} {}", - "right", - allocation.seal, - witness(&allocation, &contract), - filter.comment(allocation.seal.to_outpoint()) - ); - } - } - } + // pub fn debug_logs( + // &self, + // contract_id: ContractId, + // iface_type_name: &TypeName, + // filter: AllocationFilter, + // ) { + // let filter = match filter { + // AllocationFilter::WalletAll => Filter::WalletAll(&self.wallet), + // AllocationFilter::WalletTentative => Filter::WalletTentative(&self.wallet), + // AllocationFilter::Wallet => Filter::Wallet(&self.wallet), + // AllocationFilter::Stock => Filter::NoWallet, + // }; + + // let contract = self.contract_iface(contract_id, iface_type_name); + + // println!("Global:"); + // for global in &contract.iface.global_state { + // if let Ok(values) = contract.global(global.name.clone()) { + // for val in values { + // println!(" {} := {}", global.name, val); + // } + // } + // } - let bp_runtime = self.wallet.wallet(); - println!("\nHeight\t{:>12}\t{:68}", "Amount, ṩ", "Outpoint"); - for (derived_addr, utxos) in bp_runtime.address_coins() { - println!("{}\t{}", derived_addr.addr, derived_addr.terminal); - for row in utxos { - println!("{}\t{: >12}\t{:68}", row.height, row.amount, row.outpoint); - } - println!() - } + // println!("\nOwned:"); + // fn witness( + // allocation: &OutputAssignment, + // contract: &ContractIface>, + // ) -> String { + // allocation + // .witness + // .and_then(|w| contract.witness_info(w)) + // .map(|info| format!("{} ({})", info.id, info.ord)) + // .unwrap_or_else(|| s!("~")) + // } + // for owned in &contract.iface.assignments { + // println!(" State \t{:78}\tWitness", "Seal"); + // println!(" {}:", owned.name); + // if let Ok(allocations) = contract.fungible(owned.name.clone(), &filter) { + // for allocation in allocations { + // println!( + // " {: >9}\t{}\t{} {}", + // allocation.state.value(), + // allocation.seal, + // witness(&allocation, &contract), + // filter.comment(allocation.seal.to_outpoint()) + // ); + // } + // } + // if let Ok(allocations) = contract.data(owned.name.clone(), &filter) { + // for allocation in allocations { + // println!( + // " {: >9}\t{}\t{} {}", + // allocation.state, + // allocation.seal, + // witness(&allocation, &contract), + // filter.comment(allocation.seal.to_outpoint()) + // ); + // } + // } + // if let Ok(allocations) = contract.attachments(owned.name.clone(), &filter) { + // for allocation in allocations { + // println!( + // " {: >9}\t{}\t{} {}", + // allocation.state, + // allocation.seal, + // witness(&allocation, &contract), + // filter.comment(allocation.seal.to_outpoint()) + // ); + // } + // } + // if let Ok(allocations) = contract.rights(owned.name.clone(), &filter) { + // for allocation in allocations { + // println!( + // " {: >9}\t{}\t{} {}", + // "right", + // allocation.seal, + // witness(&allocation, &contract), + // filter.comment(allocation.seal.to_outpoint()) + // ); + // } + // } + // } - println!("\nWallet total balance: {} ṩ", bp_runtime.balance()); - } + // let bp_runtime = self.wallet.wallet(); + // println!("\nHeight\t{:>12}\t{:68}", "Amount, ṩ", "Outpoint"); + // for (derived_addr, utxos) in bp_runtime.address_coins() { + // println!("{}\t{}", derived_addr.addr, derived_addr.terminal); + // for row in utxos { + // println!("{}\t{: >12}\t{:68}", row.height, row.amount, row.outpoint); + // } + // println!() + // } - pub fn debug_history( - &self, - contract_id: ContractId, - iface_type_name: &TypeName, - details: bool, - ) { - let mut history = self.history(contract_id, iface_type_name); - history.sort_by_key(|op| op.witness.map(|w| w.ord).unwrap_or(WitnessOrd::Archived)); - if details { - println!("Operation\tValue \tState\t{:78}\tWitness", "Seal"); - } else { - println!("Operation\tValue \t{:78}\tWitness", "Seal"); - } - for ContractOp { - direction, - ty, - opids, - state, - to, - witness, - } in history - { - print!("{:9}\t", direction.to_string()); - if let AllocatedState::Amount(amount) = state { - print!("{: >9}", amount.value()); - } else { - print!("{state:>9}"); - } - if details { - print!("\t{ty}"); - } - println!( - "\t{}\t{}", - to.first().expect("at least one receiver is always present"), - witness - .map(|info| format!("{} ({})", info.id, info.ord)) - .unwrap_or_else(|| s!("~")) - ); - if details { - println!( - "\topid={}", - opids - .iter() - .map(OpId::to_string) - .collect::>() - .join("\n\topid=") - ) - } - } - } + // println!("\nWallet total balance: {} ṩ", bp_runtime.balance()); + // } - #[allow(clippy::too_many_arguments)] - pub fn send( - &mut self, - recv_wlt: &mut TestWallet, - transfer_type: TransferType, - contract_id: ContractId, - iface_type_name: &TypeName, - amount: u64, - sats: u64, - report: Option<&Report>, - ) -> (Transfer, Tx) { - let invoice = recv_wlt.invoice( - contract_id, - iface_type_name, - amount, - recv_wlt.close_method(), - transfer_type.into(), - ); - self.send_to_invoice(recv_wlt, invoice, Some(sats), None, report) - } + // pub fn debug_history( + // &self, + // contract_id: ContractId, + // iface_type_name: &TypeName, + // details: bool, + // ) { + // let mut history = self.history(contract_id, iface_type_name); + // history.sort_by_key(|op| op.witness.map(|w| w.ord).unwrap_or(WitnessOrd::Archived)); + // if details { + // println!("Operation\tValue \tState\t{:78}\tWitness", "Seal"); + // } else { + // println!("Operation\tValue \t{:78}\tWitness", "Seal"); + // } + // for ContractOp { + // direction, + // ty, + // opids, + // state, + // to, + // witness, + // } in history + // { + // print!("{:9}\t", direction.to_string()); + // if let AllocatedState::Amount(amount) = state { + // print!("{: >9}", amount.value()); + // } else { + // print!("{state:>9}"); + // } + // if details { + // print!("\t{ty}"); + // } + // println!( + // "\t{}\t{}", + // to.first().expect("at least one receiver is always present"), + // witness + // .map(|info| format!("{} ({})", info.id, info.ord)) + // .unwrap_or_else(|| s!("~")) + // ); + // if details { + // println!( + // "\topid={}", + // opids + // .iter() + // .map(OpId::to_string) + // .collect::>() + // .join("\n\topid=") + // ) + // } + // } + // } - pub fn send_to_invoice( - &mut self, - recv_wlt: &mut TestWallet, - invoice: RgbInvoice, - sats: Option, - fee: Option, - report: Option<&Report>, - ) -> (Transfer, Tx) { - let (consignment, tx) = self.transfer(invoice, sats, fee, true, report); - self.mine_tx(&tx.txid(), false); - recv_wlt.accept_transfer(consignment.clone(), report); - self.sync(); - (consignment, tx) - } + // #[allow(clippy::too_many_arguments)] + // pub fn send( + // &mut self, + // recv_wlt: &mut TestWallet, + // transfer_type: TransferType, + // contract_id: ContractId, + // iface_type_name: &TypeName, + // amount: u64, + // sats: u64, + // report: Option<&Report>, + // ) -> (Transfer, Tx) { + // let invoice = recv_wlt.invoice( + // contract_id, + // iface_type_name, + // amount, + // recv_wlt.close_method(), + // transfer_type.into(), + // ); + // self.send_to_invoice(recv_wlt, invoice, Some(sats), None, report) + // } - pub fn check_allocations( - &self, - contract_id: ContractId, - iface_type_name: &TypeName, - asset_schema: AssetSchema, - expected_fungible_allocations: Vec, - nonfungible_allocation: bool, - ) { - match asset_schema { - AssetSchema::Nia | AssetSchema::Cfa => { - let allocations = - self.contract_fungible_allocations(contract_id, iface_type_name, false); - let mut actual_fungible_allocations = allocations - .iter() - .map(|a| a.state.value()) - .collect::>(); - let mut expected_fungible_allocations = expected_fungible_allocations.clone(); - actual_fungible_allocations.sort(); - expected_fungible_allocations.sort(); - assert_eq!(actual_fungible_allocations, expected_fungible_allocations); - assert!(allocations - .iter() - .all(|a| a.seal.method() == self.close_method())); - } - AssetSchema::Uda => { - let allocations = self.contract_data_allocations(contract_id, iface_type_name); - let expected_allocations = if nonfungible_allocation { - assert_eq!( - allocations - .iter() - .filter(|a| a.state.to_string() == "000000000100000000000000") - .count(), - 1 - ); - 1 - } else { - 0 - }; - assert_eq!(allocations.len(), expected_allocations); - } - } - } + // pub fn send_to_invoice( + // &mut self, + // recv_wlt: &mut TestWallet, + // invoice: RgbInvoice, + // sats: Option, + // fee: Option, + // report: Option<&Report>, + // ) -> (Transfer, Tx) { + // let (consignment, tx) = self.transfer(invoice, sats, fee, true, report); + // self.mine_tx(&tx.txid(), false); + // recv_wlt.accept_transfer(consignment.clone(), report); + // self.sync(); + // (consignment, tx) + // } - pub fn check_history_operation( - &self, - contract_id: &ContractId, - iface_type_name: &TypeName, - txid: Option<&Txid>, - direction: OpDirection, - amount: u64, - ) { - let operation = self - .history(*contract_id, iface_type_name) - .into_iter() - .find(|co| { - co.direction == direction - && co - .witness - .map_or(true, |w| Some(w.id.as_reduced_unsafe()) == txid) - }) - .unwrap(); - assert!(matches!(operation.state, AllocatedState::Amount(amt) if amt.value() == amount)); - } + // pub fn check_allocations( + // &self, + // contract_id: ContractId, + // iface_type_name: &TypeName, + // asset_schema: AssetSchema, + // expected_fungible_allocations: Vec, + // nonfungible_allocation: bool, + // ) { + // match asset_schema { + // AssetSchema::Nia | AssetSchema::Cfa => { + // let allocations = + // self.contract_fungible_allocations(contract_id, iface_type_name, false); + // let mut actual_fungible_allocations = allocations + // .iter() + // .map(|a| a.state.value()) + // .collect::>(); + // let mut expected_fungible_allocations = expected_fungible_allocations.clone(); + // actual_fungible_allocations.sort(); + // expected_fungible_allocations.sort(); + // assert_eq!(actual_fungible_allocations, expected_fungible_allocations); + // assert!(allocations + // .iter() + // .all(|a| a.seal.method() == self.close_method())); + // } + // AssetSchema::Uda => { + // let allocations = self.contract_data_allocations(contract_id, iface_type_name); + // let expected_allocations = if nonfungible_allocation { + // assert_eq!( + // allocations + // .iter() + // .filter(|a| a.state.to_string() == "000000000100000000000000") + // .count(), + // 1 + // ); + // 1 + // } else { + // 0 + // }; + // assert_eq!(allocations.len(), expected_allocations); + // } + // } + // } - fn _construct_psbt_offchain( - &mut self, - input_outpoints: Vec<(Outpoint, u64, Terminal)>, - beneficiaries: Vec<&PsbtBeneficiary>, - tx_params: TxParams, - ) -> (Psbt, PsbtMeta) { - let mut psbt = Psbt::create(PsbtVer::V2); - - for (outpoint, value, terminal) in input_outpoints { - psbt.construct_input_expect( - Prevout::new(outpoint, Sats::from(value)), - self.wallet.wallet().descriptor(), - terminal, - tx_params.seq_no, - ); - } - if psbt.inputs().count() == 0 { - panic!("no inputs"); - } + // pub fn check_history_operation( + // &self, + // contract_id: &ContractId, + // iface_type_name: &TypeName, + // txid: Option<&Txid>, + // direction: OpDirection, + // amount: u64, + // ) { + // let operation = self + // .history(*contract_id, iface_type_name) + // .into_iter() + // .find(|co| { + // co.direction == direction + // && co + // .witness + // .map_or(true, |w| Some(w.id.as_reduced_unsafe()) == txid) + // }) + // .unwrap(); + // assert!(matches!(operation.state, AllocatedState::Amount(amt) if amt.value() == amount)); + // } - let input_value = psbt.input_sum(); - let mut max = Vec::new(); - let mut output_value = Sats::ZERO; - for beneficiary in beneficiaries { - let amount = beneficiary.amount.unwrap_or(Sats::ZERO); - output_value.checked_add_assign(amount).unwrap(); - let out = psbt.construct_output_expect(beneficiary.script_pubkey(), amount); - if beneficiary.amount.is_max() { - max.push(out.index()); - } - } - let mut remaining_value = input_value - .checked_sub(output_value) - .unwrap() - .checked_sub(tx_params.fee) - .unwrap(); - if !max.is_empty() { - let portion = remaining_value / max.len(); - for out in psbt.outputs_mut() { - if max.contains(&out.index()) { - out.amount = portion; - } - } - remaining_value = Sats::ZERO; - } + // fn _construct_psbt_offchain( + // &mut self, + // input_outpoints: Vec<(Outpoint, u64, Terminal)>, + // beneficiaries: Vec<&PsbtBeneficiary>, + // tx_params: TxParams, + // ) -> (Psbt, PsbtMeta) { + // let mut psbt = Psbt::create(PsbtVer::V2); + + // for (outpoint, value, terminal) in input_outpoints { + // psbt.construct_input_expect( + // Prevout::new(outpoint, Sats::from(value)), + // self.wallet.wallet().descriptor(), + // terminal, + // tx_params.seq_no, + // ); + // } + // if psbt.inputs().count() == 0 { + // panic!("no inputs"); + // } - let (change_vout, change_terminal) = if remaining_value > Sats::from(546u64) { - let change_index = self - .wallet - .wallet_mut() - .next_derivation_index(tx_params.change_keychain, tx_params.change_shift); - let change_terminal = Terminal::new(tx_params.change_keychain, change_index); - let change_vout = psbt - .construct_change_expect( - self.wallet.wallet().descriptor(), - change_terminal, - remaining_value, - ) - .index(); - ( - Some(Vout::from_u32(change_vout as u32)), - Some(change_terminal), - ) - } else { - (None, None) - }; + // let input_value = psbt.input_sum(); + // let mut max = Vec::new(); + // let mut output_value = Sats::ZERO; + // for beneficiary in beneficiaries { + // let amount = beneficiary.amount.unwrap_or(Sats::ZERO); + // output_value.checked_add_assign(amount).unwrap(); + // let out = psbt.construct_output_expect(beneficiary.script_pubkey(), amount); + // if beneficiary.amount.is_max() { + // max.push(out.index()); + // } + // } + // let mut remaining_value = input_value + // .checked_sub(output_value) + // .unwrap() + // .checked_sub(tx_params.fee) + // .unwrap(); + // if !max.is_empty() { + // let portion = remaining_value / max.len(); + // for out in psbt.outputs_mut() { + // if max.contains(&out.index()) { + // out.amount = portion; + // } + // } + // remaining_value = Sats::ZERO; + // } - ( - psbt, - PsbtMeta { - change_vout, - change_terminal, - }, - ) - } + // let (change_vout, change_terminal) = if remaining_value > Sats::from(546u64) { + // let change_index = self + // .wallet + // .wallet_mut() + // .next_derivation_index(tx_params.change_keychain, tx_params.change_shift); + // let change_terminal = Terminal::new(tx_params.change_keychain, change_index); + // let change_vout = psbt + // .construct_change_expect( + // self.wallet.wallet().descriptor(), + // change_terminal, + // remaining_value, + // ) + // .index(); + // ( + // Some(Vout::from_u32(change_vout as u32)), + // Some(change_terminal), + // ) + // } else { + // (None, None) + // }; + + // ( + // psbt, + // PsbtMeta { + // change_vout, + // change_terminal, + // }, + // ) + // } fn _construct_beneficiaries( &self, @@ -1468,263 +1541,263 @@ impl TestWallet { .collect() } - pub fn construct_psbt_offchain( - &mut self, - input_outpoints: Vec<(Outpoint, u64, Terminal)>, - beneficiaries: Vec<(Address, Option)>, - fee: Option, - ) -> (Psbt, PsbtMeta) { - let tx_params = TxParams::with(Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS))); - let beneficiaries = self._construct_beneficiaries(beneficiaries); - let beneficiaries: Vec<&PsbtBeneficiary> = beneficiaries.iter().collect(); - - self._construct_psbt_offchain(input_outpoints, beneficiaries, tx_params) - } - - pub fn construct_psbt( - &mut self, - input_outpoints: Vec, - beneficiaries: Vec<(Address, Option)>, - fee: Option, - ) -> (Psbt, PsbtMeta) { - let tx_params = TxParams::with(Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS))); - let beneficiaries = self._construct_beneficiaries(beneficiaries); - let beneficiaries: Vec<&PsbtBeneficiary> = beneficiaries.iter().collect(); - - self.wallet - .wallet_mut() - .construct_psbt(input_outpoints, beneficiaries, tx_params) - .unwrap() - } - - pub fn psbt_add_input(&self, psbt: &mut Psbt, utxo: Outpoint) { - for account in self.descriptor.xpubs() { - psbt.xpubs.insert(*account.xpub(), account.origin().clone()); - } - let input = self.wallet.wallet().utxo(utxo).unwrap(); - psbt.construct_input_expect( - input.to_prevout(), - self.wallet.wallet().descriptor(), - input.terminal, - SeqNo::ZERO, - ); - } - - pub fn color_psbt( - &self, - psbt: &mut Psbt, - coloring_info: ColoringInfo, - ) -> (Fascia, AssetBeneficiariesMap) { - let asset_beneficiaries = self.color_psbt_init(psbt, coloring_info); - psbt.complete_construction(); - let fascia = psbt.rgb_commit().unwrap(); - (fascia, asset_beneficiaries) - } + // pub fn construct_psbt_offchain( + // &mut self, + // input_outpoints: Vec<(Outpoint, u64, Terminal)>, + // beneficiaries: Vec<(Address, Option)>, + // fee: Option, + // ) -> (Psbt, PsbtMeta) { + // let tx_params = TxParams::with(Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS))); + // let beneficiaries = self._construct_beneficiaries(beneficiaries); + // let beneficiaries: Vec<&PsbtBeneficiary> = beneficiaries.iter().collect(); - pub fn color_psbt_init( - &self, - psbt: &mut Psbt, - coloring_info: ColoringInfo, - ) -> AssetBeneficiariesMap { - if !psbt.outputs().any(|o| o.script.is_op_return()) { - let _output = psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO); - } + // self._construct_psbt_offchain(input_outpoints, beneficiaries, tx_params) + // } - let prev_outputs = psbt - .to_unsigned_tx() - .inputs - .iter() - .map(|txin| txin.prev_output) - .map(|outpoint| XOutpoint::from(XChain::Bitcoin(outpoint))) - .collect::>(); - - let mut all_transitions: HashMap = HashMap::new(); - let mut asset_beneficiaries: AssetBeneficiariesMap = bmap![]; - let assignment_name = FieldName::from("assetOwner"); - - for (contract_id, asset_coloring_info) in coloring_info.asset_info_map.clone() { - let mut asset_transition_builder = self - .wallet - .stock() - .transition_builder(contract_id, asset_coloring_info.iface, None::<&str>) - .unwrap(); - let assignment_id = asset_transition_builder - .assignments_type(&assignment_name) - .unwrap(); - - let mut asset_available_amt = 0; - for (_, opout_state_map) in self - .wallet - .stock() - .contract_assignments_for( - contract_id, - prev_outputs - .iter() - // only retrieve assignments for owned prevouts using coloring_info - .filter(|xop| { - coloring_info.asset_info_map[&contract_id] - .input_outpoints - .contains(xop.as_reduced_unsafe()) - }) - .copied(), - ) - .unwrap() - { - for (opout, state) in opout_state_map { - if let PersistedState::Amount(amt, _, _) = &state { - asset_available_amt += amt.value(); - } - asset_transition_builder = - asset_transition_builder.add_input(opout, state).unwrap(); - } - } + // pub fn construct_psbt( + // &mut self, + // input_outpoints: Vec, + // beneficiaries: Vec<(Address, Option)>, + // fee: Option, + // ) -> (Psbt, PsbtMeta) { + // let tx_params = TxParams::with(Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS))); + // let beneficiaries = self._construct_beneficiaries(beneficiaries); + // let beneficiaries: Vec<&PsbtBeneficiary> = beneficiaries.iter().collect(); + + // self.wallet + // .wallet_mut() + // .construct_psbt(input_outpoints, beneficiaries, tx_params) + // .unwrap() + // } - let mut beneficiaries = vec![]; - let mut sending_amt = 0; - for (vout, amount) in asset_coloring_info.output_map { - if amount == 0 { - continue; - } - sending_amt += amount; - if vout as usize > psbt.outputs().count() { - panic!("invalid vout in output_map, does not exist in the given PSBT"); - } - let graph_seal = if let Some(blinding) = asset_coloring_info.static_blinding { - GraphSeal::with_blinded_vout(CloseMethod::OpretFirst, vout, blinding) - } else { - GraphSeal::new_random_vout(CloseMethod::OpretFirst, vout) - }; - let seal = BuilderSeal::Revealed(XChain::with(Layer1::Bitcoin, graph_seal)); - beneficiaries.push(seal); + // pub fn psbt_add_input(&self, psbt: &mut Psbt, utxo: Outpoint) { + // for account in self.descriptor.xpubs() { + // psbt.xpubs.insert(*account.xpub(), account.origin().clone()); + // } + // let input = self.wallet.wallet().utxo(utxo).unwrap(); + // psbt.construct_input_expect( + // input.to_prevout(), + // self.wallet.wallet().descriptor(), + // input.terminal, + // SeqNo::ZERO, + // ); + // } - let blinding_factor = if let Some(blinding) = asset_coloring_info.static_blinding { - let mut blinding_32_bytes: [u8; 32] = [0; 32]; - blinding_32_bytes[0..8].copy_from_slice(&blinding.to_le_bytes()); - BlindingFactor::try_from(blinding_32_bytes).unwrap() - } else { - BlindingFactor::random() - }; - asset_transition_builder = asset_transition_builder - .add_fungible_state_raw(assignment_id, seal, amount, blinding_factor) - .unwrap(); - } - if sending_amt > asset_available_amt { - panic!("total amount in output_map greater than available ({asset_available_amt})"); - } + // pub fn color_psbt( + // &self, + // psbt: &mut Psbt, + // coloring_info: ColoringInfo, + // ) -> (Fascia, AssetBeneficiariesMap) { + // let asset_beneficiaries = self.color_psbt_init(psbt, coloring_info); + // psbt.complete_construction(); + // let fascia = psbt.rgb_commit().unwrap(); + // (fascia, asset_beneficiaries) + // } - if let Some(nonce) = coloring_info.nonce { - asset_transition_builder = asset_transition_builder.set_nonce(nonce); - } + // pub fn color_psbt_init( + // &self, + // psbt: &mut Psbt, + // coloring_info: ColoringInfo, + // ) -> AssetBeneficiariesMap { + // if !psbt.outputs().any(|o| o.script.is_op_return()) { + // let _output = psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO); + // } - let transition = asset_transition_builder.complete_transition().unwrap(); - all_transitions.insert(contract_id, transition); - asset_beneficiaries.insert(contract_id, beneficiaries); - } + // let prev_outputs = psbt + // .to_unsigned_tx() + // .inputs + // .iter() + // .map(|txin| txin.prev_output) + // .map(|outpoint| XOutpoint::from(XChain::Bitcoin(outpoint))) + // .collect::>(); + + // let mut all_transitions: HashMap = HashMap::new(); + // let mut asset_beneficiaries: AssetBeneficiariesMap = bmap![]; + // let assignment_name = FieldName::from("assetOwner"); + + // for (contract_id, asset_coloring_info) in coloring_info.asset_info_map.clone() { + // let mut asset_transition_builder = self + // .wallet + // .stock() + // .transition_builder(contract_id, asset_coloring_info.iface, None::<&str>) + // .unwrap(); + // let assignment_id = asset_transition_builder + // .assignments_type(&assignment_name) + // .unwrap(); + + // let mut asset_available_amt = 0; + // for (_, opout_state_map) in self + // .wallet + // .stock() + // .contract_assignments_for( + // contract_id, + // prev_outputs + // .iter() + // // only retrieve assignments for owned prevouts using coloring_info + // .filter(|xop| { + // coloring_info.asset_info_map[&contract_id] + // .input_outpoints + // .contains(xop.as_reduced_unsafe()) + // }) + // .copied(), + // ) + // .unwrap() + // { + // for (opout, state) in opout_state_map { + // if let PersistedState::Amount(amt, _, _) = &state { + // asset_available_amt += amt.value(); + // } + // asset_transition_builder = + // asset_transition_builder.add_input(opout, state).unwrap(); + // } + // } + + // let mut beneficiaries = vec![]; + // let mut sending_amt = 0; + // for (vout, amount) in asset_coloring_info.output_map { + // if amount == 0 { + // continue; + // } + // sending_amt += amount; + // if vout as usize > psbt.outputs().count() { + // panic!("invalid vout in output_map, does not exist in the given PSBT"); + // } + // let graph_seal = if let Some(blinding) = asset_coloring_info.static_blinding { + // GraphSeal::with_blinded_vout(CloseMethod::OpretFirst, vout, blinding) + // } else { + // GraphSeal::new_random_vout(CloseMethod::OpretFirst, vout) + // }; + // let seal = BuilderSeal::Revealed(XChain::with(Layer1::Bitcoin, graph_seal)); + // beneficiaries.push(seal); + + // let blinding_factor = if let Some(blinding) = asset_coloring_info.static_blinding { + // let mut blinding_32_bytes: [u8; 32] = [0; 32]; + // blinding_32_bytes[0..8].copy_from_slice(&blinding.to_le_bytes()); + // BlindingFactor::try_from(blinding_32_bytes).unwrap() + // } else { + // BlindingFactor::random() + // }; + // asset_transition_builder = asset_transition_builder + // .add_fungible_state_raw(assignment_id, seal, amount, blinding_factor) + // .unwrap(); + // } + // if sending_amt > asset_available_amt { + // panic!("total amount in output_map greater than available ({asset_available_amt})"); + // } + + // if let Some(nonce) = coloring_info.nonce { + // asset_transition_builder = asset_transition_builder.set_nonce(nonce); + // } + + // let transition = asset_transition_builder.complete_transition().unwrap(); + // all_transitions.insert(contract_id, transition); + // asset_beneficiaries.insert(contract_id, beneficiaries); + // } - let (opreturn_index, _) = psbt - .to_unsigned_tx() - .outputs - .iter() - .enumerate() - .find(|(_, o)| o.script_pubkey.is_op_return()) - .expect("psbt should have an op_return output"); - let (_, opreturn_output) = psbt - .outputs_mut() - .enumerate() - .find(|(i, _)| i == &opreturn_index) - .unwrap(); - opreturn_output.set_opret_host().unwrap(); - if let Some(blinding) = coloring_info.static_blinding { - opreturn_output.set_mpc_entropy(blinding).unwrap(); - } + // let (opreturn_index, _) = psbt + // .to_unsigned_tx() + // .outputs + // .iter() + // .enumerate() + // .find(|(_, o)| o.script_pubkey.is_op_return()) + // .expect("psbt should have an op_return output"); + // let (_, opreturn_output) = psbt + // .outputs_mut() + // .enumerate() + // .find(|(i, _)| i == &opreturn_index) + // .unwrap(); + // opreturn_output.set_opret_host().unwrap(); + // if let Some(blinding) = coloring_info.static_blinding { + // opreturn_output.set_mpc_entropy(blinding).unwrap(); + // } - let tx_inputs = psbt.clone().to_unsigned_tx().inputs; - for (contract_id, transition) in all_transitions { - for (input, txin) in psbt.inputs_mut().zip(&tx_inputs) { - let prevout = txin.prev_output; - let outpoint = Outpoint::new(prevout.txid.to_byte_array().into(), prevout.vout); - if coloring_info - .asset_info_map - .clone() - .get(&contract_id) - .unwrap() - .input_outpoints - .contains(&outpoint) - { - input - .set_rgb_consumer(contract_id, transition.id()) - .unwrap(); - } - } - psbt.push_rgb_transition(transition, CloseMethod::OpretFirst) - .unwrap(); - } + // let tx_inputs = psbt.clone().to_unsigned_tx().inputs; + // for (contract_id, transition) in all_transitions { + // for (input, txin) in psbt.inputs_mut().zip(&tx_inputs) { + // let prevout = txin.prev_output; + // let outpoint = Outpoint::new(prevout.txid.to_byte_array().into(), prevout.vout); + // if coloring_info + // .asset_info_map + // .clone() + // .get(&contract_id) + // .unwrap() + // .input_outpoints + // .contains(&outpoint) + // { + // input + // .set_rgb_consumer(contract_id, transition.id()) + // .unwrap(); + // } + // } + // psbt.push_rgb_transition(transition, CloseMethod::OpretFirst) + // .unwrap(); + // } - asset_beneficiaries - } + // asset_beneficiaries + // } - pub fn consume_fascia(&mut self, fascia: Fascia, witness_txid: Txid) { - struct FasciaResolver { - witness_id: XWitnessId, - } - impl ResolveWitness for FasciaResolver { - fn resolve_pub_witness( - &self, - _: XWitnessId, - ) -> Result { - unreachable!() - } - fn resolve_pub_witness_ord( - &self, - witness_id: XWitnessId, - ) -> Result { - assert_eq!(witness_id, self.witness_id); - Ok(WitnessOrd::Tentative) - } - } + // pub fn consume_fascia(&mut self, fascia: Fascia, witness_txid: Txid) { + // struct FasciaResolver { + // witness_id: XWitnessId, + // } + // impl ResolveWitness for FasciaResolver { + // fn resolve_pub_witness( + // &self, + // _: XWitnessId, + // ) -> Result { + // unreachable!() + // } + // fn resolve_pub_witness_ord( + // &self, + // witness_id: XWitnessId, + // ) -> Result { + // assert_eq!(witness_id, self.witness_id); + // Ok(WitnessOrd::Tentative) + // } + // } - let resolver = FasciaResolver { - witness_id: XChain::Bitcoin(witness_txid), - }; + // let resolver = FasciaResolver { + // witness_id: XChain::Bitcoin(witness_txid), + // }; - self.wallet - .stock_mut() - .consume_fascia(fascia, resolver) - .unwrap(); - } + // self.wallet + // .stock_mut() + // .consume_fascia(fascia, resolver) + // .unwrap(); + // } - pub fn update_witnesses(&mut self, after_height: u32) { - let resolver = self.get_resolver(); - self.wallet - .stock_mut() - .update_witnesses(resolver, after_height) - .unwrap(); - } + // pub fn update_witnesses(&mut self, after_height: u32) { + // let resolver = self.get_resolver(); + // self.wallet + // .stock_mut() + // .update_witnesses(resolver, after_height) + // .unwrap(); + // } - pub fn create_consignments( - &self, - asset_beneficiaries: AssetBeneficiariesMap, - witness_txid: Txid, - ) -> Vec { - let mut transfers = vec![]; - let stock = self.wallet.stock(); - - for (contract_id, beneficiaries) in asset_beneficiaries { - for beneficiary in beneficiaries { - match beneficiary { - BuilderSeal::Revealed(seal) => { - let explicit_seal = XChain::Bitcoin(ExplicitSeal::new( - seal.method(), - Outpoint::new(witness_txid, seal.as_reduced_unsafe().vout), - )); - transfers.push(stock.transfer(contract_id, [explicit_seal], None).unwrap()); - } - BuilderSeal::Concealed(seal) => { - transfers.push(stock.transfer(contract_id, vec![], Some(seal)).unwrap()); - } - } - } - } - transfers - } + // pub fn create_consignments( + // &self, + // asset_beneficiaries: AssetBeneficiariesMap, + // witness_txid: Txid, + // ) -> Vec { + // let mut transfers = vec![]; + // let stock = self.wallet.stock(); + + // for (contract_id, beneficiaries) in asset_beneficiaries { + // for beneficiary in beneficiaries { + // match beneficiary { + // BuilderSeal::Revealed(seal) => { + // let explicit_seal = XChain::Bitcoin(ExplicitSeal::new( + // seal.method(), + // Outpoint::new(witness_txid, seal.as_reduced_unsafe().vout), + // )); + // transfers.push(stock.transfer(contract_id, [explicit_seal], None).unwrap()); + // } + // BuilderSeal::Concealed(seal) => { + // transfers.push(stock.transfer(contract_id, vec![], Some(seal)).unwrap()); + // } + // } + // } + // } + // transfers + // } } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 57d70c2..bf8cce7 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -71,6 +71,7 @@ pub use file_format::FileFormat; // rgb21::{EmbeddedMedia, TokenData}, // rgb25, IssuerWrapper, Rgb20, Rgb21, Rgb25, // }; +pub use helpers::DescriptorType; pub use once_cell::sync::Lazy; pub use psbt::{ Beneficiary as PsbtBeneficiary, Payment, Prevout, Psbt, PsbtConstructor, PsbtMeta, PsbtVer, @@ -89,11 +90,11 @@ pub use psbt::{ // BlindingFactor, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, // RgbWallet, TapretKey, TransferParams, Transition, WalletProvider, XOutpoint, XWitnessId, // }; +use rgb::invoice::{RgbBeneficiary, RgbInvoice}; use rgb::popls::bp::file::{BpDirMound, DirBarrow}; use rgb::Consensus; use rgb::{CallScope, ContractId, CreateParams}; use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbRuntime, RgbWallet}; - // pub use rgbstd::{ // containers::{ // BuilderSeal, ConsignmentExt, Fascia, FileContent, IndexedConsignment, Kit, Transfer, From 0a34a8c432dd138954e49fc453a2c325aabeef09 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 14 Feb 2025 22:23:00 +0800 Subject: [PATCH 10/90] feat(tests): add NonInflatableAsset schema and update issuance test for contract issue Signed-off-by: will-bitlightlabs --- tests/bitcoin.testnet/note | 13 + tests/issuance.rs | 2 +- tests/schemata/NonInflatableAsset.issuer | Bin 0 -> 2945 bytes tests/utils/helpers.rs | 1513 +++------------------- 4 files changed, 189 insertions(+), 1339 deletions(-) create mode 100644 tests/bitcoin.testnet/note create mode 100644 tests/schemata/NonInflatableAsset.issuer diff --git a/tests/bitcoin.testnet/note b/tests/bitcoin.testnet/note new file mode 100644 index 0000000..78a84e6 --- /dev/null +++ b/tests/bitcoin.testnet/note @@ -0,0 +1,13 @@ + +TODO: + +Because `tests` is the `DirExcavator` directory of `BpDirMound`, +Rgb will search for `schemata` and `contracts` in this directory. + +When detecting `contracts`, it will search in `tests/bitcoin.testnet`, + +If this directory does not exist, it will report an error, +So you need to create this directory in advance. + +The corresponding code is `rgb-std/src/mound.rs#L311` + diff --git a/tests/issuance.rs b/tests/issuance.rs index e4f1de5..57fe6bf 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -39,7 +39,7 @@ fn issue_nia(wallet_desc: DescriptorType) { // vec![issued_supply], // ); // let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); - let contract_id = wallet.issue_nia(PathBuf::from("./tests/DemoToken.yaml")); + let contract_id = wallet.issue_nia(); wallet.contract_states(Some(contract_id)); // let contract = wallet.contract_iface_class::(contract_id); // let spec = contract.spec(); diff --git a/tests/schemata/NonInflatableAsset.issuer b/tests/schemata/NonInflatableAsset.issuer new file mode 100644 index 0000000000000000000000000000000000000000..58c9fe00a03ff0679abb6f3ba8598c75a1ec2abc GIT binary patch literal 2945 zcmdT`c}x^%6rbTT*ukjZ`qOAncX=!yrb5G z7KPS|;ziZiYNXnr@d(9wm6&2}t+kaZ3YJ){x7b#p&{>4~Ps=oE)1)ui*FLA6FautX=V4 zMAh{X-5L+Fzk1d8`{lO>RCQsADX9F`y&aVkHwABFfs&&x1?MO`3jA_a0e<{WN}p3P z8AH2&ytjPD)?Uc-?sj`r%#wR6YpC%Nl>Ky{28Ij>RljgKv;hwdNBSIfX-Pp89 zGW7Ln3K(_1YR7@;Ya6<=D3p|g>-V=gnXe(@|_>5)w`nfd?<60~C*RMIYaojhxd7W2l>i}x)Lx9tv zi?$uDfcfItb*4-8`|u~9e;qmT)2d2$uOqr1*!qiV)gr)2%BOLALusz3_HNZ~zjfiu z3$E(6?CkzS?17}8GmDSqPOTc~H}uC9F{L+`hm>g}^v^tl7TkVoVA#!NJ6Fp$HyqKB zgy^7XWWZ4#&H8JdGA|)<0B)m1+d!>_XIV;k)y;tf8gbGfJ!My*sEnq;?v#TUC4qO? zP=L-XP)c)2aj$iv`@ zAF1Iv6r_=I`B8*q6A%iTb6(*Q{QHWrf8ra^N0bV$a zE!Rt(3n&Vh&48wX#R3olRx8NL0yZ097%*=h$j$~V3+#5lae(K6!vUO5AP7Jdfg}N0 z201w(Hy7mPf&6?hf4-jXyvPFF!8p*uKMs-?5fZ~%(Bk+o(}|jAqn|FhRJI|vZ`{`oKCm)#O-ey20n{GI?Du2SOpPJ;iYsoEjXZq+;<>}6ReN3@;oW~s`oU^{ z&;FQBZOUo7doY}Z$x%k4vJElZqD)6XxLS{aO6RaFqtUz0;$0ATZztL@p|G^TYdcs4 zx^=P&)+y7RMO9Nm!9x;=S5!PIf`>=Qi81 z4^BxE?@P`Z+<1lvdnG2?nE6>5nou^>t++YJ$L`$q>~hcgl$o0Ff70InRipm9&9-dd z(kA)A-Ghg&81swk#G>*Y-&e?iaax;kFQDOulbVqKXIyGKjR0ydKy6wRP%U>)ThS-G zTk, +} + +impl Default for AssetParamsBuilder { + fn default() -> Self { + Self { + params: Self::from_file("./tests/DemoToken.yaml"), + } + } +} + +impl AssetParamsBuilder { + /// Create a new builder instance + pub fn new() -> Self { + Self::default() + } + + /// Load parameters from YAML file + pub fn from_file>(path: P) -> CreateParams { + let file = File::open(path).expect("Unable to open file"); + let params: CreateParams = + serde_yaml::from_reader::<_, CreateParams>(file).expect(""); + params + } + + /// Set the contract template ID + pub fn codex_id(mut self, codex_id: CodexId) -> Self { + self.params.codex_id = codex_id; + self + } + + /// Set the consensus type + pub fn consensus(mut self, consensus: Consensus) -> Self { + self.params.consensus = consensus; + self + } + + /// Set whether it is a test network + pub fn testnet(mut self, testnet: bool) -> Self { + self.params.testnet = testnet; + self + } + + /// Set the contract method name + pub fn method(mut self, method: impl Into) -> Self { + self.params.method = method.into(); + self + } + + /// Set the contract name + pub fn name(mut self, name: impl Into) -> Self { + self.params.name = name.into(); + self + } + + /// Update name state in global states + pub fn update_name_state(mut self, value: impl Into) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "name".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Update ticker state in global states + pub fn update_ticker_state(mut self, value: impl Into) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "ticker".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Update precision state in global states + pub fn update_precision_state(mut self, value: impl Into) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "precision".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Update circulating state in global states + pub fn update_circulating_state(mut self, value: impl Into) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "circulating".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Add or update owned state + pub fn add_owned_state(mut self, seal: Outpoint, val: impl Into) -> Self { + // check if owned state exists + if let Some(state) = self + .params + .owned + .iter_mut() + .find(|s| s.name == "owned".into()) + { + // if exists, update seal and data + state.state.seal = EitherSeal::Alt(seal); + state.state.data = val.into(); + } else { + // if not exists, create a new owned state + self.params.owned.push(NamedState { + name: "owned".into(), + state: Assignment { + seal: EitherSeal::Alt(seal), + data: val.into(), + }, + }); + } + self + } + + /// Build CreateParams instance + pub fn build(self) -> CreateParams { + self.params + } +} + pub struct TestWallet { + // FIXME: should store runtime instead of wallet + // when need wallet, use runtime.defer.wallet wallet: RgbWallet, descriptor: RgbDescr, signer: Option, @@ -31,51 +185,6 @@ pub enum AllocationFilter { WalletTentative, } -// enum Filter<'w> { -// NoWallet, -// Wallet(&'w RgbWallet>), -// WalletAll(&'w RgbWallet>), -// WalletTentative(&'w RgbWallet>), -// } - -// impl AssignmentsFilter for Filter<'_> { -// fn should_include(&self, outpoint: impl Into, id: Option) -> bool { -// match self { -// Filter::Wallet(wallet) => wallet -// .wallet() -// .filter_unspent() -// .should_include(outpoint, id), -// Filter::WalletTentative(wallet) => wallet -// .wallet() -// .filter_outpoints() -// .should_include(outpoint, id), -// _ => true, -// } -// } -// } -// impl Filter<'_> { -// fn comment(&self, outpoint: XOutpoint) -> &'static str { -// let outpoint = outpoint -// .into_bp() -// .into_bitcoin() -// .expect("liquid is not yet supported"); -// match self { -// Filter::Wallet(rgb) if rgb.wallet().is_unspent(outpoint) => "", -// Filter::WalletAll(rgb) | Filter::WalletTentative(rgb) -// if rgb.wallet().is_unspent(outpoint) => -// { -// "-- unspent" -// } -// Filter::WalletAll(rgb) | Filter::WalletTentative(rgb) -// if rgb.wallet().has_outpoint(outpoint) => -// { -// "-- spent" -// } -// _ => "-- third-party", -// } -// } -// } - #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum DescriptorType { Wpkh, @@ -152,9 +261,6 @@ pub struct ColoringInfo { pub nonce: Option, } -/// Map of contract ID and list of its beneficiaries -// pub type AssetBeneficiariesMap = BTreeMap>>; - #[derive(Debug, EnumIter, Copy, Clone, PartialEq)] pub enum AssetSchema { Nia, @@ -228,268 +334,6 @@ impl AssetSchema { // } } -// #[derive(Debug)] -// pub enum AssetInfo { -// Nia { -// spec: AssetSpec, -// terms: ContractTerms, -// issue_amounts: Vec, -// }, -// Uda { -// spec: AssetSpec, -// terms: ContractTerms, -// token_data: TokenData, -// }, -// Cfa { -// name: Name, -// precision: Precision, -// details: Option
, -// terms: ContractTerms, -// issue_amounts: Vec, -// }, -// } - -// impl AssetInfo { -// fn asset_schema(&self) -> AssetSchema { -// match self { -// Self::Nia { .. } => AssetSchema::Nia, -// Self::Uda { .. } => AssetSchema::Uda, -// Self::Cfa { .. } => AssetSchema::Cfa, -// } -// } - -// fn iface_type_name(&self) -> TypeName { -// self.asset_schema().iface_type_name() -// } - -// fn schema(&self) -> Schema { -// self.asset_schema().schema() -// } - -// fn issue_impl(&self) -> IfaceImpl { -// self.asset_schema().issue_impl() -// } - -// fn scripts(&self) -> Scripts { -// self.asset_schema().scripts() -// } - -// fn types(&self) -> TypeSystem { -// self.asset_schema().types() -// } - -// fn iface(&self) -> Iface { -// self.asset_schema().iface() -// } - -// pub fn default_cfa(issue_amounts: Vec) -> Self { -// AssetInfo::cfa("CFA asset name", 0, None, "CFA terms", None, issue_amounts) -// } - -// pub fn default_nia(issue_amounts: Vec) -> Self { -// AssetInfo::nia( -// "NIATCKR", -// "NIA asset name", -// 2, -// None, -// "NIA terms", -// None, -// issue_amounts, -// ) -// } - -// pub fn default_uda() -> Self { -// AssetInfo::uda( -// "UDATCKR", -// "UDA asset name", -// None, -// "NIA terms", -// None, -// uda_token_data_minimal(), -// ) -// } - -// pub fn nia( -// ticker: &str, -// name: &str, -// precision: u8, -// details: Option<&str>, -// terms_text: &str, -// terms_media_fpath: Option<&str>, -// issue_amounts: Vec, -// ) -> Self { -// let spec = AssetSpec::with( -// ticker, -// name, -// Precision::try_from(precision).unwrap(), -// details, -// ) -// .unwrap(); -// let text = RicardianContract::from_str(terms_text).unwrap(); -// let attachment = terms_media_fpath.map(attachment_from_fpath); -// let terms = ContractTerms { -// text, -// media: attachment, -// }; -// Self::Nia { -// spec, -// terms, -// issue_amounts, -// } -// } - -// pub fn uda( -// ticker: &str, -// name: &str, -// details: Option<&str>, -// terms_text: &str, -// terms_media_fpath: Option<&str>, -// token_data: TokenData, -// ) -> AssetInfo { -// let spec = AssetSpec::with(ticker, name, Precision::try_from(0).unwrap(), details).unwrap(); -// let text = RicardianContract::from_str(terms_text).unwrap(); -// let attachment = terms_media_fpath.map(attachment_from_fpath); -// let terms = ContractTerms { -// text, -// media: attachment.clone(), -// }; -// Self::Uda { -// spec, -// terms, -// token_data, -// } -// } - -// pub fn cfa( -// name: &str, -// precision: u8, -// details: Option<&str>, -// terms_text: &str, -// terms_media_fpath: Option<&str>, -// issue_amounts: Vec, -// ) -> AssetInfo { -// let text = RicardianContract::from_str(terms_text).unwrap(); -// let attachment = terms_media_fpath.map(attachment_from_fpath); -// let terms = ContractTerms { -// text, -// media: attachment, -// }; -// Self::Cfa { -// name: Name::try_from(name.to_owned()).unwrap(), -// precision: Precision::try_from(precision).unwrap(), -// details: details.map(|d| Details::try_from(d.to_owned()).unwrap()), -// terms, -// issue_amounts, -// } -// } - -// fn add_global_state(&self, mut builder: ContractBuilder) -> ContractBuilder { -// match self { -// Self::Nia { -// spec, -// terms, -// issue_amounts, -// } => builder -// .add_global_state("spec", spec.clone()) -// .unwrap() -// .add_global_state("terms", terms.clone()) -// .unwrap() -// .add_global_state( -// "issuedSupply", -// Amount::from(issue_amounts.iter().sum::()), -// ) -// .unwrap(), -// Self::Uda { -// spec, -// terms, -// token_data, -// } => builder -// .add_global_state("spec", spec.clone()) -// .unwrap() -// .add_global_state("terms", terms.clone()) -// .unwrap() -// .add_global_state("tokens", token_data.clone()) -// .unwrap(), -// Self::Cfa { -// name, -// precision, -// details, -// terms, -// issue_amounts: issued_supply, -// } => { -// builder = builder -// .add_global_state("name", name.clone()) -// .unwrap() -// .add_global_state("precision", *precision) -// .unwrap() -// .add_global_state("terms", terms.clone()) -// .unwrap() -// .add_global_state( -// "issuedSupply", -// Amount::from(issued_supply.iter().sum::()), -// ) -// .unwrap(); -// if let Some(details) = details { -// builder = builder -// .add_global_state("details", details.clone()) -// .unwrap() -// } -// builder -// } -// } -// } - -// fn add_asset_owner( -// &self, -// mut builder: ContractBuilder, -// close_method: CloseMethod, -// outpoints: Vec, -// ) -> ContractBuilder { -// fn get_genesis_seal( -// close_method: CloseMethod, -// outpoint: Outpoint, -// ) -> BuilderSeal> { -// let blind_seal = match close_method { -// CloseMethod::TapretFirst => { -// BlindSeal::tapret_first_rand(outpoint.txid, outpoint.vout) -// } -// CloseMethod::OpretFirst => { -// BlindSeal::opret_first_rand(outpoint.txid, outpoint.vout) -// } -// }; -// let genesis_seal = GenesisSeal::from(blind_seal); -// let seal: XChain> = XChain::with(Layer1::Bitcoin, genesis_seal); -// BuilderSeal::from(seal) -// } - -// match self { -// Self::Nia { issue_amounts, .. } | Self::Cfa { issue_amounts, .. } => { -// for (amt, outpoint) in issue_amounts.iter().zip(outpoints.iter().cycle()) { -// builder = builder -// .add_fungible_state( -// "assetOwner", -// get_genesis_seal(close_method, *outpoint), -// *amt, -// ) -// .unwrap(); -// } -// builder -// } -// Self::Uda { token_data, .. } => { -// let fraction = OwnedFraction::from(1); -// let allocation = Allocation::with(token_data.index, fraction); -// builder -// .add_data( -// "assetOwner", -// get_genesis_seal(close_method, outpoints[0]), -// allocation, -// ) -// .unwrap() -// } -// } -// } -// } - pub struct Report { pub report_path: PathBuf, } @@ -645,13 +489,6 @@ fn get_indexer(indexer_url: &str) -> AnyIndexer { } } -// fn get_resolver(indexer_url: &str) -> AnyResolver { -// match INDEXER.get().unwrap() { -// Indexer::Electrum => AnyResolver::electrum_blocking(indexer_url, None).unwrap(), -// Indexer::Esplora => AnyResolver::esplora_blocking(indexer_url, None).unwrap(), -// } -// } - fn broadcast_tx(tx: &Tx, indexer_url: &str) { match get_indexer(indexer_url) { AnyIndexer::Electrum(inner) => { @@ -669,49 +506,6 @@ pub fn broadcast_tx_and_mine(tx: &Tx, instance: u8) { mine_custom(false, instance, 1); } -// pub fn attachment_from_fpath(fpath: &str) -> Attachment { -// let file_bytes = std::fs::read(fpath).unwrap(); -// let file_hash: sha256::Hash = Hash::hash(&file_bytes[..]); -// let digest = file_hash.to_byte_array().into(); -// let mime = FileFormat::from_file(fpath) -// .unwrap() -// .media_type() -// .to_string(); -// let media_ty: &'static str = Box::leak(mime.clone().into_boxed_str()); -// let media_type = MediaType::with(media_ty); -// Attachment { -// ty: media_type, -// digest, -// } -// } - -// fn uda_token_data_minimal() -> TokenData { -// TokenData { -// index: TokenIndex::from(UDA_FIXED_INDEX), -// ..Default::default() -// } -// } - -// pub fn uda_token_data( -// ticker: &str, -// name: &str, -// details: &str, -// preview: EmbeddedMedia, -// media: Attachment, -// attachments: BTreeMap, -// reserves: ProofOfReserves, -// ) -> TokenData { -// let mut token_data = uda_token_data_minimal(); -// token_data.preview = Some(preview); -// token_data.media = Some(media); -// token_data.attachments = Confined::try_from(attachments.clone()).unwrap(); -// token_data.reserves = Some(reserves); -// token_data.ticker = Some(Ticker::try_from(ticker.to_string()).unwrap()); -// token_data.name = Some(Name::try_from(name.to_string()).unwrap()); -// token_data.details = Some(Details::try_from(details.to_string()).unwrap()); -// token_data -// } - impl TestWallet { pub fn network(&self) -> Network { self.wallet.network() @@ -761,11 +555,6 @@ impl TestWallet { self.instance = instance; } - // pub fn sync_and_update_witnesses(&mut self, after_height: Option) { - // self.sync(); - // self.update_witnesses(after_height.unwrap_or(1)); - // } - pub fn switch_to_instance(&mut self, instance: u8) { self.change_instance(instance); // self.sync_and_update_witnesses(None); @@ -779,51 +568,19 @@ impl TestWallet { get_indexer(&self.indexer_url()) } - // pub fn get_resolver(&self) -> AnyResolver { - // get_resolver(&self.indexer_url()) - // } - pub fn broadcast_tx(&self, tx: &Tx) { broadcast_tx(tx, &self.indexer_url()); } - // pub fn get_witness_ord(&self, txid: &Txid) -> WitnessOrd { - // self.get_resolver() - // .resolve_pub_witness_ord(XWitnessId::Bitcoin(*txid)) - // .unwrap() - // } - - // pub fn get_tx_height(&self, txid: &Txid) -> Option { - // match self.get_witness_ord(txid) { - // WitnessOrd::Mined(witness_pos) => Some(witness_pos.height().get()), - // _ => None, - // } - // } - pub fn sync(&mut self) { let indexer = self.get_indexer(); self.wallet.update(&indexer).into_result().unwrap(); } - // pub fn close_method(&self) -> CloseMethod { - // self.wallet.wallet().seal_close_method() - // } - - // pub fn mine_tx(&self, txid: &Txid, resume: bool) { - // let mut attempts = 10; - // loop { - // mine_custom(resume, self.instance, 1); - // if self.get_tx_height(txid).is_some() { - // break; - // } - // attempts -= 1; - // if attempts == 0 { - // panic!("TX is not getting mined"); - // } - // } - // } pub fn wallet_provider(&self) -> FsTextStore { - FsTextStore::new(self.wallet_dir.clone()).expect("Broken directory structure") + let name: &str = "bp_wallet_name"; + let provider = FsTextStore::new(self.wallet_dir.join(name)).unwrap(); + provider } pub fn wallet(&self) -> RgbWallet { @@ -838,7 +595,9 @@ impl TestWallet { pub fn runtime(&self) -> RgbDirRuntime { let wallet = self.wallet(); - let runtime = RgbDirRuntime::from(DirBarrow::with(wallet, self.mound())); + let mound = self.mound(); + dbg!(&mound.schemata().collect::>()); + let runtime = RgbDirRuntime::from(DirBarrow::with(wallet, mound)); runtime } @@ -846,958 +605,36 @@ impl TestWallet { if !self.network().is_testnet() { panic!("Non-testnet networks are not yet supported"); } - BpDirMound::load_testnet(Consensus::Bitcoin, &self.wallet_dir, false) + BpDirMound::load_testnet(Consensus::Bitcoin, "./tests", false) } pub fn contracts_info(&self) -> Vec { self.mound().contracts_info().collect() } - // FIXME: - // returns a value referencing data owned by the current function - // | temporary value created here - // pub fn contracts(&self) -> Vec<(ContractId, &Stockpile>)> { - // self.mound().contracts().collect() - // } - - pub fn contract_states( - &self, - contract_id: Option, - // TODO: cannot use type `ContractState`, because it mod is private and not exported - // ) -> Vec<(ContractId, ContractState)> { - ) { + pub fn contract_states(&self, contract_id: Option) { let mut runtime = self.runtime(); let contract_states = runtime.state_all(contract_id).collect::>(); dbg!(contract_states); - todo!() } - pub fn issue_with_info( - &mut self, - // asset_info: AssetInfo, - params: CreateParams, - // close_method: CloseMethod, - // outpoints: Vec>, - ) -> ContractId { - let mut runtime = self.runtime(); + pub fn issue_nia(&mut self) -> ContractId { + let params = AssetParamsBuilder::default().name("USDT"); + // .update_circulating_state("1000000"); + self.issue_with_params(params.build()) + } + pub fn issue_with_params(&mut self, params: CreateParams) -> ContractId { + let mut runtime = self.runtime(); let contract_id = runtime .issue_to_file(params) .expect("failed to issue contract"); println!("A new contract issued with ID {contract_id}"); contract_id - // let outpoints = if outpoints.is_empty() { - // vec![self.get_utxo(None)] - // } else { - // outpoints - // .into_iter() - // .map(|o| o.unwrap_or_else(|| self.get_utxo(None))) - // .collect() - // }; - - // let mut builder = ContractBuilder::with( - // Identity::default(), - // asset_info.iface(), - // asset_info.schema(), - // asset_info.issue_impl(), - // asset_info.types(), - // asset_info.scripts(), - // ); - - // builder = asset_info.add_global_state(builder); - - // builder = asset_info.add_asset_owner(builder, close_method, outpoints); - - // let contract = builder.issue_contract().expect("failure issuing contract"); - // let resolver = self.get_resolver(); - // self.wallet - // .stock_mut() - // .import_contract(contract.clone(), resolver) - // .unwrap(); - } - - pub fn issue_nia( - &mut self, - params: PathBuf, - // issued_supply: u64, - // close_method: CloseMethod, - // outpoint: Option<&Outpoint>, - ) -> ContractId { - let file = File::open(params).expect("Unable to open parameters file"); - let params: CreateParams = - serde_yaml::from_reader::<_, CreateParams>(file).expect(""); - // let asset_info = AssetInfo::default_nia(vec![issued_supply]); - self.issue_with_info(params) } - pub fn issue_uda( - &mut self, - // close_method: CloseMethod, - outpoint: Option<&Outpoint>, - ) -> (ContractId, TypeName) { - todo!() - // let asset_info = AssetInfo::default_uda(); - // self.issue_with_info(asset_info, close_method, vec![outpoint.copied()]) - } - - pub fn issue_cfa( - &mut self, - issued_supply: u64, - // close_method: CloseMethod, - outpoint: Option<&Outpoint>, - ) -> (ContractId, TypeName) { - todo!() - // let asset_info = AssetInfo::default_cfa(vec![issued_supply]); - // self.issue_with_info(asset_info, close_method, vec![outpoint.copied()]) - } - - pub fn invoice( - &mut self, - contract_id: ContractId, - // iface_type_name: &TypeName, - amount: u64, - // close_method: CloseMethod, - invoice_type: InvoiceType, - ) -> RgbInvoice { - // let network = self.wallet.network(); - let mut runtime = self.runtime(); - let beneficiary = if invoice_type == InvoiceType::Witness { - let wout = runtime.wout(None); - RgbBeneficiary::WitnessOut(wout) - } else { - let auth = runtime.auth_token(None).expect( - "Wallet has no unspent outputs; try `fund` first, or use `-w` flag to \ - generate a witness output-based seal", - ); - RgbBeneficiary::Token(auth) - }; - - let contract_id = CallScope::ContractId(contract_id); - - let value = StrictVal::num(amount); - let mut invoice = RgbInvoice::new(contract_id, beneficiary, Some(value)); - // if let Some(api) = api { - // invoice = invoice.use_api(api.clone()); - // } - // if let Some(method) = method { - // invoice = invoice.use_method(method.clone()); - // } - // if let Some(state) = state { - // invoice = invoice.use_state(state.clone()); - // } - - invoice - // let beneficiary = match invoice_type { - // InvoiceType::Blinded(outpoint) => { - // let outpoint = if let Some(outpoint) = outpoint { - // outpoint - // } else { - // self.get_utxo(None) - // }; - // let seal = XChain::Bitcoin(GraphSeal::new_random( - // close_method, - // outpoint.txid, - // outpoint.vout, - // )); - // self.wallet.stock_mut().store_secret_seal(seal).unwrap(); - // Beneficiary::BlindedSeal(*seal.to_secret_seal().as_reduced_unsafe()) - // } - // InvoiceType::Witness => { - // let address = self.get_address(); - // Beneficiary::WitnessVout(Pay2Vout { - // address: address.payload, - // method: close_method, - // }) - // } - // }; - - // let mut builder = RgbInvoiceBuilder::new(XChainNet::bitcoin(network, beneficiary)) - // .set_contract(contract_id) - // .set_interface(iface_type_name.clone()); - // if *iface_type_name == AssetSchema::Uda.iface_type_name() { - // if amount != 1 { - // panic!("UDA amount must be 1"); - // } - // builder = builder - // .clone() - // .set_allocation(UDA_FIXED_INDEX, amount) - // .unwrap(); - // } else { - // builder = builder.clone().set_amount_raw(amount); - // } - // builder.finish() - } - - pub fn sign_finalize(&self, psbt: &mut Psbt) { - let _sig_count = psbt.sign(self.signer.as_ref().unwrap()).unwrap(); - psbt.finalize(&self.descriptor); - } - - pub fn sign_finalize_extract(&self, psbt: &mut Psbt) -> Tx { - self.sign_finalize(psbt); - psbt.extract().unwrap() - } - - // pub fn transfer( - // &mut self, - // invoice: RgbInvoice, - // sats: Option, - // fee: Option, - // broadcast: bool, - // report: Option<&Report>, - // ) -> (Transfer, Tx) { - // self.sync(); - - // let fee = Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS)); - // let sats = Sats::from_sats(sats.unwrap_or(2000)); - // let params = TransferParams::with(fee, sats); - // let pay_start = Instant::now(); - // let (mut psbt, _psbt_meta, consignment) = self.wallet.pay(&invoice, params).unwrap(); - // let pay_duration = pay_start.elapsed(); - // if let Some(report) = report { - // report.write_duration(pay_duration); - // } - - // let mut cs_path = self.wallet_dir.join("consignments"); - // std::fs::create_dir_all(&cs_path).unwrap(); - // let consignment_id = consignment.consignment_id(); - // cs_path.push(consignment_id.to_string()); - // cs_path.set_extension("yaml"); - // let mut file = std::fs::File::options() - // .read(true) - // .write(true) - // .create_new(true) - // .open(cs_path) - // .unwrap(); - // serde_yaml::to_writer(&mut file, &consignment).unwrap(); - - // let tx = self.sign_finalize_extract(&mut psbt); - - // let txid = tx.txid().to_string(); - // println!("transfer txid: {txid}, consignment: {consignment_id}"); - - // let mut tx_path = self.wallet_dir.join("transactions"); - // std::fs::create_dir_all(&tx_path).unwrap(); - // tx_path.push(&txid); - // tx_path.set_extension("yaml"); - // let mut file = std::fs::File::options() - // .read(true) - // .write(true) - // .create_new(true) - // .open(tx_path) - // .unwrap(); - // serde_yaml::to_writer(&mut file, &tx).unwrap(); - // writeln!(file, "\n---\n").unwrap(); - // serde_yaml::to_writer(&mut file, &psbt).unwrap(); - - // if broadcast { - // self.broadcast_tx(&tx); - // } - - // (consignment, tx) - // } - - // pub fn accept_transfer(&mut self, consignment: Transfer, report: Option<&Report>) { - // let mut resolver = self.get_resolver(); - // resolver.add_terminals(&consignment); - // self.accept_transfer_custom_resolver(consignment, report, &resolver); - // } - - // pub fn accept_transfer_custom_resolver( - // &mut self, - // consignment: Transfer, - // report: Option<&Report>, - // resolver: &impl ResolveWitness, - // ) { - // self.sync(); - // let validate_start = Instant::now(); - // let validated_consignment = consignment - // .validate(&resolver, self.testnet()) - // .map_err(|(status, _)| status) - // .unwrap(); - // let validate_duration = validate_start.elapsed(); - // if let Some(report) = report { - // report.write_duration(validate_duration); - // } - - // let validation_status = validated_consignment.clone().into_validation_status(); - // let validity = validation_status.validity(); - // assert_eq!(validity, Validity::Valid); - // let accept_start = Instant::now(); - // self.wallet - // .stock_mut() - // .accept_transfer(validated_consignment.clone(), &resolver) - // .unwrap(); - // let accept_duration = accept_start.elapsed(); - // if let Some(report) = report { - // report.write_duration(accept_duration); - // } - // } - - // pub fn contract_iface( - // &self, - // contract_id: ContractId, - // iface_type_name: &TypeName, - // ) -> ContractIface> { - // self.wallet - // .stock() - // .contract_iface(contract_id, iface_type_name.clone()) - // .unwrap() - // } - - // pub fn contract_iface_class( - // &self, - // contract_id: ContractId, - // ) -> C::Wrapper> { - // self.wallet - // .stock() - // .contract_iface_class::(contract_id) - // .unwrap() - // } - - // pub fn contract_fungible_allocations( - // &self, - // contract_id: ContractId, - // iface_type_name: &TypeName, - // show_tentative: bool, - // ) -> Vec { - // let filter = if show_tentative { - // Filter::WalletTentative(&self.wallet) - // } else { - // Filter::Wallet(&self.wallet) - // }; - // self.contract_iface(contract_id, iface_type_name) - // .fungible(fname!("assetOwner"), filter) - // .unwrap() - // .collect() - // } - - // pub fn contract_data_allocations( - // &self, - // contract_id: ContractId, - // iface_type_name: &TypeName, - // ) -> Vec { - // self.contract_iface(contract_id, iface_type_name) - // .data(fname!("assetOwner"), Filter::Wallet(&self.wallet)) - // .unwrap() - // .collect() - // } - - // pub fn history(&self, contract_id: ContractId, iface_type_name: &TypeName) -> Vec { - // self.wallet - // .history(contract_id, iface_type_name.clone()) - // .unwrap() - // } - - // pub fn list_contracts(&self) -> Vec { - // self.wallet.stock().contracts().unwrap().collect() - // } - - // pub fn debug_contracts(&self) { - // println!("Contracts:"); - // for info in self.list_contracts() { - // println!("{}", info.to_string().replace("\n", "\t")); - // } - // } - - // pub fn debug_logs( - // &self, - // contract_id: ContractId, - // iface_type_name: &TypeName, - // filter: AllocationFilter, - // ) { - // let filter = match filter { - // AllocationFilter::WalletAll => Filter::WalletAll(&self.wallet), - // AllocationFilter::WalletTentative => Filter::WalletTentative(&self.wallet), - // AllocationFilter::Wallet => Filter::Wallet(&self.wallet), - // AllocationFilter::Stock => Filter::NoWallet, - // }; - - // let contract = self.contract_iface(contract_id, iface_type_name); - - // println!("Global:"); - // for global in &contract.iface.global_state { - // if let Ok(values) = contract.global(global.name.clone()) { - // for val in values { - // println!(" {} := {}", global.name, val); - // } - // } - // } - - // println!("\nOwned:"); - // fn witness( - // allocation: &OutputAssignment, - // contract: &ContractIface>, - // ) -> String { - // allocation - // .witness - // .and_then(|w| contract.witness_info(w)) - // .map(|info| format!("{} ({})", info.id, info.ord)) - // .unwrap_or_else(|| s!("~")) - // } - // for owned in &contract.iface.assignments { - // println!(" State \t{:78}\tWitness", "Seal"); - // println!(" {}:", owned.name); - // if let Ok(allocations) = contract.fungible(owned.name.clone(), &filter) { - // for allocation in allocations { - // println!( - // " {: >9}\t{}\t{} {}", - // allocation.state.value(), - // allocation.seal, - // witness(&allocation, &contract), - // filter.comment(allocation.seal.to_outpoint()) - // ); - // } - // } - // if let Ok(allocations) = contract.data(owned.name.clone(), &filter) { - // for allocation in allocations { - // println!( - // " {: >9}\t{}\t{} {}", - // allocation.state, - // allocation.seal, - // witness(&allocation, &contract), - // filter.comment(allocation.seal.to_outpoint()) - // ); - // } - // } - // if let Ok(allocations) = contract.attachments(owned.name.clone(), &filter) { - // for allocation in allocations { - // println!( - // " {: >9}\t{}\t{} {}", - // allocation.state, - // allocation.seal, - // witness(&allocation, &contract), - // filter.comment(allocation.seal.to_outpoint()) - // ); - // } - // } - // if let Ok(allocations) = contract.rights(owned.name.clone(), &filter) { - // for allocation in allocations { - // println!( - // " {: >9}\t{}\t{} {}", - // "right", - // allocation.seal, - // witness(&allocation, &contract), - // filter.comment(allocation.seal.to_outpoint()) - // ); - // } - // } - // } - - // let bp_runtime = self.wallet.wallet(); - // println!("\nHeight\t{:>12}\t{:68}", "Amount, ṩ", "Outpoint"); - // for (derived_addr, utxos) in bp_runtime.address_coins() { - // println!("{}\t{}", derived_addr.addr, derived_addr.terminal); - // for row in utxos { - // println!("{}\t{: >12}\t{:68}", row.height, row.amount, row.outpoint); - // } - // println!() - // } - - // println!("\nWallet total balance: {} ṩ", bp_runtime.balance()); - // } - - // pub fn debug_history( - // &self, - // contract_id: ContractId, - // iface_type_name: &TypeName, - // details: bool, - // ) { - // let mut history = self.history(contract_id, iface_type_name); - // history.sort_by_key(|op| op.witness.map(|w| w.ord).unwrap_or(WitnessOrd::Archived)); - // if details { - // println!("Operation\tValue \tState\t{:78}\tWitness", "Seal"); - // } else { - // println!("Operation\tValue \t{:78}\tWitness", "Seal"); - // } - // for ContractOp { - // direction, - // ty, - // opids, - // state, - // to, - // witness, - // } in history - // { - // print!("{:9}\t", direction.to_string()); - // if let AllocatedState::Amount(amount) = state { - // print!("{: >9}", amount.value()); - // } else { - // print!("{state:>9}"); - // } - // if details { - // print!("\t{ty}"); - // } - // println!( - // "\t{}\t{}", - // to.first().expect("at least one receiver is always present"), - // witness - // .map(|info| format!("{} ({})", info.id, info.ord)) - // .unwrap_or_else(|| s!("~")) - // ); - // if details { - // println!( - // "\topid={}", - // opids - // .iter() - // .map(OpId::to_string) - // .collect::>() - // .join("\n\topid=") - // ) - // } - // } - // } - - // #[allow(clippy::too_many_arguments)] - // pub fn send( - // &mut self, - // recv_wlt: &mut TestWallet, - // transfer_type: TransferType, - // contract_id: ContractId, - // iface_type_name: &TypeName, - // amount: u64, - // sats: u64, - // report: Option<&Report>, - // ) -> (Transfer, Tx) { - // let invoice = recv_wlt.invoice( - // contract_id, - // iface_type_name, - // amount, - // recv_wlt.close_method(), - // transfer_type.into(), - // ); - // self.send_to_invoice(recv_wlt, invoice, Some(sats), None, report) - // } - - // pub fn send_to_invoice( - // &mut self, - // recv_wlt: &mut TestWallet, - // invoice: RgbInvoice, - // sats: Option, - // fee: Option, - // report: Option<&Report>, - // ) -> (Transfer, Tx) { - // let (consignment, tx) = self.transfer(invoice, sats, fee, true, report); - // self.mine_tx(&tx.txid(), false); - // recv_wlt.accept_transfer(consignment.clone(), report); - // self.sync(); - // (consignment, tx) - // } - - // pub fn check_allocations( - // &self, - // contract_id: ContractId, - // iface_type_name: &TypeName, - // asset_schema: AssetSchema, - // expected_fungible_allocations: Vec, - // nonfungible_allocation: bool, - // ) { - // match asset_schema { - // AssetSchema::Nia | AssetSchema::Cfa => { - // let allocations = - // self.contract_fungible_allocations(contract_id, iface_type_name, false); - // let mut actual_fungible_allocations = allocations - // .iter() - // .map(|a| a.state.value()) - // .collect::>(); - // let mut expected_fungible_allocations = expected_fungible_allocations.clone(); - // actual_fungible_allocations.sort(); - // expected_fungible_allocations.sort(); - // assert_eq!(actual_fungible_allocations, expected_fungible_allocations); - // assert!(allocations - // .iter() - // .all(|a| a.seal.method() == self.close_method())); - // } - // AssetSchema::Uda => { - // let allocations = self.contract_data_allocations(contract_id, iface_type_name); - // let expected_allocations = if nonfungible_allocation { - // assert_eq!( - // allocations - // .iter() - // .filter(|a| a.state.to_string() == "000000000100000000000000") - // .count(), - // 1 - // ); - // 1 - // } else { - // 0 - // }; - // assert_eq!(allocations.len(), expected_allocations); - // } - // } - // } - - // pub fn check_history_operation( - // &self, - // contract_id: &ContractId, - // iface_type_name: &TypeName, - // txid: Option<&Txid>, - // direction: OpDirection, - // amount: u64, - // ) { - // let operation = self - // .history(*contract_id, iface_type_name) - // .into_iter() - // .find(|co| { - // co.direction == direction - // && co - // .witness - // .map_or(true, |w| Some(w.id.as_reduced_unsafe()) == txid) - // }) - // .unwrap(); - // assert!(matches!(operation.state, AllocatedState::Amount(amt) if amt.value() == amount)); - // } - - // fn _construct_psbt_offchain( - // &mut self, - // input_outpoints: Vec<(Outpoint, u64, Terminal)>, - // beneficiaries: Vec<&PsbtBeneficiary>, - // tx_params: TxParams, - // ) -> (Psbt, PsbtMeta) { - // let mut psbt = Psbt::create(PsbtVer::V2); - - // for (outpoint, value, terminal) in input_outpoints { - // psbt.construct_input_expect( - // Prevout::new(outpoint, Sats::from(value)), - // self.wallet.wallet().descriptor(), - // terminal, - // tx_params.seq_no, - // ); - // } - // if psbt.inputs().count() == 0 { - // panic!("no inputs"); - // } - - // let input_value = psbt.input_sum(); - // let mut max = Vec::new(); - // let mut output_value = Sats::ZERO; - // for beneficiary in beneficiaries { - // let amount = beneficiary.amount.unwrap_or(Sats::ZERO); - // output_value.checked_add_assign(amount).unwrap(); - // let out = psbt.construct_output_expect(beneficiary.script_pubkey(), amount); - // if beneficiary.amount.is_max() { - // max.push(out.index()); - // } - // } - // let mut remaining_value = input_value - // .checked_sub(output_value) - // .unwrap() - // .checked_sub(tx_params.fee) - // .unwrap(); - // if !max.is_empty() { - // let portion = remaining_value / max.len(); - // for out in psbt.outputs_mut() { - // if max.contains(&out.index()) { - // out.amount = portion; - // } - // } - // remaining_value = Sats::ZERO; - // } - - // let (change_vout, change_terminal) = if remaining_value > Sats::from(546u64) { - // let change_index = self - // .wallet - // .wallet_mut() - // .next_derivation_index(tx_params.change_keychain, tx_params.change_shift); - // let change_terminal = Terminal::new(tx_params.change_keychain, change_index); - // let change_vout = psbt - // .construct_change_expect( - // self.wallet.wallet().descriptor(), - // change_terminal, - // remaining_value, - // ) - // .index(); - // ( - // Some(Vout::from_u32(change_vout as u32)), - // Some(change_terminal), - // ) - // } else { - // (None, None) - // }; - - // ( - // psbt, - // PsbtMeta { - // change_vout, - // change_terminal, - // }, - // ) - // } - - fn _construct_beneficiaries( - &self, - beneficiaries: Vec<(Address, Option)>, - ) -> Vec { - beneficiaries - .into_iter() - .map(|(addr, amt)| { - let payment = if let Some(amt) = amt { - Payment::Fixed(Sats::from_sats(amt)) - } else { - Payment::Max - }; - PsbtBeneficiary::new(addr, payment) - }) - .collect() + pub fn issue_from_file(&mut self, params_path: impl AsRef) -> ContractId { + let params = AssetParamsBuilder::from_file(params_path); + self.issue_with_params(params) } - - // pub fn construct_psbt_offchain( - // &mut self, - // input_outpoints: Vec<(Outpoint, u64, Terminal)>, - // beneficiaries: Vec<(Address, Option)>, - // fee: Option, - // ) -> (Psbt, PsbtMeta) { - // let tx_params = TxParams::with(Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS))); - // let beneficiaries = self._construct_beneficiaries(beneficiaries); - // let beneficiaries: Vec<&PsbtBeneficiary> = beneficiaries.iter().collect(); - - // self._construct_psbt_offchain(input_outpoints, beneficiaries, tx_params) - // } - - // pub fn construct_psbt( - // &mut self, - // input_outpoints: Vec, - // beneficiaries: Vec<(Address, Option)>, - // fee: Option, - // ) -> (Psbt, PsbtMeta) { - // let tx_params = TxParams::with(Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS))); - // let beneficiaries = self._construct_beneficiaries(beneficiaries); - // let beneficiaries: Vec<&PsbtBeneficiary> = beneficiaries.iter().collect(); - - // self.wallet - // .wallet_mut() - // .construct_psbt(input_outpoints, beneficiaries, tx_params) - // .unwrap() - // } - - // pub fn psbt_add_input(&self, psbt: &mut Psbt, utxo: Outpoint) { - // for account in self.descriptor.xpubs() { - // psbt.xpubs.insert(*account.xpub(), account.origin().clone()); - // } - // let input = self.wallet.wallet().utxo(utxo).unwrap(); - // psbt.construct_input_expect( - // input.to_prevout(), - // self.wallet.wallet().descriptor(), - // input.terminal, - // SeqNo::ZERO, - // ); - // } - - // pub fn color_psbt( - // &self, - // psbt: &mut Psbt, - // coloring_info: ColoringInfo, - // ) -> (Fascia, AssetBeneficiariesMap) { - // let asset_beneficiaries = self.color_psbt_init(psbt, coloring_info); - // psbt.complete_construction(); - // let fascia = psbt.rgb_commit().unwrap(); - // (fascia, asset_beneficiaries) - // } - - // pub fn color_psbt_init( - // &self, - // psbt: &mut Psbt, - // coloring_info: ColoringInfo, - // ) -> AssetBeneficiariesMap { - // if !psbt.outputs().any(|o| o.script.is_op_return()) { - // let _output = psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO); - // } - - // let prev_outputs = psbt - // .to_unsigned_tx() - // .inputs - // .iter() - // .map(|txin| txin.prev_output) - // .map(|outpoint| XOutpoint::from(XChain::Bitcoin(outpoint))) - // .collect::>(); - - // let mut all_transitions: HashMap = HashMap::new(); - // let mut asset_beneficiaries: AssetBeneficiariesMap = bmap![]; - // let assignment_name = FieldName::from("assetOwner"); - - // for (contract_id, asset_coloring_info) in coloring_info.asset_info_map.clone() { - // let mut asset_transition_builder = self - // .wallet - // .stock() - // .transition_builder(contract_id, asset_coloring_info.iface, None::<&str>) - // .unwrap(); - // let assignment_id = asset_transition_builder - // .assignments_type(&assignment_name) - // .unwrap(); - - // let mut asset_available_amt = 0; - // for (_, opout_state_map) in self - // .wallet - // .stock() - // .contract_assignments_for( - // contract_id, - // prev_outputs - // .iter() - // // only retrieve assignments for owned prevouts using coloring_info - // .filter(|xop| { - // coloring_info.asset_info_map[&contract_id] - // .input_outpoints - // .contains(xop.as_reduced_unsafe()) - // }) - // .copied(), - // ) - // .unwrap() - // { - // for (opout, state) in opout_state_map { - // if let PersistedState::Amount(amt, _, _) = &state { - // asset_available_amt += amt.value(); - // } - // asset_transition_builder = - // asset_transition_builder.add_input(opout, state).unwrap(); - // } - // } - - // let mut beneficiaries = vec![]; - // let mut sending_amt = 0; - // for (vout, amount) in asset_coloring_info.output_map { - // if amount == 0 { - // continue; - // } - // sending_amt += amount; - // if vout as usize > psbt.outputs().count() { - // panic!("invalid vout in output_map, does not exist in the given PSBT"); - // } - // let graph_seal = if let Some(blinding) = asset_coloring_info.static_blinding { - // GraphSeal::with_blinded_vout(CloseMethod::OpretFirst, vout, blinding) - // } else { - // GraphSeal::new_random_vout(CloseMethod::OpretFirst, vout) - // }; - // let seal = BuilderSeal::Revealed(XChain::with(Layer1::Bitcoin, graph_seal)); - // beneficiaries.push(seal); - - // let blinding_factor = if let Some(blinding) = asset_coloring_info.static_blinding { - // let mut blinding_32_bytes: [u8; 32] = [0; 32]; - // blinding_32_bytes[0..8].copy_from_slice(&blinding.to_le_bytes()); - // BlindingFactor::try_from(blinding_32_bytes).unwrap() - // } else { - // BlindingFactor::random() - // }; - // asset_transition_builder = asset_transition_builder - // .add_fungible_state_raw(assignment_id, seal, amount, blinding_factor) - // .unwrap(); - // } - // if sending_amt > asset_available_amt { - // panic!("total amount in output_map greater than available ({asset_available_amt})"); - // } - - // if let Some(nonce) = coloring_info.nonce { - // asset_transition_builder = asset_transition_builder.set_nonce(nonce); - // } - - // let transition = asset_transition_builder.complete_transition().unwrap(); - // all_transitions.insert(contract_id, transition); - // asset_beneficiaries.insert(contract_id, beneficiaries); - // } - - // let (opreturn_index, _) = psbt - // .to_unsigned_tx() - // .outputs - // .iter() - // .enumerate() - // .find(|(_, o)| o.script_pubkey.is_op_return()) - // .expect("psbt should have an op_return output"); - // let (_, opreturn_output) = psbt - // .outputs_mut() - // .enumerate() - // .find(|(i, _)| i == &opreturn_index) - // .unwrap(); - // opreturn_output.set_opret_host().unwrap(); - // if let Some(blinding) = coloring_info.static_blinding { - // opreturn_output.set_mpc_entropy(blinding).unwrap(); - // } - - // let tx_inputs = psbt.clone().to_unsigned_tx().inputs; - // for (contract_id, transition) in all_transitions { - // for (input, txin) in psbt.inputs_mut().zip(&tx_inputs) { - // let prevout = txin.prev_output; - // let outpoint = Outpoint::new(prevout.txid.to_byte_array().into(), prevout.vout); - // if coloring_info - // .asset_info_map - // .clone() - // .get(&contract_id) - // .unwrap() - // .input_outpoints - // .contains(&outpoint) - // { - // input - // .set_rgb_consumer(contract_id, transition.id()) - // .unwrap(); - // } - // } - // psbt.push_rgb_transition(transition, CloseMethod::OpretFirst) - // .unwrap(); - // } - - // asset_beneficiaries - // } - - // pub fn consume_fascia(&mut self, fascia: Fascia, witness_txid: Txid) { - // struct FasciaResolver { - // witness_id: XWitnessId, - // } - // impl ResolveWitness for FasciaResolver { - // fn resolve_pub_witness( - // &self, - // _: XWitnessId, - // ) -> Result { - // unreachable!() - // } - // fn resolve_pub_witness_ord( - // &self, - // witness_id: XWitnessId, - // ) -> Result { - // assert_eq!(witness_id, self.witness_id); - // Ok(WitnessOrd::Tentative) - // } - // } - - // let resolver = FasciaResolver { - // witness_id: XChain::Bitcoin(witness_txid), - // }; - - // self.wallet - // .stock_mut() - // .consume_fascia(fascia, resolver) - // .unwrap(); - // } - - // pub fn update_witnesses(&mut self, after_height: u32) { - // let resolver = self.get_resolver(); - // self.wallet - // .stock_mut() - // .update_witnesses(resolver, after_height) - // .unwrap(); - // } - - // pub fn create_consignments( - // &self, - // asset_beneficiaries: AssetBeneficiariesMap, - // witness_txid: Txid, - // ) -> Vec { - // let mut transfers = vec![]; - // let stock = self.wallet.stock(); - - // for (contract_id, beneficiaries) in asset_beneficiaries { - // for beneficiary in beneficiaries { - // match beneficiary { - // BuilderSeal::Revealed(seal) => { - // let explicit_seal = XChain::Bitcoin(ExplicitSeal::new( - // seal.method(), - // Outpoint::new(witness_txid, seal.as_reduced_unsafe().vout), - // )); - // transfers.push(stock.transfer(contract_id, [explicit_seal], None).unwrap()); - // } - // BuilderSeal::Concealed(seal) => { - // transfers.push(stock.transfer(contract_id, vec![], Some(seal)).unwrap()); - // } - // } - // } - // } - // transfers - // } } From b7e87859c5e00702249021c9dc4e0d1daf23bf6f Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 17 Feb 2025 12:11:06 +0800 Subject: [PATCH 11/90] feat: completed asset issue with custom parameters Signed-off-by: will-bitlightlabs --- tests/utils/helpers.rs | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 0352ae3..efabe79 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -120,7 +120,8 @@ impl AssetParamsBuilder { } /// Update circulating state in global states - pub fn update_circulating_state(mut self, value: impl Into) -> Self { + /// circulating type is "RGBContract.Amount" eq u64 in rust + pub fn update_circulating_state(mut self, value: u64) -> Self { if let Some(state) = self .params .global @@ -132,8 +133,8 @@ impl AssetParamsBuilder { self } - /// Add or update owned state - pub fn add_owned_state(mut self, seal: Outpoint, val: impl Into) -> Self { + /// Update owned state + pub fn update_owned_state(mut self, seal: Outpoint, val: u64) -> Self { // check if owned state exists if let Some(state) = self .params @@ -157,6 +158,18 @@ impl AssetParamsBuilder { self } + /// Add owned state + pub fn add_owned_state(mut self, seal: Outpoint, val: u64) -> Self { + self.params.owned.push(NamedState { + name: "owned".into(), + state: Assignment { + seal: EitherSeal::Alt(seal), + data: val.into(), + }, + }); + self + } + /// Build CreateParams instance pub fn build(self) -> CreateParams { self.params @@ -596,7 +609,7 @@ impl TestWallet { pub fn runtime(&self) -> RgbDirRuntime { let wallet = self.wallet(); let mound = self.mound(); - dbg!(&mound.schemata().collect::>()); + // dbg!(&mound.schemata().collect::>()); let runtime = RgbDirRuntime::from(DirBarrow::with(wallet, mound)); runtime } @@ -619,8 +632,18 @@ impl TestWallet { } pub fn issue_nia(&mut self) -> ContractId { - let params = AssetParamsBuilder::default().name("USDT"); - // .update_circulating_state("1000000"); + let fake_outpoing_zero = + "0000000000000000000000000000000000000000000000000000000000000000:0"; + let fake_outpoing_one = + "0000000000000000000000000000000000000000000000000000000000000001:0"; + let params = AssetParamsBuilder::default() + .name("USDT") + .update_name_state("USD Tether") + .update_ticker_state("USDT") + .update_precision_state("centiMilli") + .update_circulating_state(1_000_000) + .add_owned_state(Outpoint::from_str(&fake_outpoing_zero).unwrap(), 10_000) + .add_owned_state(Outpoint::from_str(&fake_outpoing_one).unwrap(), 10_000); self.issue_with_params(params.build()) } From 70e61332fb9acd72caf3a8a8928339e6a3add70e Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 17 Feb 2025 18:07:48 +0800 Subject: [PATCH 12/90] feat(tests): implement NIA issuance with custom parameters in issuance tests Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 91 ++++++++------- tests/utils/helpers.rs | 245 +++++++++++++++++++++++++++++++++++------ 2 files changed, 263 insertions(+), 73 deletions(-) diff --git a/tests/issuance.rs b/tests/issuance.rs index 57fe6bf..df46b59 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -1,7 +1,11 @@ pub mod utils; use rstest_reuse::{self, *}; -use utils::{chain::initialize, helpers::get_wallet, DescriptorType, *}; +use utils::{ + chain::initialize, + helpers::{get_wallet, NIAIssueParams}, + DescriptorType, *, +}; const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; @@ -15,52 +19,55 @@ fn descriptor_and_close_method(#[case] wallet_desc: DescriptorType) {} #[apply(descriptor_and_close_method)] fn issue_nia(wallet_desc: DescriptorType) { - println!("wallet_desc {wallet_desc:?} "); + println!("wallet_desc {wallet_desc:?}"); initialize(); let mut wallet = get_wallet(&wallet_desc); - // temporary comment out custom parameters, temporarily read from file - // let issued_supply = 999; - // let ticker = "TCKR"; - // let name = "asset name"; - // let precision = 2; - // let details = Some("some details"); - // let terms_text = "Ricardian contract"; - // let terms_media_fpath = Some(MEDIA_FPATH); - // let asset_info = AssetInfo::nia( - // ticker, - // name, - // precision, - // details, - // terms_text, - // terms_media_fpath, - // vec![issued_supply], - // ); - // let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); - let contract_id = wallet.issue_nia(); - wallet.contract_states(Some(contract_id)); - // let contract = wallet.contract_iface_class::(contract_id); - // let spec = contract.spec(); - // assert_eq!(spec.ticker.to_string(), ticker.to_string()); - // assert_eq!(spec.name.to_string(), name.to_string()); - // assert_eq!(spec.precision.decimals(), precision); - // let terms = contract.contract_terms(); - // assert_eq!(terms.text.to_string(), terms_text.to_string()); - // let terms_media = terms.media.unwrap(); - // assert_eq!(terms_media.ty.to_string(), "image/jpeg"); - // assert_eq!( - // terms_media.digest.to_string(), - // "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" - // ); - // assert_eq!(contract.total_issued_supply().value(), issued_supply); - - // let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); - // assert_eq!(allocations.len(), 1); - // let allocation = allocations[0]; - // // assert_eq!(allocation.seal.method(), close_method); - // assert_eq!(allocation.state, Amount::from(issued_supply)); + // Create NIA issuance parameters + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", 1_000_000); + + // Add initial allocations + let fake_outpoint_zero = + Outpoint::from_str("0000000000000000000000000000000000000000000000000000000000000000:0") + .unwrap(); + let fake_outpoint_one = + Outpoint::from_str("0000000000000000000000000000000000000000000000000000000000000001:0") + .unwrap(); + params + .add_allocation(fake_outpoint_zero, 500_000) + .add_allocation(fake_outpoint_one, 500_000); + + // Issue the contract + let contract_id = wallet.issue_nia_with_params(params); + + // Verify contract state + let state = wallet + .contract_state(contract_id) + .expect("Contract state does not exist"); + + // Verify immutable state + assert_eq!(state.immutable.name, "TestAsset"); + assert_eq!(state.immutable.ticker, "TEST"); + assert_eq!(state.immutable.precision, "centiMilli"); + + // Verify circulating supply + assert_eq!(state.immutable.circulating_supply, 1_000_000); + + // Verify ownership state + dbg!(&state.owned.allocations); + assert_eq!(state.owned.allocations.len(), 2); + assert!(state + .owned + .allocations + .iter() + .any(|(outpoint, amount)| *outpoint == fake_outpoint_zero && *amount == 500_000)); + assert!(state + .owned + .allocations + .iter() + .any(|(outpoint, amount)| *outpoint == fake_outpoint_one && *amount == 500_000)); } // #[apply(descriptor_and_close_method)] diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index efabe79..1c16af1 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -9,11 +9,12 @@ use rand::RngCore; use rgb::invoice::{RgbBeneficiary, RgbInvoice}; use rgb::popls::bp::file::{BpDirMound, DirBarrow}; use rgb::{ - Assignment, CallScope, CodexId, Consensus, ContractId, ContractInfo, CreateParams, EitherSeal, - MethodName, NamedState, StateAtom, + Assignment, CallScope, CellAddr, CodexId, Consensus, ContractId, ContractInfo, CreateParams, + EitherSeal, MethodName, NamedState, StateAtom, }; use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbWallet}; -use strict_types::TypeName; +use strict_types::value::EnumTag; +use strict_types::{TypeName, VariantName}; use crate::utils::chain::fund_wallet; @@ -69,19 +70,19 @@ impl AssetParamsBuilder { } /// Set the contract method name - pub fn method(mut self, method: impl Into) -> Self { - self.params.method = method.into(); + pub fn method(mut self, method: &str) -> Self { + self.params.method = VariantName::from_str(method).unwrap(); self } /// Set the contract name - pub fn name(mut self, name: impl Into) -> Self { - self.params.name = name.into(); + pub fn name(mut self, name: &str) -> Self { + self.params.name = TypeName::from_str(name).unwrap(); self } /// Update name state in global states - pub fn update_name_state(mut self, value: impl Into) -> Self { + pub fn update_name_state(mut self, value: &str) -> Self { if let Some(state) = self .params .global @@ -94,7 +95,7 @@ impl AssetParamsBuilder { } /// Update ticker state in global states - pub fn update_ticker_state(mut self, value: impl Into) -> Self { + pub fn update_ticker_state(mut self, value: &str) -> Self { if let Some(state) = self .params .global @@ -107,7 +108,7 @@ impl AssetParamsBuilder { } /// Update precision state in global states - pub fn update_precision_state(mut self, value: impl Into) -> Self { + pub fn update_precision_state(mut self, value: &str) -> Self { if let Some(state) = self .params .global @@ -158,6 +159,11 @@ impl AssetParamsBuilder { self } + pub fn clear_owned_state(mut self) -> Self { + self.params.owned.clear(); + self + } + /// Add owned state pub fn add_owned_state(mut self, seal: Outpoint, val: u64) -> Self { self.params.owned.push(NamedState { @@ -625,27 +631,10 @@ impl TestWallet { self.mound().contracts_info().collect() } - pub fn contract_states(&self, contract_id: Option) { - let mut runtime = self.runtime(); - let contract_states = runtime.state_all(contract_id).collect::>(); - dbg!(contract_states); - } - - pub fn issue_nia(&mut self) -> ContractId { - let fake_outpoing_zero = - "0000000000000000000000000000000000000000000000000000000000000000:0"; - let fake_outpoing_one = - "0000000000000000000000000000000000000000000000000000000000000001:0"; - let params = AssetParamsBuilder::default() - .name("USDT") - .update_name_state("USD Tether") - .update_ticker_state("USDT") - .update_precision_state("centiMilli") - .update_circulating_state(1_000_000) - .add_owned_state(Outpoint::from_str(&fake_outpoing_zero).unwrap(), 10_000) - .add_owned_state(Outpoint::from_str(&fake_outpoing_one).unwrap(), 10_000); - self.issue_with_params(params.build()) - } + // pub fn all_contract_states(&self) -> Vec<(ContractId, ContractState)> { + // let mut runtime = self.runtime(); + // runtime.state_all(None).collect() + // } pub fn issue_with_params(&mut self, params: CreateParams) -> ContractId { let mut runtime = self.runtime(); @@ -661,3 +650,197 @@ impl TestWallet { self.issue_with_params(params) } } + +/// Parameters for NIA (Non-Inflatable Asset) issuance +#[derive(Clone)] +pub struct NIAIssueParams { + pub name: String, + pub ticker: String, + pub precision: String, + pub circulating_supply: u64, + pub initial_allocations: Vec<(Outpoint, u64)>, +} + +impl Default for NIAIssueParams { + fn default() -> Self { + Self { + name: "USD Tether".to_string(), + ticker: "USDT".to_string(), + precision: "centiMilli".to_string(), + circulating_supply: 1_000_000, + initial_allocations: vec![], + } + } +} + +impl NIAIssueParams { + pub fn new( + name: impl Into, + ticker: impl Into, + precision: impl Into, + circulating_supply: u64, + ) -> Self { + Self { + name: name.into(), + ticker: ticker.into(), + precision: precision.into(), + circulating_supply, + initial_allocations: vec![], + } + } + + pub fn add_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { + self.initial_allocations.push((outpoint, amount)); + self + } +} + +/// RGB Contract State representation +#[derive(Debug)] +pub struct ContractState { + /// Immutable state of the contract + pub immutable: ContractImmutableState, + /// Ownership state of the contract + pub owned: ContractOwnedState, +} + +/// Contract's immutable state +#[derive(Debug)] +pub struct ContractImmutableState { + pub name: String, + pub ticker: String, + pub precision: String, + pub circulating_supply: u64, +} + +/// Contract's ownership state +#[derive(Debug)] +pub struct ContractOwnedState { + pub allocations: Vec<(Outpoint, u64)>, +} + +impl TestWallet { + pub fn issue_nia_with_params(&mut self, params: NIAIssueParams) -> ContractId { + let mut builder: AssetParamsBuilder = AssetParamsBuilder::default() + .name(params.name.as_str()) + .update_name_state(params.name.as_str()) + .update_ticker_state(params.ticker.as_str()) + .update_precision_state(params.precision.as_str()) + .update_circulating_state(params.circulating_supply) + .clear_owned_state(); + + for (outpoint, amount) in params.initial_allocations { + builder = builder.add_owned_state(outpoint, amount); + } + + self.issue_with_params(builder.build()) + } + + pub fn issue_nia(&mut self) -> ContractId { + let fake_outpoint_zero = Outpoint::from_str( + "0000000000000000000000000000000000000000000000000000000000000000:0", + ) + .unwrap(); + let fake_outpoint_one = Outpoint::from_str( + "0000000000000000000000000000000000000000000000000000000000000001:0", + ) + .unwrap(); + + let mut params = NIAIssueParams::default(); + params + .add_allocation(fake_outpoint_zero, 10_000) + .add_allocation(fake_outpoint_one, 10_000); + + self.issue_nia_with_params(params) + } + + // FIXME: + // We should make a pr to sync with Maxim, + // `ContractState` is a public data structure, + // But it is not exported, so downstreams cannot use it (here we cannot specify the return type) + // pub fn contract_state_internal(&self, contract_id: ContractId) -> Option> { + // + // So we return the decomposed data structure here temporarily, + /// Get contract state (internal implementation) + fn contract_state_internal( + &self, + contract_id: ContractId, + ) -> Option<( + BTreeMap>, + BTreeMap>>, + BTreeMap, + )> { + self.runtime() + .state_all(Some(contract_id)) + .next() + .map(|(_, state)| { + ( + state.immutable.clone(), + state.owned.clone(), + state.computed.clone(), + ) + }) + } + + /// Get contract state with parsed data structures + pub fn contract_state(&self, contract_id: ContractId) -> Option { + self.contract_state_internal(contract_id) + .map(|(immutable, owned, computed)| { + // Parse immutable state + let name = immutable + .get(&VariantName::from_str("name").unwrap()) + .and_then(|m| m.values().next()) + .map(|v| v.verified.unwrap_string()) + .unwrap_or_default(); + + let ticker = immutable + .get(&VariantName::from_str("ticker").unwrap()) + .and_then(|m| m.values().next()) + .map(|v| v.verified.unwrap_string()) + .unwrap_or_default(); + + let precision = immutable + .get(&VariantName::from_str("precision").unwrap()) + .and_then(|m| m.values().next()) + .inspect(|v| { + dbg!(&v.verified); + }) + .map(|v| { + let tag = v.verified.unwrap_enum_tag(); + if let EnumTag::Name(name) = tag { + name.to_string() + } else { + "".to_string() + } + }) + .unwrap_or_default(); + + let circulating_supply = immutable + .get(&VariantName::from_str("circulating").unwrap()) + .and_then(|m: &BTreeMap| m.values().next()) + .and_then(|v| Some(v.verified.unwrap_num().unwrap_uint::())) + .unwrap_or_default(); + + // Parse ownership state + let mut allocations = vec![]; + if let Some(owned_map) = owned.get(&VariantName::from_str("owned").unwrap()) { + for assignment in owned_map.values() { + allocations.push(( + assignment.seal, + assignment.data.unwrap_num().unwrap_uint::(), + )); + } + } + + ContractState { + immutable: ContractImmutableState { + name, + ticker, + precision, + circulating_supply, + }, + owned: ContractOwnedState { allocations }, + } + }) + } +} From e1c8e7884e955275dcb9025052497b6c2a0e808e Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 18 Feb 2025 12:31:28 +0800 Subject: [PATCH 13/90] feat(tests): Optimize asset release and test data persistence Signed-off-by: will-bitlightlabs --- tests/bitcoin.testnet/note | 13 ---------- tests/schemata/NonInflatableAsset.issuer | Bin 2945 -> 0 bytes .../issuance/NonInflatableAsset.yaml} | 0 .../schemata}/NonInflatableAsset.issuer | Bin tests/utils/helpers.rs | 23 ++++++++++++++++-- tests/utils/mod.rs | 4 +++ 6 files changed, 25 insertions(+), 15 deletions(-) delete mode 100644 tests/bitcoin.testnet/note delete mode 100644 tests/schemata/NonInflatableAsset.issuer rename tests/{DemoToken.yaml => templates/issuance/NonInflatableAsset.yaml} (100%) rename tests/{ => templates/schemata}/NonInflatableAsset.issuer (100%) diff --git a/tests/bitcoin.testnet/note b/tests/bitcoin.testnet/note deleted file mode 100644 index 78a84e6..0000000 --- a/tests/bitcoin.testnet/note +++ /dev/null @@ -1,13 +0,0 @@ - -TODO: - -Because `tests` is the `DirExcavator` directory of `BpDirMound`, -Rgb will search for `schemata` and `contracts` in this directory. - -When detecting `contracts`, it will search in `tests/bitcoin.testnet`, - -If this directory does not exist, it will report an error, -So you need to create this directory in advance. - -The corresponding code is `rgb-std/src/mound.rs#L311` - diff --git a/tests/schemata/NonInflatableAsset.issuer b/tests/schemata/NonInflatableAsset.issuer deleted file mode 100644 index 58c9fe00a03ff0679abb6f3ba8598c75a1ec2abc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2945 zcmdT`c}x^%6rbTT*ukjZ`qOAncX=!yrb5G z7KPS|;ziZiYNXnr@d(9wm6&2}t+kaZ3YJ){x7b#p&{>4~Ps=oE)1)ui*FLA6FautX=V4 zMAh{X-5L+Fzk1d8`{lO>RCQsADX9F`y&aVkHwABFfs&&x1?MO`3jA_a0e<{WN}p3P z8AH2&ytjPD)?Uc-?sj`r%#wR6YpC%Nl>Ky{28Ij>RljgKv;hwdNBSIfX-Pp89 zGW7Ln3K(_1YR7@;Ya6<=D3p|g>-V=gnXe(@|_>5)w`nfd?<60~C*RMIYaojhxd7W2l>i}x)Lx9tv zi?$uDfcfItb*4-8`|u~9e;qmT)2d2$uOqr1*!qiV)gr)2%BOLALusz3_HNZ~zjfiu z3$E(6?CkzS?17}8GmDSqPOTc~H}uC9F{L+`hm>g}^v^tl7TkVoVA#!NJ6Fp$HyqKB zgy^7XWWZ4#&H8JdGA|)<0B)m1+d!>_XIV;k)y;tf8gbGfJ!My*sEnq;?v#TUC4qO? zP=L-XP)c)2aj$iv`@ zAF1Iv6r_=I`B8*q6A%iTb6(*Q{QHWrf8ra^N0bV$a zE!Rt(3n&Vh&48wX#R3olRx8NL0yZ097%*=h$j$~V3+#5lae(K6!vUO5AP7Jdfg}N0 z201w(Hy7mPf&6?hf4-jXyvPFF!8p*uKMs-?5fZ~%(Bk+o(}|jAqn|FhRJI|vZ`{`oKCm)#O-ey20n{GI?Du2SOpPJ;iYsoEjXZq+;<>}6ReN3@;oW~s`oU^{ z&;FQBZOUo7doY}Z$x%k4vJElZqD)6XxLS{aO6RaFqtUz0;$0ATZztL@p|G^TYdcs4 zx^=P&)+y7RMO9Nm!9x;=S5!PIf`>=Qi81 z4^BxE?@P`Z+<1lvdnG2?nE6>5nou^>t++YJ$L`$q>~hcgl$o0Ff70InRipm9&9-dd z(kA)A-Ghg&81swk#G>*Y-&e?iaax;kFQDOulbVqKXIyGKjR0ydKy6wRP%U>)ThS-G zTk Self { Self { - params: Self::from_file("./tests/DemoToken.yaml"), + params: Self::from_file(NON_INFLATABLE_ASSET_TEMPLATE_PATH), } } } @@ -397,6 +397,25 @@ fn _get_wallet( std::fs::create_dir_all(&wallet_dir).unwrap(); println!("wallet dir: {wallet_dir:?}"); + // create consensus_dir for managing RGB smart contracts + let mut consensus_dir = wallet_dir.join(Consensus::Bitcoin.to_string()); + if network.is_testnet() { + consensus_dir.set_extension("testnet"); + } + std::fs::create_dir_all(&consensus_dir).unwrap(); + + // copy schema files from template directory to wallet_dir + let schemata_dir = PathBuf::from(SCHEMATA_DIR); + if schemata_dir.exists() { + for entry in std::fs::read_dir(schemata_dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + if path.is_file() { + std::fs::copy(&path, wallet_dir.join(path.file_name().unwrap())).unwrap(); + } + } + } + let xpub_account = match wallet_account { WalletAccount::Private(ref xpriv_account) => xpriv_account.to_xpub_account(), WalletAccount::Public(ref xpub_account) => xpub_account.clone(), @@ -624,7 +643,7 @@ impl TestWallet { if !self.network().is_testnet() { panic!("Non-testnet networks are not yet supported"); } - BpDirMound::load_testnet(Consensus::Bitcoin, "./tests", false) + BpDirMound::load_testnet(Consensus::Bitcoin, &self.wallet_dir, false) } pub fn contracts_info(&self) -> Vec { diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index bf8cce7..1ac8d69 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -2,6 +2,10 @@ pub mod chain; pub mod helpers; pub const TEST_DATA_DIR: &str = "test-data"; +pub const SCHEMATA_DIR: &str = "tests/templates/schemata"; +pub const ISSUANCE_DIR: &str = "tests/templates/issuance"; +pub const NON_INFLATABLE_ASSET_TEMPLATE_PATH: &str = + "tests/templates/issuance/NonInflatableAsset.yaml"; pub const INTEGRATION_DATA_DIR: &str = "integration"; pub const STRESS_DATA_DIR: &str = "stress"; From a438313258d22abb220aff8a531ae5b7c80292fc Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 18 Feb 2025 16:50:19 +0800 Subject: [PATCH 14/90] feat(tests): add CFA issuance functionality with custom parameters and templates Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 91 ++++++++---------- .../issuance/CollectibleFungibleAsset.yaml | 19 ++++ .../schemata/CollectibleFungibleAsset.issuer | Bin 0 -> 2956 bytes tests/utils/helpers.rs | 82 ++++++++++++++-- tests/utils/mod.rs | 2 + 5 files changed, 136 insertions(+), 58 deletions(-) create mode 100644 tests/templates/issuance/CollectibleFungibleAsset.yaml create mode 100644 tests/templates/schemata/CollectibleFungibleAsset.issuer diff --git a/tests/issuance.rs b/tests/issuance.rs index df46b59..dfbd1de 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -3,7 +3,7 @@ pub mod utils; use rstest_reuse::{self, *}; use utils::{ chain::initialize, - helpers::{get_wallet, NIAIssueParams}, + helpers::{get_wallet, CFAIssueParams, NIAIssueParams}, DescriptorType, *, }; @@ -70,6 +70,45 @@ fn issue_nia(wallet_desc: DescriptorType) { .any(|(outpoint, amount)| *outpoint == fake_outpoint_one && *amount == 500_000)); } +#[apply(descriptor_and_close_method)] +fn issue_cfa(wallet_desc: DescriptorType) { + println!("wallet_desc {wallet_desc:?}"); + + initialize(); + + let mut wallet = get_wallet(&wallet_desc); + + // Create CFA issuance parameters + let mut params = CFAIssueParams::new("DemoCFA", "centiMilli", 10_000); + + // Add initial allocation + let fake_outpoint = + Outpoint::from_str("b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1") + .unwrap(); + params.add_allocation(fake_outpoint, 10_000); + + // Issue the contract + let contract_id = wallet.issue_cfa_with_params(params); + + // Verify contract state + let state = wallet + .contract_state(contract_id) + .expect("Contract state does not exist"); + + // Verify immutable state + assert_eq!(state.immutable.name, "DemoCFA"); + assert_eq!(state.immutable.precision, "centiMilli"); + assert_eq!(state.immutable.circulating_supply, 10_000); + + // Verify ownership state + assert_eq!(state.owned.allocations.len(), 1); + assert!(state + .owned + .allocations + .iter() + .any(|(outpoint, amount)| *outpoint == fake_outpoint && *amount == 10_000)); +} + // #[apply(descriptor_and_close_method)] // fn issue_uda(wallet_desc: DescriptorType) { // println!("wallet_desc {wallet_desc:?} "); @@ -155,55 +194,7 @@ fn issue_nia(wallet_desc: DescriptorType) { // } // #[apply(descriptor_and_close_method)] -// fn issue_cfa(wallet_desc: DescriptorType) { -// println!("wallet_desc {wallet_desc:?} "); - -// initialize(); - -// let mut wallet = get_wallet(&wallet_desc); - -// let issued_supply = 999; -// let name = "asset name"; -// let precision = 2; -// let details = Some("some details"); -// let terms_text = "Ricardian contract"; -// let terms_media_fpath = Some(MEDIA_FPATH); -// let asset_info = AssetInfo::cfa( -// name, -// precision, -// details, -// terms_text, -// terms_media_fpath, -// vec![issued_supply], -// ); -// let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); - -// let contract = wallet.contract_iface_class::(contract_id); -// assert_eq!(contract.name().to_string(), name.to_string()); -// assert_eq!( -// contract.details().map(|d| d.to_string()), -// details.map(|d| d.to_string()) -// ); -// assert_eq!(contract.precision().decimals(), precision); -// let terms = contract.contract_terms(); -// assert_eq!(terms.text.to_string(), terms_text.to_string()); -// let terms_media = terms.media.unwrap(); -// assert_eq!(terms_media.ty.to_string(), "image/jpeg"); -// assert_eq!( -// terms_media.digest.to_string(), -// "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" -// ); -// assert_eq!(contract.total_issued_supply().value(), issued_supply); - -// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); -// assert_eq!(allocations.len(), 1); -// let allocation = allocations[0]; -// assert_eq!(allocation.seal.method(), close_method); -// assert_eq!(allocation.state, Amount::from(issued_supply)); -// } - -// #[apply(descriptor_and_close_method)] -// fn issue_nia_multiple_utxos(wallet_desc: DescriptorType) { +// fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { // println!("wallet_desc {wallet_desc:?} "); // initialize(); diff --git a/tests/templates/issuance/CollectibleFungibleAsset.yaml b/tests/templates/issuance/CollectibleFungibleAsset.yaml new file mode 100644 index 0000000..a51c770 --- /dev/null +++ b/tests/templates/issuance/CollectibleFungibleAsset.yaml @@ -0,0 +1,19 @@ +consensus: bitcoin +testnet: true +codexId: 6bl9LdZ_-BU8Skh9-f~4UazR-TFwyotq-ac4yebi-zodXJnw#weather-motif-patriot +name: DemoCFA +method: issue +timestamp: "2024-12-18T10:32:00-02:00" + +global: + - name: name + verified: DemoCFA + - name: precision + verified: centiMilli + - name: circulating + verified: 10000 + +owned: + - name: owned + seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 + data: 10000 diff --git a/tests/templates/schemata/CollectibleFungibleAsset.issuer b/tests/templates/schemata/CollectibleFungibleAsset.issuer new file mode 100644 index 0000000000000000000000000000000000000000..1e6789e7c2608b230902ed4fa9784b54fbf62513 GIT binary patch literal 2956 zcmdT`X;2hb5T5sT26iEW9FfF$EShM*6VWKhpRg1l4wdTk0KbaP*gA`#+XRd2!*?3s zuV42N#7nUP$6-ch%^Xfp_#D@Jq$FY4kFfAkxP#^`f=D|=){gr#wsnbdIfN?xo1M<5 z&c7Bw076F)_k1(g)QybjX1cVya$9rO!j7x!>O6g{lgz!FgTkq0WfO-om*4KtHKnUfA(hu|ZLS)zHgqEg)Eu=d?iMW5EGKCh zN{TQYt$RG=(VTM?s|vb0r#AmowsL($gS}?Y!mK6fCFOu@cN;YhFEv2$eT1h>7m<3i@VB13jvW7yNG-3?0)uL=9A zzOc>?k2`en?BkE^RZybtRAiIrz#vOAKImxgUP z+_}{I_>r&Id{Eoz-t9dPt%t6M?9Z-WXQ#k1+NWt#V|js>+s*220ZXIimt54Z-{SZE zm^~>!XDvTmFuJ;DK=6+X;>)kjA6(%UZFuYzGV}UdJtMBp+p<`>y6T_~QIdmZu#v=t z3>WB@rwB5ZdXP3+vh{ScsC|kSUv+n2k-@zDnt`^fP*VF-FAv%wNU|t6Y`C}HEYeIa zmJ?rZLuo;JT9UEIO1Z(LgHxnF6eHN}bYIHO@`}_?XA$K7l*FmK3?OG>uFpEA(}7&qKOkBnluTb z$&(?<$be|d6o@i2J*2#t*34uX%xa3#T>(#hzMN*F7+S>gG&fGLs1(w>v}Bga%?30L z%x1taz+wRy1FIF}E99pvT$jstc(;CUbjz~KOSc|a6_Bmr3liURWUK|uj1 zECfYGV8#ps)8@!b(!o0LtUnggiYb}pEO@q7JEMTs1)2KZm<&_X;9JZ0Ua1&(;P%;5 z2g<8=yf~m^_n}kv)dYHVC-hn!NayFt@)kBLKT literal 0 HcmV?d00001 diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index a447772..0f13d94 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -29,18 +29,19 @@ pub struct AssetParamsBuilder { params: CreateParams, } -impl Default for AssetParamsBuilder { - fn default() -> Self { +impl AssetParamsBuilder { + /// Create a new builder instance for non-inflatable asset + pub fn default_nia() -> Self { Self { params: Self::from_file(NON_INFLATABLE_ASSET_TEMPLATE_PATH), } } -} -impl AssetParamsBuilder { - /// Create a new builder instance - pub fn new() -> Self { - Self::default() + /// Create a new builder instance for collectible fungible asset + pub fn default_cfa() -> Self { + Self { + params: Self::from_file(COLLECTIBLE_FUNGIBLE_ASSET_TEMPLATE_PATH), + } } /// Load parameters from YAML file @@ -740,7 +741,7 @@ pub struct ContractOwnedState { impl TestWallet { pub fn issue_nia_with_params(&mut self, params: NIAIssueParams) -> ContractId { - let mut builder: AssetParamsBuilder = AssetParamsBuilder::default() + let mut builder: AssetParamsBuilder = AssetParamsBuilder::default_nia() .name(params.name.as_str()) .update_name_state(params.name.as_str()) .update_ticker_state(params.ticker.as_str()) @@ -863,3 +864,68 @@ impl TestWallet { }) } } + +/// Parameters for CFA (Collectible Fungible Asset) issuance +#[derive(Clone)] +pub struct CFAIssueParams { + /// Asset name + pub name: String, + /// Decimal precision for the asset + pub precision: String, + /// Total circulating supply + pub circulating_supply: u64, + /// Initial token allocations (outpoint, amount) + pub initial_allocations: Vec<(Outpoint, u64)>, +} + +impl Default for CFAIssueParams { + fn default() -> Self { + Self { + name: "Demo CFA".to_string(), + precision: "centiMilli".to_string(), + circulating_supply: 10_000, + initial_allocations: vec![], + } + } +} + +impl CFAIssueParams { + /// Create new CFA issuance parameters + pub fn new( + name: impl Into, + precision: impl Into, + circulating_supply: u64, + ) -> Self { + Self { + name: name.into(), + precision: precision.into(), + circulating_supply, + initial_allocations: vec![], + } + } + + /// Add a token allocation + pub fn add_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { + self.initial_allocations.push((outpoint, amount)); + self + } +} + +impl TestWallet { + /// Issue a CFA contract with custom parameters + pub fn issue_cfa_with_params(&mut self, params: CFAIssueParams) -> ContractId { + let mut builder = AssetParamsBuilder::default_cfa() + .name(params.name.as_str()) + .update_name_state(params.name.as_str()) + .update_precision_state(params.precision.as_str()) + .update_circulating_state(params.circulating_supply) + .clear_owned_state(); + + // Add initial allocations + for (outpoint, amount) in params.initial_allocations { + builder = builder.add_owned_state(outpoint, amount); + } + + self.issue_with_params(builder.build()) + } +} diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 1ac8d69..5d73ca3 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -6,6 +6,8 @@ pub const SCHEMATA_DIR: &str = "tests/templates/schemata"; pub const ISSUANCE_DIR: &str = "tests/templates/issuance"; pub const NON_INFLATABLE_ASSET_TEMPLATE_PATH: &str = "tests/templates/issuance/NonInflatableAsset.yaml"; +pub const COLLECTIBLE_FUNGIBLE_ASSET_TEMPLATE_PATH: &str = + "tests/templates/issuance/CollectibleFungibleAsset.yaml"; pub const INTEGRATION_DATA_DIR: &str = "integration"; pub const STRESS_DATA_DIR: &str = "stress"; From 8b7ba280b0cf5d63e55c1d370886c87d2ca06d12 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 19 Feb 2025 00:50:22 +0800 Subject: [PATCH 15/90] feat(tests): add support for multiple UTXO allocations in CFA and NIA issuance tests Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 156 +++++++++++++++++++++++------------------ tests/utils/helpers.rs | 7 +- 2 files changed, 91 insertions(+), 72 deletions(-) diff --git a/tests/issuance.rs b/tests/issuance.rs index dfbd1de..8b577d3 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -109,6 +109,92 @@ fn issue_cfa(wallet_desc: DescriptorType) { .any(|(outpoint, amount)| *outpoint == fake_outpoint && *amount == 10_000)); } +#[apply(descriptor_and_close_method)] +fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { + println!("wallet_desc {wallet_desc:?}"); + + initialize(); + + let mut wallet = get_wallet(&wallet_desc); + + // Create CFA issuance parameters with multiple allocations + let mut params = CFAIssueParams::new("Multi_UTXO_CFA", "centiMilli", 999); + + // Get multiple UTXOs and add allocations + let amounts = vec![222, 444, 333]; + for amount in amounts.iter() { + let outpoint = wallet.get_utxo(None); + params.add_allocation(outpoint, *amount); + } + + // Issue the contract + let contract_id = wallet.issue_cfa_with_params(params); + + // Verify contract state + let state = wallet + .contract_state(contract_id) + .expect("Contract state does not exist"); + + // Verify immutable state + assert_eq!(state.immutable.name, "Multi_UTXO_CFA"); + assert_eq!(state.immutable.precision, "centiMilli"); + assert_eq!(state.immutable.circulating_supply, 999); + + // Verify ownership state + assert_eq!(state.owned.allocations.len(), 3); + let total_allocated: u64 = state + .owned + .allocations + .iter() + .map(|(_, amount)| amount) + .sum(); + assert_eq!(total_allocated, 999); +} + +#[apply(descriptor_and_close_method)] +fn issue_nia_multiple_utxos(wallet_desc: DescriptorType) { + println!("wallet_desc {wallet_desc:?}"); + + initialize(); + + let mut wallet = get_wallet(&wallet_desc); + + // Create NIA issuance parameters with multiple allocations + let mut params = NIAIssueParams::new("Multi_UTXO_NIA", "MUTX", "centiMilli", 999); + + // Get multiple UTXOs and add allocations + let amounts = vec![333, 333, 333]; + for amount in amounts.iter() { + let outpoint = wallet.get_utxo(None); + params.add_allocation(outpoint, *amount); + } + + // Issue the contract + let contract_id = wallet.issue_nia_with_params(params); + + // Verify contract state + let state = wallet + .contract_state(contract_id) + .expect("Contract state does not exist"); + + // Verify immutable state + assert_eq!(state.immutable.name, "Multi_UTXO_NIA"); + assert_eq!(state.immutable.ticker, "MUTX"); + assert_eq!(state.immutable.precision, "centiMilli"); + assert_eq!(state.immutable.circulating_supply, 999); + + // Verify ownership state + assert_eq!(state.owned.allocations.len(), 3); + let total_allocated: u64 = state + .owned + .allocations + .iter() + .map(|(_, amount)| amount) + .sum(); + assert_eq!(total_allocated, 999); +} + +// TODO: RGB official is improving the feature of uda asset, will add test after it's ready // #[apply(descriptor_and_close_method)] // fn issue_uda(wallet_desc: DescriptorType) { // println!("wallet_desc {wallet_desc:?} "); @@ -192,73 +278,3 @@ fn issue_cfa(wallet_desc: DescriptorType) { // assert_eq!(allocation.seal.method(), close_method); // assert_eq!(allocation.state.to_string(), "000000000100000000000000"); // } - -// #[apply(descriptor_and_close_method)] -// fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { -// println!("wallet_desc {wallet_desc:?} "); - -// initialize(); - -// let mut wallet = get_wallet(&wallet_desc); - -// let amounts = vec![222, 444, 333]; -// let outpoints: Vec<_> = (0..amounts.len()) -// .map(|_| Some(wallet.get_utxo(None))) -// .collect(); -// let asset_info = AssetInfo::default_nia(amounts.clone()); -// let (contract_id, iface_type_name) = -// wallet.issue_with_info(asset_info, close_method, outpoints.clone()); - -// let contract = wallet.contract_iface_class::(contract_id); -// assert_eq!( -// contract.total_issued_supply().value(), -// amounts.iter().sum::() -// ); - -// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); -// assert_eq!(allocations.len(), amounts.len()); -// for (amt, outpoint) in amounts.iter().zip(outpoints.into_iter()) { -// assert!(allocations.iter().any(|a| a.state == Amount::from(*amt) -// && a.seal -// == XChain::Bitcoin(ExplicitSeal { -// method: close_method, -// txid: outpoint.unwrap().txid, -// vout: outpoint.unwrap().vout -// }))) -// } -// } - -// #[apply(descriptor_and_close_method)] -// fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { -// println!("wallet_desc {wallet_desc:?} "); - -// initialize(); - -// let mut wallet = get_wallet(&wallet_desc); - -// let amounts = vec![222, 444, 333]; -// let outpoints: Vec<_> = (0..amounts.len()) -// .map(|_| Some(wallet.get_utxo(None))) -// .collect(); -// let asset_info = AssetInfo::default_cfa(amounts.clone()); -// let (contract_id, iface_type_name) = -// wallet.issue_with_info(asset_info, close_method, outpoints.clone()); - -// let contract = wallet.contract_iface_class::(contract_id); -// assert_eq!( -// contract.total_issued_supply().value(), -// amounts.iter().sum::() -// ); - -// let allocations = wallet.contract_fungible_allocations(contract_id, &iface_type_name, false); -// assert_eq!(allocations.len(), amounts.len()); -// for (amt, outpoint) in amounts.iter().zip(outpoints.into_iter()) { -// assert!(allocations.iter().any(|a| a.state == Amount::from(*amt) -// && a.seal -// == XChain::Bitcoin(ExplicitSeal { -// method: close_method, -// txid: outpoint.unwrap().txid, -// vout: outpoint.unwrap().vout -// }))) -// } -// } diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 0f13d94..0811acb 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -555,8 +555,11 @@ impl TestWallet { } pub fn keychain(&self) -> Keychain { - // RgbKeychain::for_method(self.close_method()) - todo!() + if self.wallet.descriptor().is_taproot() { + Keychain::with(KEY_CHAIN_TAPRET) + } else { + Keychain::with(KEY_CHAIN_RGB) + } } pub fn get_derived_address(&self) -> DerivedAddr { From 59a13060d44e364311f75d617033dc2c1b72d400 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 19 Feb 2025 16:33:57 +0800 Subject: [PATCH 16/90] feat(tests): (WIP) Implement asset transfer api and related test cases Signed-off-by: will-bitlightlabs --- Cargo.lock | 1 + Cargo.toml | 1 + tests/docker/docker-compose.yml | 3 + tests/transfer.rs | 124 ++++++++++++++++++ tests/utils/chain.rs | 13 ++ tests/utils/helpers.rs | 220 +++++++++++++++++++++++++++++--- 6 files changed, 344 insertions(+), 18 deletions(-) create mode 100644 tests/transfer.rs diff --git a/Cargo.lock b/Cargo.lock index 829147f..1a9add9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1723,6 +1723,7 @@ dependencies = [ "rgb-std", "rstest", "rstest_reuse", + "serde_json", "serde_yaml", "serial_test", "strict_encoding", diff --git a/Cargo.toml b/Cargo.toml index 880c024..5ba2f39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ rand = "0.8.5" rstest = "0.19.0" rstest_reuse = "0.6.0" serde_yaml = "0.9" +serde_json = "1.0" serial_test = "3.2.0" strum = { version = "0.26.2", features = ["derive"] } strum_macros = "0.26.2" diff --git a/tests/docker/docker-compose.yml b/tests/docker/docker-compose.yml index 8193ecf..c37cdee 100644 --- a/tests/docker/docker-compose.yml +++ b/tests/docker/docker-compose.yml @@ -46,6 +46,7 @@ services: echo "fallbackfee=0.0002" >> /data/.bitcoin/bitcoin.conf echo "zmqpubrawblock=tcp://0.0.0.0:28332" >> /data/.bitcoin/bitcoin.conf echo "zmqpubrawtx=tcp://0.0.0.0:28333" >> /data/.bitcoin/bitcoin.conf + echo "txindex=1" >> /data/.bitcoin/bitcoin.conf echo "" >> /data/.bitcoin/bitcoin.conf echo "# Regtest settings" >> /data/.bitcoin/bitcoin.conf echo "[regtest]" >> /data/.bitcoin/bitcoin.conf @@ -134,6 +135,7 @@ services: echo "fallbackfee=0.0002" >> /data/.bitcoin/bitcoin.conf echo "zmqpubrawblock=tcp://0.0.0.0:28332" >> /data/.bitcoin/bitcoin.conf echo "zmqpubrawtx=tcp://0.0.0.0:28333" >> /data/.bitcoin/bitcoin.conf + echo "txindex=1" >> /data/.bitcoin/bitcoin.conf echo "" >> /data/.bitcoin/bitcoin.conf echo "# Regtest settings" >> /data/.bitcoin/bitcoin.conf echo "[regtest]" >> /data/.bitcoin/bitcoin.conf @@ -172,6 +174,7 @@ services: echo "fallbackfee=0.0002" >> /data/.bitcoin/bitcoin.conf echo "zmqpubrawblock=tcp://0.0.0.0:28332" >> /data/.bitcoin/bitcoin.conf echo "zmqpubrawtx=tcp://0.0.0.0:28333" >> /data/.bitcoin/bitcoin.conf + echo "txindex=1" >> /data/.bitcoin/bitcoin.conf echo "" >> /data/.bitcoin/bitcoin.conf echo "# Regtest settings" >> /data/.bitcoin/bitcoin.conf echo "[regtest]" >> /data/.bitcoin/bitcoin.conf diff --git a/tests/transfer.rs b/tests/transfer.rs new file mode 100644 index 0000000..0aae807 --- /dev/null +++ b/tests/transfer.rs @@ -0,0 +1,124 @@ +pub mod utils; + +use utils::{ + chain::{get_height, initialize, stop_mining}, + helpers::{get_wallet, AssetSchema, NIAIssueParams}, + DescriptorType, *, +}; + +#[test] +fn simple_transfer() { + initialize(); + + // Create two wallet instances + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + // Create and issue NIA asset + let mut params = NIAIssueParams::new("RBFTestAsset", "RBF", "centiMilli", 600); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, 600); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("RBFTestAsset", &mut wlt_2); + + let invoice = wlt_2.invoice(contract_id, 400, true); + + // First transfer attempt - with lower fee + let (consignment_1, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); + + // Receiver accepts the transfer + wlt_2.accept_transfer(&consignment_1, None); + + // Broadcast and confirm transaction + wlt_1.mine_tx(&tx.txid(), true); + + // Sync both wallets + wlt_1.sync(); + wlt_2.sync(); + + // Verify asset allocations in both wallets + // FIXME: + // very strange wlt_1, why there are two states after transfer? + // should check the helper-api implementation + // assertion `left == right` failed + // left: [200, 400] + // right: [200] + // wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![200]); + // wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![400]); + dbg!( + &wlt_1 + .runtime() + .state_own(Some(contract_id)) + .next() + .unwrap() + .1 + .owned + ); + dbg!( + &wlt_2 + .runtime() + .state_own(Some(contract_id)) + .next() + .unwrap() + .1 + .owned + ); +} + +#[test] +// FIXME: +// Invalid operation data: operation references immutable memory cell VMlnpvOd~VSldT4BePvgcH4oM68W2noeTXgTXbtBNoU:0 which was not defined. +fn rbf_transfer() { + initialize(); + + // Create two wallet instances + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + // Create and issue NIA asset + let mut params = NIAIssueParams::new("RBFTestAsset", "RBF", "centiMilli", 600); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, 600); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("RBFTestAsset", &mut wlt_2); + + // Stop mining to test RBF + stop_mining(); + let initial_height = get_height(); + + let invoice = wlt_2.invoice(contract_id, 400, true); + + // First transfer attempt - with lower fee + let (consignment_1, _) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); + + // Receiver accepts the transfer + wlt_2.accept_transfer(&consignment_1, None); + + // Verify block height hasn't changed (transaction not confirmed) + let mid_height = get_height(); + assert_eq!(initial_height, mid_height); + + // Second transfer attempt - with higher fee for RBF + let (consignment_2, tx) = wlt_1.transfer(invoice, None, Some(1000), true, None); + + // Verify block height still hasn't changed + let final_height = get_height(); + assert_eq!(initial_height, final_height); + + // Broadcast and confirm transaction + wlt_1.mine_tx(&tx.txid(), true); + + // Receiver accepts final transfer + wlt_2.accept_transfer(&consignment_2, None); + + // Sync both wallets + wlt_1.sync(); + wlt_2.sync(); + + // Verify asset allocations in both wallets + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![200]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![400]); + + // Transfer assets back to sender + wlt_2.send(&mut wlt_1, false, contract_id, 400, 2000, None); +} diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 18a8604..bb4649a 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -338,3 +338,16 @@ pub fn fund_wallet(address: String, sats: Option, instance: u8) -> String { mine_custom(false, instance, 1); txid } + +pub fn get_raw_transaction(txid: &str, instance: u8) -> serde_json::Value { + let raw_tx = _bitcoin_cli_cmd(instance, vec!["getrawtransaction", txid, "true"]); + serde_json::from_str(&raw_tx).unwrap() +} + +pub fn is_tx_confirmed(txid: &str, instance: u8) -> bool { + let raw_tx = get_raw_transaction(txid, instance); + if raw_tx.get("confirmations").is_none() { + return false; + } + raw_tx.get("confirmations").unwrap().as_u64().unwrap() > 0 +} diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 0811acb..1f0a7a7 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -2,9 +2,13 @@ use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::fs::{File, OpenOptions}; use std::path::{Path, PathBuf}; +use std::sync::atomic::{AtomicU32, Ordering}; +use std::sync::OnceLock; use std::time::Duration; +use std::time::Instant; use bp::{seals::WTxoSeal, Outpoint}; +use psbt::TxParams; use rand::RngCore; use rgb::invoice::{RgbBeneficiary, RgbInvoice}; use rgb::popls::bp::file::{BpDirMound, DirBarrow}; @@ -12,12 +16,14 @@ use rgb::{ Assignment, CallScope, CellAddr, CodexId, Consensus, ContractId, ContractInfo, CreateParams, EitherSeal, MethodName, NamedState, StateAtom, }; +use rgbp::CoinselectStrategy; use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbWallet}; use strict_types::value::EnumTag; use strict_types::{TypeName, VariantName}; use crate::utils::chain::fund_wallet; +use super::chain::is_tx_confirmed; use super::{ chain::{indexer_url, mine_custom, Indexer, INDEXER}, *, @@ -672,6 +678,202 @@ impl TestWallet { let params = AssetParamsBuilder::from_file(params_path); self.issue_with_params(params) } + + pub fn mine_tx(&self, txid: &Txid, resume: bool) { + let mut attempts = 10; + loop { + mine_custom(resume, self.instance, 1); + if is_tx_confirmed(&txid.to_string(), self.instance) { + break; + } + attempts -= 1; + if attempts == 0 { + panic!("TX is not getting mined"); + } + } + } + + // send a contract to another wallet by copy contract dir to another wallet dir + pub fn send_contract(&mut self, contract_name: &str, to_wallet: &mut TestWallet) { + let mut src_consensus_dir = self.wallet_dir.join(Consensus::Bitcoin.to_string()); + let mut dst_consensus_dir = to_wallet.wallet_dir.join(Consensus::Bitcoin.to_string()); + if self.network().is_testnet() { + src_consensus_dir.set_extension("testnet"); + dst_consensus_dir.set_extension("testnet"); + } + let src_contract_dir = src_consensus_dir.join(format!("{contract_name}.contract")); + let dst_contract_dir = dst_consensus_dir.join(format!("{contract_name}.contract")); + std::fs::create_dir_all(&dst_contract_dir).unwrap(); + let read_dir = std::fs::read_dir(&src_contract_dir).unwrap(); + for entry in read_dir { + let entry = entry.unwrap(); + let path = entry.path(); + let dst_path = dst_contract_dir.join(path.file_name().unwrap()); + std::fs::copy(&path, &dst_path).unwrap(); + } + } + + /// Generate an invoice + pub fn invoice( + &mut self, + contract_id: ContractId, + amount: u64, + wout: bool, + ) -> RgbInvoice { + let mut runtime = self.runtime(); + let beneficiary = if wout { + let wout = runtime.wout(None); + RgbBeneficiary::WitnessOut(wout) + } else { + let auth = runtime.auth_token(None).unwrap(); + RgbBeneficiary::Token(auth) + }; + let value = StrictVal::num(amount); + RgbInvoice::new(contract_id, beneficiary, Some(value)) + } + + /// Send assets to the specified invoice + pub fn send( + &mut self, + recv_wallet: &mut TestWallet, + wout: bool, + contract_id: ContractId, + amount: u64, + sats: u64, + report: Option<&Report>, + ) -> (PathBuf, Tx) { + let invoice = recv_wallet.invoice(contract_id, amount, wout); + self.send_to_invoice(recv_wallet, invoice, Some(sats), None, report) + } + + /// Send assets to the specified invoice + pub fn send_to_invoice( + &mut self, + recv_wallet: &mut TestWallet, + invoice: RgbInvoice, + sats: Option, + fee: Option, + report: Option<&Report>, + ) -> (PathBuf, Tx) { + let (consignment, tx) = self.transfer(invoice, sats, fee, true, report); + broadcast_tx_and_mine(&tx, self.instance); + recv_wallet.accept_transfer(&consignment, report); + self.sync(); + (consignment, tx) + } + + /// Transfer assets and generate a transaction + pub fn transfer( + &mut self, + invoice: RgbInvoice, + sats: Option, + fee: Option, + broadcast: bool, + report: Option<&Report>, + ) -> (PathBuf, Tx) { + static COUNTER: OnceLock = OnceLock::new(); + let counter = COUNTER.get_or_init(|| AtomicU32::new(0)); + counter.fetch_add(1, Ordering::SeqCst); + let consignment_no = counter.load(Ordering::SeqCst); + + self.sync(); + + let fee = Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS)); + let sats = Sats::from_sats(sats.unwrap_or(2000)); + let strategy = CoinselectStrategy::Aggregate; + let pay_start = Instant::now(); + let params = TxParams::with(fee); + let (mut psbt, terminal) = self + .runtime() + .pay_invoice(&invoice, strategy, params, Some(sats)) + .unwrap(); + + let pay_duration = pay_start.elapsed(); + if let Some(report) = report { + report.write_duration(pay_duration); + } + + let tx = self.sign_finalize_extract(&mut psbt); + + println!( + "transfer txid: {}, consignment: {consignment_no}", + tx.txid() + ); + + if broadcast { + self.broadcast_tx(&tx); + } + + let consignment = self + .wallet_dir + .join(format!("consignment-{consignment_no}")) + .with_extension("rgb"); + + self.mound() + .consign_to_file(invoice.scope, [terminal], &consignment) + .unwrap(); + + (consignment, tx) + } + + /// Accept a transfer + pub fn accept_transfer(&mut self, consignment: &Path, report: Option<&Report>) { + self.sync(); + let accept_start = Instant::now(); + self.runtime().consume_from_file(consignment).unwrap(); + let accept_duration = accept_start.elapsed(); + if let Some(report) = report { + report.write_duration(accept_duration); + } + } + + /// Check asset allocations + pub fn check_allocations( + &mut self, + contract_id: ContractId, + asset_schema: AssetSchema, + mut expected_fungible_allocations: Vec, + // nonfungible_allocation: bool, + ) { + match asset_schema { + AssetSchema::Nia | AssetSchema::Cfa => { + let state = self + .runtime() + .state_own(Some(contract_id)) + .next() + .unwrap() + .1; + let mut actual_fungible_allocations = state + .owned + .get("owned") + .unwrap() + .iter() + .inspect(|(_, assignment)| { + dbg!(assignment); + }) + .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) + .collect::>(); + actual_fungible_allocations.sort(); + expected_fungible_allocations.sort(); + assert_eq!(actual_fungible_allocations, expected_fungible_allocations); + } + AssetSchema::Uda => { + todo!() + } + } + } + + /// Sign and finalize PSBT + pub fn sign_finalize(&self, psbt: &mut Psbt) { + let _sig_count = psbt.sign(self.signer.as_ref().unwrap()).unwrap(); + psbt.finalize(self.wallet.descriptor()); + } + + /// Sign, finalize, and extract the transaction + pub fn sign_finalize_extract(&self, psbt: &mut Psbt) -> Tx { + self.sign_finalize(psbt); + psbt.extract().unwrap() + } } /// Parameters for NIA (Non-Inflatable Asset) issuance @@ -759,24 +961,6 @@ impl TestWallet { self.issue_with_params(builder.build()) } - pub fn issue_nia(&mut self) -> ContractId { - let fake_outpoint_zero = Outpoint::from_str( - "0000000000000000000000000000000000000000000000000000000000000000:0", - ) - .unwrap(); - let fake_outpoint_one = Outpoint::from_str( - "0000000000000000000000000000000000000000000000000000000000000001:0", - ) - .unwrap(); - - let mut params = NIAIssueParams::default(); - params - .add_allocation(fake_outpoint_zero, 10_000) - .add_allocation(fake_outpoint_one, 10_000); - - self.issue_nia_with_params(params) - } - // FIXME: // We should make a pr to sync with Maxim, // `ContractState` is a public data structure, From bb43d53295bf81eec7024a1049433845ade0adf6 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 20 Feb 2025 13:40:51 +0800 Subject: [PATCH 17/90] chore: Refactoring rgb-runtime in helper and adjusting the simple-transfer test-case Signed-off-by: will-bitlightlabs --- Cargo.lock | 73 +++++++------ bp-core | 2 +- bp-electrum-client | 2 +- bp-esplora-client | 2 +- bp-std | 2 +- bp-wallet | 2 +- client_side_validation | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-std | 2 +- rust-aluvm | 2 +- sonic | 2 +- strict-types | 2 +- tests/transfer.rs | 73 ++++++------- tests/utils/helpers.rs | 226 +++++++++-------------------------------- ultrasonic | 2 +- zk-aluvm | 2 +- 17 files changed, 147 insertions(+), 253 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a9add9..f06cb8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,7 +28,7 @@ dependencies = [ [[package]] name = "aluvm" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "baid64", @@ -263,7 +263,7 @@ checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" [[package]] name = "bp-consensus" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "chrono", @@ -275,7 +275,7 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-consensus", @@ -291,7 +291,7 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "base85", @@ -304,7 +304,7 @@ dependencies = [ [[package]] name = "bp-derive" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-consensus", @@ -318,7 +318,7 @@ dependencies = [ [[package]] name = "bp-electrum" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-std", @@ -335,7 +335,7 @@ dependencies = [ [[package]] name = "bp-esplora" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-std", @@ -348,9 +348,24 @@ dependencies = [ "tokio", ] +[[package]] +name = "bp-esplora" +version = "0.12.0-beta.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec6536fdc52c7be3e5d1b5204e5276f7f782225fb6fc7080411039d32bc47f4" +dependencies = [ + "amplify", + "bp-std", + "log", + "minreq", + "serde", + "serde_with 3.11.0", + "sha2", +] + [[package]] name = "bp-invoice" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bech32", @@ -362,7 +377,7 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "baid64", @@ -377,7 +392,7 @@ dependencies = [ [[package]] name = "bp-std" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-consensus", @@ -394,11 +409,11 @@ dependencies = [ [[package]] name = "bp-wallet" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-electrum", - "bp-esplora", + "bp-esplora 0.12.0-beta.5.1", "bp-std", "descriptors", "nonasync", @@ -492,7 +507,7 @@ dependencies = [ [[package]] name = "commit_encoding_derive" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "amplify_syn", @@ -503,7 +518,7 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "commit_encoding_derive", @@ -633,7 +648,7 @@ dependencies = [ [[package]] name = "descriptors" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-derive", @@ -1022,7 +1037,7 @@ dependencies = [ [[package]] name = "hypersonic" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "aluvm", "amplify", @@ -1464,7 +1479,7 @@ dependencies = [ [[package]] name = "psbt" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "base64 0.22.1", @@ -1622,7 +1637,7 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-core", @@ -1637,7 +1652,7 @@ dependencies = [ [[package]] name = "rgb-invoice" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "baid64", @@ -1653,7 +1668,7 @@ dependencies = [ [[package]] name = "rgb-psbt" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-core", @@ -1663,7 +1678,7 @@ dependencies = [ [[package]] name = "rgb-runtime" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-std", @@ -1682,7 +1697,7 @@ dependencies = [ [[package]] name = "rgb-std" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-core", @@ -1709,7 +1724,7 @@ dependencies = [ "bitcoin_hashes", "bp-core", "bp-electrum", - "bp-esplora", + "bp-esplora 0.12.0-beta.5", "bp-invoice", "bp-std", "bp-wallet", @@ -2138,7 +2153,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "single_use_seals" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "serde", "strict_encoding", @@ -2171,7 +2186,7 @@ dependencies = [ [[package]] name = "sonic-api" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "aluvm", "amplify", @@ -2189,7 +2204,7 @@ dependencies = [ [[package]] name = "sonic-callreq" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "baid64", @@ -2231,7 +2246,7 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.8.1" +version = "2.8.2" dependencies = [ "amplify", "baid64", @@ -2530,7 +2545,7 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ultrasonic" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "amplify", "baid64", @@ -2951,7 +2966,7 @@ dependencies = [ [[package]] name = "zk-aluvm" -version = "0.12.0-beta.4" +version = "0.12.0-beta.5" dependencies = [ "aluvm", "amplify", diff --git a/bp-core b/bp-core index 6fbc7f1..f26f459 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit 6fbc7f16d028d12d6d1336a9aa7752ea8ae06e15 +Subproject commit f26f45921fdf6083e09620dc05b6e990dc639c42 diff --git a/bp-electrum-client b/bp-electrum-client index 1d2b08a..c820723 160000 --- a/bp-electrum-client +++ b/bp-electrum-client @@ -1 +1 @@ -Subproject commit 1d2b08ada85b742d8a0f7548ed6bb5a760aef51e +Subproject commit c820723a453c40c50db876cd9b6db1897e0e94b6 diff --git a/bp-esplora-client b/bp-esplora-client index 056891e..b382527 160000 --- a/bp-esplora-client +++ b/bp-esplora-client @@ -1 +1 @@ -Subproject commit 056891e5f86aa3dac80628541e4e44fee0479507 +Subproject commit b382527a1392fff01492f69905d7cacd030169c1 diff --git a/bp-std b/bp-std index 91aaf51..1e8eb90 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit 91aaf51498126f6a514f0d9af80888465e5dbfee +Subproject commit 1e8eb9008221e429e67f1caa6ffe9ffb54bde5e4 diff --git a/bp-wallet b/bp-wallet index 5546f0a..54102a7 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 5546f0ad5d7aee3d8d92d4a5604095cf2ec834fe +Subproject commit 54102a7413da2227bcbb049998b5cbefc894ca02 diff --git a/client_side_validation b/client_side_validation index 6746486..76b3cde 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit 67464863d8dae8aaf52807cc0b07a198232ac5b2 +Subproject commit 76b3cdec2f82b5c9cbed32a9b80124b8602f397e diff --git a/rgb b/rgb index bc2b889..5bd42bf 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit bc2b88921e8886238f0ac0d00ed9a43edf3289c2 +Subproject commit 5bd42bfefd2614b353505baaf95041640ac2ff82 diff --git a/rgb-core b/rgb-core index 4a020e0..6603689 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 4a020e09dcf4e30edc41432e3c9f92f3c13ad0ac +Subproject commit 66036890a42604014e4388538eef943283171581 diff --git a/rgb-std b/rgb-std index a368811..088f179 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit a368811a2fbaf8385d8da6de7bf5a2ce3d01e8af +Subproject commit 088f1795df9a3d3c905b6628cea7e5c31988ae4e diff --git a/rust-aluvm b/rust-aluvm index 8b009cd..0a59555 160000 --- a/rust-aluvm +++ b/rust-aluvm @@ -1 +1 @@ -Subproject commit 8b009cde66a210e35b7db6b2cb36ab2bc2fa60cd +Subproject commit 0a5955595de41b58e390b8d3028bd49e091a410d diff --git a/sonic b/sonic index debfacf..4af3e1b 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit debfacf6ca53977abcdaa5c64450b0eb51049503 +Subproject commit 4af3e1bcbe3aed862ce9e422f373650f3c817930 diff --git a/strict-types b/strict-types index 0292feb..302acf4 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit 0292feb72ffa51dccbaaabc4e6e0ba9ad9a5ebbc +Subproject commit 302acf4b1c4a5b128e9af6a3433c94a1b0774073 diff --git a/tests/transfer.rs b/tests/transfer.rs index 0aae807..febf416 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -6,6 +6,8 @@ use utils::{ DescriptorType, *, }; +// FIXME: +// If invoice: wout is false, the asset transfer succeeds; if true, the asset transfer fails #[test] fn simple_transfer() { initialize(); @@ -13,18 +15,28 @@ fn simple_transfer() { // Create two wallet instances let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + let supply = 600; + let asset_name = "TestAsset"; // Create and issue NIA asset - let mut params = NIAIssueParams::new("RBFTestAsset", "RBF", "centiMilli", 600); + let mut params = NIAIssueParams::new(asset_name, "RBF", "centiMilli", supply); let outpoint = wlt_1.get_utxo(None); - params.add_allocation(outpoint, 600); + params.add_allocation(outpoint, supply); let contract_id = wlt_1.issue_nia_with_params(params); - wlt_1.send_contract("RBFTestAsset", &mut wlt_2); + wlt_1.send_contract(asset_name, &mut wlt_2); + // TODO: Because the RGB mound currently cannot dynamically load contracts, + // It needs to be reloaded at a special time, and consider submitting a PR to RGB + wlt_2.reload_runtime(); - let invoice = wlt_2.invoice(contract_id, 400, true); + // pub type DirMound = Mound, DirExcavator>; + // let mound: &mut rgb::Mound, rgb::DirExcavator> = &mut wlt_1.runtime().mound; + + let assign = 400; + // recive asset by utxo + let invoice = wlt_2.invoice(contract_id, assign, false, Some(0)); // First transfer attempt - with lower fee - let (consignment_1, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); + let (consignment_1, tx) = wlt_1.transfer(invoice, None, Some(500), true, None); // Receiver accepts the transfer wlt_2.accept_transfer(&consignment_1, None); @@ -36,36 +48,29 @@ fn simple_transfer() { wlt_1.sync(); wlt_2.sync(); - // Verify asset allocations in both wallets - // FIXME: - // very strange wlt_1, why there are two states after transfer? - // should check the helper-api implementation - // assertion `left == right` failed - // left: [200, 400] - // right: [200] - // wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![200]); - // wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![400]); - dbg!( - &wlt_1 - .runtime() - .state_own(Some(contract_id)) - .next() - .unwrap() - .1 - .owned - ); - dbg!( - &wlt_2 - .runtime() - .state_own(Some(contract_id)) - .next() - .unwrap() - .1 - .owned - ); + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![supply - assign]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign]); + + // let assign_wlt1 = 200; + // let invoice = wlt_1.invoice(contract_id, assign_wlt1, false, Some(0)); + // let (consignment_2, tx) = wlt_2.transfer(invoice, None, Some(500), true, None); + // wlt_1.accept_transfer(&consignment_2, None); + // wlt_2.mine_tx(&tx.txid(), true); + + // // Sync both wallets + // wlt_1.sync(); + // wlt_2.sync(); + + // wlt_1.check_allocations( + // contract_id, + // AssetSchema::Nia, + // vec![supply - assign + assign_wlt1], + // ); + // wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign - assign_wlt1]); } #[test] +#[ignore] // FIXME: // Invalid operation data: operation references immutable memory cell VMlnpvOd~VSldT4BePvgcH4oM68W2noeTXgTXbtBNoU:0 which was not defined. fn rbf_transfer() { @@ -86,7 +91,7 @@ fn rbf_transfer() { stop_mining(); let initial_height = get_height(); - let invoice = wlt_2.invoice(contract_id, 400, true); + let invoice = wlt_2.invoice(contract_id, 400, false, Some(0)); // First transfer attempt - with lower fee let (consignment_1, _) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); @@ -120,5 +125,5 @@ fn rbf_transfer() { wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![400]); // Transfer assets back to sender - wlt_2.send(&mut wlt_1, false, contract_id, 400, 2000, None); + wlt_2.send(&mut wlt_1, false, contract_id, 400, 2000, Some(0), None); } diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 1f0a7a7..a363dcd 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -190,9 +190,7 @@ impl AssetParamsBuilder { } pub struct TestWallet { - // FIXME: should store runtime instead of wallet - // when need wallet, use runtime.defer.wallet - wallet: RgbWallet, + runtime: RgbDirRuntime, descriptor: RgbDescr, signer: Option, wallet_dir: PathBuf, @@ -300,66 +298,6 @@ impl fmt::Display for AssetSchema { } } -impl AssetSchema { - // fn iface_type_name(&self) -> TypeName { - // tn!(match self { - // Self::Nia => "RGB20Fixed", - // Self::Uda => "RGB21Unique", - // Self::Cfa => "RGB25Base", - // }) - // } - - // fn schema(&self) -> Schema { - // match self { - // Self::Nia => NonInflatableAsset::schema(), - // Self::Uda => UniqueDigitalAsset::schema(), - // Self::Cfa => CollectibleFungibleAsset::schema(), - // } - // } - - // fn issue_impl(&self) -> IfaceImpl { - // match self { - // Self::Nia => NonInflatableAsset::issue_impl(), - // Self::Uda => UniqueDigitalAsset::issue_impl(), - // Self::Cfa => CollectibleFungibleAsset::issue_impl(), - // } - // } - - // fn scripts(&self) -> Scripts { - // match self { - // Self::Nia => NonInflatableAsset::scripts(), - // Self::Uda => UniqueDigitalAsset::scripts(), - // Self::Cfa => CollectibleFungibleAsset::scripts(), - // } - // } - - // fn types(&self) -> TypeSystem { - // match self { - // Self::Nia => NonInflatableAsset::types(), - // Self::Uda => UniqueDigitalAsset::types(), - // Self::Cfa => CollectibleFungibleAsset::types(), - // } - // } - - // fn iface(&self) -> Iface { - // match self { - // Self::Nia => Rgb20::iface(&Rgb20::FIXED), - // Self::Uda => Rgb21::iface(&Rgb21::NONE), - // Self::Cfa => Rgb25::iface(&Rgb25::NONE), - // } - // } - - // fn get_valid_kit(&self) -> ValidKit { - // let mut kit = Kit::default(); - // kit.schemata.push(self.schema()).unwrap(); - // kit.ifaces.push(self.iface()).unwrap(); - // kit.iimpls.push(self.issue_impl()).unwrap(); - // kit.scripts.extend(self.scripts().into_values()).unwrap(); - // kit.types = self.types(); - // kit.validate().unwrap() - // } -} - pub struct Report { pub report_path: PathBuf, } @@ -427,21 +365,7 @@ fn _get_wallet( WalletAccount::Private(ref xpriv_account) => xpriv_account.to_xpub_account(), WalletAccount::Public(ref xpub_account) => xpub_account.clone(), }; - const OPRET_KEYCHAINS: [Keychain; 3] = [ - Keychain::INNER, - Keychain::OUTER, - Keychain::with(KEY_CHAIN_RGB), - ]; - const TAPRET_KEYCHAINS: [Keychain; 4] = [ - Keychain::INNER, - Keychain::OUTER, - Keychain::with(KEY_CHAIN_RGB), - Keychain::with(KEY_CHAIN_TAPRET), - ]; - let keychains: &[Keychain] = match *descriptor_type { - DescriptorType::Tr => &TAPRET_KEYCHAINS[..], - DescriptorType::Wpkh => &OPRET_KEYCHAINS[..], - }; + let keychains: &[Keychain] = &[Keychain::INNER, Keychain::OUTER]; let xpub_derivable = XpubDerivable::with(xpub_account.clone(), keychains); let noise = xpub_derivable.xpub().chain_code().to_byte_array(); @@ -450,23 +374,14 @@ fn _get_wallet( DescriptorType::Tr => RgbDescr::key_only_unfunded(xpub_derivable, noise), }; - let name = "bp_wallet_name"; - let provider = FsTextStore::new(wallet_dir.join(name)).unwrap(); - let wallet = RgbWallet::create(provider, descriptor.clone(), network, true) - .expect("Unable to create wallet"); - - // for asset_schema in AssetSchema::iter() { - // let valid_kit = asset_schema.get_valid_kit(); - // wallet.stock_mut().import_kit(valid_kit).unwrap(); - // } - let signer = match wallet_account { WalletAccount::Private(xpriv_account) => Some(TestnetSigner::new(xpriv_account)), WalletAccount::Public(_) => None, }; - let mut wallet = TestWallet { - wallet, + let runtime = make_runtime(&descriptor, network, &wallet_dir); + let mut test_wallet = TestWallet { + runtime, descriptor, signer, wallet_dir, @@ -475,10 +390,20 @@ fn _get_wallet( // TODO: remove if once found solution for esplora 'Too many requests' error if network.is_testnet() { - wallet.sync(); + test_wallet.sync(); } - wallet + test_wallet +} + +fn make_runtime(descriptor: &RgbDescr, network: Network, wallet_dir: &PathBuf) -> RgbDirRuntime { + let name = "bp_wallet.wallet"; + let provider = FsTextStore::new(wallet_dir.join(name)).unwrap(); + let wallet = RgbWallet::create(provider, descriptor.clone(), network, true) + .expect("Unable to create wallet"); + + let mound = BpDirMound::load_testnet(Consensus::Bitcoin, &wallet_dir, false); + RgbDirRuntime::from(DirBarrow::with(wallet, mound)) } pub fn get_wallet(descriptor_type: &DescriptorType) -> TestWallet { @@ -553,24 +478,17 @@ pub fn broadcast_tx_and_mine(tx: &Tx, instance: u8) { impl TestWallet { pub fn network(&self) -> Network { - self.wallet.network() + self.runtime.wallet.network() } pub fn testnet(&self) -> bool { self.network().is_testnet() } - pub fn keychain(&self) -> Keychain { - if self.wallet.descriptor().is_taproot() { - Keychain::with(KEY_CHAIN_TAPRET) - } else { - Keychain::with(KEY_CHAIN_RGB) - } - } - pub fn get_derived_address(&self) -> DerivedAddr { - self.wallet - .addresses(self.keychain()) + self.runtime + .wallet + .addresses(Keychain::OUTER) .next() .expect("no addresses left") } @@ -584,7 +502,7 @@ impl TestWallet { let txid = Txid::from_str(&fund_wallet(address.to_string(), sats, self.instance)).unwrap(); self.sync(); let mut vout = None; - let coins = self.wallet.address_coins(); + let coins = self.runtime.wallet.address_coins(); assert!(!coins.is_empty()); for (_derived_addr, utxos) in coins { for utxo in utxos { @@ -599,13 +517,18 @@ impl TestWallet { } } + // TODO: Because the RGB mound currently cannot dynamically load contracts, + // It needs to be reloaded at a special time, and consider submitting a PR to RGB + pub fn reload_runtime(&mut self) { + self.runtime = make_runtime(&self.descriptor, self.network(), &self.wallet_dir); + } + pub fn change_instance(&mut self, instance: u8) { self.instance = instance; } pub fn switch_to_instance(&mut self, instance: u8) { self.change_instance(instance); - // self.sync_and_update_witnesses(None); } pub fn indexer_url(&self) -> String { @@ -622,52 +545,20 @@ impl TestWallet { pub fn sync(&mut self) { let indexer = self.get_indexer(); - self.wallet.update(&indexer).into_result().unwrap(); - } - - pub fn wallet_provider(&self) -> FsTextStore { - let name: &str = "bp_wallet_name"; - let provider = FsTextStore::new(self.wallet_dir.join(name)).unwrap(); - provider + self.runtime.wallet.update(&indexer).into_result().unwrap(); } - pub fn wallet(&self) -> RgbWallet { - let provider = self.wallet_provider(); - RgbWallet::load(provider, true).unwrap_or_else(|_| { - panic!( - "Error: unable to load wallet from path `{}`", - self.wallet_dir.display() - ) - }) - } - - pub fn runtime(&self) -> RgbDirRuntime { - let wallet = self.wallet(); - let mound = self.mound(); - // dbg!(&mound.schemata().collect::>()); - let runtime = RgbDirRuntime::from(DirBarrow::with(wallet, mound)); - runtime - } - - pub fn mound(&self) -> BpDirMound { - if !self.network().is_testnet() { - panic!("Non-testnet networks are not yet supported"); - } - BpDirMound::load_testnet(Consensus::Bitcoin, &self.wallet_dir, false) + pub fn runtime(&mut self) -> &mut RgbDirRuntime { + &mut self.runtime } pub fn contracts_info(&self) -> Vec { - self.mound().contracts_info().collect() + self.runtime.mound.contracts_info().collect() } - // pub fn all_contract_states(&self) -> Vec<(ContractId, ContractState)> { - // let mut runtime = self.runtime(); - // runtime.state_all(None).collect() - // } - pub fn issue_with_params(&mut self, params: CreateParams) -> ContractId { - let mut runtime = self.runtime(); - let contract_id = runtime + let contract_id = self + .runtime .issue_to_file(params) .expect("failed to issue contract"); println!("A new contract issued with ID {contract_id}"); @@ -693,7 +584,6 @@ impl TestWallet { } } - // send a contract to another wallet by copy contract dir to another wallet dir pub fn send_contract(&mut self, contract_name: &str, to_wallet: &mut TestWallet) { let mut src_consensus_dir = self.wallet_dir.join(Consensus::Bitcoin.to_string()); let mut dst_consensus_dir = to_wallet.wallet_dir.join(Consensus::Bitcoin.to_string()); @@ -713,26 +603,27 @@ impl TestWallet { } } - /// Generate an invoice pub fn invoice( &mut self, contract_id: ContractId, amount: u64, wout: bool, + nonce: Option, ) -> RgbInvoice { - let mut runtime = self.runtime(); let beneficiary = if wout { - let wout = runtime.wout(None); + let wout = self.runtime.wout(nonce); RgbBeneficiary::WitnessOut(wout) } else { - let auth = runtime.auth_token(None).unwrap(); + // funding wallet + let _ = self.get_utxo(None); + // dbg!(self.runtime.wallet.utxos().collect::>()); + let auth = self.runtime.auth_token(nonce).unwrap(); RgbBeneficiary::Token(auth) }; let value = StrictVal::num(amount); RgbInvoice::new(contract_id, beneficiary, Some(value)) } - /// Send assets to the specified invoice pub fn send( &mut self, recv_wallet: &mut TestWallet, @@ -740,13 +631,13 @@ impl TestWallet { contract_id: ContractId, amount: u64, sats: u64, + nonce: Option, report: Option<&Report>, ) -> (PathBuf, Tx) { - let invoice = recv_wallet.invoice(contract_id, amount, wout); + let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce); self.send_to_invoice(recv_wallet, invoice, Some(sats), None, report) } - /// Send assets to the specified invoice pub fn send_to_invoice( &mut self, recv_wallet: &mut TestWallet, @@ -762,7 +653,6 @@ impl TestWallet { (consignment, tx) } - /// Transfer assets and generate a transaction pub fn transfer( &mut self, invoice: RgbInvoice, @@ -784,7 +674,7 @@ impl TestWallet { let pay_start = Instant::now(); let params = TxParams::with(fee); let (mut psbt, terminal) = self - .runtime() + .runtime .pay_invoice(&invoice, strategy, params, Some(sats)) .unwrap(); @@ -809,40 +699,33 @@ impl TestWallet { .join(format!("consignment-{consignment_no}")) .with_extension("rgb"); - self.mound() + self.runtime + .mound .consign_to_file(invoice.scope, [terminal], &consignment) .unwrap(); (consignment, tx) } - /// Accept a transfer pub fn accept_transfer(&mut self, consignment: &Path, report: Option<&Report>) { self.sync(); let accept_start = Instant::now(); - self.runtime().consume_from_file(consignment).unwrap(); + self.runtime.consume_from_file(consignment).unwrap(); let accept_duration = accept_start.elapsed(); if let Some(report) = report { report.write_duration(accept_duration); } } - /// Check asset allocations pub fn check_allocations( &mut self, contract_id: ContractId, asset_schema: AssetSchema, mut expected_fungible_allocations: Vec, - // nonfungible_allocation: bool, ) { match asset_schema { AssetSchema::Nia | AssetSchema::Cfa => { - let state = self - .runtime() - .state_own(Some(contract_id)) - .next() - .unwrap() - .1; + let state = self.runtime.state_own(Some(contract_id)).next().unwrap().1; let mut actual_fungible_allocations = state .owned .get("owned") @@ -863,13 +746,11 @@ impl TestWallet { } } - /// Sign and finalize PSBT pub fn sign_finalize(&self, psbt: &mut Psbt) { let _sig_count = psbt.sign(self.signer.as_ref().unwrap()).unwrap(); - psbt.finalize(self.wallet.descriptor()); + psbt.finalize(self.runtime.wallet.descriptor()); } - /// Sign, finalize, and extract the transaction pub fn sign_finalize_extract(&self, psbt: &mut Psbt) -> Tx { self.sign_finalize(psbt); psbt.extract().unwrap() @@ -961,16 +842,9 @@ impl TestWallet { self.issue_with_params(builder.build()) } - // FIXME: - // We should make a pr to sync with Maxim, - // `ContractState` is a public data structure, - // But it is not exported, so downstreams cannot use it (here we cannot specify the return type) - // pub fn contract_state_internal(&self, contract_id: ContractId) -> Option> { - // - // So we return the decomposed data structure here temporarily, /// Get contract state (internal implementation) fn contract_state_internal( - &self, + &mut self, contract_id: ContractId, ) -> Option<( BTreeMap>, @@ -990,7 +864,7 @@ impl TestWallet { } /// Get contract state with parsed data structures - pub fn contract_state(&self, contract_id: ContractId) -> Option { + pub fn contract_state(&mut self, contract_id: ContractId) -> Option { self.contract_state_internal(contract_id) .map(|(immutable, owned, computed)| { // Parse immutable state diff --git a/ultrasonic b/ultrasonic index 2bb7be9..4bd48cf 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit 2bb7be96e316746363ff3e4f1f2ccb1c8496a94a +Subproject commit 4bd48cf423fc344aa8a137cf42f9cc562fdde510 diff --git a/zk-aluvm b/zk-aluvm index 08bf763..c3bb703 160000 --- a/zk-aluvm +++ b/zk-aluvm @@ -1 +1 @@ -Subproject commit 08bf763f88f84a2c6a6c0f2b72fbab365d649754 +Subproject commit c3bb7030c993b76640949b9ce3ef29d384abb8e4 From 4eca2f575b49b82455f0b427b1b150264ec50732 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 20 Feb 2025 17:46:06 +0800 Subject: [PATCH 18/90] feat(tests): Refactor simple_transfer test to support dynamic WitnessOut parameter Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 75 ++++++++++++++++++++++++++++-------------- tests/utils/helpers.rs | 6 ++-- 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index febf416..5ca71d3 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1,15 +1,19 @@ pub mod utils; +use rstest_reuse::{self, *}; use utils::{ chain::{get_height, initialize, stop_mining}, helpers::{get_wallet, AssetSchema, NIAIssueParams}, DescriptorType, *, }; -// FIXME: -// If invoice: wout is false, the asset transfer succeeds; if true, the asset transfer fails -#[test] -fn simple_transfer() { +#[template] +#[rstest] +#[case(true)] +#[case(false)] +fn wout(#[case] wout: bool) {} +#[apply(wout)] +fn simple_transfer(wout: bool) { initialize(); // Create two wallet instances @@ -33,10 +37,12 @@ fn simple_transfer() { let assign = 400; // recive asset by utxo - let invoice = wlt_2.invoice(contract_id, assign, false, Some(0)); + let invoice = wlt_2.invoice(contract_id, assign, wout, Some(0)); - // First transfer attempt - with lower fee - let (consignment_1, tx) = wlt_1.transfer(invoice, None, Some(500), true, None); + // send asset to wlt2 + // if `wout` is true (WitnessOut), + // wlt2 will have a 3000 Sats UTXO, which will be spent to transfer assets to wlt1 in the next step + let (consignment_1, tx) = wlt_1.transfer(invoice, Some(3000), Some(500), true, None); // Receiver accepts the transfer wlt_2.accept_transfer(&consignment_1, None); @@ -51,28 +57,46 @@ fn simple_transfer() { wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![supply - assign]); wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign]); - // let assign_wlt1 = 200; - // let invoice = wlt_1.invoice(contract_id, assign_wlt1, false, Some(0)); - // let (consignment_2, tx) = wlt_2.transfer(invoice, None, Some(500), true, None); - // wlt_1.accept_transfer(&consignment_2, None); - // wlt_2.mine_tx(&tx.txid(), true); + let assign_wlt1 = 200; + let invoice = wlt_1.invoice(contract_id, assign_wlt1, wout, Some(0)); + dbg!( + "wlt2", + wlt_2.runtime().wallet.balance(), + wlt_2.runtime().wallet.coins().collect::>() + ); + // Sats cost: 500 fee + 2000 sats(default) = 2500 + let (consignment_2, tx) = wlt_2.transfer(invoice, None, Some(500), true, None); + wlt_1.accept_transfer(&consignment_2, None); + wlt_2.mine_tx(&tx.txid(), true); // // Sync both wallets - // wlt_1.sync(); - // wlt_2.sync(); - - // wlt_1.check_allocations( - // contract_id, - // AssetSchema::Nia, - // vec![supply - assign + assign_wlt1], - // ); - // wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign - assign_wlt1]); + wlt_1.sync(); + wlt_2.sync(); + + // owned state + dbg!(wlt_1 + .runtime() + .state_own(Some(contract_id)) + .collect::>()); + dbg!(wlt_2 + .runtime() + .state_own(Some(contract_id)) + .collect::>()); + + wlt_1.check_allocations( + contract_id, + AssetSchema::Nia, + vec![supply - assign, assign_wlt1], + ); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign - assign_wlt1]); } #[test] -#[ignore] // FIXME: -// Invalid operation data: operation references immutable memory cell VMlnpvOd~VSldT4BePvgcH4oM68W2noeTXgTXbtBNoU:0 which was not defined. +// called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) +// +// RBF transfer fails in the second asset transfer, +// Likely due to the inability to spend the same asset balance twice. fn rbf_transfer() { initialize(); @@ -86,13 +110,14 @@ fn rbf_transfer() { params.add_allocation(outpoint, 600); let contract_id = wlt_1.issue_nia_with_params(params); wlt_1.send_contract("RBFTestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + let invoice = wlt_2.invoice(contract_id, 400, false, Some(0)); // Stop mining to test RBF stop_mining(); let initial_height = get_height(); - let invoice = wlt_2.invoice(contract_id, 400, false, Some(0)); - // First transfer attempt - with lower fee let (consignment_1, _) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index a363dcd..6e55284 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -617,6 +617,7 @@ impl TestWallet { // funding wallet let _ = self.get_utxo(None); // dbg!(self.runtime.wallet.utxos().collect::>()); + // because auth_token needs a UTXO, so we need to fund `(send+mine)` the wallet first let auth = self.runtime.auth_token(nonce).unwrap(); RgbBeneficiary::Token(auth) }; @@ -665,11 +666,11 @@ impl TestWallet { let counter = COUNTER.get_or_init(|| AtomicU32::new(0)); counter.fetch_add(1, Ordering::SeqCst); let consignment_no = counter.load(Ordering::SeqCst); - self.sync(); let fee = Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS)); let sats = Sats::from_sats(sats.unwrap_or(2000)); + let strategy = CoinselectStrategy::Aggregate; let pay_start = Instant::now(); let params = TxParams::with(fee); @@ -731,9 +732,6 @@ impl TestWallet { .get("owned") .unwrap() .iter() - .inspect(|(_, assignment)| { - dbg!(assignment); - }) .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) .collect::>(); actual_fungible_allocations.sort(); From 173a5b06ae542b222a864aed0b0d2d6f5aa1cb73 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 21 Feb 2025 12:53:47 +0800 Subject: [PATCH 19/90] feat(tests): Implement transfer loop related test cases Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 183 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 182 insertions(+), 1 deletion(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 5ca71d3..c432886 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -3,10 +3,14 @@ pub mod utils; use rstest_reuse::{self, *}; use utils::{ chain::{get_height, initialize, stop_mining}, - helpers::{get_wallet, AssetSchema, NIAIssueParams}, + helpers::{get_wallet, AssetSchema, CFAIssueParams, NIAIssueParams, TransferType}, DescriptorType, *, }; +type TT = TransferType; +type DT = DescriptorType; +type AS = AssetSchema; + #[template] #[rstest] #[case(true)] @@ -152,3 +156,180 @@ fn rbf_transfer() { // Transfer assets back to sender wlt_2.send(&mut wlt_1, false, contract_id, 400, 2000, Some(0), None); } + +#[rstest] +// blinded: nia - nia +#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::Nia, AS::Nia)] +#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::Nia, AS::Nia)] +#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::Nia, AS::Nia)] +#[case(TT::Blinded, DT::Tr, DT::Tr, AS::Nia, AS::Nia)] +// blinded: nia - cfa +#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::Nia, AS::Cfa)] +#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::Nia, AS::Cfa)] +#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::Nia, AS::Cfa)] +#[case(TT::Blinded, DT::Tr, DT::Tr, AS::Nia, AS::Cfa)] +// blinded: cfa - cfa +#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::Cfa, AS::Cfa)] +#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::Cfa, AS::Cfa)] +#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::Cfa, AS::Cfa)] +#[case(TT::Blinded, DT::Tr, DT::Tr, AS::Cfa, AS::Cfa)] +// FIXME: `calling to method absent in Codex API` +// When using the same utxo for issue, the transfer will report an error +// should sync issue to doctor +// +// TODO: UDA related asset feature, RGB core library is being improved, +// And the test case for UDA assets will be added later +fn transfer_loop( + #[case] transfer_type: TransferType, + #[case] wlt_1_desc: DescriptorType, + #[case] wlt_2_desc: DescriptorType, + #[case] asset_schema_1: AssetSchema, + #[case] asset_schema_2: AssetSchema, +) { + println!( + "transfer_type {transfer_type:?} wlt_1_desc {wlt_1_desc:?} wlt_2_desc {wlt_2_desc:?} \ + asset_schema_1 {asset_schema_1:?} asset_schema_2 {asset_schema_2:?}" + ); + + initialize(); + + let mut wlt_1 = get_wallet(&wlt_1_desc); + let mut wlt_2 = get_wallet(&wlt_2_desc); + + let issued_supply_1 = 999; + let issued_supply_2 = 666; + + let sats = 9000; + + // wlt_1 issues 2 assets on the same UTXO + let utxo = wlt_1.get_utxo(None); + + // Issue first asset + let contract_id_1 = match asset_schema_1 { + AssetSchema::Nia => { + let mut params = + NIAIssueParams::new("TestAsset1", "TEST1", "centiMilli", issued_supply_1); + params.add_allocation(utxo, issued_supply_1); + wlt_1.issue_nia_with_params(params) + } + AssetSchema::Cfa => { + let mut params = CFAIssueParams::new("TestAsset1", "centiMilli", issued_supply_1); + params.add_allocation(utxo, issued_supply_1); + wlt_1.issue_cfa_with_params(params) + } + AssetSchema::Uda => { + // TODO: UDA is not supported yet + panic!("UDA is not supported yet"); + } + }; + + // Issue second asset + let contract_id_2 = match asset_schema_2 { + AssetSchema::Nia => { + let mut params = + NIAIssueParams::new("TestAsset2", "TEST2", "centiMilli", issued_supply_2); + params.add_allocation(utxo, issued_supply_2); + wlt_1.issue_nia_with_params(params) + } + AssetSchema::Cfa => { + let mut params = CFAIssueParams::new("TestAsset2", "centiMilli", issued_supply_2); + params.add_allocation(utxo, issued_supply_2); + wlt_1.issue_cfa_with_params(params) + } + AssetSchema::Uda => { + // TODO: UDA is not supported yet + panic!("UDA is not supported yet"); + } + }; + + // Share contract info with wallet 2 + wlt_1.send_contract("TestAsset1", &mut wlt_2); + wlt_1.send_contract("TestAsset2", &mut wlt_2); + wlt_2.reload_runtime(); + + // Verify initial allocations + wlt_1.check_allocations(contract_id_1, asset_schema_1, vec![issued_supply_1]); + wlt_1.check_allocations(contract_id_2, asset_schema_2, vec![issued_supply_2]); + + // wlt_1 spends asset 1 + let amount_1 = if asset_schema_1 == AssetSchema::Uda { + 1 + } else { + 99 + }; + let wout = match transfer_type { + TransferType::Blinded => false, + TransferType::Witness => true, + }; + wlt_1.send( + &mut wlt_2, + wout, + contract_id_1, + amount_1, + sats, + Some(0), + None, + ); + + // Verify allocations after first transfer + wlt_1.check_allocations( + contract_id_1, + asset_schema_1, + vec![issued_supply_1 - amount_1], + ); + wlt_1.check_allocations(contract_id_2, asset_schema_2, vec![issued_supply_2]); + wlt_2.check_allocations(contract_id_1, asset_schema_1, vec![amount_1]); + + // wlt_1 spends asset 1 change (only if possible) + if asset_schema_1 != AssetSchema::Uda { + let amount_2 = 33; + wlt_1.send( + &mut wlt_2, + wout, + contract_id_1, + amount_2, + sats, + Some(0), + None, + ); + + // Verify allocations after second transfer + wlt_1.check_allocations( + contract_id_1, + asset_schema_1, + vec![issued_supply_1 - amount_1 - amount_2], + ); + wlt_1.check_allocations(contract_id_2, asset_schema_2, vec![issued_supply_2]); + wlt_2.check_allocations(contract_id_1, asset_schema_1, vec![amount_1, amount_2]); + } + + // wlt_1 spends asset 2 + let amount_3 = if asset_schema_2 == AssetSchema::Uda { + 1 + } else { + 22 + }; + wlt_1.send(&mut wlt_2, wout, contract_id_2, amount_3, sats, None, None); + + // Verify final allocations + if asset_schema_1 != AssetSchema::Uda { + let amount_2 = 33; + wlt_1.check_allocations( + contract_id_1, + asset_schema_1, + vec![issued_supply_1 - amount_1 - amount_2], + ); + } else { + wlt_1.check_allocations( + contract_id_1, + asset_schema_1, + vec![issued_supply_1 - amount_1], + ); + } + wlt_1.check_allocations( + contract_id_2, + asset_schema_2, + vec![issued_supply_2 - amount_3], + ); + wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3]); +} From e90541c2a6a8eeb04f43161b06e824913b20aa1a Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 21 Feb 2025 20:16:47 +0800 Subject: [PATCH 20/90] feat(tests): Refactoring transfer-loop logic to cover full test scenarios Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 149 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 139 insertions(+), 10 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index c432886..7730f4c 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1,6 +1,7 @@ pub mod utils; use rstest_reuse::{self, *}; +use std::panic::{catch_unwind, AssertUnwindSafe}; use utils::{ chain::{get_height, initialize, stop_mining}, helpers::{get_wallet, AssetSchema, CFAIssueParams, NIAIssueParams, TransferType}, @@ -175,10 +176,15 @@ fn rbf_transfer() { #[case(TT::Blinded, DT::Tr, DT::Tr, AS::Cfa, AS::Cfa)] // FIXME: `calling to method absent in Codex API` // When using the same utxo for issue, the transfer will report an error -// should sync issue to doctor +// +// There is also a strange phenomenon that when all assets issued using the same utxo are CFA types, no errors are reported. +// rgb-test cmd: cargo test transfer_loop::case_09 +// If both are NIA or the first asset NIA, an error will occur. +// rgb-test cmd: cargo test transfer_loop::case_01 // // TODO: UDA related asset feature, RGB core library is being improved, // And the test case for UDA assets will be added later + fn transfer_loop( #[case] transfer_type: TransferType, #[case] wlt_1_desc: DescriptorType, @@ -199,7 +205,7 @@ fn transfer_loop( let issued_supply_1 = 999; let issued_supply_2 = 666; - let sats = 9000; + let mut sats = 9000; // wlt_1 issues 2 assets on the same UTXO let utxo = wlt_1.get_utxo(None); @@ -252,10 +258,10 @@ fn transfer_loop( wlt_1.check_allocations(contract_id_2, asset_schema_2, vec![issued_supply_2]); // wlt_1 spends asset 1 - let amount_1 = if asset_schema_1 == AssetSchema::Uda { - 1 - } else { + let amount_1 = if asset_schema_1 != AssetSchema::Uda { 99 + } else { + 1 }; let wout = match transfer_type { TransferType::Blinded => false, @@ -292,8 +298,6 @@ fn transfer_loop( Some(0), None, ); - - // Verify allocations after second transfer wlt_1.check_allocations( contract_id_1, asset_schema_1, @@ -304,10 +308,10 @@ fn transfer_loop( } // wlt_1 spends asset 2 - let amount_3 = if asset_schema_2 == AssetSchema::Uda { - 1 - } else { + let amount_3 = if asset_schema_2 != AssetSchema::Uda { 22 + } else { + 1 }; wlt_1.send(&mut wlt_2, wout, contract_id_2, amount_3, sats, None, None); @@ -332,4 +336,129 @@ fn transfer_loop( vec![issued_supply_2 - amount_3], ); wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3]); + + // wlt_2 spends received allocation(s) of asset 1 + let amount_4 = if asset_schema_1 != AssetSchema::Uda { + 111 + } else { + 1 + }; + let amount_2 = if asset_schema_1 != AssetSchema::Uda { + 33 + } else { + 0 + }; + sats -= 1000; + wlt_2.send(&mut wlt_1, wout, contract_id_1, amount_4, sats, None, None); + wlt_1.check_allocations( + contract_id_1, + asset_schema_1, + vec![issued_supply_1 - amount_1 - amount_2, amount_4], + ); + wlt_1.check_allocations( + contract_id_2, + asset_schema_2, + vec![issued_supply_2 - amount_3], + ); + wlt_2.check_allocations( + contract_id_1, + asset_schema_1, + vec![amount_1 + amount_2 - amount_4], + ); + wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3]); + + // wlt_2 spends asset 2 + let amount_5 = if asset_schema_2 != AssetSchema::Uda { + 11 + } else { + 1 + }; + sats -= 1000; + wlt_2.send(&mut wlt_1, wout, contract_id_2, amount_5, sats, None, None); + wlt_1.check_allocations( + contract_id_1, + asset_schema_1, + vec![issued_supply_1 - amount_1 - amount_2, amount_4], + ); + wlt_1.check_allocations( + contract_id_2, + asset_schema_2, + vec![issued_supply_2 - amount_3, amount_5], + ); + + // for debug + { + let wlt_1_contract_2_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); + dbg!(wlt_1_contract_2_state.collect::>()); + } + + wlt_2.check_allocations( + contract_id_1, + asset_schema_1, + vec![amount_1 + amount_2 - amount_4], + ); + wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3 - amount_5]); + + // wlt_1 spends asset 1, received back + let amount_6 = if asset_schema_1 != AssetSchema::Uda { + issued_supply_1 - amount_1 - amount_2 + amount_4 + } else { + 1 + }; + sats -= 1000; + wlt_1.send(&mut wlt_2, wout, contract_id_1, amount_6, sats, None, None); + wlt_1.check_allocations(contract_id_1, asset_schema_1, vec![]); + // for debug + { + let wlt_1_contract_2_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); + dbg!(wlt_1_contract_2_state.collect::>()); + } + + // Theoretically, there should be two outputs, one for the change UTXO and one for the income UTXO. + // But because the change UTXO is associated with two assets (asset 1 and asset 2), asset 1 has been fully transferred to the UTXO of wlt2. + // So there will only be one UTXO, which combines the change and income of asset 2. + // + // In most cases, it will be merged into one UTXO, + // And in a few cases, there will be two UTXOs. + if let Err(_) = catch_unwind(AssertUnwindSafe(|| { + wlt_1.check_allocations( + contract_id_2, + asset_schema_2, + vec![issued_supply_2 - amount_3 + amount_5], + ); + })) { + wlt_1.check_allocations( + contract_id_2, + asset_schema_2, + vec![issued_supply_2 - amount_3, amount_5], + ); + } + + wlt_2.check_allocations( + contract_id_1, + asset_schema_1, + vec![amount_1 + amount_2 - amount_4, amount_6], + ); + wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3 - amount_5]); + + // wlt_1 spends asset 2, received back + let amount_7 = if asset_schema_2 != AssetSchema::Uda { + issued_supply_2 - amount_3 + amount_5 + } else { + 1 + }; + sats -= 1000; + wlt_1.send(&mut wlt_2, wout, contract_id_2, amount_7, sats, None, None); + wlt_1.check_allocations(contract_id_1, asset_schema_1, vec![]); + wlt_1.check_allocations(contract_id_2, asset_schema_2, vec![]); + wlt_2.check_allocations( + contract_id_1, + asset_schema_1, + vec![amount_1 + amount_2 - amount_4, amount_6], + ); + wlt_2.check_allocations( + contract_id_2, + asset_schema_2, + vec![amount_3 - amount_5, amount_7], + ); } From a8b34b4a41331c86d691f8188105185c4618d8d9 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 24 Feb 2025 15:13:44 +0800 Subject: [PATCH 21/90] feat(tests): Add test cases accept_0conf and same_transfer_twice_no_update_witnesses Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 139 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index 7730f4c..2387e46 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -462,3 +462,142 @@ fn transfer_loop( vec![amount_3 - amount_5, amount_7], ); } + +// TODO: The `update_witnesses` method has been removed in RGB V0.12, +// So this test case may need to be removed or redesigned +// Need to sync with Dr. Maxim +#[rstest] +#[ignore = "fix needed"] +#[case(TransferType::Blinded)] +#[case(TransferType::Witness)] +fn same_transfer_twice_update_witnesses(#[case] transfer_type: TransferType) {} + +#[rstest] +#[case(TransferType::Blinded)] +#[case(TransferType::Witness)] +fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) { + println!("transfer_type {transfer_type:?}"); + + // TODO: This test case aims to verify if asset transfers are handled correctly when using RBF (Replace-By-Fee) with the same invoice + // In RGB V0.11, there was an inflation attack vulnerability where using RBF with the same invoice would cause the receiver to record two receive states, + // while the sender only paid the assets once. This resulted in the total circulating assets exceeding the issued amount. + // + // In RGB V0.12, since it's not possible to use RBF with the same invoice, we cannot test for this inflation attack. + // NOTE: When paying the same invoice for the second time, the error `called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient)` occurs + // Need to consult with Dr. Maxim on how to construct RBF asset transfer examples using the current API. + + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issue_supply = 2000; + // Create and issue NIA asset + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issue_supply); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, issue_supply); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + let amount = 100; + let wout = match transfer_type { + TransferType::Blinded => false, + TransferType::Witness => true, + }; + let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0)); + let _ = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + + dbg!(wlt_1 + .runtime() + .state_all(None) + .map(|(c, s)| { s.owned }) + .collect::>()); + dbg!(wlt_1 + .runtime() + .state_own(None) + .map(|(c, s)| { s.owned }) + .collect::>()); + + // dbg!(wlt_2 + // .runtime() + // .state_all(None) + // .map(|(c, s)| { s.owned }) + // .collect::>()); + // dbg!(wlt_2 + // .runtime() + // .state_own(None) + // .map(|(c, s)| { s.owned }) + // .collect::>()); + + // TODO: called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) + let (consignment, _) = wlt_1.transfer(invoice, None, Some(1000), true, None); + + wlt_2.accept_transfer(&consignment, None); + + let wlt_2_contract_state = wlt_2.runtime().state_own(None).map(|s| s.1.owned); + dbg!(wlt_2_contract_state.collect::>()); + + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amount]); + + wlt_2.send(&mut wlt_1, wout, contract_id, amount, 1000, None, None); + + let wlt_1_contract_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); + dbg!(wlt_1_contract_state.collect::>()); + + let mut wlt_3 = get_wallet(&DescriptorType::Wpkh); + wlt_1.send_contract("TestAsset", &mut wlt_3); + wlt_3.reload_runtime(); + + wlt_1.send( + &mut wlt_3, + wout, + contract_id, + issue_supply, + 1000, + None, + None, + ); + let wlt_3_contract_state = wlt_3.runtime().state_own(None).map(|s| s.1.owned); + dbg!(wlt_3_contract_state.collect::>()); +} + +#[test] +fn accept_0conf() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issue_supply = 600; + // Create and issue NIA asset + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issue_supply); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, issue_supply); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + let amt = 200; + let invoice = wlt_2.invoice(contract_id, amt, true, Some(0)); + let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, None, true, None); + let txid = tx.txid(); + + wlt_2.accept_transfer(&consignment, None); + + // wlt_2 sees the allocation even if TX has not been mined + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amt]); + + wlt_1.sync(); + + let wlt_1_change_amt = issue_supply - amt; + + // wlt_1 needs to get tentative allocations to see its change from the unmined TX + let wlt_1_contract_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); + dbg!(wlt_1_contract_state.collect::>()); + + // after mining, wlt_1 doesn't need to get tentative allocations to see the change + wlt_1.mine_tx(&txid, false); + wlt_1.sync(); + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_change_amt]); +} From a8524ea5fdebbc8af929ff9fa9deb893afd8fbde Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 24 Feb 2025 19:56:36 +0800 Subject: [PATCH 22/90] feat(tests): Add comprehensive tests for NIA asset transfers and allocations Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index 2387e46..7479ac7 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -601,3 +601,113 @@ fn accept_0conf() { wlt_1.sync(); wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_change_amt]); } + +#[test] +fn tapret_wlt_receiving_opret() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Tr); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", 600); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, 600); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + // First transfer: wlt_1 -> wlt_2, transfer 400 + wlt_1.send(&mut wlt_2, false, contract_id, 400, 5000, None, None); + + // Second transfer: wlt_2 -> wlt_1, transfer 100 + let invoice = wlt_1.invoice(contract_id, 100, true, Some(0)); + wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); + + // Third transfer: wlt_1 -> wlt_2, transfer 290 + wlt_1.send(&mut wlt_2, true, contract_id, 290, 1000, None, None); + + // Fourth transfer: wlt_2 -> wlt_1, transfer 560 + wlt_2.send(&mut wlt_1, false, contract_id, 560, 1000, None, None); + + // Fifth transfer: wlt_1 -> wlt_2, transfer 570 + wlt_1.send(&mut wlt_2, false, contract_id, 570, 1000, None, None); + + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![30, 570]); +} + +#[test] +fn check_fungible_history() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issue_supply = 600; + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issue_supply); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, issue_supply); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + // debug contract info + dbg!(wlt_1.contracts_info()); + dbg!(wlt_1 + .runtime() + .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) + .collect::>()); + + // transfer + let amt = 200; + let (_, tx) = wlt_1.send(&mut wlt_2, true, contract_id, amt, 1000, None, None); + let _txid = tx.txid(); + + // debug contract state + dbg!(wlt_1 + .runtime() + .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) + .collect::>()); + dbg!(wlt_2 + .runtime() + .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) + .collect::>()); + + // check allocations + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![issue_supply - amt]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amt]); +} + +#[test] +fn send_to_oneself() { + initialize(); + + let mut wlt = get_wallet(&DescriptorType::Wpkh); + + let issue_supply = 600; + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issue_supply); + let outpoint = wlt.get_utxo(None); + params.add_allocation(outpoint, issue_supply); + let contract_id = wlt.issue_nia_with_params(params); + + // Transfer 200 to yourself + let amt = 200; + let invoice = wlt.invoice(contract_id, amt, true, Some(0)); + let (consignment, tx) = wlt.transfer(invoice.clone(), None, None, true, None); + wlt.mine_tx(&tx.txid(), false); + wlt.accept_transfer(&consignment, None); + wlt.sync(); + + // debug contract state + dbg!(wlt + .runtime() + .state_own(None) + .map(|s| s.1.owned) + .collect::>()); + + // check allocations + wlt.check_allocations(contract_id, AssetSchema::Nia, vec![amt, issue_supply - amt]); +} From eb216b4d732af466b5c172a1bc917191c67b0be2 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 26 Feb 2025 12:53:52 +0800 Subject: [PATCH 23/90] feat(tests): Update transfer tests for RGB v0.12 migration and API changes Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 100 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 7 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 7479ac7..326a4d5 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1,3 +1,26 @@ +// RGB v0.12 Migration Notes: +// 1. Seal Type Unification (RFC: https://github.com/RGB-WG/RFC/issues/16) +// - Unified seal type replaces distinct opret and tapret seals +// - Seal type is automatically determined by wallet type (Taproot/WPKH) +// - CloseMethod parameter has been removed from contract genesis +// - Contract no longer commits to specific seal types +// +// 2. API Changes and Migration Strategy: +// - Removed APIs: +// * update_witnesses: Will be replaced with new rollback procedure +// * CloseMethod related parameters: No longer needed due to seal unification +// - Test Case Handling: +// * Existing tests dependent on removed APIs: Marked as #[ignore] with tracking issues +// * New tests: Focus on wallet type interactions rather than seal types +// * Complex test cases will be implemented after evaluating: +// - RGB protocol documentation and examples +// - Implementation approaches for Lightning Network, multi-sig and interactive transactions +// +// 3. Implementation Notes: +// - Test cases focus on wallet type (Taproot/WPKH) interactions +// - Complex test scenarios are defined but implementation deferred +// - Ignored tests will be updated once new APIs are available + pub mod utils; use rstest_reuse::{self, *}; @@ -37,9 +60,6 @@ fn simple_transfer(wout: bool) { // It needs to be reloaded at a special time, and consider submitting a PR to RGB wlt_2.reload_runtime(); - // pub type DirMound = Mound, DirExcavator>; - // let mound: &mut rgb::Mound, rgb::DirExcavator> = &mut wlt_1.runtime().mound; - let assign = 400; // recive asset by utxo let invoice = wlt_2.invoice(contract_id, assign, wout, Some(0)); @@ -82,10 +102,12 @@ fn simple_transfer(wout: bool) { dbg!(wlt_1 .runtime() .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) .collect::>()); dbg!(wlt_2 .runtime() .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) .collect::>()); wlt_1.check_allocations( @@ -463,15 +485,35 @@ fn transfer_loop( ); } -// TODO: The `update_witnesses` method has been removed in RGB V0.12, -// So this test case may need to be removed or redesigned -// Need to sync with Dr. Maxim +// Test case pending new rollback procedure API +// Will be updated once the high-level API for rollback handling is available #[rstest] -#[ignore = "fix needed"] +#[ignore = "Awaiting new rollback procedure API in RGB v0.12"] #[case(TransferType::Blinded)] #[case(TransferType::Witness)] fn same_transfer_twice_update_witnesses(#[case] transfer_type: TransferType) {} +// Complex test cases - Implementation deferred to final phase +// These test cases will be implemented last, after evaluating: +// 1. Available documentation and examples from RGB protocol +// 2. If no official examples exist, Bitlight will explore implementation approaches for: +// - Lightning Network test-cases integration +// - Multi-signature operations +// - Interactive transaction construction +// Reference: https://github.com/RGB-WG/rgb/blob/v0.12/doc/Payments.md + +#[test] +#[ignore = "Pending Lightning Network integration documentation"] +fn ln_transfers() { + // TODO: Implement Lightning Network transfer tests +} + +#[test] +#[ignore = "Pending multi-signature workflow documentation"] +fn collaborative_transfer() { + // TODO: Implement multi-signature transfer tests +} + #[rstest] #[case(TransferType::Blinded)] #[case(TransferType::Witness)] @@ -711,3 +753,47 @@ fn send_to_oneself() { // check allocations wlt.check_allocations(contract_id, AssetSchema::Nia, vec![amt, issue_supply - amt]); } + +#[rstest] +#[ignore = "fix needed (calling to method absent in Codex API)"] +#[case(DescriptorType::Tr, DescriptorType::Tr)] +#[ignore = "fix needed (calling to method absent in Codex API)"] +#[case(DescriptorType::Tr, DescriptorType::Wpkh)] +#[ignore = "fix needed (calling to method absent in Codex API)"] +#[case(DescriptorType::Wpkh, DescriptorType::Tr)] +#[ignore = "fix needed (calling to method absent in Codex API)"] +#[case(DescriptorType::Wpkh, DescriptorType::Wpkh)] +fn blank_tapret_opret(#[case] descriptor_type_0: DescriptorType, #[case] descriptor_type_1: DescriptorType) { + initialize(); + + let mut wlt_1 = get_wallet(&descriptor_type_0); + let mut wlt_2 = get_wallet(&descriptor_type_1); + + // Create and issue first NIA asset + let mut params_0 = NIAIssueParams::new("TestAsset1", "TEST1", "centiMilli", 200); + let outpoint = wlt_1.get_utxo(None); + params_0.add_allocation(outpoint, 200); + let contract_id_0 = wlt_1.issue_nia_with_params(params_0); + wlt_1.send_contract("TestAsset1", &mut wlt_2); + wlt_2.reload_runtime(); + + // Create and issue second NIA asset (to be moved in blank) + let mut params_1 = NIAIssueParams::new("TestAsset2", "TEST2", "centiMilli", 100); + params_1.add_allocation(outpoint, 100); + let contract_id_1 = wlt_1.issue_nia_with_params(params_1); + wlt_1.send_contract("TestAsset2", &mut wlt_2); + wlt_2.reload_runtime(); + + // First transfer: wlt_1 -> wlt_2, transfer 200 of first asset + wlt_1.send(&mut wlt_2, false, contract_id_0, 200, 1000, None, None); + + // Second transfer: wlt_1 -> wlt_2, transfer 100 of second asset + // This tests the blank transfer functionality with different descriptor types + wlt_1.send(&mut wlt_2, false, contract_id_1, 100, 1000, None, None); + + // Verify final allocations + wlt_1.check_allocations(contract_id_0, AssetSchema::Nia, vec![]); + wlt_1.check_allocations(contract_id_1, AssetSchema::Nia, vec![]); + wlt_2.check_allocations(contract_id_0, AssetSchema::Nia, vec![200]); + wlt_2.check_allocations(contract_id_1, AssetSchema::Nia, vec![100]); +} From 63e12a4fea1d8aba60c44523cf61e7d279c6acee Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 27 Feb 2025 16:58:52 +0800 Subject: [PATCH 24/90] feat(tests): adapt reorg_history test cases for RGB v0.12 Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 339 +++++++++++++++++++++++++++++++++++++++-- tests/utils/helpers.rs | 24 ++- 2 files changed, 347 insertions(+), 16 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 326a4d5..a7d330e 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -24,11 +24,18 @@ pub mod utils; use rstest_reuse::{self, *}; +use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use utils::{ - chain::{get_height, initialize, stop_mining}, - helpers::{get_wallet, AssetSchema, CFAIssueParams, NIAIssueParams, TransferType}, - DescriptorType, *, + chain::{ + connect_reorg_nodes, disconnect_reorg_nodes, get_height, get_height_custom, initialize, + mine_custom, stop_mining, + }, + helpers::{ + broadcast_tx_and_mine, get_wallet, get_wallet_custom, AssetSchema, CFAIssueParams, + HistoryType, NIAIssueParams, ReorgType, TransferType, + }, + DescriptorType, INSTANCE_2, INSTANCE_3, *, }; type TT = TransferType; @@ -62,7 +69,7 @@ fn simple_transfer(wout: bool) { let assign = 400; // recive asset by utxo - let invoice = wlt_2.invoice(contract_id, assign, wout, Some(0)); + let invoice = wlt_2.invoice(contract_id, assign, wout, Some(0), true); // send asset to wlt2 // if `wout` is true (WitnessOut), @@ -83,7 +90,7 @@ fn simple_transfer(wout: bool) { wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign]); let assign_wlt1 = 200; - let invoice = wlt_1.invoice(contract_id, assign_wlt1, wout, Some(0)); + let invoice = wlt_1.invoice(contract_id, assign_wlt1, wout, Some(0), true); dbg!( "wlt2", wlt_2.runtime().wallet.balance(), @@ -139,7 +146,7 @@ fn rbf_transfer() { wlt_1.send_contract("RBFTestAsset", &mut wlt_2); wlt_2.reload_runtime(); - let invoice = wlt_2.invoice(contract_id, 400, false, Some(0)); + let invoice = wlt_2.invoice(contract_id, 400, false, Some(0), true); // Stop mining to test RBF stop_mining(); @@ -498,7 +505,7 @@ fn same_transfer_twice_update_witnesses(#[case] transfer_type: TransferType) {} // 1. Available documentation and examples from RGB protocol // 2. If no official examples exist, Bitlight will explore implementation approaches for: // - Lightning Network test-cases integration -// - Multi-signature operations +// - Multi-signature operations // - Interactive transaction construction // Reference: https://github.com/RGB-WG/rgb/blob/v0.12/doc/Payments.md @@ -547,7 +554,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) TransferType::Blinded => false, TransferType::Witness => true, }; - let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0)); + let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), true); let _ = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); dbg!(wlt_1 @@ -621,7 +628,7 @@ fn accept_0conf() { wlt_2.reload_runtime(); let amt = 200; - let invoice = wlt_2.invoice(contract_id, amt, true, Some(0)); + let invoice = wlt_2.invoice(contract_id, amt, true, Some(0), true); let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, None, true, None); let txid = tx.txid(); @@ -662,7 +669,7 @@ fn tapret_wlt_receiving_opret() { wlt_1.send(&mut wlt_2, false, contract_id, 400, 5000, None, None); // Second transfer: wlt_2 -> wlt_1, transfer 100 - let invoice = wlt_1.invoice(contract_id, 100, true, Some(0)); + let invoice = wlt_1.invoice(contract_id, 100, true, Some(0), true); wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); // Third transfer: wlt_1 -> wlt_2, transfer 290 @@ -737,7 +744,7 @@ fn send_to_oneself() { // Transfer 200 to yourself let amt = 200; - let invoice = wlt.invoice(contract_id, amt, true, Some(0)); + let invoice = wlt.invoice(contract_id, amt, true, Some(0), true); let (consignment, tx) = wlt.transfer(invoice.clone(), None, None, true, None); wlt.mine_tx(&tx.txid(), false); wlt.accept_transfer(&consignment, None); @@ -763,7 +770,10 @@ fn send_to_oneself() { #[case(DescriptorType::Wpkh, DescriptorType::Tr)] #[ignore = "fix needed (calling to method absent in Codex API)"] #[case(DescriptorType::Wpkh, DescriptorType::Wpkh)] -fn blank_tapret_opret(#[case] descriptor_type_0: DescriptorType, #[case] descriptor_type_1: DescriptorType) { +fn blank_tapret_opret( + #[case] descriptor_type_0: DescriptorType, + #[case] descriptor_type_1: DescriptorType, +) { initialize(); let mut wlt_1 = get_wallet(&descriptor_type_0); @@ -797,3 +807,308 @@ fn blank_tapret_opret(#[case] descriptor_type_0: DescriptorType, #[case] descrip wlt_2.check_allocations(contract_id_0, AssetSchema::Nia, vec![200]); wlt_2.check_allocations(contract_id_1, AssetSchema::Nia, vec![100]); } + +#[rstest] +// Unable to accept a consignment: unknown seal definition for cell address qMWtQjXCWjJAXdrg7npyI2KZz3vXNVyZhoomqF7v8z4:0. +#[case(HistoryType::Linear, ReorgType::ChangeOrder)] +// #[ignore = "fix needed"] +#[case(HistoryType::Linear, ReorgType::Revert)] +#[case(HistoryType::Branching, ReorgType::ChangeOrder)] +// #[ignore = "fix needed"] +#[case(HistoryType::Branching, ReorgType::Revert)] +#[case(HistoryType::Merging, ReorgType::ChangeOrder)] +// #[ignore = "fix needed"] +#[case(HistoryType::Merging, ReorgType::Revert)] +#[serial] +fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgType) { + println!("history_type {history_type:?} reorg_type {reorg_type:?}"); + + initialize(); + connect_reorg_nodes(); + + let mut wlt_1 = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + let mut wlt_2 = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + + let issued_supply = 600; + + // Initialize contract based on history type + let contract_id = match history_type { + HistoryType::Linear | HistoryType::Branching => { + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issued_supply); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, issued_supply); + wlt_1.issue_nia_with_params(params) + } + HistoryType::Merging => { + // For merging, we create a contract with multiple allocations + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", 600); + params.add_allocation(wlt_1.get_utxo(None), 400); + // Adding a second allocation to the same outpoint + params.add_allocation(wlt_1.get_utxo(None), 200); + wlt_1.issue_nia_with_params(params) + } + }; + + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + // Generate UTXOs before asset transfer to avoid mining blocks during transfer, affecting the test + let _utxo_wlt_1_1 = wlt_1.get_utxo(None); + let _utxo_wlt_1_2 = wlt_1.get_utxo(None); + let _utxo_wlt_2_1 = wlt_2.get_utxo(None); + let _utxo_wlt_2_2 = wlt_2.get_utxo(None); + mine_custom(false, INSTANCE_2, 6); + + dbg!(get_height_custom(INSTANCE_2)); + dbg!(get_height_custom(INSTANCE_3)); + + disconnect_reorg_nodes(); + + // Create transactions based on history type + let txs = match history_type { + HistoryType::Linear => { + let amt_0 = 590; + // Create blinded invoice with specific UTXO + let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), false); + let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + dbg!(wlt_1 + .runtime() + .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) + .collect::>()); + + let amt_1 = 100; + let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), false); + let (_, tx_1) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); + dbg!(wlt_1 + .runtime() + .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) + .collect::>()); + + let amt_2 = 80; + let invoice = wlt_2.invoice(contract_id, amt_2, false, Some(0), false); + let (_, tx_2) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + + vec![tx_0, tx_1, tx_2] + } + HistoryType::Branching => { + let amt_0 = 600; + let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), false); + let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + + let amt_1 = 200; + let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), false); + let (_, tx_1) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); + + let amt_2 = amt_0 - amt_1 - 1; + let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), false); + let (_, tx_2) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); + + vec![tx_0, tx_1, tx_2] + } + HistoryType::Merging => { + let amt_0 = 400; + let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), false); + let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); + + let amt_1 = 200; + let invoice = wlt_2.invoice(contract_id, amt_1, false, Some(0), false); + let (_, tx_1) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); + + let amt_2 = amt_0 + amt_1 - 1; + let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), false); + let (_, tx_2) = wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); + + vec![tx_0, tx_1, tx_2] + } + }; + + dbg!(wlt_1 + .runtime() + .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) + .collect::>()); + dbg!(wlt_2 + .runtime() + .state_own(Some(contract_id)) + .map(|s| { s.1.owned }) + .collect::>()); + + // Test different reorg scenarios + match (history_type, reorg_type) { + (HistoryType::Linear, ReorgType::ChangeOrder) => { + broadcast_tx_and_mine(&txs[2], INSTANCE_3); + broadcast_tx_and_mine(&txs[1], INSTANCE_3); + broadcast_tx_and_mine(&txs[0], INSTANCE_3); + wlt_1.switch_to_instance(INSTANCE_3); + wlt_2.switch_to_instance(INSTANCE_3); + let wlt_1_alloc_1 = 10; + let wlt_1_alloc_2 = 20; + let wlt_2_alloc_1 = 490; + let wlt_2_alloc_2 = 80; + wlt_1.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_1_alloc_1, wlt_1_alloc_2], + ); + wlt_2.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_2_alloc_1, wlt_2_alloc_2], + ); + } + (HistoryType::Linear | HistoryType::Branching, ReorgType::Revert) => { + broadcast_tx_and_mine(&txs[1], INSTANCE_3); + broadcast_tx_and_mine(&txs[2], INSTANCE_3); + wlt_1.switch_to_instance(INSTANCE_3); + wlt_2.switch_to_instance(INSTANCE_3); + let wlt_1_alloc_1 = 600; + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); + } + (HistoryType::Branching, ReorgType::ChangeOrder) => { + broadcast_tx_and_mine(&txs[1], INSTANCE_3); + broadcast_tx_and_mine(&txs[2], INSTANCE_3); + broadcast_tx_and_mine(&txs[0], INSTANCE_3); + wlt_1.switch_to_instance(INSTANCE_3); + wlt_2.switch_to_instance(INSTANCE_3); + let wlt_1_alloc_1 = 200; + let wlt_1_alloc_2 = 399; + let wlt_2_alloc_1 = 1; + wlt_1.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_1_alloc_1, wlt_1_alloc_2], + ); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + } + (HistoryType::Merging, ReorgType::ChangeOrder) => { + broadcast_tx_and_mine(&txs[1], INSTANCE_3); + broadcast_tx_and_mine(&txs[0], INSTANCE_3); + broadcast_tx_and_mine(&txs[2], INSTANCE_3); + wlt_1.switch_to_instance(INSTANCE_3); + wlt_2.switch_to_instance(INSTANCE_3); + let wlt_1_alloc_1 = 599; + let wlt_2_alloc_1 = 1; + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + } + (HistoryType::Merging, ReorgType::Revert) => { + broadcast_tx_and_mine(&txs[1], INSTANCE_3); + broadcast_tx_and_mine(&txs[2], INSTANCE_3); + wlt_1.switch_to_instance(INSTANCE_3); + wlt_2.switch_to_instance(INSTANCE_3); + let wlt_1_alloc_1 = 400; + let wlt_2_alloc_1 = 200; + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + } + } + + mine_custom(false, INSTANCE_3, 3); + connect_reorg_nodes(); + wlt_1.switch_to_instance(INSTANCE_2); + wlt_2.switch_to_instance(INSTANCE_2); + + let mut wlt_3 = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + + // Verify final state based on history type + match history_type { + HistoryType::Linear => { + let wlt_1_alloc_1 = 10; + let wlt_1_alloc_2 = 20; + let wlt_1_amt = wlt_1_alloc_1 + wlt_1_alloc_2; + let wlt_2_alloc_1 = 490; + let wlt_2_alloc_2 = 80; + let wlt_2_amt = wlt_2_alloc_1 + wlt_2_alloc_2; + wlt_1.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_1_alloc_1, wlt_1_alloc_2], + ); + wlt_2.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_2_alloc_1, wlt_2_alloc_2], + ); + + // Test spending the final allocations + wlt_1.send_contract("TestAsset", &mut wlt_3); + wlt_3.reload_runtime(); + wlt_1.send(&mut wlt_3, false, contract_id, wlt_1_amt, 1000, None, None); + wlt_2.send(&mut wlt_3, false, contract_id, wlt_2_amt, 1000, None, None); + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_3.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_amt, wlt_2_amt]); + } + HistoryType::Branching => { + let wlt_1_alloc_1 = 200; + let wlt_1_alloc_2 = 399; + let wlt_1_amt = wlt_1_alloc_1 + wlt_1_alloc_2; + let wlt_2_alloc_1 = 1; + wlt_1.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_1_alloc_1, wlt_1_alloc_2], + ); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + + // Test spending the final allocations + wlt_1.send_contract("TestAsset", &mut wlt_3); + wlt_3.reload_runtime(); + wlt_1.send(&mut wlt_3, false, contract_id, wlt_1_amt, 1000, None, None); + wlt_2.send( + &mut wlt_3, + false, + contract_id, + wlt_2_alloc_1, + 1000, + None, + None, + ); + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_3.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_1_amt, wlt_2_alloc_1], + ); + } + HistoryType::Merging => { + let wlt_1_alloc_1 = 599; + let wlt_2_alloc_1 = 1; + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + + // Test spending the final allocations + wlt_1.send_contract("TestAsset", &mut wlt_3); + wlt_3.reload_runtime(); + wlt_1.send( + &mut wlt_3, + false, + contract_id, + wlt_1_alloc_1, + 1000, + None, + None, + ); + wlt_2.send( + &mut wlt_3, + false, + contract_id, + wlt_2_alloc_1, + 1000, + None, + None, + ); + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_3.check_allocations( + contract_id, + AssetSchema::Nia, + vec![wlt_1_alloc_1, wlt_2_alloc_1], + ); + } + } +} diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 6e55284..5aa67bf 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -465,7 +465,16 @@ fn broadcast_tx(tx: &Tx, indexer_url: &str) { inner.transaction_broadcast(tx).unwrap(); } AnyIndexer::Esplora(inner) => { - inner.broadcast(tx).unwrap(); + inner + .broadcast(tx) + .map_err(|e| { + dbg!( + tx.inputs.iter().map(|i| i.prev_output).collect::>(), + &e + ); + e + }) + .unwrap(); } _ => unreachable!("unsupported indexer"), } @@ -603,21 +612,28 @@ impl TestWallet { } } + // force_create_utxo: Whether to force create a new UTXO. + // Note: This will mine a block. pub fn invoice( &mut self, contract_id: ContractId, amount: u64, wout: bool, nonce: Option, + force_create_utxo: bool, ) -> RgbInvoice { let beneficiary = if wout { let wout = self.runtime.wout(nonce); RgbBeneficiary::WitnessOut(wout) } else { - // funding wallet - let _ = self.get_utxo(None); + if force_create_utxo { + // Create a new UTXO if requested. + // Required for auth token generation when wout=false. + let _ = self.get_utxo(None); + } // dbg!(self.runtime.wallet.utxos().collect::>()); // because auth_token needs a UTXO, so we need to fund `(send+mine)` the wallet first + // FIXME: Design an `auth_token` that can customize the UTXO let auth = self.runtime.auth_token(nonce).unwrap(); RgbBeneficiary::Token(auth) }; @@ -635,7 +651,7 @@ impl TestWallet { nonce: Option, report: Option<&Report>, ) -> (PathBuf, Tx) { - let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce); + let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce, true); self.send_to_invoice(recv_wallet, invoice, Some(sats), None, report) } From c3465ff075cdecd5b6365966b15f8499abec844a Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 28 Feb 2025 13:52:07 +0800 Subject: [PATCH 25/90] feat(tests): custom coinselect, auth_token & payments for reorg tests Signed-off-by: will-bitlightlabs --- Cargo.lock | 1 + Cargo.toml | 3 + tests/transfer.rs | 106 ++++++++++++++-------- tests/utils/helpers.rs | 201 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 253 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f06cb8b..83c3adf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1728,6 +1728,7 @@ dependencies = [ "bp-invoice", "bp-std", "bp-wallet", + "commit_verify", "descriptors", "file-format", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 5ba2f39..69747a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,9 @@ amplify = { path = "./rust-amplify" } strict_encoding = { path = "./strict-encoding/rust" } ## strict-types strict_types = { path = "./strict-types" } +## commit_verify +commit_verify = { path = "./client_side_validation/commit_verify" } + [patch.crates-io] # patching all RGB-related deps, to measure code coverage diff --git a/tests/transfer.rs b/tests/transfer.rs index a7d330e..c46e973 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -69,7 +69,7 @@ fn simple_transfer(wout: bool) { let assign = 400; // recive asset by utxo - let invoice = wlt_2.invoice(contract_id, assign, wout, Some(0), true); + let invoice = wlt_2.invoice(contract_id, assign, wout, Some(0), None); // send asset to wlt2 // if `wout` is true (WitnessOut), @@ -90,7 +90,7 @@ fn simple_transfer(wout: bool) { wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign]); let assign_wlt1 = 200; - let invoice = wlt_1.invoice(contract_id, assign_wlt1, wout, Some(0), true); + let invoice = wlt_1.invoice(contract_id, assign_wlt1, wout, Some(0), None); dbg!( "wlt2", wlt_2.runtime().wallet.balance(), @@ -146,7 +146,7 @@ fn rbf_transfer() { wlt_1.send_contract("RBFTestAsset", &mut wlt_2); wlt_2.reload_runtime(); - let invoice = wlt_2.invoice(contract_id, 400, false, Some(0), true); + let invoice = wlt_2.invoice(contract_id, 400, false, Some(0), None); // Stop mining to test RBF stop_mining(); @@ -554,7 +554,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) TransferType::Blinded => false, TransferType::Witness => true, }; - let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), true); + let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), None); let _ = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); dbg!(wlt_1 @@ -628,7 +628,7 @@ fn accept_0conf() { wlt_2.reload_runtime(); let amt = 200; - let invoice = wlt_2.invoice(contract_id, amt, true, Some(0), true); + let invoice = wlt_2.invoice(contract_id, amt, true, Some(0), None); let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, None, true, None); let txid = tx.txid(); @@ -669,7 +669,7 @@ fn tapret_wlt_receiving_opret() { wlt_1.send(&mut wlt_2, false, contract_id, 400, 5000, None, None); // Second transfer: wlt_2 -> wlt_1, transfer 100 - let invoice = wlt_1.invoice(contract_id, 100, true, Some(0), true); + let invoice = wlt_1.invoice(contract_id, 100, true, Some(0), None); wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); // Third transfer: wlt_1 -> wlt_2, transfer 290 @@ -744,7 +744,7 @@ fn send_to_oneself() { // Transfer 200 to yourself let amt = 200; - let invoice = wlt.invoice(contract_id, amt, true, Some(0), true); + let invoice = wlt.invoice(contract_id, amt, true, Some(0), None); let (consignment, tx) = wlt.transfer(invoice.clone(), None, None, true, None); wlt.mine_tx(&tx.txid(), false); wlt.accept_transfer(&consignment, None); @@ -810,14 +810,37 @@ fn blank_tapret_opret( #[rstest] // Unable to accept a consignment: unknown seal definition for cell address qMWtQjXCWjJAXdrg7npyI2KZz3vXNVyZhoomqF7v8z4:0. +#[ignore = "fix needed"] #[case(HistoryType::Linear, ReorgType::ChangeOrder)] +// TODO: This test case does not meet expectations, after (transferring 600 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 600 +// thread 'reorg_history::case_2' panicked at tests/utils/helpers.rs:909:17: +// assertion `left == right` failed +// left: [10, 20] +// right: [600] // #[ignore = "fix needed"] +#[ignore = "fix needed"] #[case(HistoryType::Linear, ReorgType::Revert)] +// Unable to accept a consignment: unknown seal definition for cell address c6z0I0hYqaO6dV9qOjrP1lK4PJprjVAaAOdGCoqAdOY:0. +#[ignore = "fix needed"] #[case(HistoryType::Branching, ReorgType::ChangeOrder)] // #[ignore = "fix needed"] +// TODO: This test case does not meet expectations, after (transferring 600 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 600 +// thread 'reorg_history::case_4' panicked at tests/utils/helpers.rs:909:17: +// assertion `left == right` failed +// left: [200, 399] +// right: [600] +#[ignore = "fix needed"] #[case(HistoryType::Branching, ReorgType::Revert)] +// Unable to accept a consignment: unknown seal definition for cell address FrGmm~6ro7YOlE9bEuyCLcLt9AlX2uZOZRmjHEq6yyA:0. +#[ignore = "fix needed"] #[case(HistoryType::Merging, ReorgType::ChangeOrder)] // #[ignore = "fix needed"] +// TODO: This test case does not meet expectations, after (transferring 400 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 400 +// thread 'reorg_history::case_6' panicked at tests/utils/helpers.rs:909:17: +// assertion `left == right` failed +// left: [599] +// right: [400] +#[ignore = "fix needed"] #[case(HistoryType::Merging, ReorgType::Revert)] #[serial] fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgType) { @@ -853,10 +876,10 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_2.reload_runtime(); // Generate UTXOs before asset transfer to avoid mining blocks during transfer, affecting the test - let _utxo_wlt_1_1 = wlt_1.get_utxo(None); - let _utxo_wlt_1_2 = wlt_1.get_utxo(None); - let _utxo_wlt_2_1 = wlt_2.get_utxo(None); - let _utxo_wlt_2_2 = wlt_2.get_utxo(None); + let utxo_wlt_1_1 = wlt_1.get_utxo(None); + let utxo_wlt_1_2 = wlt_1.get_utxo(None); + let utxo_wlt_2_1 = wlt_2.get_utxo(None); + let utxo_wlt_2_2 = wlt_2.get_utxo(None); mine_custom(false, INSTANCE_2, 6); dbg!(get_height_custom(INSTANCE_2)); @@ -867,73 +890,76 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp // Create transactions based on history type let txs = match history_type { HistoryType::Linear => { + // Set the coin selection strategy to true small size + // This setting is very important, it avoids selecting the output of the revert transaction as input + wlt_1.set_coinselect_strategy(helpers::CustomCoinselectStrategy::TrueSmallSize); let amt_0 = 590; // Create blinded invoice with specific UTXO - let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), false); + let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); - dbg!(wlt_1 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); + // dbg!(wlt_1 + // .runtime() + // .state_own(Some(contract_id)) + // .map(|s| { s.1.owned }) + // .collect::>()); let amt_1 = 100; - let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), false); + let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_1_1)); let (_, tx_1) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); - dbg!(wlt_1 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); + // dbg!(wlt_1 + // .runtime() + // .state_own(Some(contract_id)) + // .map(|s| { s.1.owned }) + // .collect::>()); let amt_2 = 80; - let invoice = wlt_2.invoice(contract_id, amt_2, false, Some(0), false); + let invoice = wlt_2.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_2_2)); let (_, tx_2) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); vec![tx_0, tx_1, tx_2] } HistoryType::Branching => { let amt_0 = 600; - let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), false); + let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); let amt_1 = 200; - let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), false); + let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_1_1)); let (_, tx_1) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); let amt_2 = amt_0 - amt_1 - 1; - let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), false); + let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_1_2)); let (_, tx_2) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); vec![tx_0, tx_1, tx_2] } HistoryType::Merging => { let amt_0 = 400; - let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), false); + let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); let amt_1 = 200; - let invoice = wlt_2.invoice(contract_id, amt_1, false, Some(0), false); + let invoice = wlt_2.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_2_2)); let (_, tx_1) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); let amt_2 = amt_0 + amt_1 - 1; - let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), false); + let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_1_1)); let (_, tx_2) = wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); vec![tx_0, tx_1, tx_2] } }; - dbg!(wlt_1 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); - dbg!(wlt_2 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); + // dbg!(wlt_1 + // .runtime() + // .state_own(Some(contract_id)) + // .map(|s| { s.1.owned }) + // .collect::>()); + // dbg!(wlt_2 + // .runtime() + // .state_own(Some(contract_id)) + // .map(|s| { s.1.owned }) + // .collect::>()); // Test different reorg scenarios match (history_type, reorg_type) { diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 5aa67bf..04c0e87 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -8,16 +8,19 @@ use std::time::Duration; use std::time::Instant; use bp::{seals::WTxoSeal, Outpoint}; +use commit_verify::{Digest, DigestExt, Sha256}; use psbt::TxParams; use rand::RngCore; use rgb::invoice::{RgbBeneficiary, RgbInvoice}; use rgb::popls::bp::file::{BpDirMound, DirBarrow}; +use rgb::popls::bp::{Coinselect, OpRequestSet, WalletProvider}; use rgb::{ - Assignment, CallScope, CellAddr, CodexId, Consensus, ContractId, ContractInfo, CreateParams, - EitherSeal, MethodName, NamedState, StateAtom, + Assignment, AuthToken, CallScope, CellAddr, CodexId, Consensus, ContractId, ContractInfo, + CreateParams, EitherSeal, MethodName, NamedState, RgbSealDef, StateAtom, StateCalc, }; -use rgbp::CoinselectStrategy; use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbWallet}; +use rgbp::{CoinselectStrategy, PayError}; +use rgpsbt::ScriptResolver; use strict_types::value::EnumTag; use strict_types::{TypeName, VariantName}; @@ -195,6 +198,7 @@ pub struct TestWallet { signer: Option, wallet_dir: PathBuf, instance: u8, + coinselect_strategy: CustomCoinselectStrategy, } enum WalletAccount { @@ -332,6 +336,98 @@ impl Report { } } +/// Custom RGB coinselection strategy for more precise control over UTXO selection +/// +/// # Usage Example +/// +/// ``` +/// // Create wallet +/// let mut wallet = get_wallet(&DescriptorType::Wpkh); +/// +/// // Set to true small size strategy (selects UTXOs with maximum values) +/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::TrueSmallSize); +/// +/// // Or use standard strategies +/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::Standard(CoinselectStrategy::Aggregate)); +/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::Standard(CoinselectStrategy::SmallSize)); +/// +/// // For transfers requiring specific UTXOs (like testing reorganization history), use: +/// let (consignment, tx) = wallet.transfer_with_specific_utxo(invoice, specific_utxo, sats, fee, broadcast, report); +/// ``` +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum CustomCoinselectStrategy { + /// Use standard RGB coinselection strategies + /// - Aggregate: Collects many small outputs until target amount is reached + /// - SmallSize: Collects minimum number of outputs but without proper value sorting + Standard(CoinselectStrategy), + + /// Enhanced coinselection strategy that truly minimizes transaction size + /// by selecting the minimum number of UTXOs with largest asset values. + /// This strategy: + /// 1. First sorts all available colored UTXOs by their asset amount + /// 2. Selects the minimum number of largest-value UTXOs needed to satisfy the transfer + /// 3. Results in smallest possible transaction size by using fewer inputs + TrueSmallSize, +} + +impl Default for CustomCoinselectStrategy { + fn default() -> Self { + Self::Standard(CoinselectStrategy::default()) + } +} + +/// Implementation of the Coinselect trait for our custom strategy +impl Coinselect for CustomCoinselectStrategy { + fn coinselect( + &mut self, + invoiced_state: &StrictVal, + calc: &mut (impl StateCalc + ?Sized), + // Sorted vector by values + owned_state: Vec<(CellAddr, &StrictVal)>, + ) -> Option> { + match self { + // For standard strategies, delegate to the original implementation + CustomCoinselectStrategy::Standard(strategy) => { + strategy.coinselect(invoiced_state, calc, owned_state) + } + + // True small size implementation - sort by value before selection + CustomCoinselectStrategy::TrueSmallSize => { + // Clone the state to allow sorting (we need to own the data) + let mut value_sorted_state: Vec<(CellAddr, &StrictVal, u64)> = owned_state + .iter() + .filter_map(|(addr, val)| { + // Extract numeric value (assuming we're dealing with u64 values) + let amount: u64 = val.unwrap_num().unwrap_uint(); + Some((*addr, *val, amount)) + }) + .collect(); + + // Sort by value in descending order (largest first) + value_sorted_state.sort_by(|a, b| b.2.cmp(&a.2)); + + // Now use the sorted state for iteration + let res = value_sorted_state + .into_iter() + .take_while(|(_, val, _)| { + if calc.is_satisfied(invoiced_state) { + return false; + } + calc.accumulate(val).is_ok() + }) + .map(|(addr, _, _)| addr) + .collect(); + + if !calc.is_satisfied(invoiced_state) { + return None; + }; + + Some(res) + } + } + } +} + fn _get_wallet( descriptor_type: &DescriptorType, network: Network, @@ -386,6 +482,7 @@ fn _get_wallet( signer, wallet_dir, instance, + coinselect_strategy: CustomCoinselectStrategy::default(), }; // TODO: remove if once found solution for esplora 'Too many requests' error @@ -612,35 +709,66 @@ impl TestWallet { } } - // force_create_utxo: Whether to force create a new UTXO. - // Note: This will mine a block. + /// Creates an RGB invoice with either a witness output or auth token beneficiary + /// + /// # Arguments + /// * `contract_id` - ID of the RGB contract + /// * `amount` - Amount of RGB asset to transfer + /// * `wout` - Whether to use witness output (true) or auth token (false) + /// * `nonce` - Optional nonce for seal generation + /// * `utxo` - Optional UTXO to use for auth token. If None and wout=false, a new UTXO will be created pub fn invoice( &mut self, contract_id: ContractId, amount: u64, wout: bool, nonce: Option, - force_create_utxo: bool, + mut utxo: Option, ) -> RgbInvoice { let beneficiary = if wout { let wout = self.runtime.wout(nonce); RgbBeneficiary::WitnessOut(wout) } else { - if force_create_utxo { - // Create a new UTXO if requested. - // Required for auth token generation when wout=false. - let _ = self.get_utxo(None); + if utxo.is_none() { + // Create new UTXO for auth token if none provided + utxo = Some(self.get_utxo(None)); } - // dbg!(self.runtime.wallet.utxos().collect::>()); - // because auth_token needs a UTXO, so we need to fund `(send+mine)` the wallet first - // FIXME: Design an `auth_token` that can customize the UTXO - let auth = self.runtime.auth_token(nonce).unwrap(); - RgbBeneficiary::Token(auth) + + let auth = self.create_auth_token_with_utxo(nonce, utxo.unwrap()); + + RgbBeneficiary::Token(auth.unwrap()) }; let value = StrictVal::num(amount); RgbInvoice::new(contract_id, beneficiary, Some(value)) } + /// Generates a noise engine for seal randomization + /// This is a clone of the internal noise_engine implementation from rgb-std, + /// since the original is not public and we need it for custom UTXO selection + fn noise_engine(&self) -> Sha256 { + let noise_seed = self.runtime.wallet.noise_seed(); + let mut noise_engine = Sha256::new(); + noise_engine.input_raw(noise_seed.as_ref()); + noise_engine + } + + /// Creates an auth token for a specific UTXO + /// + /// This is a custom implementation that allows specifying the UTXO to use, + /// unlike the standard rgb-std auth_token which automatically selects a UTXO. + /// We need this to support custom UTXO selection for auth tokens. + pub fn create_auth_token_with_utxo( + &mut self, + nonce: Option, + outpoint: Outpoint, + ) -> Option { + let nonce = nonce.unwrap_or_else(|| self.runtime.wallet.next_nonce()); + let seal = WTxoSeal::no_fallback(outpoint, self.noise_engine(), nonce); + let auth = seal.auth_token(); + self.runtime.wallet.register_seal(seal); + Some(auth) + } + pub fn send( &mut self, recv_wallet: &mut TestWallet, @@ -651,7 +779,7 @@ impl TestWallet { nonce: Option, report: Option<&Report>, ) -> (PathBuf, Tx) { - let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce, true); + let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce, None); self.send_to_invoice(recv_wallet, invoice, Some(sats), None, report) } @@ -670,6 +798,33 @@ impl TestWallet { (consignment, tx) } + /// Pay an invoice producing PSBT ready to be signed. + /// + /// This is a custom implementation of rgb-runtime's pay_invoice that supports + /// custom coinselection strategies. + /// + /// TODO: Keep this implementation in sync with the official rgb-runtime pay_invoice + /// method to ensure consistent behavior and avoid divergence. + pub fn pay_invoice( + &mut self, + invoice: &RgbInvoice, + strategy: impl Coinselect, + params: TxParams, + giveaway: Option, + ) -> Result<(Psbt, AuthToken), PayError> { + let request = self.runtime.fulfill(invoice, strategy, giveaway)?; + let script = OpRequestSet::with(request.clone()); + let psbt = self.runtime.transfer(script, params)?; + let terminal = match invoice.auth { + RgbBeneficiary::Token(auth) => auth, + RgbBeneficiary::WitnessOut(wout) => request + .resolve_seal(wout, psbt.script_resolver()) + .expect("witness out must be present in the PSBT") + .auth_token(), + }; + Ok((psbt, terminal)) + } + pub fn transfer( &mut self, invoice: RgbInvoice, @@ -687,11 +842,10 @@ impl TestWallet { let fee = Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS)); let sats = Sats::from_sats(sats.unwrap_or(2000)); - let strategy = CoinselectStrategy::Aggregate; + let strategy = self.coinselect_strategy; let pay_start = Instant::now(); let params = TxParams::with(fee); let (mut psbt, terminal) = self - .runtime .pay_invoice(&invoice, strategy, params, Some(sats)) .unwrap(); @@ -769,6 +923,17 @@ impl TestWallet { self.sign_finalize(psbt); psbt.extract().unwrap() } + + /// Set the coin selection strategy + pub fn set_coinselect_strategy(&mut self, strategy: CustomCoinselectStrategy) -> &mut Self { + self.coinselect_strategy = strategy; + self + } + + /// Get the current coin selection strategy + pub fn coinselect_strategy(&self) -> CustomCoinselectStrategy { + self.coinselect_strategy + } } /// Parameters for NIA (Non-Inflatable Asset) issuance From 007cdaaed30630c6a630da578091e35324b5407a Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 28 Feb 2025 16:52:38 +0800 Subject: [PATCH 26/90] feat(tests): Add test cases for genesis revert and mainnet wallet receiving Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 89 ++++++++++++++++++++++++++++++++++++++++-- tests/utils/helpers.rs | 11 ++++-- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index c46e973..38b68ac 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -26,14 +26,15 @@ pub mod utils; use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::str::FromStr; use utils::{ chain::{ connect_reorg_nodes, disconnect_reorg_nodes, get_height, get_height_custom, initialize, mine_custom, stop_mining, }, helpers::{ - broadcast_tx_and_mine, get_wallet, get_wallet_custom, AssetSchema, CFAIssueParams, - HistoryType, NIAIssueParams, ReorgType, TransferType, + broadcast_tx_and_mine, get_mainnet_wallet, get_wallet, get_wallet_custom, AssetSchema, + CFAIssueParams, HistoryType, NIAIssueParams, ReorgType, TransferType, }, DescriptorType, INSTANCE_2, INSTANCE_3, *, }; @@ -817,7 +818,6 @@ fn blank_tapret_opret( // assertion `left == right` failed // left: [10, 20] // right: [600] -// #[ignore = "fix needed"] #[ignore = "fix needed"] #[case(HistoryType::Linear, ReorgType::Revert)] // Unable to accept a consignment: unknown seal definition for cell address c6z0I0hYqaO6dV9qOjrP1lK4PJprjVAaAOdGCoqAdOY:0. @@ -1138,3 +1138,86 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp } } } + +// TODO: Awaiting new rollback procedure API in RGB v0.12 +#[rstest] +#[case(false)] +#[case(true)] +#[serial] +fn revert_genesis(#[case] with_transfers: bool) { + println!("with_transfers {with_transfers}"); + + initialize(); + // connecting before disconnecting since disconnect is not idempotent + connect_reorg_nodes(); + disconnect_reorg_nodes(); + + let mut wlt = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + + let issued_supply = 600; + let utxo = wlt.get_utxo(None); + + // Create and issue NIA asset + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issued_supply); + params.add_allocation(utxo, issued_supply); + let contract_id = wlt.issue_nia_with_params(params); + + wlt.check_allocations(contract_id, AssetSchema::Nia, vec![issued_supply]); + + if with_transfers { + let mut recv_wlt = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + let amt = 200; + wlt.send_contract("TestAsset", &mut recv_wlt); + recv_wlt.reload_runtime(); + wlt.send(&mut recv_wlt, false, contract_id, amt, 1000, None, None); + wlt.check_allocations(contract_id, AssetSchema::Nia, vec![issued_supply - amt]); + } + + // TODO: The following code uses APIs that have been removed in RGB v0.12 + // Need to implement new rollback procedure once the API is available + // + // assert!(matches!( + // wlt.get_witness_ord(&utxo.txid), + // WitnessOrd::Mined(_) + // )); + // wlt.switch_to_instance(INSTANCE_3); + // assert_eq!(wlt.get_witness_ord(&utxo.txid), WitnessOrd::Archived); + // + // wlt.check_allocations( + // contract_id, + // AssetSchema::Nia, + // vec![], + // ); +} + +#[test] +#[ignore = "fix needed"] +fn mainnet_wlt_receiving_test_asset() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + // FIXME: Because the latest `Mound` structure in rgb does not support setting the mainnet, + // The default `Mound.testnet` is eq true, which cannot correctly initialize the mainnet wallet, + // So this test case cannot be executed temporarily + let mut wlt_2 = get_mainnet_wallet(); + + // Create and issue NIA asset + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", 700); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, 700); + let contract_id = wlt_1.issue_nia_with_params(params); + + let utxo = + Outpoint::from_str("bebcfcb200a17763f6932a6d6fca9448a4b46c5b737cc3810769a7403ef79ce6:0") + .unwrap(); + let invoice = wlt_2.invoice(contract_id, 150, false, None, Some(utxo)); + + let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); + wlt_1.mine_tx(&tx.txid(), false); + match wlt_2.accept_transfer(&consignment, None) { + Err(e) => { + dbg!(e); + } + _ => panic!("validation must fail"), + } +} diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 04c0e87..b6bf58c 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -793,7 +793,7 @@ impl TestWallet { ) -> (PathBuf, Tx) { let (consignment, tx) = self.transfer(invoice, sats, fee, true, report); broadcast_tx_and_mine(&tx, self.instance); - recv_wallet.accept_transfer(&consignment, report); + recv_wallet.accept_transfer(&consignment, report).unwrap(); self.sync(); (consignment, tx) } @@ -878,14 +878,19 @@ impl TestWallet { (consignment, tx) } - pub fn accept_transfer(&mut self, consignment: &Path, report: Option<&Report>) { + pub fn accept_transfer( + &mut self, + consignment: &Path, + report: Option<&Report>, + ) -> std::io::Result<()> { self.sync(); let accept_start = Instant::now(); - self.runtime.consume_from_file(consignment).unwrap(); + self.runtime.consume_from_file(consignment)?; let accept_duration = accept_start.elapsed(); if let Some(report) = report { report.write_duration(accept_duration); } + Ok(()) } pub fn check_allocations( From 770d4d8dd46b0349cf7e32aed2c831c69aa0cd1c Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 3 Mar 2025 23:16:54 +0800 Subject: [PATCH 27/90] feat(tests): Update transfer tests for RGB v0.12 and add V12 test summary documentation Signed-off-by: will-bitlightlabs --- .../{test-summary.md => V11-test-summary.md} | 0 tests/dev-log/V12-test-summary-en.md | 118 ++ tests/dev-log/V12-test-summary.md | 115 ++ tests/dev-log/v12-first-test.log | 1351 +++++++++++++++++ tests/transfer.rs | 3 + 5 files changed, 1587 insertions(+) rename tests/dev-log/{test-summary.md => V11-test-summary.md} (100%) create mode 100644 tests/dev-log/V12-test-summary-en.md create mode 100644 tests/dev-log/V12-test-summary.md create mode 100644 tests/dev-log/v12-first-test.log diff --git a/tests/dev-log/test-summary.md b/tests/dev-log/V11-test-summary.md similarity index 100% rename from tests/dev-log/test-summary.md rename to tests/dev-log/V11-test-summary.md diff --git a/tests/dev-log/V12-test-summary-en.md b/tests/dev-log/V12-test-summary-en.md new file mode 100644 index 0000000..4b506bf --- /dev/null +++ b/tests/dev-log/V12-test-summary-en.md @@ -0,0 +1,118 @@ +# RGB v0.12 First Phase Testing Summary + +This is the first test run of RGB v0.12. While the full test suite is still under development, we have completed the design of most transfer test cases. + +## Test Execution Overview + +| Test Type | Total | Passed | Failed | Ignored | +| ---------------------------------- | ----- | ------ | ------ | ------- | +| [issuance.rs](http://issuance.rs/) | 16 | 16 | 0 | 0 | +| [transfer.rs](http://transfer.rs/) | 36 | 9 | 12 | 15 | +| Total | 52 | 25 | 12 | 15 | + +## Detailed Test Status + +### Ignored Tests + +1. blank_tapret_opret::case_1..4 - Fix needed (calling to method absent in Codex API) +2. mainnet_wlt_receiving_test_asset - Fix needed + - Error: The `Mound` structure in RGB v0.12 does not support setting the mainnet + - Context: From issue_mainnet_wlt_receiving_test_asset.md: "The default `Mound.testnet` is eq true, which cannot correctly initialize the mainnet wallet" +3. reorg_history::case_1 - Fix needed + - Error: "Unable to accept a consignment: unknown seal definition for cell address qMWtQjXCWjJAXdrg7npyI2KZz3vXNVyZhoomqF7v8z4:0." + - Context: Test simulates blockchain reorganization with Linear history and ChangeOrder type +4. reorg_history::case_2 - Fix needed + - Error: "assertion `left == right` failed, left: [10, 20], right: [600]" + - Context: Test simulates blockchain reorganization with Linear history and Revert type +5. reorg_history::case_3 - Fix needed + - Error: "Unable to accept a consignment: unknown seal definition for cell address c6z0I0hYqaO6dV9qOjrP1lK4PJprjVAaAOdGCoqAdOY:0." + - Context: Test simulates blockchain reorganization with Branching history and ChangeOrder type +6. reorg_history::case_4 - Fix needed + - Error: "assertion `left == right` failed, left: [200, 399], right: [600]" + - Context: Test simulates blockchain reorganization with Branching history and Revert type +7. reorg_history::case_5 - Fix needed + - Error: "Unable to accept a consignment: unknown seal definition for cell address FrGmm~6ro7YOlE9bEuyCLcLt9AlX2uZOZRmjHEq6yyA:0." + - Context: Test simulates blockchain reorganization with Merging history and ChangeOrder type +8. reorg_history::case_6 - Fix needed + - Error: "assertion `left == right` failed, left: [599], right: [400]" + - Context: Test simulates blockchain reorganization with Merging history and Revert type +9. same_transfer_twice_update_witnesses::case_1 - Awaiting new rollback procedure API in RGB v0.12 + - Context: Test requires the ability to update witnesses, which was removed in v0.12 and will be replaced with a new rollback procedure +10. same_transfer_twice_update_witnesses::case_2 - Awaiting new rollback procedure API in RGB v0.12 +- Context: Same issue as case_1 +1. collaborative_transfer - Pending multi-signature workflow documentation +- Context: Test requires implementation of multi-signature workflow. Current documentation is minimal and the underlying API is complex to understand. Initial implementation was unsuccessful. Plan to focus on this implementation in later phases after core functionality is stable. +1. ln_transfers - Pending Lightning Network integration documentation +- Context: Test requires implementation of multi-signature workflow. Current documentation is minimal and the underlying API is complex to understand. Initial implementation was unsuccessful. Plan to focus on this implementation in later phases after core functionality is stable. + +### Failed Tests + +1. rbf_transfer - Fulfill(StateInsufficient) + - Error: `called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` + - Context: Test attempts to replace a transaction with a higher fee (RBF) but fails because the state is insufficient to fulfill the second transfer +2. same_transfer_twice_no_update_witnesses::case_1 - Fulfill(StateInsufficient) + - Error: `called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` + - Context: Test attempts to use the same invoice twice without updating witnesses, which is not supported in v0.12 +3. same_transfer_twice_no_update_witnesses::case_2 - Fulfill(StateInsufficient) + - Error: `called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` + - Context: Same issue as case_1, related to invoice reuse +4. tapret_wlt_receiving_opret - Transaction already in block chain + - Error: "Transaction already in block chain" + - Context: Test attempts to create multiple transfers between Taproot and WPKH wallets. The test passes when run individually but fails with transaction conflicts when run as part of the full test suite, suggesting a need to restructure test isolation +5. transfer_loop::case_01 - calling to method absent in Codex API + - Error: Method missing in the new Codex API + - Context: Test attempts to transfer assets between different wallet types and asset schemas +6. transfer_loop::case_02 - calling to method absent in Codex API + - Same issue as case_01 +7. transfer_loop::case_03 - calling to method absent in Codex API + - Same issue as case_01 +8. transfer_loop::case_04 - calling to method absent in Codex API + - Same issue as case_01 +9. transfer_loop::case_05 - calling to method absent in Codex API + - Same issue as case_01 +10. transfer_loop::case_06 - calling to method absent in Codex API + - Same issue as case_01 +11. transfer_loop::case_07 - calling to method absent in Codex API + - Same issue as case_01 +12. transfer_loop::case_08 - calling to method absent in Codex API + - Same issue as case_01 + +### Passed Tests + +1. issue_cfa::case_1 - case_4 (all 4 tests) + - Context: Successfully issues Collectible Fungible Assets with various parameters +2. issue_nia::case_1 - case_4 (all 4 tests) + - Context: Successfully issues Non-Inflatable Assets with various parameters +3. issue_cfa_multiple_utxos::case_1 - case_4 (all 4 tests) + - Context: Successfully issues Collectible Fungible Assets with allocations across multiple UTXOs +4. issue_nia_multiple_utxos::case_1 - case_4 (all 4 tests) + - Context: Successfully issues Non-Inflatable Assets with allocations across multiple UTXOs +5. accept_0conf + - Context: Successfully tests accepting unconfirmed (0-conf) transactions +6. send_to_oneself + - Context: Successfully tests sending assets to the same wallet +7. check_fungible_history + - Context: Successfully tests checking the history of fungible assets +8. transfer_loop::case_09 - case_12 (4 tests) + - Context: Successfully tests a subset of transfer loop cases with specific wallet and asset combinations + +## Analysis Summary + +1. **Success Rate**: 48% (25/52) +2. **Main Issues**: + - Asset issuance tests ([issuance.rs](http://issuance.rs/)) all pass, except for UDA assets missing `.issuer`, indicating core issuance functionality has been successfully migrated to v0.12 + - Transfer-related tests ([transfer.rs](http://transfer.rs/)) have numerous issues, primarily in these areas: + - **API Instability**: Multiple transfer_loop tests and blank_tapret_opret tests fail with "calling to method absent in Codex API" errors, indicating breaking changes and instability in the API transition from v0.11 to v0.12. Some previously available methods have been removed or modified, requiring updates to test implementations + - **State Insufficient errors**: rbf_transfer and same_transfer_twice_no_update_witnesses tests fail with "Fulfill(StateInsufficient)" errors, indicating that the state management for these scenarios needs to be updated + - **Invoice reuse not supported**: Tests attempting to reuse the same invoice fail with "Fulfill(StateInsufficient)" errors, as noted in same_transfer_twice_no_update_witnesses: "In RGB V0.12, since it's not possible to use RBF with the same invoice, we cannot test for this inflation attack" + - **Blockchain reorganization handling**: The API does not yet have a stable mechanism for handling blockchain reorganization scenarios, as evidenced by the reorg_history test failures showing incorrect asset allocations after reorganization +3. **Migration Progress Assessment**: + - Asset issuance functionality migration is highly complete, including multi-UTXO allocation scenarios + - Basic transfer functionality is partially available, such as accept_0conf, send_to_oneself, and some transfer_loop tests + - Advanced transfer functionality (such as RBF, reorganization history, Lightning Network integration, etc.) has not yet been fully migrated +4. **Next Steps and Support Needed**: + - Request guidance to resolve "calling to method absent in Codex API" issues + - Fix StateInsufficient errors + - Implement contract architecture support for blockchain reorganization scenarios, with related rollback procedure API + - Add support for invoice reuse and RBF scenarios + - Provide documentation on payment scripts and internal state transition APIs to implement more complex transfer scenario tests, such as multi-signature and Lightning Network integration \ No newline at end of file diff --git a/tests/dev-log/V12-test-summary.md b/tests/dev-log/V12-test-summary.md new file mode 100644 index 0000000..6dc1e0e --- /dev/null +++ b/tests/dev-log/V12-test-summary.md @@ -0,0 +1,115 @@ +# RGB v0.12 第一阶段测试执行情况汇总 + +这是RGB v0.12的首次测试运行。虽然完整的测试套件仍在开发中,但我们已经完成了大部分转账测试用例的设计。 + +## 测试执行概览 + +| 测试类型 | 总数 | 通过 | 失败 | 忽略 | +| ----------- | ---- | ---- | ---- | ---- | +| issuance.rs | 16 | 16 | 0 | 0 | +| transfer.rs | 36 | 9 | 12 | 15 | +| 总计 | 52 | 25 | 12 | 15 | + +## 详细测试状态 + +### 已忽略的测试 (ignored) +1. blank_tapret_opret::case_1..4 - 需要修复 (调用Codex API中不存在的方法) +2. mainnet_wlt_receiving_test_asset - 需要修复 + - 错误:RGB v0.12中的`Mound`结构不支持设置主网 + - 上下文:来自issue_mainnet_wlt_receiving_test_asset.md:"默认的`Mound.testnet`等于true,无法正确初始化主网钱包" +3. reorg_history::case_1 - 需要修复 + - 错误:"Unable to accept a consignment: unknown seal definition for cell address qMWtQjXCWjJAXdrg7npyI2KZz3vXNVyZhoomqF7v8z4:0." + - 上下文:测试模拟具有线性历史和ChangeOrder类型的区块链重组 +4. reorg_history::case_2 - 需要修复 + - 错误:"assertion `left == right` failed, left: [10, 20], right: [600]" + - 上下文:测试模拟具有线性历史和Revert类型的区块链重组 +5. reorg_history::case_3 - 需要修复 + - 错误:"Unable to accept a consignment: unknown seal definition for cell address c6z0I0hYqaO6dV9qOjrP1lK4PJprjVAaAOdGCoqAdOY:0." + - 上下文:测试模拟具有分支历史和ChangeOrder类型的区块链重组 +6. reorg_history::case_4 - 需要修复 + - 错误:"assertion `left == right` failed, left: [200, 399], right: [600]" + - 上下文:测试模拟具有分支历史和Revert类型的区块链重组 +7. reorg_history::case_5 - 需要修复 + - 错误:"Unable to accept a consignment: unknown seal definition for cell address FrGmm~6ro7YOlE9bEuyCLcLt9AlX2uZOZRmjHEq6yyA:0." + - 上下文:测试模拟具有合并历史和ChangeOrder类型的区块链重组 +8. reorg_history::case_6 - 需要修复 + - 错误:"assertion `left == right` failed, left: [599], right: [400]" + - 上下文:测试模拟具有合并历史和Revert类型的区块链重组 +9. same_transfer_twice_update_witnesses::case_1 - 等待RGB v0.12中的新回滚程序API + - 上下文:测试需要更新见证的能力,该功能在v0.12中已被移除,将由新的回滚程序API替代 +10. same_transfer_twice_update_witnesses::case_2 - 等待RGB v0.12中的新回滚程序API + - 上下文:与case_1相同的问题 +11. collaborative_transfer - 等待多重签名工作流文档 + - 上下文:测试需要实现多重签名工作流。当前文档很少,底层API复杂难懂。初步实现未成功。计划在核心功能稳定后的后续阶段专注于此实现。 +12. ln_transfers - 等待闪电网络集成文档 + - 上下文:测试需要实现多重签名工作流。当前文档很少,底层API复杂难懂。初步实现未成功。计划在核心功能稳定后的后续阶段专注于此实现。 + +### 失败的测试 (failed) +1. rbf_transfer - Fulfill(StateInsufficient) + - 错误:`called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` + - 上下文:测试尝试用更高的手续费替换交易(RBF),但由于状态不足以完成第二次转账而失败 +2. same_transfer_twice_no_update_witnesses::case_1 - Fulfill(StateInsufficient) + - 错误:`called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` + - 上下文:测试尝试在不更新见证的情况下两次使用相同的发票,这在v0.12中不受支持 +3. same_transfer_twice_no_update_witnesses::case_2 - Fulfill(StateInsufficient) + - 错误:`called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` + - 上下文:与case_1相同的问题,与发票重用相关 +4. tapret_wlt_receiving_opret - Transaction already in block chain + - 错误:"Transaction already in block chain" + - 上下文:测试尝试在Taproot和WPKH钱包之间创建多次转账。该测试单独运行时通过,但作为完整测试套件的一部分运行时因交易冲突而失败,表明需要重构测试隔离 +5. transfer_loop::case_01 - calling to method absent in Codex API + - 错误:新的Codex API中缺少方法 + - 上下文:测试尝试在不同钱包类型和资产模式之间转移资产 +6. transfer_loop::case_02 - calling to method absent in Codex API + - 与case_01相同的问题 +7. transfer_loop::case_03 - calling to method absent in Codex API + - 与case_01相同的问题 +8. transfer_loop::case_04 - calling to method absent in Codex API + - 与case_01相同的问题 +9. transfer_loop::case_05 - calling to method absent in Codex API + - 与case_01相同的问题 +10. transfer_loop::case_06 - calling to method absent in Codex API + - 与case_01相同的问题 +11. transfer_loop::case_07 - calling to method absent in Codex API + - 与case_01相同的问题 +12. transfer_loop::case_08 - calling to method absent in Codex API + - 与case_01相同的问题 + +### 通过的测试 (passed) +1. issue_cfa::case_1 - case_4 (所有4个测试) + - 上下文:成功发行具有各种参数的可收集的可替代资产(CFA) +2. issue_nia::case_1 - case_4 (所有4个测试) + - 上下文:成功发行具有各种参数的不可膨胀资产(NIA) +3. issue_cfa_multiple_utxos::case_1 - case_4 (所有4个测试) + - 上下文:成功发行在多个UTXO上分配的可收集的可替代资产(CFA) +4. issue_nia_multiple_utxos::case_1 - case_4 (所有4个测试) + - 上下文:成功发行在多个UTXO上分配的不可膨胀资产(NIA) +5. accept_0conf + - 上下文:成功测试接受未确认(0-conf)交易 +6. send_to_oneself + - 上下文:成功测试向同一钱包发送资产 +7. check_fungible_history + - 上下文:成功测试检查可替代资产的历史 +8. transfer_loop::case_09 - case_12 (4个测试) + - 上下文:成功测试特定钱包和资产组合的部分转账循环情况 + +## 分析总结 + +1. **成功率**: 48% (25/52) +2. **主要问题**: + - 资产发行相关测试(issuance.rs)全部通过,除了UDA资产缺少`.issuer`,表明核心发行功能已成功迁移到v0.12 + - 转账相关测试(transfer.rs)存在较多问题,主要集中在以下几个方面: + - **API不稳定性**:多个transfer_loop测试和blank_tapret_opret测试失败,出现"calling to method absent in Codex API"错误,表明从v0.11到v0.12的API转换过程中存在破坏性变更和不稳定性。一些以前可用的方法已被移除或修改,需要更新测试实现 + - **状态不足错误**:rbf_transfer和same_transfer_twice_no_update_witnesses测试失败,出现"Fulfill(StateInsufficient)"错误,表明这些场景的状态管理需要更新 + - **发票不支持重用**:尝试重用相同发票的测试失败,出现"Fulfill(StateInsufficient)"错误,正如same_transfer_twice_no_update_witnesses中所述:"在RGB V0.12中,由于不可能使用RBF和相同的发票,我们无法测试这种通胀攻击" + - **区块链重组处理**:API尚未有稳定的机制来处理区块链重组场景,这从reorg_history测试失败中可以看出,重组后资产分配不正确 +3. **迁移进展评估**: + - 资产发行功能迁移完成度高,包括多UTXO分配的情况 + - 基本转账功能部分可用,如accept_0conf、send_to_oneself和部分transfer_loop测试 + - 高级转账功能(如RBF、重组历史、闪电网络集成等)尚未完成迁移 +4. **下一步期望优先获取的支持**: + - 请求指导解决"calling to method absent in Codex API"问题 + - 修复StateInsufficient错误 + - 实现合约架构支持区块链重组场景,有相关的rollback procedure API + - 添加对发票重用和RBF场景的支持 + - 提供关于支付脚本和内部状态转换API的文档,以实现更复杂的转账场景测试,如多签名和闪电网络集成 diff --git a/tests/dev-log/v12-first-test.log b/tests/dev-log/v12-first-test.log new file mode 100644 index 0000000..a5e2f31 --- /dev/null +++ b/tests/dev-log/v12-first-test.log @@ -0,0 +1,1351 @@ +warning: `rgb-tests` (test "transfer") generated 20 warnings (10 duplicates) (run `cargo fix --test "transfer"` to apply 1 suggestion) + Finished `test` profile [unoptimized + debuginfo] target(s) in 8.50s + Running tests/issuance.rs (target/debug/deps/issuance-14bf51e9d8ee949c) + +running 16 tests +wallet_desc Tr +wallet_desc Wpkh +wallet_desc Wpkh +wallet_desc Tr +wallet_desc Wpkh +wallet_desc Tr +wallet_desc Wpkh +wallet_desc Tr +starting test services... +wallet dir: "test-data/integration/c3b8a9ca" +wallet dir: "test-data/integration/6ecd7b84" +wallet dir: "test-data/integration/b81c5451" +wallet dir: "test-data/integration/47e4d839" +wallet dir: "test-data/integration/723288fe" +wallet dir: "test-data/integration/62c37ee1" +wallet dir: "test-data/integration/53483baa" +wallet dir: "test-data/integration/1212899d" +A new contract issued with ID contract:4Z0OzxrC-GdteSzh-2cgWzc6-PawIvI~-WyCnX2m-HxtV_Vg +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_cfa::case_2 ... ok +wallet_desc Wpkh +wallet dir: "test-data/integration/b45df1e5" +A new contract issued with ID contract:qr23Xxof-Fzsy8rd-oZ8Y4wc-BaaZvuJ-MBKh2qR-D~H4bek +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_cfa::case_1 ... ok +wallet_desc Wpkh +wallet dir: "test-data/integration/691426a9" +A new contract issued with ID contract:NQO8p0vd-JWYcCy5-Og6TXi9-yTxcvlg-AGAIY_9-gSLHulQ +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_cfa::case_4 ... ok +wallet_desc Tr +wallet dir: "test-data/integration/f8d53132" +A new contract issued with ID contract:mJIFRnZ4-y_zit8M-GY9u3UF-fdaHct0-MUy3USS-4yLvo6I +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_cfa::case_3 ... ok +wallet_desc Tr +wallet dir: "test-data/integration/529b7132" +A new contract issued with ID contract:Eb13C_xq-U29y1Wc-iJ6PcoQ-V~xRU74-QG7Y1J8-VxZID4E +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +[tests/issuance.rs:59:5] &state.owned.allocations = [ + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), + vout: Vout( + 0, + ), + }, + 500000, + ), + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), + vout: Vout( + 0, + ), + }, + 500000, + ), +] +test issue_nia::case_1 ... ok +wallet_desc Wpkh +wallet dir: "test-data/integration/c9f37b64" +A new contract issued with ID contract:mRg2N_aF-uB4SMSd-JLURSmP-ypYXXO4-MC6fhFP-zNGVekU +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +[tests/issuance.rs:59:5] &state.owned.allocations = [ + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), + vout: Vout( + 0, + ), + }, + 500000, + ), + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), + vout: Vout( + 0, + ), + }, + 500000, + ), +] +test issue_nia::case_3 ... ok +wallet_desc Wpkh +wallet dir: "test-data/integration/c1d39754" +A new contract issued with ID contract:c0~DmmtE-LAJzcKW-ikEEJ9Z-KtiuqJB-G5WhYQA-D7MTnHs +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +[tests/issuance.rs:59:5] &state.owned.allocations = [ + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), + vout: Vout( + 0, + ), + }, + 500000, + ), + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), + vout: Vout( + 0, + ), + }, + 500000, + ), +] +test issue_nia::case_2 ... ok +wallet_desc Tr +A new contract issued with ID contract:RfIDBjvW-pEIT6Rs-z3HNzrA-uRCR5H5-mdXI9j~-JJDj35c +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +[tests/issuance.rs:59:5] &state.owned.allocations = [ + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), + vout: Vout( + 0, + ), + }, + 500000, + ), + ( + Outpoint { + txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), + vout: Vout( + 0, + ), + }, + 500000, + ), +] +wallet dir: "test-data/integration/0bf90c30" +test issue_nia::case_4 ... ok +wallet_desc Tr +wallet dir: "test-data/integration/dbaa1f04" +test issue_cfa_multiple_utxos::case_1 has been running for over 60 seconds +test issue_cfa_multiple_utxos::case_2 has been running for over 60 seconds +test issue_cfa_multiple_utxos::case_3 has been running for over 60 seconds +test issue_cfa_multiple_utxos::case_4 has been running for over 60 seconds +A new contract issued with ID contract:oQQeEZW6-o83mtD2-J3nwy76-NClY1Op-W5SrptL-KQMB8X8 +A new contract issued with ID contract:f4n~qKMC-dnXWzGZ-3rRru~n-KjK6qTR-nThsVYG-mukpbpQ +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_nia_multiple_utxos::case_2 ... ok +test issue_cfa_multiple_utxos::case_2 ... ok +A new contract issued with ID contract:GWpU7ND9-VbzVX~X-z_rTnOM-TYqkkxc-mhMBJrN-78ZD~SY +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_cfa_multiple_utxos::case_1 ... ok +A new contract issued with ID contract:xYls1diR-IWh9m4j-Mq1dEzy-QkWC6Hd-Doe7sAC-eNKbAjE +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +A new contract issued with ID contract:wspuABJy-BskUelq-xS3XwoN-jOWn5cS-FJuSJRx-pBnXKkY +test issue_cfa_multiple_utxos::case_3 ... ok +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_nia_multiple_utxos::case_1 ... ok +A new contract issued with ID contract:7slgDA4u-bAqvKaZ-ld9_FW2-mnDFN29-kYZeJgO-NRzNP1g +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +A new contract issued with ID contract:Vu5~832o-FwECgUE-hIcNMVE-92~cD70-q78inlB-3seFHiA +A new contract issued with ID contract:j7abCp5p-KhezRWv-4BHKjY_-Pl7eJOE-urCnnbo-p~0q9Tg +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +[tests/utils/helpers.rs:1071:25] &v.verified = Enum( + Name( + VariantName( + "centiMilli", + ), + ), +) +test issue_cfa_multiple_utxos::case_4 ... ok +test issue_nia_multiple_utxos::case_3 ... ok +test issue_nia_multiple_utxos::case_4 ... ok + +test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 66.98s + + Running tests/transfer.rs (target/debug/deps/transfer-356099b53e0807f1) + +running 36 tests +test blank_tapret_opret::case_1 ... ignored, fix needed (calling to method absent in Codex API) +test blank_tapret_opret::case_2 ... ignored, fix needed (calling to method absent in Codex API) +test blank_tapret_opret::case_3 ... ignored, fix needed (calling to method absent in Codex API) +test blank_tapret_opret::case_4 ... ignored, fix needed (calling to method absent in Codex API) +test collaborative_transfer ... ignored, Pending multi-signature workflow documentation +test ln_transfers ... ignored, Pending Lightning Network integration documentation +test mainnet_wlt_receiving_test_asset ... ignored, fix needed +test reorg_history::case_1 ... ignored, fix needed +test reorg_history::case_2 ... ignored, fix needed +test reorg_history::case_3 ... ignored, fix needed +test reorg_history::case_4 ... ignored, fix needed +test reorg_history::case_5 ... ignored, fix needed +test reorg_history::case_6 ... ignored, fix needed +test same_transfer_twice_update_witnesses::case_1 ... ignored, Awaiting new rollback procedure API in RGB v0.12 +test same_transfer_twice_update_witnesses::case_2 ... ignored, Awaiting new rollback procedure API in RGB v0.12 +transfer_type Witness +transfer_type Blinded +starting test services... +with_transfers true +wallet dir: "test-data/integration/fb687462" +wallet dir: "test-data/integration/127c91cb" +wallet dir: "test-data/integration/5d243af8" +wallet dir: "test-data/integration/22d5a33a" +wallet dir: "test-data/integration/ec235ef7" +wallet dir: "test-data/integration/1ca4a0c1" +wallet dir: "test-data/integration/a3fbeb5d" +wallet dir: "test-data/integration/55865b11" +wallet dir: "test-data/integration/b50e95cf" +disconnect_reorg_nodes:instance:3 peers: [ +] +disconnect_reorg_nodes:instance:2 peers: [ +] +wallet dir: "test-data/integration/aed25b32" +A new contract issued with ID contract:CIwYp0Lo-_mpu~QN-mNueQ_q-I7AiYrb-s5Hdoio-MOsD7y4 +A new contract issued with ID contract:QeVEgypp-gGErzYy-HDV_QJR-dDaDiWP-X55jlVQ-mTmcIZc +A new contract issued with ID contract:NZoT~Amj-FlZI5cN-Gz4VGN0-50KTStz-MDPveMQ-ZlnJ3YE +A new contract issued with ID contract:M99chdch-1K1OQk9-je1Djzq-nHhsWWD-_XWJDbH-VJ9B4VA +A new contract issued with ID contract:6TRYS4R9-jnAG~VQ-7HiGsOs-IGMhFv7-St85Aeu-wupaeGs +A new contract issued with ID contract:6HojmiMu-JKcmdLE-l40gTKu-9CtCLAI-70109qe-qEUQwgc +wallet dir: "test-data/integration/c1953eff" +transfer txid: d8e2ac957b52392b30513823177c2f6482645aaf561c74eecb323193f3686420, consignment: 1 +transfer txid: 32b495841f92ad53d986caec36492c133b0b8a06c14339ba2ea7d41919fc772b, consignment: 2 +[tests/transfer.rs:562:5] wlt_1.runtime().state_all(None).map(|(c, s)| { s.owned }).collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(498de1142e27d9e96b315ad16709d22d26afd019e5689e86b3f0a4d18d034775), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(32b495841f92ad53d986caec36492c133b0b8a06c14339ba2ea7d41919fc772b), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 100, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(498de1142e27d9e96b315ad16709d22d26afd019e5689e86b3f0a4d18d034775), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(32b495841f92ad53d986caec36492c133b0b8a06c14339ba2ea7d41919fc772b), + vout: Vout( + 2, + ), + }, + data: Number( + Uint( + 1900, + ), + ), + }, + }, + }, +] +[tests/transfer.rs:567:5] wlt_1.runtime().state_own(None).map(|(c, s)| { s.owned }).collect::>() = [ + { + VariantName( + "owned", + ): {}, + }, +] +transfer txid: 764d2f4ddcca87f69e66b975487a370e1bd56ebf645279ad914a051589e5287b, consignment: 3 +thread 'same_transfer_twice_no_update_witnesses::case_2' panicked at tests/utils/helpers.rs:850:14: +called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +test same_transfer_twice_no_update_witnesses::case_2 ... FAILED +[tests/transfer.rs:648:5] wlt_1_contract_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(d5621ee862de91c173fba1b92fd0f34b130f8a124a08ca8fdf89e049dc3cfe5c), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(d8e2ac957b52392b30513823177c2f6482645aaf561c74eecb323193f3686420), + vout: Vout( + 2, + ), + }, + data: Number( + Uint( + 400, + ), + ), + }, + }, + }, +] +test accept_0conf has been running for over 60 seconds +test check_fungible_history has been running for over 60 seconds +test rbf_transfer has been running for over 60 seconds +test revert_genesis::case_1 has been running for over 60 seconds +transfer txid: 52d1826463b537e0dfdaf113d2f5ed48504c65cf5fe3f52cc55df25a36d1e915, consignment: 5 +test revert_genesis::case_2 has been running for over 60 seconds +test same_transfer_twice_no_update_witnesses::case_1 has been running for over 60 seconds +test send_to_oneself has been running for over 60 seconds +transfer txid: a7c1a5f3aae77ea6aefec7798a9fe59cfcd48dbd1f70631450b0e7a4f86f0c22, consignment: 6 +[tests/transfer.rs:562:5] wlt_1.runtime().state_all(None).map(|(c, s)| { s.owned }).collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(b3ccb0ba6327395dcb978c87a58177b6f182032a71f9a82c93dccb2e828dd45a), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(a7c1a5f3aae77ea6aefec7798a9fe59cfcd48dbd1f70631450b0e7a4f86f0c22), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 1900, + ), + ), + }, + }, + }, +] +[tests/transfer.rs:567:5] wlt_1.runtime().state_own(None).map(|(c, s)| { s.owned }).collect::>() = [ + { + VariantName( + "owned", + ): {}, + }, +] +test accept_0conf ... ok +transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Nia +wallet dir: "test-data/integration/fce20f94" +thread 'same_transfer_twice_no_update_witnesses::case_1' panicked at tests/utils/helpers.rs:850:14: +called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) +test same_transfer_twice_no_update_witnesses::case_1 ... FAILED +transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Nia +wallet dir: "test-data/integration/5a2d6f5c" +transfer txid: c86e077a61446cb8ad7ea1bd524894bc5f4ae2564fa96a6ad1ccf05789c72b5c, consignment: 7 +wallet dir: "test-data/integration/3a9eebd4" +wallet dir: "test-data/integration/0b827ff4" +[tests/transfer.rs:758:5] wlt.runtime().state_own(None).map(|s| s.1.owned).collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(105402272fd310f1664efa7c7617afd893c029e375c27d38fd35f012f1e8a367), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(764d2f4ddcca87f69e66b975487a370e1bd56ebf645279ad914a051589e5287b), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 200, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(105402272fd310f1664efa7c7617afd893c029e375c27d38fd35f012f1e8a367), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(764d2f4ddcca87f69e66b975487a370e1bd56ebf645279ad914a051589e5287b), + vout: Vout( + 2, + ), + }, + data: Number( + Uint( + 400, + ), + ), + }, + }, + }, +] +test send_to_oneself ... ok +transfer_type Blinded wlt_1_desc Tr wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Nia +wallet dir: "test-data/integration/4fe26820" +wallet dir: "test-data/integration/f645aea1" +thread 'rbf_transfer' panicked at tests/utils/helpers.rs:850:14: +called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) +test rbf_transfer ... FAILED +transfer_type Blinded wlt_1_desc Tr wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Nia +wallet dir: "test-data/integration/d065e778" +wallet dir: "test-data/integration/7dbf82b2" +test tapret_wlt_receiving_opret has been running for over 60 seconds +test transfer_loop::case_01 has been running for over 60 seconds +test transfer_loop::case_02 has been running for over 60 seconds +test transfer_loop::case_03 has been running for over 60 seconds +test transfer_loop::case_04 has been running for over 60 seconds +forcibly breaking mining wait +forcibly breaking mining wait +A new contract issued with ID contract:JXRNCAC0-vqFi9C1-YvEq5AT-7xIfPjl-cIPmR3O-zvgooro +A new contract issued with ID contract:1M2HqAF2-eWcMDR6-S5xA5TE-azdsrDf-UIhKu~z-l1~m_x0 +A new contract issued with ID contract:YEHU4iOj-ywIiHVW-An7KqAo-SjrSgXN-Y0N75C7-nsuQ0sM +A new contract issued with ID contract:pLQI5l16-VfpM_1d-1_3gcl3-Xjql042-qO1UXAY-jscJDo0 +A new contract issued with ID contract:F1mG3CDQ-HjKYFiB-15f0Pl9-82DZE0I-tdreTRU-ADw_JTk +A new contract issued with ID contract:9Kxul6xe-S9WQe_X-MXrdh1C-wgshmVK-172kAXm-LQqJicI +test revert_genesis::case_2 ... ok +transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Cfa +wallet dir: "test-data/integration/29648f8e" +wallet dir: "test-data/integration/3707dcd5" +wallet dir: "test-data/integration/95ffcfe6" +wallet dir: "test-data/integration/06e00797" +A new contract issued with ID contract:x~61iNNI-KLMsSHY-pa3WW01-~hHnn4Z-jcFPEoN-vJKoYG4 +A new contract issued with ID contract:_opB7KYm-9lnqvCB-aO~hbix-p8aFQFJ-jKdTp~U-OUpTOe4 +A new contract issued with ID contract:AuPtCKRe-rCcSxFR-99p3c3Y-sDhSzAM-63uVLv6-0aZbKt0 +[tests/transfer.rs:708:5] wlt_1.contracts_info() = [ + ContractInfo { + id: ContractId( + Array<32>(c7feb588d34828b32c4876296b7596d35fe11e79f86637053c4a0dbc92a8606e), + ), + name: Named( + TypeName( + "TestAsset", + ), + ), + issuer: Identity( + RString( + "ssi:anonymous", + ), + ), + timestamp: 2024-12-18T12:32:00Z, + codex: CodexInfo { + id: CodexId( + Array<32>(ce7c10195856adf45af1e96935a02c516516c57b01fb85250bf4df4c4461066e), + ), + name: Confined( + "NonInflatableAsset", + ), + developer: Identity( + RString( + "dns:pandoraprime.ch", + ), + ), + timestamp: 2024-11-25T10:08:27Z, + }, + consensus: Bitcoin, + testnet: true, + }, +] +[tests/transfer.rs:709:5] wlt_1.runtime().state_own(Some(contract_id)).map(|s| +{ s.1.owned }).collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(a66abae6e7ed55ddd77e5f42a22105c31d0179af5d93d591315e94872b8a0bbc), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(73895d87802e07c6207496d4cf0c577bcc115727bae6e94b9d569e29099f1ffb), + vout: Vout( + 0, + ), + }, + data: Number( + Uint( + 600, + ), + ), + }, + }, + }, +] +A new contract issued with ID contract:RbyDBkD3-PQMeXRs-HomsVSf-PprU097-YEprjWy-1p~0UY8 +A new contract issued with ID contract:Iq5HSxB4-uKEKYXi-cpWwtDv-R2IE12P-tmR5nZq-09MB4DY +thread 'transfer_loop::case_02' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +thread 'transfer_loop::case_04' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +test transfer_loop::case_02 ... FAILED +transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Cfa +wallet dir: "test-data/integration/84dffb5f" +test transfer_loop::case_04 ... FAILED +transfer_type Blinded wlt_1_desc Tr wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Cfa +wallet dir: "test-data/integration/ad31517a" +thread 'transfer_loop::case_03' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +test transfer_loop::case_03 ... FAILED +transfer_type Blinded wlt_1_desc Tr wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Cfa +wallet dir: "test-data/integration/01b7ced5" +transfer txid: 81beabcfc3e2814c93613956a11ef74a8302adfd2650036f8bca07b63963975f, consignment: 13 +wallet dir: "test-data/integration/ebb6c6cc" +wallet dir: "test-data/integration/9a9000b0" +wallet dir: "test-data/integration/fcc6104d" +A new contract issued with ID contract:6oY3HBBW-WoLM0BC-qfNmS5m-Hiiv0Xh-~EgbGMN-o6auh9Y +A new contract issued with ID contract:TABg8Zsd-BkgEjpT-Aaf~tVB-4n8dsUB-AzyT9IE-0ok4DlI +A new contract issued with ID contract:SZEB7SUU-d90Lj6_-TgJvZza-3Ud4Rgt-SPZmZp5-8gTma5A +A new contract issued with ID contract:Rg0F_IyI-u8S8n1r-qb2f_37-J0OWn2_-t05jqaj-ZIOZgfw +thread 'transfer_loop::case_01' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +test transfer_loop::case_01 ... FAILED +transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Wpkh asset_schema_1 Cfa asset_schema_2 Cfa +wallet dir: "test-data/integration/2ae8ebbf" +A new contract issued with ID contract:dJx9RCNL-ApW16Sn-pV~3DPx-FZfHKZ6-RijjyRD-F9WbxYE +A new contract issued with ID contract:KVKT_rDM-im70d9o-QTAC7SD-RfL8yqA-A0ap3K8-YcpGiHQ +transfer txid: 94a03dd0f8142ff1624e6cf05811576efd4b8bc77e929f9bbab5cbf227eebdc9, consignment: 15 +[tests/transfer.rs:721:5] wlt_1.runtime().state_own(Some(contract_id)).map(|s| +{ s.1.owned }).collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(b7d555b88f6932c0de780ab2af37df2c40007869d45b2e2040a722c1fecef225), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(81beabcfc3e2814c93613956a11ef74a8302adfd2650036f8bca07b63963975f), + vout: Vout( + 2, + ), + }, + data: Number( + Uint( + 400, + ), + ), + }, + }, + }, +] +[tests/transfer.rs:726:5] wlt_2.runtime().state_own(Some(contract_id)).map(|s| +{ s.1.owned }).collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(b7d555b88f6932c0de780ab2af37df2c40007869d45b2e2040a722c1fecef225), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(81beabcfc3e2814c93613956a11ef74a8302adfd2650036f8bca07b63963975f), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 200, + ), + ), + }, + }, + }, +] +with_transfers false +test check_fungible_history ... ok +transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Tr asset_schema_1 Cfa asset_schema_2 Cfa +wallet dir: "test-data/integration/1dff19fa" +wallet dir: "test-data/integration/6b3f7e48" +wallet dir: "test-data/integration/fd23c744" +disconnect_reorg_nodes:instance:3 peers: [ +] +disconnect_reorg_nodes:instance:2 peers: [ +] +wallet dir: "test-data/integration/03f95445" +A new contract issued with ID contract:4AUpeDyY-_WDY00i-KYzTYYd-bN4Ywl8-w3yFJj3-wc9uY~8 +test revert_genesis::case_1 ... ok +transfer_type Blinded wlt_1_desc Tr wlt_2_desc Wpkh asset_schema_1 Cfa asset_schema_2 Cfa +wallet dir: "test-data/integration/165cb223" +wallet dir: "test-data/integration/0a5c7dc0" +A new contract issued with ID contract:jPR6QljT-QHBn1fd-iGfnrxp-aSjJBM7-EdzkQPg-_ynQlEM +A new contract issued with ID contract:eMkXEEbK-~p0jzZ9-j~STIAl-uIh7XB7-hk2OtiY-3oPTTtQ +wallet dir: "test-data/integration/18daf55a" +wallet dir: "test-data/integration/178e0889" +A new contract issued with ID contract:Rigqlc5i-P~7Gxau-w75O8UY-IdMxJFO-_ooE9~K-9a648iI +A new contract issued with ID contract:jy~Ej6SI-Q2B23Rm-1g7kahT-V~36Qr_-ax6JMe2-AFLZRuY +transfer txid: 8788bb5ef3ef432e81d85caf9f26b5a30dfeca26b2a10c73a45584a2f319b7e5, consignment: 16 +transfer txid: 38115c5307ccc89e84bda26eb05d2c44a6e6c4272555b4ffd13caabad021842c, consignment: 17 +transfer txid: 38e29d25cb31466c4a7cb5261f37123dfb7838af00921cebf7c6ef92a2a3d867, consignment: 18 +A new contract issued with ID contract:LzMGZEx8-EfgYgQx-ZRyEKEy-noUbpLB-9PHWVPC-B_5r4Kg +A new contract issued with ID contract:KMbA50Sa-g2uTaq4-zKxhqzM-nZD_W2f-KU1V_ky-qmz4h0o +A new contract issued with ID contract:F2z~~fIF-OjQoxeJ-BbSbkKl-7I~dYCv-DOTVBEG-YsG6hjU +transfer txid: 1b54e31ddac3a18ca1953cffc4b6156328a09fef832683a243b114b8957dfefd, consignment: 19 +transfer txid: 0d429b07175bf13edc847bcdb50a2a8a6c9e4abe45f9aaddaba9caf5f8dc82be, consignment: 21 +transfer txid: 61962ff0ce375de435b331b24dbd52d440dab500eaf894e2ce710ecad2b50d9b, consignment: 20 +transfer txid: b0bdd0b16177fefc98039bb0445345eff13985b24c711d46b19471639376e611, consignment: 23 +transfer txid: 807f574197702f9a8df1e1530af6b74518db84269a8774ae7525e03150bd72e9, consignment: 24 +transfer txid: 49805441d2df33bc1467e2beee398381991b0c3782d95a17d313fcb0675c5bc6, consignment: 22 +transfer txid: f6a6d3422f72d24fd87988660a69b278568b4860bf37d183dddf7f3f419cd03b, consignment: 26 +transfer txid: 8589750221b23e4ffed8b84d4abedf7484c41fca173100b66280171f26232b7f, consignment: 25 +thread 'transfer_loop::case_05' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +test transfer_loop::case_05 ... FAILED +transfer_type Blinded wlt_1_desc Tr wlt_2_desc Tr asset_schema_1 Cfa asset_schema_2 Cfa +wallet dir: "test-data/integration/af24bda7" +transfer txid: acdbaa67b547b21c8ca936e36a1f41291a19e6c2a99d0a273b541942a6906fff, consignment: 28 +transfer txid: b87398da716a41f2970adc61121b70c27cabb7e8d40500d9995bc2f9d00deda5, consignment: 29 +wallet dir: "test-data/integration/20b56ed4" +transfer txid: b85afc69021a4fcf8cb8052f9cd008972658864b8cb90cda50f6a604b9d8c47f, consignment: 30 +[tests/utils/helpers.rs:568:21] tx.inputs.iter().map(|i| i.prev_output).collect::>() = [ + Outpoint { + txid: Array<32>(595832f4127ca4b26e7d9f6bb90e393b20a2a0b34ac48ce7aa0f77be24cc6cb8), + vout: Vout( + 0, + ), + }, +] +[tests/utils/helpers.rs:568:21] &e = HttpResponse { + status: 400, + message: "sendrawtransaction RPC error: {\"code\":-27,\"message\":\"Transaction already in block chain\"}", +} +thread 'tapret_wlt_receiving_opret' panicked at tests/utils/helpers.rs:574:18: +called `Result::unwrap()` on an `Err` value: HttpResponse { status: 400, message: "sendrawtransaction RPC error: {\"code\":-27,\"message\":\"Transaction already in block chain\"}" } +test tapret_wlt_receiving_opret ... FAILED +A new contract issued with ID contract:6X8H4Hte-j9wAx6o-WZWA9S4-S0pk9ar-lisk3vV-wOLxzag +A new contract issued with ID contract:vg3TWTC9-SqtTlB5-lKHQrNQ-pbj25Wg-8p3ZUyr-_SEQ9Fc +thread 'transfer_loop::case_06' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +test transfer_loop::case_06 ... FAILED +thread 'transfer_loop::case_07' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +test transfer_loop::case_07 ... FAILED +transfer txid: a2ad7050d23b566f8d1d0ecfc5f4fd15b61f6c0b46f83a34c694a7b451e2f6fa, consignment: 33 +thread 'transfer_loop::case_08' panicked at sonic/api/src/schema.rs:84:14: +calling to method absent in Codex API +test transfer_loop::case_08 ... FAILED +transfer txid: bee77f26ac6b44af531f12bdf31f13e6386b396b36b1a6bf5e4890f0af2254fc, consignment: 35 +transfer txid: 907e7d07e1aa0d6129aa0b5dbcf9528a7149ab94681e6010ab1859ae7a3beebd, consignment: 36 +transfer txid: 900288520864289efbd0d8a604af9cc4d25182e1ebb5064b58a7e1e5b8575abb, consignment: 37 +transfer txid: 86448b4d1c93b875a009c70a3ed793ecdf0a077c7810eaca513ea127df3357f7, consignment: 38 +transfer txid: c84794743ace45d932f8d6ee5e063e27797892ef17100d7e7e24619dec5360df, consignment: 41 +transfer txid: 606f0fc715b2c7a0e27e4ae5399121e563c88a7b99b4a91c1cdd749bb1e6ddff, consignment: 39 +transfer txid: 5f638aafdf2e4261a811622d271b0a5dfa10e94d86224b7acc8c195e26ed90e2, consignment: 40 +transfer txid: b53398068e54ea4d74acb0afa4b0d6dbded2d5ae51927274d7f93985f53e9625, consignment: 42 +transfer txid: c005f7fba2f8d3694f1f573840972b1336093d8d752857be30b1756bb4c74963, consignment: 43 +transfer txid: b93a5edfcdf91d332e877a8f0e26c9297eb04b2c365aa39621ff38e5ce78df05, consignment: 45 +transfer txid: 0a583e16e58b1d3b98ccf22f57b43ea230c72e048790bc852b6f6bff72745e02, consignment: 44 +transfer txid: 6370419e089e94afdb960198a5c590ef4af67b42af628897dcb62cae1e184e5b, consignment: 46 +[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(5b31306bed3f28e13590d1081d9bcbd4684ce6be2bcbe4e9869da2dfcf8da582), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(c1252ce1747030aa12c4d789023f4381429cea6a5bebb1190b55a4e70de81ecd), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 111, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(d9bbd6856212642394341486fa4b17ed67b3edeb5b60ff1278fbe86c0b4dff9b), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(bee77f26ac6b44af531f12bdf31f13e6386b396b36b1a6bf5e4890f0af2254fc), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 867, + ), + ), + }, + }, + }, + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(5c5e1396753ab6d64031ad79554259d9ba4dea8bb27ce599bcb75c7e99cf929d), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(ee6ffdc6f1bb1fc04b7c72b51182eb34a56aca8a61a25ba5bff7a3c1d1ff710c), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(a26a48962e0ea4f47463f5b45c7e4649d7de68f517c80bbd6f2f4cf5e68b9660), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(bee77f26ac6b44af531f12bdf31f13e6386b396b36b1a6bf5e4890f0af2254fc), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + }, + }, +] +[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(a064ae6cf4d98415cec7be52c3ffd3e4e9cf174377b09a79d4c6c05c98a4972a), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(900288520864289efbd0d8a604af9cc4d25182e1ebb5064b58a7e1e5b8575abb), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(a8db0cbcbd960aef723a9afb0588ba18fa853d80c5ae13e96fc0cfc332cd3b64), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(c8107905d86a1f9f68466bce46233bfcfcda49b29ab03169f74b8b774627bb44), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + }, + }, + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(6aae48b92b6a0a018699d80bc149f3fea124e808bd9d8268e048900243c34de4), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(900288520864289efbd0d8a604af9cc4d25182e1ebb5064b58a7e1e5b8575abb), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 867, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(70bdcadb4c3ce99592737353bc4f62b9a717ed05e25f5801d6643306c6d31718), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(840608def10c6747bec77e6cc614a4e68e16081efd798a3aabad9aad4d8a926b), + vout: Vout( + 0, + ), + }, + data: Number( + Uint( + 111, + ), + ), + }, + }, + }, +] +test transfer_loop::case_09 has been running for over 60 seconds +test transfer_loop::case_10 has been running for over 60 seconds +transfer txid: bb5d25f95d0ce13db29a6892e99bc02f18833f1821a4f5197e998639990e6713, consignment: 49 +transfer txid: 2855d899c87314a74877d5f68a571c8d72425b02118c9dcd78b0299168e90125, consignment: 48 +transfer txid: c3bf69e92182d1e3e93e0ab105810682e0514205e3163cdc7b19f93307421527, consignment: 47 +[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(6863afc3d8e25308042d56aae7ce08e86d4c9b9f851251a072f40e89e5f0f38c), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(d82f1d8807da8288e2060a123f6d178e08b97722f798a781755436581b163bf5), + vout: Vout( + 0, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(c6159f6a7f58ee05c6d6be7ba8a71bfb94078085b7e41b10fc83b3f832735ebf), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(86448b4d1c93b875a009c70a3ed793ecdf0a077c7810eaca513ea127df3357f7), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + }, + }, + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(e06e555d565898c31fff2febd753b1c7fefa2e58be2a4a284d36ab1aa87607fa), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(9f9c2b9ffe2b335897d676b13b3c0d6252df05ac9f26a5ff8b0b10c3fe20157a), + vout: Vout( + 0, + ), + }, + data: Number( + Uint( + 111, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(e3cb747c2f553eb017d0d64bc236e5391a2a8643eaebf8e1a8f0b922717b86d0), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(86448b4d1c93b875a009c70a3ed793ecdf0a077c7810eaca513ea127df3357f7), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 867, + ), + ), + }, + }, + }, +] +test transfer_loop::case_11 has been running for over 60 seconds +transfer txid: e076018c18a723574583af1ebcae93e03d76ef6ecea7e60ff97bbb9b8047a373, consignment: 50 +[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(63622a49d1f8a779ba2b4e740bbabc375731a278404ea641e656a8b18961f395), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(2855d899c87314a74877d5f68a571c8d72425b02118c9dcd78b0299168e90125), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(a8db0cbcbd960aef723a9afb0588ba18fa853d80c5ae13e96fc0cfc332cd3b64), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(c8107905d86a1f9f68466bce46233bfcfcda49b29ab03169f74b8b774627bb44), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + }, + }, + { + VariantName( + "owned", + ): {}, + }, +] +thread 'transfer_loop::case_10' panicked at tests/utils/helpers.rs:914:17: +assertion `left == right` failed + left: [11, 644] + right: [655] +[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): {}, + }, + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(5c5e1396753ab6d64031ad79554259d9ba4dea8bb27ce599bcb75c7e99cf929d), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(ee6ffdc6f1bb1fc04b7c72b51182eb34a56aca8a61a25ba5bff7a3c1d1ff710c), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(a1d102045c3fb4f3822d62b0f994b9637c388ac9f7fad4d0eb021dce96d230bb), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(c3bf69e92182d1e3e93e0ab105810682e0514205e3163cdc7b19f93307421527), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + }, + }, +] +thread 'transfer_loop::case_09' panicked at tests/utils/helpers.rs:914:17: +assertion `left == right` failed + left: [11, 644] + right: [655] +[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(60d126dafdfca72926d32187509a0ae03b7cabcf8dd7116a6f0427ca40aa3e1e), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(e076018c18a723574583af1ebcae93e03d76ef6ecea7e60ff97bbb9b8047a373), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(6863afc3d8e25308042d56aae7ce08e86d4c9b9f851251a072f40e89e5f0f38c), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(d82f1d8807da8288e2060a123f6d178e08b97722f798a781755436581b163bf5), + vout: Vout( + 0, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + }, + }, + { + VariantName( + "owned", + ): {}, + }, +] +thread 'transfer_loop::case_11' panicked at tests/utils/helpers.rs:914:17: +assertion `left == right` failed + left: [11, 644] + right: [655] +transfer txid: 14176fd58d2d56a9f66414e314666d59cc7c08c3b036bd408eb7cb321148ae89, consignment: 52 +transfer txid: da5369f1bfdf9c9068caeabe5b0325a5d2a24c523a1eaf700db7bdb5f1f99dd6, consignment: 51 +transfer txid: f4641d46f284e542aedb69c3515b1876c5ff4c94b71a19dc13f465521381a066, consignment: 53 +transfer txid: 697e2dcec845e593e0c3ffdfa65ba59cd6829c36995bf8470fcf9e2927f8ce64, consignment: 54 +[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(207ec47bb8f85d23cc630027f2355884a35f4e8645d52a9f2a2bdf282d44867c), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(c4512d6e4e0db3e7eb5f4b3204a74583e0e1eee5f7dc43dc7efe29f475cbd403), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(37072c6093b3e3026b87eeece3f23d0531a55702e790e04865b8cdb8b056ea2e), + ), + pos: 1, + }: Assignment { + seal: Outpoint { + txid: Array<32>(0a583e16e58b1d3b98ccf22f57b43ea230c72e048790bc852b6f6bff72745e02), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + }, + }, + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(674273677b864e0f92ec399012e4bc1bf6f112a5649aef8e3870544431224e24), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(0a583e16e58b1d3b98ccf22f57b43ea230c72e048790bc852b6f6bff72745e02), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 867, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(fa32075db4b159ea4467ec1e20538715254566555c2e15fefca71f274757fc6c), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(5d0c848b907391acde837244305935a826f000df53a46829825c9b96f02d43c4), + vout: Vout( + 0, + ), + }, + data: Number( + Uint( + 111, + ), + ), + }, + }, + }, +] +test transfer_loop::case_10 ... ok +test transfer_loop::case_09 ... ok +test transfer_loop::case_12 has been running for over 60 seconds +transfer txid: 44332505f8aad577eae3f83d1c12bf5b39186f4d6b186c8f660b3c3e4a7da665, consignment: 55 +test transfer_loop::case_11 ... ok +[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ + { + VariantName( + "owned", + ): { + CellAddr { + opid: Opid( + Array<32>(207ec47bb8f85d23cc630027f2355884a35f4e8645d52a9f2a2bdf282d44867c), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(c4512d6e4e0db3e7eb5f4b3204a74583e0e1eee5f7dc43dc7efe29f475cbd403), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 11, + ), + ), + }, + CellAddr { + opid: Opid( + Array<32>(c89fd96b42db7d11ba35f8c4ef84c518fe0f1cec10ef559f24d4330782fe9b72), + ), + pos: 0, + }: Assignment { + seal: Outpoint { + txid: Array<32>(44332505f8aad577eae3f83d1c12bf5b39186f4d6b186c8f660b3c3e4a7da665), + vout: Vout( + 1, + ), + }, + data: Number( + Uint( + 644, + ), + ), + }, + }, + }, + { + VariantName( + "owned", + ): {}, + }, +] +thread 'transfer_loop::case_12' panicked at tests/utils/helpers.rs:914:17: +assertion `left == right` failed + left: [11, 644] + right: [655] +transfer txid: 6881a0b4b1723a71af7748e767c77823b7e5e15f538d7cfca0c3368b0ea72aef, consignment: 56 +test transfer_loop::case_12 ... ok + +failures: + +failures: + rbf_transfer + same_transfer_twice_no_update_witnesses::case_1 + same_transfer_twice_no_update_witnesses::case_2 + tapret_wlt_receiving_opret + transfer_loop::case_01 + transfer_loop::case_02 + transfer_loop::case_03 + transfer_loop::case_04 + transfer_loop::case_05 + transfer_loop::case_06 + transfer_loop::case_07 + transfer_loop::case_08 + +test result: FAILED. 9 passed; 12 failed; 15 ignored; 0 measured; 0 filtered out; finished in 290.95s + +error: test failed, to rerun pass `--test transfer` diff --git a/tests/transfer.rs b/tests/transfer.rs index 38b68ac..0bf7d13 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -498,6 +498,7 @@ fn transfer_loop( #[rstest] #[ignore = "Awaiting new rollback procedure API in RGB v0.12"] #[case(TransferType::Blinded)] +#[ignore = "Awaiting new rollback procedure API in RGB v0.12"] #[case(TransferType::Witness)] fn same_transfer_twice_update_witnesses(#[case] transfer_type: TransferType) {} @@ -653,6 +654,7 @@ fn accept_0conf() { } #[test] +#[serial] fn tapret_wlt_receiving_opret() { initialize(); @@ -687,6 +689,7 @@ fn tapret_wlt_receiving_opret() { } #[test] +#[serial] fn check_fungible_history() { initialize(); From a59a798d545cbc9b5b8e7ce1c801e4c04c8ace86 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 4 Mar 2025 00:37:26 +0800 Subject: [PATCH 28/90] feat(tests): Add invoice reuse and update tests for RGB v0.12 API changes Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 169 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index 0bf7d13..bab87df 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -23,10 +23,12 @@ pub mod utils; +use bp::Tx; use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; +use utils::helpers::CustomCoinselectStrategy; use utils::{ chain::{ connect_reorg_nodes, disconnect_reorg_nodes, get_height, get_height_custom, initialize, @@ -1224,3 +1226,170 @@ fn mainnet_wlt_receiving_test_asset() { _ => panic!("validation must fail"), } } + +#[rstest] +#[case(TT::Blinded)] +#[case(TT::Witness)] +#[serial] +fn invoice_reuse(#[case] transfer_type: TransferType) { + println!("transfer_type {transfer_type:?}"); + + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + wlt_1.set_coinselect_strategy(CustomCoinselectStrategy::TrueSmallSize); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + // Create and issue assets + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", 900); + params.add_allocation(wlt_1.get_utxo(None), 500); + params.add_allocation(wlt_1.get_utxo(None), 400); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + let amount = 300; + // Create invoice + let invoice = wlt_2.invoice(contract_id, amount, false, None, None); + + // First use invoice + wlt_1.send_to_invoice(&mut wlt_2, invoice.clone(), Some(500), None, None); + + // Second use same invoice + let (_, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(600), None, None); + + // FIXME: There is a question here, + // should the two transfers of the same invoice be processed as one transfer by RBF, + // or should they correspond to two transfers? + + // Check asset allocations + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![100, 200]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amount, amount]); + + // FIXME: The following code needs to be redesigned in RGB v0.12 + // Note: In RGB v0.12, the type of consignment has been changed to PathBuf, no longer directly containing the bundles field + // This test needs to be redesigned in RGB v0.12 + + // The original test assertion: assert_eq!(consignment.bundles.len(), 1); +} + +#[test] +#[ignore = "fix needed"] // https://github.com/BP-WG/bp-wallet/issues/70 +#[serial] +fn sync_mainnet_wlt() { + initialize(); + + // FIXME: Because the latest `Mound` structure in rgb does not support setting the mainnet, + // The default `Mound.testnet` is eq true, which cannot correctly initialize the mainnet wallet, + // So this test case cannot be executed temporarily + let mut wlt_1 = get_mainnet_wallet(); + + wlt_1.sync(); +} + +#[test] +#[ignore = "Needs to be updated to accommodate API changes to RGB v0.12"] +#[serial] +fn receive_from_unbroadcasted_transfer_to_blinded() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_3 = get_wallet(&DescriptorType::Wpkh); + + // Create and issue assets + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", 600); + let utxo = wlt_1.get_utxo(None); + params.add_allocation(utxo, 600); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + wlt_1.send_contract("TestAsset", &mut wlt_3); + wlt_3.reload_runtime(); + + // Get UTXO and create invoice + let utxo = wlt_2.get_utxo(None); + broadcast_tx_and_mine(&Tx::from_str(&utxo.txid.to_string()).unwrap(), 0); + + // In RGB v0.12, the invoice API has been changed + let invoice = wlt_2.invoice(contract_id, 100, false, None, Some(utxo)); + + // Create transfer but do not broadcast its TX + let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + let txid = tx.txid(); + + // Note: The following code needs to be redesigned in RGB v0.12 + // The original test used a custom OffchainResolver to handle unbroadcasted transactions + // In RGB v0.12, the validation and parsing mechanisms may have changed + + // TODO: Implement a custom resolver for RGB v0.12 + // The original code: + /* + struct OffchainResolver<'a, 'cons, const TRANSFER: bool> { + witness_id: XWitnessId, + consignment: &'cons IndexedConsignment<'cons, TRANSFER>, + fallback: &'a AnyResolver, + } + impl ResolveWitness for OffchainResolver<'_, '_, TRANSFER> { + fn resolve_pub_witness( + &self, + witness_id: XWitnessId, + ) -> Result { + self.consignment + .pub_witness(witness_id) + .and_then(|p| p.map_ref(|pw| pw.tx().cloned()).transpose()) + .ok_or(WitnessResolverError::Unknown(witness_id)) + .or_else(|_| self.fallback.resolve_pub_witness(witness_id)) + } + fn resolve_pub_witness_ord( + &self, + witness_id: XWitnessId, + ) -> Result { + if witness_id != self.witness_id { + return self.fallback.resolve_pub_witness_ord(witness_id); + } + Ok(WitnessOrd::Tentative) + } + } + + let resolver = OffchainResolver { + witness_id: XChain::Bitcoin(txid), + consignment: &IndexedConsignment::new(&consignment), + fallback: &wlt_2.get_resolver(), + }; + */ + + // In RGB v0.12, the API for accepting transfers may have changed + // The original code: + // wlt_2.accept_transfer_custom_resolver(consignment.clone(), None, &resolver); + + // Due to API changes, this test is temporarily ignored + println!("The test needs to be updated to adapt to the API changes in RGB v0.12"); + println!("Transaction ID: {}", txid); + + // The following steps are from the original test, need to be adjusted according to the API changes in RGB v0.12 + /* + let invoice = wlt_3.invoice( + contract_id, + &iface_type_name, + 50, + wlt_2.close_method(), + InvoiceType::Witness, + ); + let (consignment, tx) = wlt_2.transfer(invoice, Some(2000), None, true, None); + wlt_2.mine_tx(&tx.txid(), false); + + // consignment validation fails because it notices an unbroadcasted TX in the history + let res = consignment.validate(&wlt_3.get_resolver(), wlt_3.testnet()); + assert!(res.is_err()); + let validation_status = match res { + Ok(validated_consignment) => validated_consignment.validation_status().clone(), + Err((status, _consignment)) => status, + }; + assert_eq!(validation_status.failures.len(), 1); + assert!(matches!( + validation_status.failures[0], + Failure::SealNoPubWitness(_, _, _) + )); + */ +} From a0d7350d6b4dfdb5b93ed141293fa275bd2d3db8 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 5 Mar 2025 01:24:48 +0800 Subject: [PATCH 29/90] feat(tests): Added stress tests and enhanced reporting capabilities to support RGB v0.12 migration Signed-off-by: will-bitlightlabs --- tests/stress.rs | 175 +++++++++++++++ tests/utils/helpers.rs | 480 ++++++++++++++++++++++++++++++++++++++--- tests/utils/mod.rs | 2 +- 3 files changed, 629 insertions(+), 28 deletions(-) create mode 100644 tests/stress.rs diff --git a/tests/stress.rs b/tests/stress.rs new file mode 100644 index 0000000..8804521 --- /dev/null +++ b/tests/stress.rs @@ -0,0 +1,175 @@ +// RGB v0.12 Migration Notes: +// 1. Seal Type Unification (RFC: https://github.com/RGB-WG/RFC/issues/16) +// - Unified seal type replaces distinct opret and tapret seals +// - Seal type is automatically determined by wallet type (Taproot/WPKH) +// - CloseMethod parameter has been removed from contract genesis +// - Contract no longer commits to specific seal types +// +// 2. API Changes and Migration Strategy: +// - Removed APIs: +// * update_witnesses: Will be replaced with new rollback procedure +// * CloseMethod related parameters: No longer needed due to seal unification +// - Test Case Handling: +// * Existing tests dependent on removed APIs: Marked as #[ignore] with tracking issues +// * New tests: Focus on wallet type interactions rather than seal types +// * Complex test cases will be implemented after evaluating: +// - RGB protocol documentation and examples +// - Implementation approaches for Lightning Network, multi-sig and interactive transactions + +#![allow(unused_imports)] + +use rstest::rstest; +use serial_test::serial; +use std::env::VarError; +use std::io::Write; +use std::path::PathBuf; +use std::str::FromStr; +use std::time::Instant; +use time::OffsetDateTime; +use utils::{ + chain::initialize, + helpers::{get_wallet, MetricDefinition, MetricType, Report, TransferType}, + DescriptorType, DEFAULT_FEE_ABS, STRESS_DATA_DIR, TEST_DATA_DIR, +}; + +pub mod utils; + +// Aliases for shorter test case definitions +type TT = TransferType; +type DT = DescriptorType; + +#[rstest] +#[case(false, DT::Wpkh, DT::Wpkh)] +#[case(false, DT::Wpkh, DT::Tr)] +#[case(false, DT::Tr, DT::Wpkh)] +#[case(false, DT::Tr, DT::Tr)] +#[case(true, DT::Wpkh, DT::Wpkh)] +#[case(true, DT::Wpkh, DT::Tr)] +#[case(true, DT::Tr, DT::Wpkh)] +#[case(true, DT::Tr, DT::Tr)] +#[serial] +fn back_and_forth( + #[case] wout: bool, + #[case] wlt_1_desc: DescriptorType, + #[case] wlt_2_desc: DescriptorType, +) { + println!("wout {wout:?} wlt_1_desc {wlt_1_desc:?} wlt_2_desc {wlt_2_desc:?}"); + + initialize(); + + let stress_tests_dir = PathBuf::from(TEST_DATA_DIR).join(STRESS_DATA_DIR); + std::fs::create_dir_all(&stress_tests_dir).unwrap(); + let fname = OffsetDateTime::now_utc().unix_timestamp().to_string(); + let mut fpath = stress_tests_dir.join(fname); + fpath.set_extension("csv"); + println!("report path: {}", fpath.to_string_lossy()); + + // Create Report instance with metrics + let metrics = vec![ + MetricDefinition { + name: "wlt_1_pay".to_string(), + metric_type: MetricType::Duration, + description: "Time taken for wallet 1 to pay".to_string(), + }, + MetricDefinition { + name: "wlt_2_accept".to_string(), + metric_type: MetricType::Duration, + description: "Time taken for wallet 2 to accept".to_string(), + }, + MetricDefinition { + name: "wlt_2_pay".to_string(), + metric_type: MetricType::Duration, + description: "Time taken for wallet 2 to pay".to_string(), + }, + MetricDefinition { + name: "wlt_1_accept".to_string(), + metric_type: MetricType::Duration, + description: "Time taken for wallet 1 to accept".to_string(), + }, + MetricDefinition { + name: "send_1_amount".to_string(), + metric_type: MetricType::Integer, + description: "Amount sent from wallet 1".to_string(), + }, + MetricDefinition { + name: "send_2_amount".to_string(), + metric_type: MetricType::Integer, + description: "Amount sent from wallet 2".to_string(), + }, + ]; + + let mut report = Report::new(fpath, metrics, Some(10)).unwrap(); + + let mut wlt_1 = get_wallet(&wlt_1_desc).with_id("wlt_1"); + let mut wlt_2 = get_wallet(&wlt_2_desc).with_id("wlt_2"); + + let issued_supply = u64::MAX; + + // In RGB v0.12, the close_method parameter is no longer required + // Create and issue assets + let mut params = + utils::helpers::NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issued_supply); + let utxo = wlt_1.get_utxo(None); + params.add_allocation(utxo, issued_supply); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + let loops = match std::env::var("LOOPS") { + Ok(val) if u16::from_str(&val).is_ok() => u16::from_str(&val).unwrap(), + Err(VarError::NotPresent) => 50, + _ => { + panic!("invalid loops value: must be a u16 number") + } + }; + + let sats_base = 3600; + let mut sats_send = sats_base * loops as u64; + let now = Instant::now(); + for i in 1..=loops { + println!("loop {i}/{loops}"); + sats_send -= DEFAULT_FEE_ABS * 2; + + // In RGB v0.12, the send method parameters have been changed + wlt_1.send( + &mut wlt_2, + wout, + contract_id, + issued_supply - i as u64, + sats_send, + None, + Some(&mut report), + ); + + // Record the amount sent from wallet 1 + report.add_integer("send_1_amount", sats_send).unwrap(); + + sats_send -= DEFAULT_FEE_ABS * 2; + + wlt_2.send( + &mut wlt_1, + wout, + contract_id, + issued_supply - i as u64 - 1, + sats_send, + None, + Some(&mut report), + ); + + // Record the amount sent from wallet 2 + report.add_integer("send_2_amount", sats_send).unwrap(); + + // End the row for this iteration + report.end_row().unwrap(); + } + let elapsed = now.elapsed(); + println!("Total time: {:.2?}", elapsed); + println!("Average time per transfer: {:.2?}", elapsed / loops as u32); + + // Generate and save test summary + match report.generate_summary() { + // Ok(summary) => println!("Test summary saved to: {}", report.report_path.display()), + Ok(summary) => println!("{}", summary), + Err(e) => println!("Failed to save test summary: {}", e), + } +} diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index b6bf58c..e24cea2 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::fs::{File, OpenOptions}; +use std::io::Write; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::OnceLock; @@ -199,6 +200,8 @@ pub struct TestWallet { wallet_dir: PathBuf, instance: u8, coinselect_strategy: CustomCoinselectStrategy, + /// Optional wallet identifier for reporting purposes + wallet_id: Option, } enum WalletAccount { @@ -302,37 +305,436 @@ impl fmt::Display for AssetSchema { } } +/// Test metric type +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum MetricType { + /// Duration (milliseconds) + Duration, + /// Integer value + Integer, + /// Float value + Float, + /// Text value + Text, +} + +/// Test metric definition +#[derive(Debug, Clone)] +pub struct MetricDefinition { + /// Metric name + pub name: String, + /// Metric type + pub metric_type: MetricType, + /// Metric description + pub description: String, +} + +/// Test report structure pub struct Report { + /// Report file path pub report_path: PathBuf, + /// Metric definitions + metrics: Vec, + /// File handle + file: Option, + /// Buffer for rows + buffer: Vec, + /// Current row being built + current_row: HashMap, + /// Buffer flush threshold + flush_threshold: usize, } +/// Report error types +#[derive(Debug)] +pub enum ReportError { + /// IO error + Io(std::io::Error), + /// Format error + Format(String), + /// Metric error + Metric(String), +} + +impl From for ReportError { + fn from(err: std::io::Error) -> Self { + ReportError::Io(err) + } +} + +impl std::fmt::Display for ReportError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ReportError::Io(err) => write!(f, "IO error: {}", err), + ReportError::Format(msg) => write!(f, "Format error: {}", msg), + ReportError::Metric(msg) => write!(f, "Metric error: {}", msg), + } + } +} + +impl std::error::Error for ReportError {} + impl Report { - pub fn write_header(&self, fields: &[&str]) { - let mut file = std::fs::File::options() - .read(true) + /// Create new report instance + pub fn new( + path: PathBuf, + metrics: Vec, + flush_threshold: Option, + ) -> Result { + let mut report = Self { + report_path: path, + metrics, + file: None, + buffer: Vec::new(), + current_row: HashMap::new(), + flush_threshold: flush_threshold.unwrap_or(10), + }; + + // Initialize report file + report.initialize()?; + + Ok(report) + } + + /// Initialize report file + fn initialize(&mut self) -> Result<(), ReportError> { + let headers: Vec = self.metrics.iter().map(|m| m.name.clone()).collect(); + + let file = OpenOptions::new() .write(true) - .create_new(true) - .open(&self.report_path) - .unwrap(); - file.write_all(format!("{}\n", fields.join(";")).as_bytes()) - .unwrap(); + .create(true) + .truncate(true) + .open(&self.report_path)?; + + let mut file = file; + file.write_all(format!("{}\n", headers.join(";")).as_bytes())?; + + // Save file handle for subsequent use + self.file = Some(file); + + Ok(()) } - pub fn write_duration(&self, duration: Duration) { - let mut file = OpenOptions::new() - .append(true) - .open(&self.report_path) - .unwrap(); - file.write_all(format!("{};", duration.as_millis()).as_bytes()) - .unwrap(); + /// Get file handle + fn get_file(&mut self) -> Result<&mut File, ReportError> { + if self.file.is_none() { + let file = OpenOptions::new() + .write(true) + .append(true) + .open(&self.report_path)?; + + self.file = Some(file); + } + + Ok(self.file.as_mut().unwrap()) + } + + /// Add duration metric by name + pub fn add_duration(&mut self, name: &str, duration: Duration) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Duration)?; + self.current_row + .insert(name.to_string(), duration.as_millis().to_string()); + Ok(()) + } + + /// Add integer metric by name + pub fn add_integer(&mut self, name: &str, value: u64) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Integer)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Add float metric by name + pub fn add_float(&mut self, name: &str, value: f64) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Float)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Add text metric by name + pub fn add_text(&mut self, name: &str, value: &str) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Text)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Add arbitrary type metric by name (auto conversion) + pub fn add_value(&mut self, name: &str, value: T) -> Result<(), ReportError> { + if !self.metrics.iter().any(|m| m.name == name) { + return Err(ReportError::Metric(format!( + "Metric name '{}' not found", + name + ))); + } + + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Helper method to check if metric name exists and has correct type + fn check_metric_name_and_type( + &self, + name: &str, + expected_type: MetricType, + ) -> Result<(), ReportError> { + let metric = self.metrics.iter().find(|m| m.name == name); + + match metric { + Some(m) if m.metric_type == expected_type => Ok(()), + Some(m) => Err(ReportError::Metric(format!( + "Metric '{}' type mismatch, expected {:?}, actual {:?}", + name, expected_type, m.metric_type + ))), + None => Err(ReportError::Metric(format!( + "Metric name '{}' not found", + name + ))), + } + } + + /// Complete current row and add to buffer + pub fn end_row(&mut self) -> Result<(), ReportError> { + // Ensure all metrics have values + for metric in &self.metrics { + if !self.current_row.contains_key(&metric.name) { + self.current_row.insert(metric.name.clone(), String::new()); + } + } + + // Create row in the same order as metrics + let row = self + .metrics + .iter() + .map(|m| self.current_row.get(&m.name).cloned().unwrap_or_default()) + .collect::>() + .join(";"); + + self.buffer.push(row); + + // Clear current row for next use + self.current_row.clear(); + + // If buffer reaches threshold, flush to file + if self.buffer.len() >= self.flush_threshold { + self.flush_buffer()?; + } + + Ok(()) + } + + /// Write buffer content to file + pub fn flush_buffer(&mut self) -> Result<(), ReportError> { + if self.buffer.is_empty() { + return Ok(()); + } + + // Clone buffer contents to avoid borrow conflict + let buffer_contents = self.buffer.clone(); + let file = self.get_file()?; + + for row in buffer_contents.iter() { + file.write_all(format!("{}\n", row).as_bytes())?; + } + + self.buffer.clear(); + + Ok(()) } + /// Generate summary statistics + pub fn generate_summary(&mut self) -> Result { + // Ensure all data is written to file + self.flush_buffer()?; + + // Read CSV file + let content = std::fs::read_to_string(&self.report_path)?; + let lines: Vec<&str> = content.lines().collect(); + + if lines.is_empty() { + return Err(ReportError::Format("CSV file is empty".to_string())); + } + + // Parse headers + let headers: Vec<&str> = lines[0].split(';').collect(); + + // Prepare data structure + let mut data: Vec> = vec![Vec::new(); headers.len()]; + + // Parse data rows + for line in lines.iter().skip(1) { + let values: Vec<&str> = line.split(';').collect(); + for (i, value) in values.iter().enumerate() { + if i >= headers.len() { + break; + } + + if let Ok(num) = value.parse::() { + data[i].push(num); + } + } + } + + // Generate summary + let mut summary = String::new(); + summary.push_str("# Performance Test Summary\n\n"); + summary.push_str("| Metric | Average | Minimum | Maximum | Sample Count |\n"); + summary.push_str("|------|--------|--------|--------|--------|\n"); + + for (i, header) in headers.iter().enumerate() { + if data[i].is_empty() { + continue; + } + + let values = &data[i]; + let avg = values.iter().sum::() / values.len() as f64; + let min = values.iter().fold(f64::INFINITY, |a, &b| a.min(b)); + let max = values.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b)); + + // Format output based on metric type + let metric_type = if i < self.metrics.len() { + self.metrics[i].metric_type + } else { + MetricType::Float + }; + + match metric_type { + MetricType::Duration => { + summary.push_str(&format!( + "| {} | {:.2} ms | {:.2} ms | {:.2} ms | {} |\n", + header, + avg, + min, + max, + values.len() + )); + } + MetricType::Integer | MetricType::Float => { + summary.push_str(&format!( + "| {} | {:.2} | {:.2} | {:.2} | {} |\n", + header, + avg, + min, + max, + values.len() + )); + } + MetricType::Text => { + summary.push_str(&format!("| {} | - | - | - | {} |\n", header, values.len())); + } + } + } + + Ok(summary) + } + + /// Save summary statistics to file + pub fn save_summary(&mut self) -> Result { + let summary = self.generate_summary()?; + + let mut summary_path = self.report_path.clone(); + summary_path.set_extension("md"); + + let mut file = std::fs::File::create(&summary_path)?; + file.write_all(summary.as_bytes())?; + + Ok(summary_path) + } + + /// Generate chart data + pub fn generate_chart_data(&mut self) -> Result { + // Ensure all data is written to file + self.flush_buffer()?; + + // Read CSV file + let content = std::fs::read_to_string(&self.report_path)?; + let lines: Vec<&str> = content.lines().collect(); + + if lines.is_empty() { + return Err(ReportError::Format("CSV file is empty".to_string())); + } + + // Parse headers + let headers: Vec<&str> = lines[0].split(';').collect(); + + // Prepare data structure + let mut data: Vec> = vec![Vec::new(); headers.len()]; + + // Parse data rows + for line in lines.iter().skip(1) { + let values: Vec<&str> = line.split(';').collect(); + for (i, value) in values.iter().enumerate() { + if i >= headers.len() { + break; + } + + if let Ok(num) = value.parse::() { + data[i].push(num); + } + } + } + + // Generate JSON + let mut json = String::from("{\n"); + + for (i, header) in headers.iter().enumerate() { + if i > 0 { + json.push_str(",\n"); + } + + json.push_str(&format!(" \"{}\": [", header)); + + for (j, value) in data[i].iter().enumerate() { + if j > 0 { + json.push_str(", "); + } + json.push_str(&format!("{}", value)); + } + + json.push_str("]"); + } + + json.push_str("\n}"); + + // Save JSON + let mut chart_path = self.report_path.clone(); + chart_path.set_extension("json"); + + let mut file = std::fs::File::create(&chart_path)?; + file.write_all(json.as_bytes())?; + + Ok(chart_path) + } + + /// Ensure all data is written on drop + pub fn finalize(&mut self) -> Result<(), ReportError> { + self.flush_buffer() + } + + /// For backward compatibility + pub fn write_header(&self, _fields: &[&str]) { + // Do nothing, headers are now defined by metrics + } + + /// For backward compatibility + pub fn write_duration(&self, _duration: Duration) { + // Do nothing, use add_duration instead + } + + /// For backward compatibility + pub fn write_value(&self, _value: T) { + // Do nothing, use add_value instead + } + + /// For backward compatibility pub fn end_line(&self) { - let mut file = OpenOptions::new() - .append(true) - .open(&self.report_path) - .unwrap(); - file.write_all("\n".as_bytes()).unwrap(); + // Do nothing, use end_row instead + } +} + +impl Drop for Report { + fn drop(&mut self) { + // Try to flush buffer, ignore errors + let _ = self.flush_buffer(); } } @@ -483,6 +885,7 @@ fn _get_wallet( wallet_dir, instance, coinselect_strategy: CustomCoinselectStrategy::default(), + wallet_id: None, }; // TODO: remove if once found solution for esplora 'Too many requests' error @@ -777,7 +1180,7 @@ impl TestWallet { amount: u64, sats: u64, nonce: Option, - report: Option<&Report>, + report: Option<&mut Report>, ) -> (PathBuf, Tx) { let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce, None); self.send_to_invoice(recv_wallet, invoice, Some(sats), None, report) @@ -789,10 +1192,18 @@ impl TestWallet { invoice: RgbInvoice, sats: Option, fee: Option, - report: Option<&Report>, + mut report: Option<&mut Report>, ) -> (PathBuf, Tx) { - let (consignment, tx) = self.transfer(invoice, sats, fee, true, report); + // We need to handle the report parameter carefully to avoid moving it + let transfer_report = match &mut report { + Some(r) => Some(&mut **r), + None => None, + }; + + let (consignment, tx) = self.transfer(invoice, sats, fee, true, transfer_report); broadcast_tx_and_mine(&tx, self.instance); + + // Now use the original report parameter recv_wallet.accept_transfer(&consignment, report).unwrap(); self.sync(); (consignment, tx) @@ -831,7 +1242,7 @@ impl TestWallet { sats: Option, fee: Option, broadcast: bool, - report: Option<&Report>, + report: Option<&mut Report>, ) -> (PathBuf, Tx) { static COUNTER: OnceLock = OnceLock::new(); let counter = COUNTER.get_or_init(|| AtomicU32::new(0)); @@ -851,7 +1262,8 @@ impl TestWallet { let pay_duration = pay_start.elapsed(); if let Some(report) = report { - report.write_duration(pay_duration); + let column_name = format!("{}_pay", self.wallet_id()); + report.add_duration(&column_name, pay_duration).unwrap(); } let tx = self.sign_finalize_extract(&mut psbt); @@ -881,14 +1293,15 @@ impl TestWallet { pub fn accept_transfer( &mut self, consignment: &Path, - report: Option<&Report>, + report: Option<&mut Report>, ) -> std::io::Result<()> { self.sync(); let accept_start = Instant::now(); self.runtime.consume_from_file(consignment)?; let accept_duration = accept_start.elapsed(); if let Some(report) = report { - report.write_duration(accept_duration); + let column_name = format!("{}_accept", self.wallet_id()); + report.add_duration(&column_name, accept_duration).unwrap(); } Ok(()) } @@ -939,6 +1352,19 @@ impl TestWallet { pub fn coinselect_strategy(&self) -> CustomCoinselectStrategy { self.coinselect_strategy } + + /// Set wallet identifier for reporting purposes + pub fn with_id(mut self, id: impl Into) -> Self { + self.wallet_id = Some(id.into()); + self + } + + /// Get wallet identifier, or a default if not set + pub fn wallet_id(&self) -> String { + self.wallet_id + .clone() + .unwrap_or_else(|| format!("wallet_{}", self.instance)) + } } /// Parameters for NIA (Non-Inflatable Asset) issuance diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 5d73ca3..002d6df 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -21,7 +21,7 @@ pub const ESPLORA_3_REGTEST_URL: &str = "http://127.0.0.1:3003"; pub const ESPLORA_MAINNET_URL: &str = "https://blockstream.info/api"; pub const FAKE_TXID: &str = "e5a3e577309df31bd606f48049049d2e1e02b048206ba232944fcc053a176ccb:0"; pub const UDA_FIXED_INDEX: u32 = 0; -pub const DEFAULT_FEE_ABS: u64 = 400; +pub const DEFAULT_FEE_ABS: u64 = 600; pub const INSTANCE_1: u8 = 1; pub const INSTANCE_2: u8 = 2; From 282a9902517a9e77e6f5a4c04461c8ad7f8106db Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 5 Mar 2025 22:01:42 +0800 Subject: [PATCH 30/90] feat(tests): Enhance stress test reporting and add detailed performance metrics Signed-off-by: will-bitlightlabs --- Cargo.lock | 69 ++++++++++++++++++ Cargo.toml | 3 +- tests/stress.rs | 68 ++++++++++++------ tests/transfer.rs | 159 ++++++++++++++++++++++++++++++++++++----- tests/utils/helpers.rs | 135 ++++++++++++++++++++++++---------- tests/utils/mod.rs | 2 +- 6 files changed, 356 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83c3adf..3e8e95b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,6 +432,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytecount" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" + [[package]] name = "byteorder" version = "1.5.0" @@ -1373,6 +1379,17 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "papergrid" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b915f831b85d984193fdc3d3611505871dc139b2534530fa01c1a6a6707b6723" +dependencies = [ + "bytecount", + "fnv", + "unicode-width", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -1468,6 +1485,28 @@ dependencies = [ "syn 2.0.95", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "proc-macro2" version = "1.0.92" @@ -1746,6 +1785,7 @@ dependencies = [ "strict_types", "strum", "strum_macros", + "tabled", "time", ] @@ -2337,6 +2377,29 @@ dependencies = [ "futures-core", ] +[[package]] +name = "tabled" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121d8171ee5687a4978d1b244f7d99c43e7385a272185a2f1e1fa4dc0979d444" +dependencies = [ + "papergrid", + "tabled_derive", +] + +[[package]] +name = "tabled_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d9946811baad81710ec921809e2af67ad77719418673b2a3794932d57b7538" +dependencies = [ + "heck 0.5.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "tempfile" version = "3.10.1" @@ -2579,6 +2642,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unsafe-libyaml" version = "0.2.11" diff --git a/Cargo.toml b/Cargo.toml index 69747a6..e56b6fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ serde_json = "1.0" serial_test = "3.2.0" strum = { version = "0.26.2", features = ["derive"] } strum_macros = "0.26.2" -time = "0.3.34" +time = { version = "0.3.34", features = ["formatting"] } # RGB-related deps ## bp-core @@ -63,6 +63,7 @@ strict_encoding = { path = "./strict-encoding/rust" } strict_types = { path = "./strict-types" } ## commit_verify commit_verify = { path = "./client_side_validation/commit_verify" } +tabled = "0.18.0" [patch.crates-io] diff --git a/tests/stress.rs b/tests/stress.rs index 8804521..f115820 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -20,12 +20,13 @@ use rstest::rstest; use serial_test::serial; -use std::env::VarError; use std::io::Write; use std::path::PathBuf; use std::str::FromStr; use std::time::Instant; -use time::OffsetDateTime; +use std::{env::VarError, fs::File}; +use time::format_description::well_known::Iso8601; +use time::{format_description, OffsetDateTime}; use utils::{ chain::initialize, helpers::{get_wallet, MetricDefinition, MetricType, Report, TransferType}, @@ -53,14 +54,22 @@ fn back_and_forth( #[case] wlt_1_desc: DescriptorType, #[case] wlt_2_desc: DescriptorType, ) { + // case_7: `{\"code\":-26,\"message\":\"min relay fee not met, 600 < 671\"}"` + // Define a fee constant to prevent errors when the number of transaction inputs is too high + const MIN_RELAY_FEE: u64 = 800; println!("wout {wout:?} wlt_1_desc {wlt_1_desc:?} wlt_2_desc {wlt_2_desc:?}"); initialize(); let stress_tests_dir = PathBuf::from(TEST_DATA_DIR).join(STRESS_DATA_DIR); std::fs::create_dir_all(&stress_tests_dir).unwrap(); - let fname = OffsetDateTime::now_utc().unix_timestamp().to_string(); - let mut fpath = stress_tests_dir.join(fname); + let summary_name = format!("wout_{wout}_wlt_1_{wlt_1_desc}_wlt_2_{wlt_2_desc}"); + + let format = + format_description::parse("[year]_[month]_[day]_[hour]_[minute]_[second]").unwrap(); + let date = OffsetDateTime::now_utc().format(&format).unwrap(); + let filename = format!("{}_{}", summary_name, date); + let mut fpath = stress_tests_dir.join(&filename); fpath.set_extension("csv"); println!("report path: {}", fpath.to_string_lossy()); @@ -71,6 +80,21 @@ fn back_and_forth( metric_type: MetricType::Duration, description: "Time taken for wallet 1 to pay".to_string(), }, + MetricDefinition { + name: "wlt_1_pay_consignment_size".to_string(), + metric_type: MetricType::Bytes, + description: "Size of the consignment file for wallet 1".to_string(), + }, + MetricDefinition { + name: "wlt_1_pay_txin_count".to_string(), + metric_type: MetricType::Integer, + description: "Number of inputs in the transaction for wallet 1".to_string(), + }, + MetricDefinition { + name: "wlt_1_pay_txout_count".to_string(), + metric_type: MetricType::Integer, + description: "Number of outputs in the transaction for wallet 1".to_string(), + }, MetricDefinition { name: "wlt_2_accept".to_string(), metric_type: MetricType::Duration, @@ -82,19 +106,24 @@ fn back_and_forth( description: "Time taken for wallet 2 to pay".to_string(), }, MetricDefinition { - name: "wlt_1_accept".to_string(), - metric_type: MetricType::Duration, - description: "Time taken for wallet 1 to accept".to_string(), + name: "wlt_2_pay_consignment_size".to_string(), + metric_type: MetricType::Bytes, + description: "Size of the consignment file for wallet 2".to_string(), }, MetricDefinition { - name: "send_1_amount".to_string(), + name: "wlt_2_pay_txin_count".to_string(), metric_type: MetricType::Integer, - description: "Amount sent from wallet 1".to_string(), + description: "Number of inputs in the transaction for wallet 2".to_string(), }, MetricDefinition { - name: "send_2_amount".to_string(), + name: "wlt_2_pay_txout_count".to_string(), metric_type: MetricType::Integer, - description: "Amount sent from wallet 2".to_string(), + description: "Number of outputs in the transaction for wallet 2".to_string(), + }, + MetricDefinition { + name: "wlt_1_accept".to_string(), + metric_type: MetricType::Duration, + description: "Time taken for wallet 1 to accept".to_string(), }, ]; @@ -123,12 +152,12 @@ fn back_and_forth( } }; - let sats_base = 3600; + let sats_base = 3601; let mut sats_send = sats_base * loops as u64; let now = Instant::now(); for i in 1..=loops { println!("loop {i}/{loops}"); - sats_send -= DEFAULT_FEE_ABS * 2; + sats_send -= MIN_RELAY_FEE * 2; // In RGB v0.12, the send method parameters have been changed wlt_1.send( @@ -137,13 +166,11 @@ fn back_and_forth( contract_id, issued_supply - i as u64, sats_send, + Some(MIN_RELAY_FEE), None, Some(&mut report), ); - // Record the amount sent from wallet 1 - report.add_integer("send_1_amount", sats_send).unwrap(); - sats_send -= DEFAULT_FEE_ABS * 2; wlt_2.send( @@ -152,13 +179,11 @@ fn back_and_forth( contract_id, issued_supply - i as u64 - 1, sats_send, + Some(MIN_RELAY_FEE), None, Some(&mut report), ); - // Record the amount sent from wallet 2 - report.add_integer("send_2_amount", sats_send).unwrap(); - // End the row for this iteration report.end_row().unwrap(); } @@ -167,9 +192,8 @@ fn back_and_forth( println!("Average time per transfer: {:.2?}", elapsed / loops as u32); // Generate and save test summary - match report.generate_summary() { - // Ok(summary) => println!("Test summary saved to: {}", report.report_path.display()), - Ok(summary) => println!("{}", summary), + match report.save_summary(&filename) { + Ok(summary) => println!("{}", std::fs::read_to_string(summary).unwrap()), Err(e) => println!("Failed to save test summary: {}", e), } } diff --git a/tests/transfer.rs b/tests/transfer.rs index bab87df..ae4e781 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -187,7 +187,16 @@ fn rbf_transfer() { wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![400]); // Transfer assets back to sender - wlt_2.send(&mut wlt_1, false, contract_id, 400, 2000, Some(0), None); + wlt_2.send( + &mut wlt_1, + false, + contract_id, + 400, + 2000, + None, + Some(0), + None, + ); } #[rstest] @@ -305,6 +314,7 @@ fn transfer_loop( contract_id_1, amount_1, sats, + None, Some(0), None, ); @@ -327,6 +337,7 @@ fn transfer_loop( contract_id_1, amount_2, sats, + None, Some(0), None, ); @@ -345,7 +356,16 @@ fn transfer_loop( } else { 1 }; - wlt_1.send(&mut wlt_2, wout, contract_id_2, amount_3, sats, None, None); + wlt_1.send( + &mut wlt_2, + wout, + contract_id_2, + amount_3, + sats, + None, + None, + None, + ); // Verify final allocations if asset_schema_1 != AssetSchema::Uda { @@ -381,7 +401,16 @@ fn transfer_loop( 0 }; sats -= 1000; - wlt_2.send(&mut wlt_1, wout, contract_id_1, amount_4, sats, None, None); + wlt_2.send( + &mut wlt_1, + wout, + contract_id_1, + amount_4, + sats, + None, + None, + None, + ); wlt_1.check_allocations( contract_id_1, asset_schema_1, @@ -406,7 +435,16 @@ fn transfer_loop( 1 }; sats -= 1000; - wlt_2.send(&mut wlt_1, wout, contract_id_2, amount_5, sats, None, None); + wlt_2.send( + &mut wlt_1, + wout, + contract_id_2, + amount_5, + sats, + None, + None, + None, + ); wlt_1.check_allocations( contract_id_1, asset_schema_1, @@ -438,7 +476,16 @@ fn transfer_loop( 1 }; sats -= 1000; - wlt_1.send(&mut wlt_2, wout, contract_id_1, amount_6, sats, None, None); + wlt_1.send( + &mut wlt_2, + wout, + contract_id_1, + amount_6, + sats, + None, + None, + None, + ); wlt_1.check_allocations(contract_id_1, asset_schema_1, vec![]); // for debug { @@ -480,7 +527,16 @@ fn transfer_loop( 1 }; sats -= 1000; - wlt_1.send(&mut wlt_2, wout, contract_id_2, amount_7, sats, None, None); + wlt_1.send( + &mut wlt_2, + wout, + contract_id_2, + amount_7, + sats, + None, + None, + None, + ); wlt_1.check_allocations(contract_id_1, asset_schema_1, vec![]); wlt_1.check_allocations(contract_id_2, asset_schema_2, vec![]); wlt_2.check_allocations( @@ -593,7 +649,16 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amount]); - wlt_2.send(&mut wlt_1, wout, contract_id, amount, 1000, None, None); + wlt_2.send( + &mut wlt_1, + wout, + contract_id, + amount, + 1000, + None, + None, + None, + ); let wlt_1_contract_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); dbg!(wlt_1_contract_state.collect::>()); @@ -610,6 +675,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) 1000, None, None, + None, ); let wlt_3_contract_state = wlt_3.runtime().state_own(None).map(|s| s.1.owned); dbg!(wlt_3_contract_state.collect::>()); @@ -671,20 +737,20 @@ fn tapret_wlt_receiving_opret() { wlt_2.reload_runtime(); // First transfer: wlt_1 -> wlt_2, transfer 400 - wlt_1.send(&mut wlt_2, false, contract_id, 400, 5000, None, None); + wlt_1.send(&mut wlt_2, false, contract_id, 400, 5000, None, None, None); // Second transfer: wlt_2 -> wlt_1, transfer 100 let invoice = wlt_1.invoice(contract_id, 100, true, Some(0), None); wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); // Third transfer: wlt_1 -> wlt_2, transfer 290 - wlt_1.send(&mut wlt_2, true, contract_id, 290, 1000, None, None); + wlt_1.send(&mut wlt_2, true, contract_id, 290, 1000, None, None, None); // Fourth transfer: wlt_2 -> wlt_1, transfer 560 - wlt_2.send(&mut wlt_1, false, contract_id, 560, 1000, None, None); + wlt_2.send(&mut wlt_1, false, contract_id, 560, 1000, None, None, None); // Fifth transfer: wlt_1 -> wlt_2, transfer 570 - wlt_1.send(&mut wlt_2, false, contract_id, 570, 1000, None, None); + wlt_1.send(&mut wlt_2, false, contract_id, 570, 1000, None, None, None); wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![30, 570]); @@ -716,7 +782,7 @@ fn check_fungible_history() { // transfer let amt = 200; - let (_, tx) = wlt_1.send(&mut wlt_2, true, contract_id, amt, 1000, None, None); + let (_, tx) = wlt_1.send(&mut wlt_2, true, contract_id, amt, 1000, None, None, None); let _txid = tx.txid(); // debug contract state @@ -801,11 +867,29 @@ fn blank_tapret_opret( wlt_2.reload_runtime(); // First transfer: wlt_1 -> wlt_2, transfer 200 of first asset - wlt_1.send(&mut wlt_2, false, contract_id_0, 200, 1000, None, None); + wlt_1.send( + &mut wlt_2, + false, + contract_id_0, + 200, + 1000, + None, + None, + None, + ); // Second transfer: wlt_1 -> wlt_2, transfer 100 of second asset // This tests the blank transfer functionality with different descriptor types - wlt_1.send(&mut wlt_2, false, contract_id_1, 100, 1000, None, None); + wlt_1.send( + &mut wlt_2, + false, + contract_id_1, + 100, + 1000, + None, + None, + None, + ); // Verify final allocations wlt_1.check_allocations(contract_id_0, AssetSchema::Nia, vec![]); @@ -1067,8 +1151,26 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp // Test spending the final allocations wlt_1.send_contract("TestAsset", &mut wlt_3); wlt_3.reload_runtime(); - wlt_1.send(&mut wlt_3, false, contract_id, wlt_1_amt, 1000, None, None); - wlt_2.send(&mut wlt_3, false, contract_id, wlt_2_amt, 1000, None, None); + wlt_1.send( + &mut wlt_3, + false, + contract_id, + wlt_1_amt, + 1000, + None, + None, + None, + ); + wlt_2.send( + &mut wlt_3, + false, + contract_id, + wlt_2_amt, + 1000, + None, + None, + None, + ); wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); wlt_3.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_amt, wlt_2_amt]); @@ -1088,7 +1190,16 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp // Test spending the final allocations wlt_1.send_contract("TestAsset", &mut wlt_3); wlt_3.reload_runtime(); - wlt_1.send(&mut wlt_3, false, contract_id, wlt_1_amt, 1000, None, None); + wlt_1.send( + &mut wlt_3, + false, + contract_id, + wlt_1_amt, + 1000, + None, + None, + None, + ); wlt_2.send( &mut wlt_3, false, @@ -1097,6 +1208,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp 1000, None, None, + None, ); wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); @@ -1123,6 +1235,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp 1000, None, None, + None, ); wlt_2.send( &mut wlt_3, @@ -1132,6 +1245,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp 1000, None, None, + None, ); wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); @@ -1174,7 +1288,16 @@ fn revert_genesis(#[case] with_transfers: bool) { let amt = 200; wlt.send_contract("TestAsset", &mut recv_wlt); recv_wlt.reload_runtime(); - wlt.send(&mut recv_wlt, false, contract_id, amt, 1000, None, None); + wlt.send( + &mut recv_wlt, + false, + contract_id, + amt, + 1000, + None, + None, + None, + ); wlt.check_allocations(contract_id, AssetSchema::Nia, vec![issued_supply - amt]); } diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index e24cea2..315508d 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -8,6 +8,7 @@ use std::sync::OnceLock; use std::time::Duration; use std::time::Instant; +use bp::Weight; use bp::{seals::WTxoSeal, Outpoint}; use commit_verify::{Digest, DigestExt, Sha256}; use psbt::TxParams; @@ -33,6 +34,12 @@ use super::{ *, }; +use tabled::settings::{ + object::{Columns, Rows}, + Alignment, Modify, Style, +}; +use tabled::{builder::Builder, Table, Tabled}; + /// RGB Asset creation parameters builder #[derive(Clone)] pub struct AssetParamsBuilder { @@ -310,6 +317,8 @@ impl fmt::Display for AssetSchema { pub enum MetricType { /// Duration (milliseconds) Duration, + /// Bytes value + Bytes, /// Integer value Integer, /// Float value @@ -437,6 +446,13 @@ impl Report { Ok(()) } + /// Add bytes metric by name + pub fn add_bytes(&mut self, name: &str, value: u64) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Bytes)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + /// Add integer metric by name pub fn add_integer(&mut self, name: &str, value: u64) -> Result<(), ReportError> { self.check_metric_name_and_type(name, MetricType::Integer)?; @@ -574,11 +590,21 @@ impl Report { } } - // Generate summary - let mut summary = String::new(); - summary.push_str("# Performance Test Summary\n\n"); - summary.push_str("| Metric | Average | Minimum | Maximum | Sample Count |\n"); - summary.push_str("|------|--------|--------|--------|--------|\n"); + #[derive(Tabled)] + struct MetricSummary { + #[tabled(rename = "Metric")] + metric: String, + #[tabled(rename = "Average")] + average: String, + #[tabled(rename = "Minimum")] + minimum: String, + #[tabled(rename = "Maximum")] + maximum: String, + #[tabled(rename = "Sample Count")] + count: String, + } + + let mut summaries = Vec::new(); for (i, header) in headers.iter().enumerate() { if data[i].is_empty() { @@ -597,42 +623,56 @@ impl Report { MetricType::Float }; - match metric_type { - MetricType::Duration => { - summary.push_str(&format!( - "| {} | {:.2} ms | {:.2} ms | {:.2} ms | {} |\n", - header, - avg, - min, - max, - values.len() - )); - } - MetricType::Integer | MetricType::Float => { - summary.push_str(&format!( - "| {} | {:.2} | {:.2} | {:.2} | {} |\n", - header, - avg, - min, - max, - values.len() - )); - } - MetricType::Text => { - summary.push_str(&format!("| {} | - | - | - | {} |\n", header, values.len())); - } - } + let (avg_str, min_str, max_str) = match metric_type { + MetricType::Duration => ( + format!("{:.2} ms", avg), + format!("{:.2} ms", min), + format!("{:.2} ms", max), + ), + MetricType::Bytes => ( + format!("{:.2} B", avg), + format!("{:.2} B", min), + format!("{:.2} B", max), + ), + MetricType::Integer | MetricType::Float => ( + format!("{:.2}", avg), + format!("{:.2}", min), + format!("{:.2}", max), + ), + MetricType::Text => ("-".to_string(), "-".to_string(), "-".to_string()), + }; + + summaries.push(MetricSummary { + metric: header.to_string(), + average: avg_str, + minimum: min_str, + maximum: max_str, + count: values.len().to_string(), + }); } + // Create the table and style it + let mut table = Table::new(summaries); + table + .with(Style::markdown()) + .with(Modify::new(Columns::new(1..)).with(Alignment::right())); + + // Generate the final Markdown output + let mut summary = String::new(); + summary.push_str("# Performance Test Summary\n\n"); + summary.push_str(&table.to_string()); + Ok(summary) } /// Save summary statistics to file - pub fn save_summary(&mut self) -> Result { + pub fn save_summary(&mut self, name: &str) -> Result { let summary = self.generate_summary()?; - let mut summary_path = self.report_path.clone(); - summary_path.set_extension("md"); + let summary_path = self + .report_path + .clone() + .with_file_name(format!("{}.md", name)); let mut file = std::fs::File::create(&summary_path)?; file.write_all(summary.as_bytes())?; @@ -1179,11 +1219,12 @@ impl TestWallet { contract_id: ContractId, amount: u64, sats: u64, + fee: Option, nonce: Option, report: Option<&mut Report>, ) -> (PathBuf, Tx) { let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce, None); - self.send_to_invoice(recv_wallet, invoice, Some(sats), None, report) + self.send_to_invoice(recv_wallet, invoice, Some(sats), fee, report) } pub fn send_to_invoice( @@ -1261,10 +1302,6 @@ impl TestWallet { .unwrap(); let pay_duration = pay_start.elapsed(); - if let Some(report) = report { - let column_name = format!("{}_pay", self.wallet_id()); - report.add_duration(&column_name, pay_duration).unwrap(); - } let tx = self.sign_finalize_extract(&mut psbt); @@ -1287,6 +1324,28 @@ impl TestWallet { .consign_to_file(invoice.scope, [terminal], &consignment) .unwrap(); + if let Some(report) = report { + let wallet_id = self.wallet_id(); + let column_name = format!("{}_pay", wallet_id); + report.add_duration(&column_name, pay_duration).unwrap(); + + let consigment_column_name = format!("{}_pay_consignment_size", wallet_id); + let file_size = std::fs::metadata(&consignment).unwrap().len(); + report + .add_bytes(&consigment_column_name, file_size) + .unwrap(); + + let txin_column_name = format!("{}_pay_txin_count", wallet_id); + report + .add_integer(&txin_column_name, tx.inputs.len() as u64) + .unwrap(); + + let txout_column_name = format!("{}_pay_txout_count", wallet_id); + report + .add_integer(&txout_column_name, tx.outputs.len() as u64) + .unwrap(); + } + (consignment, tx) } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 002d6df..5d73ca3 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -21,7 +21,7 @@ pub const ESPLORA_3_REGTEST_URL: &str = "http://127.0.0.1:3003"; pub const ESPLORA_MAINNET_URL: &str = "https://blockstream.info/api"; pub const FAKE_TXID: &str = "e5a3e577309df31bd606f48049049d2e1e02b048206ba232944fcc053a176ccb:0"; pub const UDA_FIXED_INDEX: u32 = 0; -pub const DEFAULT_FEE_ABS: u64 = 600; +pub const DEFAULT_FEE_ABS: u64 = 400; pub const INSTANCE_1: u8 = 1; pub const INSTANCE_2: u8 = 2; From b340c815ae038fdc184b91dcee46f2cbbe9fb270 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 6 Mar 2025 21:22:49 +0800 Subject: [PATCH 31/90] feat(tests): Remove outdated test logs and summary files Signed-off-by: will-bitlightlabs --- tests-dev-log/submodule-0212-update.log | 79 - .../submodules-0212-older-status.bak | 21 - .../submodules-0212-updated-status.bak | 21 - tests/dev-log/V11-test-summary.md | 63 - tests/dev-log/V12-test-summary-en.md | 118 -- tests/dev-log/V12-test-summary.md | 115 -- tests/dev-log/v11-first-test.log | 210 --- tests/dev-log/v11-second-test.log | 196 --- tests/dev-log/v12-first-test.log | 1351 ----------------- 9 files changed, 2174 deletions(-) delete mode 100644 tests-dev-log/submodule-0212-update.log delete mode 100644 tests-dev-log/submodules-0212-older-status.bak delete mode 100644 tests-dev-log/submodules-0212-updated-status.bak delete mode 100644 tests/dev-log/V11-test-summary.md delete mode 100644 tests/dev-log/V12-test-summary-en.md delete mode 100644 tests/dev-log/V12-test-summary.md delete mode 100644 tests/dev-log/v11-first-test.log delete mode 100644 tests/dev-log/v11-second-test.log delete mode 100644 tests/dev-log/v12-first-test.log diff --git a/tests-dev-log/submodule-0212-update.log b/tests-dev-log/submodule-0212-update.log deleted file mode 100644 index 2d71204..0000000 --- a/tests-dev-log/submodule-0212-update.log +++ /dev/null @@ -1,79 +0,0 @@ ----- submodule: rgb-std -Previous HEAD position was fe00f28 chore: fix clippy lints -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: rust-aluvm -Previous HEAD position was c1a9225 Merge branch 'v0.12' -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: rgb-interfaces -Previous HEAD position was 70b5528 chore: release v0.11.0-beta.9 -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: client_side_validation -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: bp-core -Previous HEAD position was 38939b3 chore: update dependnecies -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: rgb-core -Previous HEAD position was 5dbad491 release v0.12.0-beta.4 -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: bp-std -Previous HEAD position was 091ac1e chore: fix clippy lints -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: rgb-schemata -WARNING: branch "v0.12" not found ----- submodule: strict-types -WARNING: branch "v0.12" not found ----- submodule: strict-encoding -WARNING: branch "v0.12" not found ----- submodule: bp-electrum-client -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: rust-amplify -WARNING: branch "v0.12" not found ----- submodule: rgb -Previous HEAD position was e6adad0 chore: add description to rgb-wallet crate -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: bp-wallet -Previous HEAD position was 1787494 chore: update dependencies in convert crate -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: amplify-num -WARNING: branch "v0.12" not found ----- submodule: amplify-derive -WARNING: branch "v0.12" not found ----- submodule: ascii-armor -WARNING: branch "v0.12" not found ----- submodule: bp-esplora-client -Previous HEAD position was ed54091 chore: release v0.12.0-beta.4 -branch 'v0.12' set up to track 'origin/v0.12'. -Switched to a new branch 'v0.12' -Already up to date. ----- submodule: vesper -WARNING: branch "v0.12" not found ----- submodule: rust-baid64 -WARNING: branch "v0.12" not found ----- submodule: amplify-nonasync -WARNING: branch "v0.12" not found ----- submodule: zk-aluvm -WARNING: branch "v0.12" not found ----- submodule: ultrasonic -WARNING: branch "v0.12" not found ----- submodule: sonic -WARNING: branch "v0.12" not found \ No newline at end of file diff --git a/tests-dev-log/submodules-0212-older-status.bak b/tests-dev-log/submodules-0212-older-status.bak deleted file mode 100644 index e26a642..0000000 --- a/tests-dev-log/submodules-0212-older-status.bak +++ /dev/null @@ -1,21 +0,0 @@ - bb36a490d68ccf7d574b5926bfc7f8b9509776f2 amplify-derive tags/v4.0.1) - 9f4f5861d0fe314c2928a3e0f516f69c7377c2d3 amplify-nonasync tags/v0.1.3) - 98cda24f2ed2d19ffaba743f59f9ad34464bb492 amplify-num tags/v0.5.3) - 38939b3b33e68045fdf1a4b78c13ea5ca9e8ec02 bp-core tags/v0.12.0-beta.4) - 1d2b08ada85b742d8a0f7548ed6bb5a760aef51e bp-electrum-client tags/v0.12.0-beta.4) - ed54091c5f72af0e7a8b63932a6eb8a1aa12d041 bp-esplora-client tags/v0.12.0-beta.4) - 091ac1ebd7d59b4b7ba01e00d1dd14c5fb32c14d bp-std tags/v0.12.0-beta.4) - 1787494ca47d72bb35cdf848295b24c92db188bf bp-wallet tags/v0.12.0-beta.4) - 67464863d8dae8aaf52807cc0b07a198232ac5b2 client_side_validation tags/v0.12.0-beta.4) - e6adad01a73a81434368984ddc21f0a43d92c552 rgb tags/v0.12.0-beta.4) - 5dbad491d06d616c69ae2e84b3a0c9b8065ff38b rgb-core tags/v0.12.0-beta.4) - fe00f2820c2bc05df16080e499b24496f0456e4d rgb-std tags/v0.12.0-beta.4) - c1a9225398db4b912161bff40890fde86404d76e rust-aluvm tags/v0.12.0-beta.4) - cc510c350e2fcc2d1f7bf7de47a59e7f4a7520a2 rust-amplify tags/v4.8.0) - 7e6a7c36013b30df597c85e6c3f3464d928e4563 rust-baid64 tags/v0.4.1) - 7abeadb9af079b066c1b420aeaaa7a9fc778eb95 sonic tags/v0.12.0-beta.4) - f7be0a7a046fe97289bda5f0b13bd57d7108b61e strict-encoding tags/v2.8.1) - 0292feb72ffa51dccbaaabc4e6e0ba9ad9a5ebbc strict-types tags/v2.8.1) - cb634619676a319b818a36604ce2a317c0a3c447 ultrasonic tags/v0.12.0-beta.4) - 6e1c889e9b951ac709d7db0e57d02dc427446527 vesper tags/v0.1.0) - 08bf763f88f84a2c6a6c0f2b72fbab365d649754 zk-aluvm tags/v0.12.0-beta.4) diff --git a/tests-dev-log/submodules-0212-updated-status.bak b/tests-dev-log/submodules-0212-updated-status.bak deleted file mode 100644 index c3ab064..0000000 --- a/tests-dev-log/submodules-0212-updated-status.bak +++ /dev/null @@ -1,21 +0,0 @@ - bb36a490d68ccf7d574b5926bfc7f8b9509776f2 amplify-derive tags/v4.0.1) - 9f4f5861d0fe314c2928a3e0f516f69c7377c2d3 amplify-nonasync tags/v0.1.3) - 98cda24f2ed2d19ffaba743f59f9ad34464bb492 amplify-num tags/v0.5.3) - 6fbc7f16d028d12d6d1336a9aa7752ea8ae06e15 bp-core heads/v0.12) - 1d2b08ada85b742d8a0f7548ed6bb5a760aef51e bp-electrum-client tags/v0.12.0-beta.4) - 056891e5f86aa3dac80628541e4e44fee0479507 bp-esplora-client heads/v0.12) - 91aaf51498126f6a514f0d9af80888465e5dbfee bp-std heads/v0.12) - 5546f0ad5d7aee3d8d92d4a5604095cf2ec834fe bp-wallet heads/v0.12) - 67464863d8dae8aaf52807cc0b07a198232ac5b2 client_side_validation tags/v0.12.0-beta.4) - bc2b88921e8886238f0ac0d00ed9a43edf3289c2 rgb heads/v0.12) - 4a020e09dcf4e30edc41432e3c9f92f3c13ad0ac rgb-core heads/v0.12) - a368811a2fbaf8385d8da6de7bf5a2ce3d01e8af rgb-std heads/v0.12) - 8b009cde66a210e35b7db6b2cb36ab2bc2fa60cd rust-aluvm heads/v0.12) - cc510c350e2fcc2d1f7bf7de47a59e7f4a7520a2 rust-amplify tags/v4.8.0) - 7e6a7c36013b30df597c85e6c3f3464d928e4563 rust-baid64 tags/v0.4.1) - 7abeadb9af079b066c1b420aeaaa7a9fc778eb95 sonic tags/v0.12.0-beta.4) - f7be0a7a046fe97289bda5f0b13bd57d7108b61e strict-encoding tags/v2.8.1) - 0292feb72ffa51dccbaaabc4e6e0ba9ad9a5ebbc strict-types tags/v2.8.1) - cb634619676a319b818a36604ce2a317c0a3c447 ultrasonic tags/v0.12.0-beta.4) - 6e1c889e9b951ac709d7db0e57d02dc427446527 vesper tags/v0.1.0) - 08bf763f88f84a2c6a6c0f2b72fbab365d649754 zk-aluvm tags/v0.12.0-beta.4) diff --git a/tests/dev-log/V11-test-summary.md b/tests/dev-log/V11-test-summary.md deleted file mode 100644 index baa687e..0000000 --- a/tests/dev-log/V11-test-summary.md +++ /dev/null @@ -1,63 +0,0 @@ -# RGB v11 基线测试执行情况汇总 - -## 测试执行概览 - -| 测试类型 | 总数 | 通过 | 失败 | 忽略 | -| ------------- | ---- | ---- | ---- | ---- | -| issuance.rs | 20 | 20 | 0 | 0 | -| stress.rs | 6 | 0 | 0 | 6 | -| transfers.rs | 101 | 88 | 0 | 13 | -| validation.rs | 6 | 5 | 0 | 1 | -| 总计 | 133 | 113 | 0 | 20 | - -## 详细测试状态 - -### V11遗留问题 (ignored, 需要在V12验证是否修复) -1. blank_tapret_opret::case_1 -2. blank_tapret_opret::case_3 -3. blank_tapret_opret::case_4 -4. invoice_reuse::case_1 (可能不是bug,但行为异常) -5. ln_transfers::case_2 -6. reorg_history::case_2 -7. reorg_history::case_4 -8. reorg_history::case_6 -9. revert_genesis::case_1 -10. revert_genesis::case_2 -11. same_transfer_twice_no_update_witnesses::case_1 -12. same_transfer_twice_update_witnesses::case_1 -13. sync_mainnet_wlt -14. validate_consignment_generate (one-shot) - -### 正常通过的关键测试 (ok) -1. mainnet_wlt_receiving_test_asset -2. accept_0conf -3. check_fungible_history -4. invoice_reuse::case_2 -5. ln_transfers::case_1 -6. rbf_transfer -7. collaborative_transfer -8. send_to_oneself -9. receive_from_unbroadcasted_transfer_to_blinded -10. tapret_wlt_receiving_opret -11. transfer_loop::case_01 - case_72 (所有72个transfer_loop测试) -12. reorg_history::case_1 -13. reorg_history::case_3 -14. reorg_history::case_5 -15. validate_consignment_chain_fail -16. validate_consignment_bundles_fail -17. validate_consignment_genesis_fail -18. validate_consignment_resolver_error -19. validate_consignment_success - -## 分析总结 - -1. **成功率**: 85% (113/133) -2. **主要问题**: - - 旧版遗留主要集中在特殊交易场景, 需要后续在V12验证是否修复 - - 之前的节点连接问题已经解决,所有reorg_history测试都通过了 - -3. **稳定性评估**: - - 基本功能测试(issuance.rs)全部通过,表明核心功能稳定 - - 压力测试(stress.rs)全部被忽略,需要单独评估 - - 转账相关测试(transfers.rs)大部分通过,剩余问题都是已知的V11遗留问题 - - 验证相关测试(validation.rs)表现良好,只有一个测试被忽略 \ No newline at end of file diff --git a/tests/dev-log/V12-test-summary-en.md b/tests/dev-log/V12-test-summary-en.md deleted file mode 100644 index 4b506bf..0000000 --- a/tests/dev-log/V12-test-summary-en.md +++ /dev/null @@ -1,118 +0,0 @@ -# RGB v0.12 First Phase Testing Summary - -This is the first test run of RGB v0.12. While the full test suite is still under development, we have completed the design of most transfer test cases. - -## Test Execution Overview - -| Test Type | Total | Passed | Failed | Ignored | -| ---------------------------------- | ----- | ------ | ------ | ------- | -| [issuance.rs](http://issuance.rs/) | 16 | 16 | 0 | 0 | -| [transfer.rs](http://transfer.rs/) | 36 | 9 | 12 | 15 | -| Total | 52 | 25 | 12 | 15 | - -## Detailed Test Status - -### Ignored Tests - -1. blank_tapret_opret::case_1..4 - Fix needed (calling to method absent in Codex API) -2. mainnet_wlt_receiving_test_asset - Fix needed - - Error: The `Mound` structure in RGB v0.12 does not support setting the mainnet - - Context: From issue_mainnet_wlt_receiving_test_asset.md: "The default `Mound.testnet` is eq true, which cannot correctly initialize the mainnet wallet" -3. reorg_history::case_1 - Fix needed - - Error: "Unable to accept a consignment: unknown seal definition for cell address qMWtQjXCWjJAXdrg7npyI2KZz3vXNVyZhoomqF7v8z4:0." - - Context: Test simulates blockchain reorganization with Linear history and ChangeOrder type -4. reorg_history::case_2 - Fix needed - - Error: "assertion `left == right` failed, left: [10, 20], right: [600]" - - Context: Test simulates blockchain reorganization with Linear history and Revert type -5. reorg_history::case_3 - Fix needed - - Error: "Unable to accept a consignment: unknown seal definition for cell address c6z0I0hYqaO6dV9qOjrP1lK4PJprjVAaAOdGCoqAdOY:0." - - Context: Test simulates blockchain reorganization with Branching history and ChangeOrder type -6. reorg_history::case_4 - Fix needed - - Error: "assertion `left == right` failed, left: [200, 399], right: [600]" - - Context: Test simulates blockchain reorganization with Branching history and Revert type -7. reorg_history::case_5 - Fix needed - - Error: "Unable to accept a consignment: unknown seal definition for cell address FrGmm~6ro7YOlE9bEuyCLcLt9AlX2uZOZRmjHEq6yyA:0." - - Context: Test simulates blockchain reorganization with Merging history and ChangeOrder type -8. reorg_history::case_6 - Fix needed - - Error: "assertion `left == right` failed, left: [599], right: [400]" - - Context: Test simulates blockchain reorganization with Merging history and Revert type -9. same_transfer_twice_update_witnesses::case_1 - Awaiting new rollback procedure API in RGB v0.12 - - Context: Test requires the ability to update witnesses, which was removed in v0.12 and will be replaced with a new rollback procedure -10. same_transfer_twice_update_witnesses::case_2 - Awaiting new rollback procedure API in RGB v0.12 -- Context: Same issue as case_1 -1. collaborative_transfer - Pending multi-signature workflow documentation -- Context: Test requires implementation of multi-signature workflow. Current documentation is minimal and the underlying API is complex to understand. Initial implementation was unsuccessful. Plan to focus on this implementation in later phases after core functionality is stable. -1. ln_transfers - Pending Lightning Network integration documentation -- Context: Test requires implementation of multi-signature workflow. Current documentation is minimal and the underlying API is complex to understand. Initial implementation was unsuccessful. Plan to focus on this implementation in later phases after core functionality is stable. - -### Failed Tests - -1. rbf_transfer - Fulfill(StateInsufficient) - - Error: `called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` - - Context: Test attempts to replace a transaction with a higher fee (RBF) but fails because the state is insufficient to fulfill the second transfer -2. same_transfer_twice_no_update_witnesses::case_1 - Fulfill(StateInsufficient) - - Error: `called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` - - Context: Test attempts to use the same invoice twice without updating witnesses, which is not supported in v0.12 -3. same_transfer_twice_no_update_witnesses::case_2 - Fulfill(StateInsufficient) - - Error: `called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` - - Context: Same issue as case_1, related to invoice reuse -4. tapret_wlt_receiving_opret - Transaction already in block chain - - Error: "Transaction already in block chain" - - Context: Test attempts to create multiple transfers between Taproot and WPKH wallets. The test passes when run individually but fails with transaction conflicts when run as part of the full test suite, suggesting a need to restructure test isolation -5. transfer_loop::case_01 - calling to method absent in Codex API - - Error: Method missing in the new Codex API - - Context: Test attempts to transfer assets between different wallet types and asset schemas -6. transfer_loop::case_02 - calling to method absent in Codex API - - Same issue as case_01 -7. transfer_loop::case_03 - calling to method absent in Codex API - - Same issue as case_01 -8. transfer_loop::case_04 - calling to method absent in Codex API - - Same issue as case_01 -9. transfer_loop::case_05 - calling to method absent in Codex API - - Same issue as case_01 -10. transfer_loop::case_06 - calling to method absent in Codex API - - Same issue as case_01 -11. transfer_loop::case_07 - calling to method absent in Codex API - - Same issue as case_01 -12. transfer_loop::case_08 - calling to method absent in Codex API - - Same issue as case_01 - -### Passed Tests - -1. issue_cfa::case_1 - case_4 (all 4 tests) - - Context: Successfully issues Collectible Fungible Assets with various parameters -2. issue_nia::case_1 - case_4 (all 4 tests) - - Context: Successfully issues Non-Inflatable Assets with various parameters -3. issue_cfa_multiple_utxos::case_1 - case_4 (all 4 tests) - - Context: Successfully issues Collectible Fungible Assets with allocations across multiple UTXOs -4. issue_nia_multiple_utxos::case_1 - case_4 (all 4 tests) - - Context: Successfully issues Non-Inflatable Assets with allocations across multiple UTXOs -5. accept_0conf - - Context: Successfully tests accepting unconfirmed (0-conf) transactions -6. send_to_oneself - - Context: Successfully tests sending assets to the same wallet -7. check_fungible_history - - Context: Successfully tests checking the history of fungible assets -8. transfer_loop::case_09 - case_12 (4 tests) - - Context: Successfully tests a subset of transfer loop cases with specific wallet and asset combinations - -## Analysis Summary - -1. **Success Rate**: 48% (25/52) -2. **Main Issues**: - - Asset issuance tests ([issuance.rs](http://issuance.rs/)) all pass, except for UDA assets missing `.issuer`, indicating core issuance functionality has been successfully migrated to v0.12 - - Transfer-related tests ([transfer.rs](http://transfer.rs/)) have numerous issues, primarily in these areas: - - **API Instability**: Multiple transfer_loop tests and blank_tapret_opret tests fail with "calling to method absent in Codex API" errors, indicating breaking changes and instability in the API transition from v0.11 to v0.12. Some previously available methods have been removed or modified, requiring updates to test implementations - - **State Insufficient errors**: rbf_transfer and same_transfer_twice_no_update_witnesses tests fail with "Fulfill(StateInsufficient)" errors, indicating that the state management for these scenarios needs to be updated - - **Invoice reuse not supported**: Tests attempting to reuse the same invoice fail with "Fulfill(StateInsufficient)" errors, as noted in same_transfer_twice_no_update_witnesses: "In RGB V0.12, since it's not possible to use RBF with the same invoice, we cannot test for this inflation attack" - - **Blockchain reorganization handling**: The API does not yet have a stable mechanism for handling blockchain reorganization scenarios, as evidenced by the reorg_history test failures showing incorrect asset allocations after reorganization -3. **Migration Progress Assessment**: - - Asset issuance functionality migration is highly complete, including multi-UTXO allocation scenarios - - Basic transfer functionality is partially available, such as accept_0conf, send_to_oneself, and some transfer_loop tests - - Advanced transfer functionality (such as RBF, reorganization history, Lightning Network integration, etc.) has not yet been fully migrated -4. **Next Steps and Support Needed**: - - Request guidance to resolve "calling to method absent in Codex API" issues - - Fix StateInsufficient errors - - Implement contract architecture support for blockchain reorganization scenarios, with related rollback procedure API - - Add support for invoice reuse and RBF scenarios - - Provide documentation on payment scripts and internal state transition APIs to implement more complex transfer scenario tests, such as multi-signature and Lightning Network integration \ No newline at end of file diff --git a/tests/dev-log/V12-test-summary.md b/tests/dev-log/V12-test-summary.md deleted file mode 100644 index 6dc1e0e..0000000 --- a/tests/dev-log/V12-test-summary.md +++ /dev/null @@ -1,115 +0,0 @@ -# RGB v0.12 第一阶段测试执行情况汇总 - -这是RGB v0.12的首次测试运行。虽然完整的测试套件仍在开发中,但我们已经完成了大部分转账测试用例的设计。 - -## 测试执行概览 - -| 测试类型 | 总数 | 通过 | 失败 | 忽略 | -| ----------- | ---- | ---- | ---- | ---- | -| issuance.rs | 16 | 16 | 0 | 0 | -| transfer.rs | 36 | 9 | 12 | 15 | -| 总计 | 52 | 25 | 12 | 15 | - -## 详细测试状态 - -### 已忽略的测试 (ignored) -1. blank_tapret_opret::case_1..4 - 需要修复 (调用Codex API中不存在的方法) -2. mainnet_wlt_receiving_test_asset - 需要修复 - - 错误:RGB v0.12中的`Mound`结构不支持设置主网 - - 上下文:来自issue_mainnet_wlt_receiving_test_asset.md:"默认的`Mound.testnet`等于true,无法正确初始化主网钱包" -3. reorg_history::case_1 - 需要修复 - - 错误:"Unable to accept a consignment: unknown seal definition for cell address qMWtQjXCWjJAXdrg7npyI2KZz3vXNVyZhoomqF7v8z4:0." - - 上下文:测试模拟具有线性历史和ChangeOrder类型的区块链重组 -4. reorg_history::case_2 - 需要修复 - - 错误:"assertion `left == right` failed, left: [10, 20], right: [600]" - - 上下文:测试模拟具有线性历史和Revert类型的区块链重组 -5. reorg_history::case_3 - 需要修复 - - 错误:"Unable to accept a consignment: unknown seal definition for cell address c6z0I0hYqaO6dV9qOjrP1lK4PJprjVAaAOdGCoqAdOY:0." - - 上下文:测试模拟具有分支历史和ChangeOrder类型的区块链重组 -6. reorg_history::case_4 - 需要修复 - - 错误:"assertion `left == right` failed, left: [200, 399], right: [600]" - - 上下文:测试模拟具有分支历史和Revert类型的区块链重组 -7. reorg_history::case_5 - 需要修复 - - 错误:"Unable to accept a consignment: unknown seal definition for cell address FrGmm~6ro7YOlE9bEuyCLcLt9AlX2uZOZRmjHEq6yyA:0." - - 上下文:测试模拟具有合并历史和ChangeOrder类型的区块链重组 -8. reorg_history::case_6 - 需要修复 - - 错误:"assertion `left == right` failed, left: [599], right: [400]" - - 上下文:测试模拟具有合并历史和Revert类型的区块链重组 -9. same_transfer_twice_update_witnesses::case_1 - 等待RGB v0.12中的新回滚程序API - - 上下文:测试需要更新见证的能力,该功能在v0.12中已被移除,将由新的回滚程序API替代 -10. same_transfer_twice_update_witnesses::case_2 - 等待RGB v0.12中的新回滚程序API - - 上下文:与case_1相同的问题 -11. collaborative_transfer - 等待多重签名工作流文档 - - 上下文:测试需要实现多重签名工作流。当前文档很少,底层API复杂难懂。初步实现未成功。计划在核心功能稳定后的后续阶段专注于此实现。 -12. ln_transfers - 等待闪电网络集成文档 - - 上下文:测试需要实现多重签名工作流。当前文档很少,底层API复杂难懂。初步实现未成功。计划在核心功能稳定后的后续阶段专注于此实现。 - -### 失败的测试 (failed) -1. rbf_transfer - Fulfill(StateInsufficient) - - 错误:`called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` - - 上下文:测试尝试用更高的手续费替换交易(RBF),但由于状态不足以完成第二次转账而失败 -2. same_transfer_twice_no_update_witnesses::case_1 - Fulfill(StateInsufficient) - - 错误:`called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` - - 上下文:测试尝试在不更新见证的情况下两次使用相同的发票,这在v0.12中不受支持 -3. same_transfer_twice_no_update_witnesses::case_2 - Fulfill(StateInsufficient) - - 错误:`called Result::unwrap() on an Err value: Fulfill(StateInsufficient)` - - 上下文:与case_1相同的问题,与发票重用相关 -4. tapret_wlt_receiving_opret - Transaction already in block chain - - 错误:"Transaction already in block chain" - - 上下文:测试尝试在Taproot和WPKH钱包之间创建多次转账。该测试单独运行时通过,但作为完整测试套件的一部分运行时因交易冲突而失败,表明需要重构测试隔离 -5. transfer_loop::case_01 - calling to method absent in Codex API - - 错误:新的Codex API中缺少方法 - - 上下文:测试尝试在不同钱包类型和资产模式之间转移资产 -6. transfer_loop::case_02 - calling to method absent in Codex API - - 与case_01相同的问题 -7. transfer_loop::case_03 - calling to method absent in Codex API - - 与case_01相同的问题 -8. transfer_loop::case_04 - calling to method absent in Codex API - - 与case_01相同的问题 -9. transfer_loop::case_05 - calling to method absent in Codex API - - 与case_01相同的问题 -10. transfer_loop::case_06 - calling to method absent in Codex API - - 与case_01相同的问题 -11. transfer_loop::case_07 - calling to method absent in Codex API - - 与case_01相同的问题 -12. transfer_loop::case_08 - calling to method absent in Codex API - - 与case_01相同的问题 - -### 通过的测试 (passed) -1. issue_cfa::case_1 - case_4 (所有4个测试) - - 上下文:成功发行具有各种参数的可收集的可替代资产(CFA) -2. issue_nia::case_1 - case_4 (所有4个测试) - - 上下文:成功发行具有各种参数的不可膨胀资产(NIA) -3. issue_cfa_multiple_utxos::case_1 - case_4 (所有4个测试) - - 上下文:成功发行在多个UTXO上分配的可收集的可替代资产(CFA) -4. issue_nia_multiple_utxos::case_1 - case_4 (所有4个测试) - - 上下文:成功发行在多个UTXO上分配的不可膨胀资产(NIA) -5. accept_0conf - - 上下文:成功测试接受未确认(0-conf)交易 -6. send_to_oneself - - 上下文:成功测试向同一钱包发送资产 -7. check_fungible_history - - 上下文:成功测试检查可替代资产的历史 -8. transfer_loop::case_09 - case_12 (4个测试) - - 上下文:成功测试特定钱包和资产组合的部分转账循环情况 - -## 分析总结 - -1. **成功率**: 48% (25/52) -2. **主要问题**: - - 资产发行相关测试(issuance.rs)全部通过,除了UDA资产缺少`.issuer`,表明核心发行功能已成功迁移到v0.12 - - 转账相关测试(transfer.rs)存在较多问题,主要集中在以下几个方面: - - **API不稳定性**:多个transfer_loop测试和blank_tapret_opret测试失败,出现"calling to method absent in Codex API"错误,表明从v0.11到v0.12的API转换过程中存在破坏性变更和不稳定性。一些以前可用的方法已被移除或修改,需要更新测试实现 - - **状态不足错误**:rbf_transfer和same_transfer_twice_no_update_witnesses测试失败,出现"Fulfill(StateInsufficient)"错误,表明这些场景的状态管理需要更新 - - **发票不支持重用**:尝试重用相同发票的测试失败,出现"Fulfill(StateInsufficient)"错误,正如same_transfer_twice_no_update_witnesses中所述:"在RGB V0.12中,由于不可能使用RBF和相同的发票,我们无法测试这种通胀攻击" - - **区块链重组处理**:API尚未有稳定的机制来处理区块链重组场景,这从reorg_history测试失败中可以看出,重组后资产分配不正确 -3. **迁移进展评估**: - - 资产发行功能迁移完成度高,包括多UTXO分配的情况 - - 基本转账功能部分可用,如accept_0conf、send_to_oneself和部分transfer_loop测试 - - 高级转账功能(如RBF、重组历史、闪电网络集成等)尚未完成迁移 -4. **下一步期望优先获取的支持**: - - 请求指导解决"calling to method absent in Codex API"问题 - - 修复StateInsufficient错误 - - 实现合约架构支持区块链重组场景,有相关的rollback procedure API - - 添加对发票重用和RBF场景的支持 - - 提供关于支付脚本和内部状态转换API的文档,以实现更复杂的转账场景测试,如多签名和闪电网络集成 diff --git a/tests/dev-log/v11-first-test.log b/tests/dev-log/v11-first-test.log deleted file mode 100644 index d688062..0000000 --- a/tests/dev-log/v11-first-test.log +++ /dev/null @@ -1,210 +0,0 @@ -$ SKIP_INIT=true cargo test -zsh: correct 'test' to 'tests' [nyae]? n - Compiling rgb-tests v0.1.0 (/Users/bincheng_paopao/project/repo/rust/myself/well/rgb-tests) - Building [=======================> ] 308/310: validation(... - Finished `test` profile [unoptimized + debuginfo] target(s) in 7.58s - Running tests/issuance.rs (target/debug/deps/issuance-e9f8eff5ebec6da9) - -running 20 tests -test issue_cfa::case_2 ... ok -test issue_cfa::case_1 ... ok -test issue_cfa::case_4 ... ok -test issue_cfa::case_3 ... ok -test issue_nia::case_1 ... ok -test issue_nia::case_2 ... ok -test issue_nia::case_3 ... ok -test issue_nia::case_4 ... ok -test issue_cfa_multiple_utxos::case_1 ... ok -test issue_cfa_multiple_utxos::case_2 ... ok -test issue_cfa_multiple_utxos::case_3 ... ok -test issue_cfa_multiple_utxos::case_4 ... ok -test issue_uda::case_1 ... ok -test issue_uda::case_2 ... ok -test issue_uda::case_4 ... ok -test issue_uda::case_3 ... ok -test issue_nia_multiple_utxos::case_2 ... ok -test issue_nia_multiple_utxos::case_1 ... ok -test issue_nia_multiple_utxos::case_4 ... ok -test issue_nia_multiple_utxos::case_3 ... ok - -test result: ok. 20 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 24.75s - - Running tests/stress.rs (target/debug/deps/stress-643c591558ebdbe5) - -running 6 tests -test back_and_forth::case_1 ... ignored, run a single case if desired -test back_and_forth::case_2 ... ignored, run a single case if desired -test back_and_forth::case_3 ... ignored, run a single case if desired -test back_and_forth::case_4 ... ignored, run a single case if desired -test back_and_forth::case_5 ... ignored, run a single case if desired -test back_and_forth::case_6 ... ignored, run a single case if desired - -test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out; finished in 0.00s - - Running tests/transfers.rs (target/debug/deps/transfers-cce5ca197e08de6d) - -running 101 tests -test blank_tapret_opret::case_1 ... ignored, fix needed -test blank_tapret_opret::case_3 ... ignored, fix needed -test blank_tapret_opret::case_4 ... ignored, fix needed -test invoice_reuse::case_1 ... ignored, probably not a bug, but still unexpected -test ln_transfers::case_2 ... ignored, fix needed -test mainnet_wlt_receiving_test_asset ... ok -test accept_0conf ... ok -test reorg_history::case_1 ... FAILED -test reorg_history::case_2 ... ignored, fix needed -test reorg_history::case_3 ... FAILED -test reorg_history::case_4 ... ignored, fix needed -test reorg_history::case_5 ... FAILED -test reorg_history::case_6 ... ignored, fix needed -test revert_genesis::case_1 ... ignored, fix needed -test revert_genesis::case_2 ... ignored, fix needed -test same_transfer_twice_no_update_witnesses::case_1 ... ignored, fix needed -test check_fungible_history ... ok -test same_transfer_twice_update_witnesses::case_1 ... ignored, fix needed -test invoice_reuse::case_2 ... ok -test ln_transfers::case_1 ... ok -test sync_mainnet_wlt ... ignored, fix needed -test same_transfer_twice_no_update_witnesses::case_2 - should panic ... ok -test rbf_transfer ... ok -test collaborative_transfer ... ok -test send_to_oneself ... ok -test blank_tapret_opret::case_2 ... ok -test same_transfer_twice_update_witnesses::case_2 ... ok -test receive_from_unbroadcasted_transfer_to_blinded ... ok -test tapret_wlt_receiving_opret ... ok -test transfer_loop::case_01 has been running for over 60 seconds -test transfer_loop::case_02 has been running for over 60 seconds -test transfer_loop::case_03 has been running for over 60 seconds -test transfer_loop::case_04 has been running for over 60 seconds -test transfer_loop::case_05 has been running for over 60 seconds -test transfer_loop::case_06 has been running for over 60 seconds -test transfer_loop::case_07 has been running for over 60 seconds -test transfer_loop::case_01 ... ok -test transfer_loop::case_02 ... ok -test transfer_loop::case_03 ... ok -test transfer_loop::case_05 ... ok -test transfer_loop::case_04 ... ok -test transfer_loop::case_06 ... ok -test transfer_loop::case_07 ... ok -test transfer_loop::case_08 has been running for over 60 seconds -test transfer_loop::case_08 ... ok -test transfer_loop::case_09 has been running for over 60 seconds -test transfer_loop::case_10 has been running for over 60 seconds -test transfer_loop::case_11 has been running for over 60 seconds -test transfer_loop::case_12 has been running for over 60 seconds -test transfer_loop::case_13 has been running for over 60 seconds -test transfer_loop::case_14 has been running for over 60 seconds -test transfer_loop::case_15 has been running for over 60 seconds -test transfer_loop::case_09 ... ok -test transfer_loop::case_11 ... ok -test transfer_loop::case_10 ... ok -test transfer_loop::case_13 ... ok -test transfer_loop::case_12 ... ok -test transfer_loop::case_14 ... ok -test transfer_loop::case_15 ... ok -test transfer_loop::case_16 has been running for over 60 seconds -test transfer_loop::case_16 ... ok -test transfer_loop::case_17 has been running for over 60 seconds -test transfer_loop::case_18 has been running for over 60 seconds -test transfer_loop::case_19 has been running for over 60 seconds -test transfer_loop::case_20 has been running for over 60 seconds -test transfer_loop::case_21 has been running for over 60 seconds -test transfer_loop::case_22 has been running for over 60 seconds -test transfer_loop::case_23 has been running for over 60 seconds -test transfer_loop::case_17 ... ok -test transfer_loop::case_19 ... ok -test transfer_loop::case_18 ... ok -test transfer_loop::case_21 ... ok -test transfer_loop::case_20 ... ok -test transfer_loop::case_22 ... ok -test transfer_loop::case_23 ... ok -test transfer_loop::case_24 has been running for over 60 seconds -test transfer_loop::case_24 ... ok -test transfer_loop::case_25 has been running for over 60 seconds -test transfer_loop::case_26 has been running for over 60 seconds -test transfer_loop::case_27 has been running for over 60 seconds -test transfer_loop::case_28 has been running for over 60 seconds -test transfer_loop::case_29 has been running for over 60 seconds -test transfer_loop::case_25 ... ok -test transfer_loop::case_27 ... ok -test transfer_loop::case_26 ... ok -test transfer_loop::case_30 has been running for over 60 seconds -test transfer_loop::case_28 ... ok -test transfer_loop::case_29 ... ok -test transfer_loop::case_31 has been running for over 60 seconds -test transfer_loop::case_30 ... ok -test transfer_loop::case_31 ... ok -test transfer_loop::case_32 has been running for over 60 seconds -test transfer_loop::case_37 ... ok -test transfer_loop::case_32 ... ok -test transfer_loop::case_38 ... ok -test transfer_loop::case_39 ... ok -test transfer_loop::case_33 has been running for over 60 seconds -test transfer_loop::case_34 has been running for over 60 seconds -test transfer_loop::case_35 has been running for over 60 seconds -test transfer_loop::case_36 has been running for over 60 seconds -test transfer_loop::case_33 ... ok -test transfer_loop::case_34 ... ok -test transfer_loop::case_35 ... ok -test transfer_loop::case_36 ... ok -test transfer_loop::case_41 ... ok -test transfer_loop::case_40 ... ok -test transfer_loop::case_42 ... ok -test transfer_loop::case_43 ... ok -test transfer_loop::case_45 ... ok -test transfer_loop::case_46 ... ok -test transfer_loop::case_44 ... ok -test transfer_loop::case_47 ... ok -test transfer_loop::case_49 ... ok -test transfer_loop::case_48 ... ok -test transfer_loop::case_50 ... ok -test transfer_loop::case_51 ... ok -test transfer_loop::case_53 ... ok -test transfer_loop::case_54 ... ok -test transfer_loop::case_52 ... ok -test transfer_loop::case_55 ... ok -test transfer_loop::case_57 ... ok -test transfer_loop::case_58 ... ok -test transfer_loop::case_56 ... ok -test transfer_loop::case_59 ... ok -test transfer_loop::case_61 ... ok -test transfer_loop::case_63 ... ok -test transfer_loop::case_62 ... ok -test transfer_loop::case_60 ... ok -test transfer_loop::case_65 ... ok -test transfer_loop::case_66 ... ok -test transfer_loop::case_64 ... ok -test transfer_loop::case_67 ... ok -test transfer_loop::case_70 ... ok -test transfer_loop::case_69 ... ok -test transfer_loop::case_68 ... ok -test transfer_loop::case_71 ... ok -test transfer_loop::case_72 ... ok - -failures: - ----- reorg_history::case_1 stdout ---- -history_type Linear reorg_type ChangeOrder -Output { status: ExitStatus(unix_wait_status(5888)), stdout: "", stderr: "" } -thread 'reorg_history::case_1' panicked at tests/utils/chain.rs:120:9: -failed to get successful output with args ["addnode", "172.30.2.205:18444", "add"] -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace - ----- reorg_history::case_3 stdout ---- -history_type Branching reorg_type ChangeOrder -Output { status: ExitStatus(unix_wait_status(5888)), stdout: "", stderr: "" } -thread 'reorg_history::case_3' panicked at tests/utils/chain.rs:120:9: -failed to get successful output with args ["addnode", "172.30.2.205:18444", "add"] - ----- reorg_history::case_5 stdout ---- -history_type Merging reorg_type ChangeOrder -Output { status: ExitStatus(unix_wait_status(5888)), stdout: "", stderr: "" } -thread 'reorg_history::case_5' panicked at tests/utils/chain.rs:120:9: -failed to get successful output with args ["addnode", "172.30.2.205:18444", "add"] - - -failures: - reorg_history::case_1 - reorg_history::case_3 - reorg_history::case_5 \ No newline at end of file diff --git a/tests/dev-log/v11-second-test.log b/tests/dev-log/v11-second-test.log deleted file mode 100644 index f69d44b..0000000 --- a/tests/dev-log/v11-second-test.log +++ /dev/null @@ -1,196 +0,0 @@ - Finished `test` profile [unoptimized + debuginfo] target(s) in 0.58s - Running tests/issuance.rs (target/debug/deps/issuance-e9f8eff5ebec6da9) - -running 20 tests -test issue_cfa::case_2 ... ok -test issue_cfa::case_1 ... ok -test issue_cfa::case_3 ... ok -test issue_cfa::case_4 ... ok -test issue_nia::case_1 ... ok -test issue_nia::case_4 ... ok -test issue_nia::case_3 ... ok -test issue_nia::case_2 ... ok -test issue_cfa_multiple_utxos::case_2 ... ok -test issue_cfa_multiple_utxos::case_3 ... ok -test issue_cfa_multiple_utxos::case_4 ... ok -test issue_cfa_multiple_utxos::case_1 ... ok -test issue_uda::case_4 ... ok -test issue_uda::case_2 ... ok -test issue_uda::case_3 ... ok -test issue_uda::case_1 ... ok -test issue_nia_multiple_utxos::case_1 ... ok -test issue_nia_multiple_utxos::case_2 ... ok -test issue_nia_multiple_utxos::case_3 ... ok -test issue_nia_multiple_utxos::case_4 ... ok - -test result: ok. 20 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 25.28s - - Running tests/stress.rs (target/debug/deps/stress-643c591558ebdbe5) - -running 6 tests -test back_and_forth::case_1 ... ignored, run a single case if desired -test back_and_forth::case_2 ... ignored, run a single case if desired -test back_and_forth::case_3 ... ignored, run a single case if desired -test back_and_forth::case_4 ... ignored, run a single case if desired -test back_and_forth::case_5 ... ignored, run a single case if desired -test back_and_forth::case_6 ... ignored, run a single case if desired - -test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out; finished in 0.00s - - Running tests/transfers.rs (target/debug/deps/transfers-cce5ca197e08de6d) - -running 101 tests -test blank_tapret_opret::case_1 ... ignored, fix needed -test blank_tapret_opret::case_3 ... ignored, fix needed -test blank_tapret_opret::case_4 ... ignored, fix needed -test invoice_reuse::case_1 ... ignored, probably not a bug, but still unexpected -test ln_transfers::case_2 ... ignored, fix needed -test mainnet_wlt_receiving_test_asset ... ok -test accept_0conf ... ok -test check_fungible_history ... ok -test reorg_history::case_2 ... ignored, fix needed -test invoice_reuse::case_2 ... ok -test reorg_history::case_4 ... ignored, fix needed -test ln_transfers::case_1 ... ok -test reorg_history::case_6 ... ignored, fix needed -test revert_genesis::case_1 ... ignored, fix needed -test revert_genesis::case_2 ... ignored, fix needed -test same_transfer_twice_no_update_witnesses::case_1 ... ignored, fix needed -test rbf_transfer ... ok -test same_transfer_twice_update_witnesses::case_1 ... ignored, fix needed -test collaborative_transfer ... ok -test blank_tapret_opret::case_2 ... ok -test sync_mainnet_wlt ... ignored, fix needed -test send_to_oneself ... ok -test same_transfer_twice_no_update_witnesses::case_2 - should panic ... ok -test receive_from_unbroadcasted_transfer_to_blinded ... ok -test same_transfer_twice_update_witnesses::case_2 ... ok -test reorg_history::case_1 has been running for over 60 seconds -test reorg_history::case_3 has been running for over 60 seconds -test reorg_history::case_5 has been running for over 60 seconds -test tapret_wlt_receiving_opret ... ok -test reorg_history::case_1 ... ok -test transfer_loop::case_01 has been running for over 60 seconds -test transfer_loop::case_02 has been running for over 60 seconds -test transfer_loop::case_03 has been running for over 60 seconds -test transfer_loop::case_04 has been running for over 60 seconds -test transfer_loop::case_01 ... ok -test transfer_loop::case_02 ... ok -test transfer_loop::case_03 ... ok -test transfer_loop::case_04 ... ok -test transfer_loop::case_05 has been running for over 60 seconds -test transfer_loop::case_06 has been running for over 60 seconds -test transfer_loop::case_05 ... ok -test reorg_history::case_3 ... ok -test transfer_loop::case_06 ... ok -test transfer_loop::case_07 has been running for over 60 seconds -test transfer_loop::case_08 has been running for over 60 seconds -test transfer_loop::case_09 has been running for over 60 seconds -test transfer_loop::case_10 has been running for over 60 seconds -test transfer_loop::case_08 ... ok -test transfer_loop::case_07 ... ok -test transfer_loop::case_09 ... ok -test transfer_loop::case_10 ... ok -test transfer_loop::case_11 has been running for over 60 seconds -test transfer_loop::case_12 has been running for over 60 seconds -test transfer_loop::case_13 has been running for over 60 seconds -test transfer_loop::case_11 ... ok -test transfer_loop::case_12 ... ok -test transfer_loop::case_13 ... ok -test reorg_history::case_5 ... ok -test transfer_loop::case_14 has been running for over 60 seconds -test transfer_loop::case_15 has been running for over 60 seconds -test transfer_loop::case_16 has been running for over 60 seconds -test transfer_loop::case_17 has been running for over 60 seconds -test transfer_loop::case_14 ... ok -test transfer_loop::case_15 ... ok -test transfer_loop::case_16 ... ok -test transfer_loop::case_17 ... ok -test transfer_loop::case_18 has been running for over 60 seconds -test transfer_loop::case_19 has been running for over 60 seconds -test transfer_loop::case_20 has been running for over 60 seconds -test transfer_loop::case_21 has been running for over 60 seconds -test transfer_loop::case_18 ... ok -test transfer_loop::case_19 ... ok -test transfer_loop::case_20 ... ok -test transfer_loop::case_21 ... ok -test transfer_loop::case_22 has been running for over 60 seconds -test transfer_loop::case_23 has been running for over 60 seconds -test transfer_loop::case_24 has been running for over 60 seconds -test transfer_loop::case_25 has been running for over 60 seconds -test transfer_loop::case_25 ... ok -test transfer_loop::case_22 ... ok -test transfer_loop::case_23 ... ok -test transfer_loop::case_24 ... ok -test transfer_loop::case_26 has been running for over 60 seconds -test transfer_loop::case_26 ... ok -test transfer_loop::case_27 has been running for over 60 seconds -test transfer_loop::case_28 has been running for over 60 seconds -test transfer_loop::case_29 has been running for over 60 seconds -test transfer_loop::case_27 ... ok -test transfer_loop::case_28 ... ok -test transfer_loop::case_29 ... ok -test transfer_loop::case_30 has been running for over 60 seconds -test transfer_loop::case_31 has been running for over 60 seconds -test transfer_loop::case_32 has been running for over 60 seconds -test transfer_loop::case_33 has been running for over 60 seconds -test transfer_loop::case_30 ... ok -test transfer_loop::case_33 ... ok -test transfer_loop::case_32 ... ok -test transfer_loop::case_31 ... ok -test transfer_loop::case_37 ... ok -test transfer_loop::case_34 has been running for over 60 seconds -test transfer_loop::case_34 ... ok -test transfer_loop::case_35 has been running for over 60 seconds -test transfer_loop::case_36 has been running for over 60 seconds -test transfer_loop::case_35 ... ok -test transfer_loop::case_36 ... ok -test transfer_loop::case_38 ... ok -test transfer_loop::case_41 ... ok -test transfer_loop::case_39 ... ok -test transfer_loop::case_40 ... ok -test transfer_loop::case_42 ... ok -test transfer_loop::case_43 ... ok -test transfer_loop::case_44 ... ok -test transfer_loop::case_45 ... ok -test transfer_loop::case_46 ... ok -test transfer_loop::case_47 ... ok -test transfer_loop::case_48 ... ok -test transfer_loop::case_49 ... ok -test transfer_loop::case_50 ... ok -test transfer_loop::case_51 ... ok -test transfer_loop::case_53 ... ok -test transfer_loop::case_54 ... ok -test transfer_loop::case_52 ... ok -test transfer_loop::case_55 ... ok -test transfer_loop::case_57 ... ok -test transfer_loop::case_56 ... ok -test transfer_loop::case_58 ... ok -test transfer_loop::case_59 ... ok -test transfer_loop::case_61 ... ok -test transfer_loop::case_62 ... ok -test transfer_loop::case_63 ... ok -test transfer_loop::case_60 ... ok -test transfer_loop::case_65 ... ok -test transfer_loop::case_64 ... ok -test transfer_loop::case_66 ... ok -test transfer_loop::case_67 ... ok -test transfer_loop::case_69 ... ok -test transfer_loop::case_68 ... ok -test transfer_loop::case_70 ... ok -test transfer_loop::case_71 ... ok -test transfer_loop::case_72 ... ok - -test result: ok. 88 passed; 0 failed; 13 ignored; 0 measured; 0 filtered out; finished in 623.16s - - Running tests/validation.rs (target/debug/deps/validation-7513d6bfd30f0852) - -running 6 tests -test validate_consignment_generate ... ignored, one-shot -test validate_consignment_chain_fail ... ok -test validate_consignment_bundles_fail ... ok -test validate_consignment_genesis_fail ... ok -test validate_consignment_resolver_error ... ok -test validate_consignment_success ... ok - -test result: ok. 5 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.36s \ No newline at end of file diff --git a/tests/dev-log/v12-first-test.log b/tests/dev-log/v12-first-test.log deleted file mode 100644 index a5e2f31..0000000 --- a/tests/dev-log/v12-first-test.log +++ /dev/null @@ -1,1351 +0,0 @@ -warning: `rgb-tests` (test "transfer") generated 20 warnings (10 duplicates) (run `cargo fix --test "transfer"` to apply 1 suggestion) - Finished `test` profile [unoptimized + debuginfo] target(s) in 8.50s - Running tests/issuance.rs (target/debug/deps/issuance-14bf51e9d8ee949c) - -running 16 tests -wallet_desc Tr -wallet_desc Wpkh -wallet_desc Wpkh -wallet_desc Tr -wallet_desc Wpkh -wallet_desc Tr -wallet_desc Wpkh -wallet_desc Tr -starting test services... -wallet dir: "test-data/integration/c3b8a9ca" -wallet dir: "test-data/integration/6ecd7b84" -wallet dir: "test-data/integration/b81c5451" -wallet dir: "test-data/integration/47e4d839" -wallet dir: "test-data/integration/723288fe" -wallet dir: "test-data/integration/62c37ee1" -wallet dir: "test-data/integration/53483baa" -wallet dir: "test-data/integration/1212899d" -A new contract issued with ID contract:4Z0OzxrC-GdteSzh-2cgWzc6-PawIvI~-WyCnX2m-HxtV_Vg -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_cfa::case_2 ... ok -wallet_desc Wpkh -wallet dir: "test-data/integration/b45df1e5" -A new contract issued with ID contract:qr23Xxof-Fzsy8rd-oZ8Y4wc-BaaZvuJ-MBKh2qR-D~H4bek -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_cfa::case_1 ... ok -wallet_desc Wpkh -wallet dir: "test-data/integration/691426a9" -A new contract issued with ID contract:NQO8p0vd-JWYcCy5-Og6TXi9-yTxcvlg-AGAIY_9-gSLHulQ -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_cfa::case_4 ... ok -wallet_desc Tr -wallet dir: "test-data/integration/f8d53132" -A new contract issued with ID contract:mJIFRnZ4-y_zit8M-GY9u3UF-fdaHct0-MUy3USS-4yLvo6I -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_cfa::case_3 ... ok -wallet_desc Tr -wallet dir: "test-data/integration/529b7132" -A new contract issued with ID contract:Eb13C_xq-U29y1Wc-iJ6PcoQ-V~xRU74-QG7Y1J8-VxZID4E -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -[tests/issuance.rs:59:5] &state.owned.allocations = [ - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), - vout: Vout( - 0, - ), - }, - 500000, - ), - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), - vout: Vout( - 0, - ), - }, - 500000, - ), -] -test issue_nia::case_1 ... ok -wallet_desc Wpkh -wallet dir: "test-data/integration/c9f37b64" -A new contract issued with ID contract:mRg2N_aF-uB4SMSd-JLURSmP-ypYXXO4-MC6fhFP-zNGVekU -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -[tests/issuance.rs:59:5] &state.owned.allocations = [ - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), - vout: Vout( - 0, - ), - }, - 500000, - ), - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), - vout: Vout( - 0, - ), - }, - 500000, - ), -] -test issue_nia::case_3 ... ok -wallet_desc Wpkh -wallet dir: "test-data/integration/c1d39754" -A new contract issued with ID contract:c0~DmmtE-LAJzcKW-ikEEJ9Z-KtiuqJB-G5WhYQA-D7MTnHs -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -[tests/issuance.rs:59:5] &state.owned.allocations = [ - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), - vout: Vout( - 0, - ), - }, - 500000, - ), - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), - vout: Vout( - 0, - ), - }, - 500000, - ), -] -test issue_nia::case_2 ... ok -wallet_desc Tr -A new contract issued with ID contract:RfIDBjvW-pEIT6Rs-z3HNzrA-uRCR5H5-mdXI9j~-JJDj35c -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -[tests/issuance.rs:59:5] &state.owned.allocations = [ - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000000), - vout: Vout( - 0, - ), - }, - 500000, - ), - ( - Outpoint { - txid: Array<32>(0000000000000000000000000000000000000000000000000000000000000001), - vout: Vout( - 0, - ), - }, - 500000, - ), -] -wallet dir: "test-data/integration/0bf90c30" -test issue_nia::case_4 ... ok -wallet_desc Tr -wallet dir: "test-data/integration/dbaa1f04" -test issue_cfa_multiple_utxos::case_1 has been running for over 60 seconds -test issue_cfa_multiple_utxos::case_2 has been running for over 60 seconds -test issue_cfa_multiple_utxos::case_3 has been running for over 60 seconds -test issue_cfa_multiple_utxos::case_4 has been running for over 60 seconds -A new contract issued with ID contract:oQQeEZW6-o83mtD2-J3nwy76-NClY1Op-W5SrptL-KQMB8X8 -A new contract issued with ID contract:f4n~qKMC-dnXWzGZ-3rRru~n-KjK6qTR-nThsVYG-mukpbpQ -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_nia_multiple_utxos::case_2 ... ok -test issue_cfa_multiple_utxos::case_2 ... ok -A new contract issued with ID contract:GWpU7ND9-VbzVX~X-z_rTnOM-TYqkkxc-mhMBJrN-78ZD~SY -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_cfa_multiple_utxos::case_1 ... ok -A new contract issued with ID contract:xYls1diR-IWh9m4j-Mq1dEzy-QkWC6Hd-Doe7sAC-eNKbAjE -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -A new contract issued with ID contract:wspuABJy-BskUelq-xS3XwoN-jOWn5cS-FJuSJRx-pBnXKkY -test issue_cfa_multiple_utxos::case_3 ... ok -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_nia_multiple_utxos::case_1 ... ok -A new contract issued with ID contract:7slgDA4u-bAqvKaZ-ld9_FW2-mnDFN29-kYZeJgO-NRzNP1g -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -A new contract issued with ID contract:Vu5~832o-FwECgUE-hIcNMVE-92~cD70-q78inlB-3seFHiA -A new contract issued with ID contract:j7abCp5p-KhezRWv-4BHKjY_-Pl7eJOE-urCnnbo-p~0q9Tg -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -[tests/utils/helpers.rs:1071:25] &v.verified = Enum( - Name( - VariantName( - "centiMilli", - ), - ), -) -test issue_cfa_multiple_utxos::case_4 ... ok -test issue_nia_multiple_utxos::case_3 ... ok -test issue_nia_multiple_utxos::case_4 ... ok - -test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 66.98s - - Running tests/transfer.rs (target/debug/deps/transfer-356099b53e0807f1) - -running 36 tests -test blank_tapret_opret::case_1 ... ignored, fix needed (calling to method absent in Codex API) -test blank_tapret_opret::case_2 ... ignored, fix needed (calling to method absent in Codex API) -test blank_tapret_opret::case_3 ... ignored, fix needed (calling to method absent in Codex API) -test blank_tapret_opret::case_4 ... ignored, fix needed (calling to method absent in Codex API) -test collaborative_transfer ... ignored, Pending multi-signature workflow documentation -test ln_transfers ... ignored, Pending Lightning Network integration documentation -test mainnet_wlt_receiving_test_asset ... ignored, fix needed -test reorg_history::case_1 ... ignored, fix needed -test reorg_history::case_2 ... ignored, fix needed -test reorg_history::case_3 ... ignored, fix needed -test reorg_history::case_4 ... ignored, fix needed -test reorg_history::case_5 ... ignored, fix needed -test reorg_history::case_6 ... ignored, fix needed -test same_transfer_twice_update_witnesses::case_1 ... ignored, Awaiting new rollback procedure API in RGB v0.12 -test same_transfer_twice_update_witnesses::case_2 ... ignored, Awaiting new rollback procedure API in RGB v0.12 -transfer_type Witness -transfer_type Blinded -starting test services... -with_transfers true -wallet dir: "test-data/integration/fb687462" -wallet dir: "test-data/integration/127c91cb" -wallet dir: "test-data/integration/5d243af8" -wallet dir: "test-data/integration/22d5a33a" -wallet dir: "test-data/integration/ec235ef7" -wallet dir: "test-data/integration/1ca4a0c1" -wallet dir: "test-data/integration/a3fbeb5d" -wallet dir: "test-data/integration/55865b11" -wallet dir: "test-data/integration/b50e95cf" -disconnect_reorg_nodes:instance:3 peers: [ -] -disconnect_reorg_nodes:instance:2 peers: [ -] -wallet dir: "test-data/integration/aed25b32" -A new contract issued with ID contract:CIwYp0Lo-_mpu~QN-mNueQ_q-I7AiYrb-s5Hdoio-MOsD7y4 -A new contract issued with ID contract:QeVEgypp-gGErzYy-HDV_QJR-dDaDiWP-X55jlVQ-mTmcIZc -A new contract issued with ID contract:NZoT~Amj-FlZI5cN-Gz4VGN0-50KTStz-MDPveMQ-ZlnJ3YE -A new contract issued with ID contract:M99chdch-1K1OQk9-je1Djzq-nHhsWWD-_XWJDbH-VJ9B4VA -A new contract issued with ID contract:6TRYS4R9-jnAG~VQ-7HiGsOs-IGMhFv7-St85Aeu-wupaeGs -A new contract issued with ID contract:6HojmiMu-JKcmdLE-l40gTKu-9CtCLAI-70109qe-qEUQwgc -wallet dir: "test-data/integration/c1953eff" -transfer txid: d8e2ac957b52392b30513823177c2f6482645aaf561c74eecb323193f3686420, consignment: 1 -transfer txid: 32b495841f92ad53d986caec36492c133b0b8a06c14339ba2ea7d41919fc772b, consignment: 2 -[tests/transfer.rs:562:5] wlt_1.runtime().state_all(None).map(|(c, s)| { s.owned }).collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(498de1142e27d9e96b315ad16709d22d26afd019e5689e86b3f0a4d18d034775), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(32b495841f92ad53d986caec36492c133b0b8a06c14339ba2ea7d41919fc772b), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 100, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(498de1142e27d9e96b315ad16709d22d26afd019e5689e86b3f0a4d18d034775), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(32b495841f92ad53d986caec36492c133b0b8a06c14339ba2ea7d41919fc772b), - vout: Vout( - 2, - ), - }, - data: Number( - Uint( - 1900, - ), - ), - }, - }, - }, -] -[tests/transfer.rs:567:5] wlt_1.runtime().state_own(None).map(|(c, s)| { s.owned }).collect::>() = [ - { - VariantName( - "owned", - ): {}, - }, -] -transfer txid: 764d2f4ddcca87f69e66b975487a370e1bd56ebf645279ad914a051589e5287b, consignment: 3 -thread 'same_transfer_twice_no_update_witnesses::case_2' panicked at tests/utils/helpers.rs:850:14: -called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -test same_transfer_twice_no_update_witnesses::case_2 ... FAILED -[tests/transfer.rs:648:5] wlt_1_contract_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(d5621ee862de91c173fba1b92fd0f34b130f8a124a08ca8fdf89e049dc3cfe5c), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(d8e2ac957b52392b30513823177c2f6482645aaf561c74eecb323193f3686420), - vout: Vout( - 2, - ), - }, - data: Number( - Uint( - 400, - ), - ), - }, - }, - }, -] -test accept_0conf has been running for over 60 seconds -test check_fungible_history has been running for over 60 seconds -test rbf_transfer has been running for over 60 seconds -test revert_genesis::case_1 has been running for over 60 seconds -transfer txid: 52d1826463b537e0dfdaf113d2f5ed48504c65cf5fe3f52cc55df25a36d1e915, consignment: 5 -test revert_genesis::case_2 has been running for over 60 seconds -test same_transfer_twice_no_update_witnesses::case_1 has been running for over 60 seconds -test send_to_oneself has been running for over 60 seconds -transfer txid: a7c1a5f3aae77ea6aefec7798a9fe59cfcd48dbd1f70631450b0e7a4f86f0c22, consignment: 6 -[tests/transfer.rs:562:5] wlt_1.runtime().state_all(None).map(|(c, s)| { s.owned }).collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(b3ccb0ba6327395dcb978c87a58177b6f182032a71f9a82c93dccb2e828dd45a), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(a7c1a5f3aae77ea6aefec7798a9fe59cfcd48dbd1f70631450b0e7a4f86f0c22), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 1900, - ), - ), - }, - }, - }, -] -[tests/transfer.rs:567:5] wlt_1.runtime().state_own(None).map(|(c, s)| { s.owned }).collect::>() = [ - { - VariantName( - "owned", - ): {}, - }, -] -test accept_0conf ... ok -transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Nia -wallet dir: "test-data/integration/fce20f94" -thread 'same_transfer_twice_no_update_witnesses::case_1' panicked at tests/utils/helpers.rs:850:14: -called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) -test same_transfer_twice_no_update_witnesses::case_1 ... FAILED -transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Nia -wallet dir: "test-data/integration/5a2d6f5c" -transfer txid: c86e077a61446cb8ad7ea1bd524894bc5f4ae2564fa96a6ad1ccf05789c72b5c, consignment: 7 -wallet dir: "test-data/integration/3a9eebd4" -wallet dir: "test-data/integration/0b827ff4" -[tests/transfer.rs:758:5] wlt.runtime().state_own(None).map(|s| s.1.owned).collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(105402272fd310f1664efa7c7617afd893c029e375c27d38fd35f012f1e8a367), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(764d2f4ddcca87f69e66b975487a370e1bd56ebf645279ad914a051589e5287b), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 200, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(105402272fd310f1664efa7c7617afd893c029e375c27d38fd35f012f1e8a367), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(764d2f4ddcca87f69e66b975487a370e1bd56ebf645279ad914a051589e5287b), - vout: Vout( - 2, - ), - }, - data: Number( - Uint( - 400, - ), - ), - }, - }, - }, -] -test send_to_oneself ... ok -transfer_type Blinded wlt_1_desc Tr wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Nia -wallet dir: "test-data/integration/4fe26820" -wallet dir: "test-data/integration/f645aea1" -thread 'rbf_transfer' panicked at tests/utils/helpers.rs:850:14: -called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) -test rbf_transfer ... FAILED -transfer_type Blinded wlt_1_desc Tr wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Nia -wallet dir: "test-data/integration/d065e778" -wallet dir: "test-data/integration/7dbf82b2" -test tapret_wlt_receiving_opret has been running for over 60 seconds -test transfer_loop::case_01 has been running for over 60 seconds -test transfer_loop::case_02 has been running for over 60 seconds -test transfer_loop::case_03 has been running for over 60 seconds -test transfer_loop::case_04 has been running for over 60 seconds -forcibly breaking mining wait -forcibly breaking mining wait -A new contract issued with ID contract:JXRNCAC0-vqFi9C1-YvEq5AT-7xIfPjl-cIPmR3O-zvgooro -A new contract issued with ID contract:1M2HqAF2-eWcMDR6-S5xA5TE-azdsrDf-UIhKu~z-l1~m_x0 -A new contract issued with ID contract:YEHU4iOj-ywIiHVW-An7KqAo-SjrSgXN-Y0N75C7-nsuQ0sM -A new contract issued with ID contract:pLQI5l16-VfpM_1d-1_3gcl3-Xjql042-qO1UXAY-jscJDo0 -A new contract issued with ID contract:F1mG3CDQ-HjKYFiB-15f0Pl9-82DZE0I-tdreTRU-ADw_JTk -A new contract issued with ID contract:9Kxul6xe-S9WQe_X-MXrdh1C-wgshmVK-172kAXm-LQqJicI -test revert_genesis::case_2 ... ok -transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Cfa -wallet dir: "test-data/integration/29648f8e" -wallet dir: "test-data/integration/3707dcd5" -wallet dir: "test-data/integration/95ffcfe6" -wallet dir: "test-data/integration/06e00797" -A new contract issued with ID contract:x~61iNNI-KLMsSHY-pa3WW01-~hHnn4Z-jcFPEoN-vJKoYG4 -A new contract issued with ID contract:_opB7KYm-9lnqvCB-aO~hbix-p8aFQFJ-jKdTp~U-OUpTOe4 -A new contract issued with ID contract:AuPtCKRe-rCcSxFR-99p3c3Y-sDhSzAM-63uVLv6-0aZbKt0 -[tests/transfer.rs:708:5] wlt_1.contracts_info() = [ - ContractInfo { - id: ContractId( - Array<32>(c7feb588d34828b32c4876296b7596d35fe11e79f86637053c4a0dbc92a8606e), - ), - name: Named( - TypeName( - "TestAsset", - ), - ), - issuer: Identity( - RString( - "ssi:anonymous", - ), - ), - timestamp: 2024-12-18T12:32:00Z, - codex: CodexInfo { - id: CodexId( - Array<32>(ce7c10195856adf45af1e96935a02c516516c57b01fb85250bf4df4c4461066e), - ), - name: Confined( - "NonInflatableAsset", - ), - developer: Identity( - RString( - "dns:pandoraprime.ch", - ), - ), - timestamp: 2024-11-25T10:08:27Z, - }, - consensus: Bitcoin, - testnet: true, - }, -] -[tests/transfer.rs:709:5] wlt_1.runtime().state_own(Some(contract_id)).map(|s| -{ s.1.owned }).collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(a66abae6e7ed55ddd77e5f42a22105c31d0179af5d93d591315e94872b8a0bbc), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(73895d87802e07c6207496d4cf0c577bcc115727bae6e94b9d569e29099f1ffb), - vout: Vout( - 0, - ), - }, - data: Number( - Uint( - 600, - ), - ), - }, - }, - }, -] -A new contract issued with ID contract:RbyDBkD3-PQMeXRs-HomsVSf-PprU097-YEprjWy-1p~0UY8 -A new contract issued with ID contract:Iq5HSxB4-uKEKYXi-cpWwtDv-R2IE12P-tmR5nZq-09MB4DY -thread 'transfer_loop::case_02' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -thread 'transfer_loop::case_04' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -test transfer_loop::case_02 ... FAILED -transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Cfa -wallet dir: "test-data/integration/84dffb5f" -test transfer_loop::case_04 ... FAILED -transfer_type Blinded wlt_1_desc Tr wlt_2_desc Wpkh asset_schema_1 Nia asset_schema_2 Cfa -wallet dir: "test-data/integration/ad31517a" -thread 'transfer_loop::case_03' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -test transfer_loop::case_03 ... FAILED -transfer_type Blinded wlt_1_desc Tr wlt_2_desc Tr asset_schema_1 Nia asset_schema_2 Cfa -wallet dir: "test-data/integration/01b7ced5" -transfer txid: 81beabcfc3e2814c93613956a11ef74a8302adfd2650036f8bca07b63963975f, consignment: 13 -wallet dir: "test-data/integration/ebb6c6cc" -wallet dir: "test-data/integration/9a9000b0" -wallet dir: "test-data/integration/fcc6104d" -A new contract issued with ID contract:6oY3HBBW-WoLM0BC-qfNmS5m-Hiiv0Xh-~EgbGMN-o6auh9Y -A new contract issued with ID contract:TABg8Zsd-BkgEjpT-Aaf~tVB-4n8dsUB-AzyT9IE-0ok4DlI -A new contract issued with ID contract:SZEB7SUU-d90Lj6_-TgJvZza-3Ud4Rgt-SPZmZp5-8gTma5A -A new contract issued with ID contract:Rg0F_IyI-u8S8n1r-qb2f_37-J0OWn2_-t05jqaj-ZIOZgfw -thread 'transfer_loop::case_01' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -test transfer_loop::case_01 ... FAILED -transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Wpkh asset_schema_1 Cfa asset_schema_2 Cfa -wallet dir: "test-data/integration/2ae8ebbf" -A new contract issued with ID contract:dJx9RCNL-ApW16Sn-pV~3DPx-FZfHKZ6-RijjyRD-F9WbxYE -A new contract issued with ID contract:KVKT_rDM-im70d9o-QTAC7SD-RfL8yqA-A0ap3K8-YcpGiHQ -transfer txid: 94a03dd0f8142ff1624e6cf05811576efd4b8bc77e929f9bbab5cbf227eebdc9, consignment: 15 -[tests/transfer.rs:721:5] wlt_1.runtime().state_own(Some(contract_id)).map(|s| -{ s.1.owned }).collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(b7d555b88f6932c0de780ab2af37df2c40007869d45b2e2040a722c1fecef225), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(81beabcfc3e2814c93613956a11ef74a8302adfd2650036f8bca07b63963975f), - vout: Vout( - 2, - ), - }, - data: Number( - Uint( - 400, - ), - ), - }, - }, - }, -] -[tests/transfer.rs:726:5] wlt_2.runtime().state_own(Some(contract_id)).map(|s| -{ s.1.owned }).collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(b7d555b88f6932c0de780ab2af37df2c40007869d45b2e2040a722c1fecef225), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(81beabcfc3e2814c93613956a11ef74a8302adfd2650036f8bca07b63963975f), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 200, - ), - ), - }, - }, - }, -] -with_transfers false -test check_fungible_history ... ok -transfer_type Blinded wlt_1_desc Wpkh wlt_2_desc Tr asset_schema_1 Cfa asset_schema_2 Cfa -wallet dir: "test-data/integration/1dff19fa" -wallet dir: "test-data/integration/6b3f7e48" -wallet dir: "test-data/integration/fd23c744" -disconnect_reorg_nodes:instance:3 peers: [ -] -disconnect_reorg_nodes:instance:2 peers: [ -] -wallet dir: "test-data/integration/03f95445" -A new contract issued with ID contract:4AUpeDyY-_WDY00i-KYzTYYd-bN4Ywl8-w3yFJj3-wc9uY~8 -test revert_genesis::case_1 ... ok -transfer_type Blinded wlt_1_desc Tr wlt_2_desc Wpkh asset_schema_1 Cfa asset_schema_2 Cfa -wallet dir: "test-data/integration/165cb223" -wallet dir: "test-data/integration/0a5c7dc0" -A new contract issued with ID contract:jPR6QljT-QHBn1fd-iGfnrxp-aSjJBM7-EdzkQPg-_ynQlEM -A new contract issued with ID contract:eMkXEEbK-~p0jzZ9-j~STIAl-uIh7XB7-hk2OtiY-3oPTTtQ -wallet dir: "test-data/integration/18daf55a" -wallet dir: "test-data/integration/178e0889" -A new contract issued with ID contract:Rigqlc5i-P~7Gxau-w75O8UY-IdMxJFO-_ooE9~K-9a648iI -A new contract issued with ID contract:jy~Ej6SI-Q2B23Rm-1g7kahT-V~36Qr_-ax6JMe2-AFLZRuY -transfer txid: 8788bb5ef3ef432e81d85caf9f26b5a30dfeca26b2a10c73a45584a2f319b7e5, consignment: 16 -transfer txid: 38115c5307ccc89e84bda26eb05d2c44a6e6c4272555b4ffd13caabad021842c, consignment: 17 -transfer txid: 38e29d25cb31466c4a7cb5261f37123dfb7838af00921cebf7c6ef92a2a3d867, consignment: 18 -A new contract issued with ID contract:LzMGZEx8-EfgYgQx-ZRyEKEy-noUbpLB-9PHWVPC-B_5r4Kg -A new contract issued with ID contract:KMbA50Sa-g2uTaq4-zKxhqzM-nZD_W2f-KU1V_ky-qmz4h0o -A new contract issued with ID contract:F2z~~fIF-OjQoxeJ-BbSbkKl-7I~dYCv-DOTVBEG-YsG6hjU -transfer txid: 1b54e31ddac3a18ca1953cffc4b6156328a09fef832683a243b114b8957dfefd, consignment: 19 -transfer txid: 0d429b07175bf13edc847bcdb50a2a8a6c9e4abe45f9aaddaba9caf5f8dc82be, consignment: 21 -transfer txid: 61962ff0ce375de435b331b24dbd52d440dab500eaf894e2ce710ecad2b50d9b, consignment: 20 -transfer txid: b0bdd0b16177fefc98039bb0445345eff13985b24c711d46b19471639376e611, consignment: 23 -transfer txid: 807f574197702f9a8df1e1530af6b74518db84269a8774ae7525e03150bd72e9, consignment: 24 -transfer txid: 49805441d2df33bc1467e2beee398381991b0c3782d95a17d313fcb0675c5bc6, consignment: 22 -transfer txid: f6a6d3422f72d24fd87988660a69b278568b4860bf37d183dddf7f3f419cd03b, consignment: 26 -transfer txid: 8589750221b23e4ffed8b84d4abedf7484c41fca173100b66280171f26232b7f, consignment: 25 -thread 'transfer_loop::case_05' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -test transfer_loop::case_05 ... FAILED -transfer_type Blinded wlt_1_desc Tr wlt_2_desc Tr asset_schema_1 Cfa asset_schema_2 Cfa -wallet dir: "test-data/integration/af24bda7" -transfer txid: acdbaa67b547b21c8ca936e36a1f41291a19e6c2a99d0a273b541942a6906fff, consignment: 28 -transfer txid: b87398da716a41f2970adc61121b70c27cabb7e8d40500d9995bc2f9d00deda5, consignment: 29 -wallet dir: "test-data/integration/20b56ed4" -transfer txid: b85afc69021a4fcf8cb8052f9cd008972658864b8cb90cda50f6a604b9d8c47f, consignment: 30 -[tests/utils/helpers.rs:568:21] tx.inputs.iter().map(|i| i.prev_output).collect::>() = [ - Outpoint { - txid: Array<32>(595832f4127ca4b26e7d9f6bb90e393b20a2a0b34ac48ce7aa0f77be24cc6cb8), - vout: Vout( - 0, - ), - }, -] -[tests/utils/helpers.rs:568:21] &e = HttpResponse { - status: 400, - message: "sendrawtransaction RPC error: {\"code\":-27,\"message\":\"Transaction already in block chain\"}", -} -thread 'tapret_wlt_receiving_opret' panicked at tests/utils/helpers.rs:574:18: -called `Result::unwrap()` on an `Err` value: HttpResponse { status: 400, message: "sendrawtransaction RPC error: {\"code\":-27,\"message\":\"Transaction already in block chain\"}" } -test tapret_wlt_receiving_opret ... FAILED -A new contract issued with ID contract:6X8H4Hte-j9wAx6o-WZWA9S4-S0pk9ar-lisk3vV-wOLxzag -A new contract issued with ID contract:vg3TWTC9-SqtTlB5-lKHQrNQ-pbj25Wg-8p3ZUyr-_SEQ9Fc -thread 'transfer_loop::case_06' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -test transfer_loop::case_06 ... FAILED -thread 'transfer_loop::case_07' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -test transfer_loop::case_07 ... FAILED -transfer txid: a2ad7050d23b566f8d1d0ecfc5f4fd15b61f6c0b46f83a34c694a7b451e2f6fa, consignment: 33 -thread 'transfer_loop::case_08' panicked at sonic/api/src/schema.rs:84:14: -calling to method absent in Codex API -test transfer_loop::case_08 ... FAILED -transfer txid: bee77f26ac6b44af531f12bdf31f13e6386b396b36b1a6bf5e4890f0af2254fc, consignment: 35 -transfer txid: 907e7d07e1aa0d6129aa0b5dbcf9528a7149ab94681e6010ab1859ae7a3beebd, consignment: 36 -transfer txid: 900288520864289efbd0d8a604af9cc4d25182e1ebb5064b58a7e1e5b8575abb, consignment: 37 -transfer txid: 86448b4d1c93b875a009c70a3ed793ecdf0a077c7810eaca513ea127df3357f7, consignment: 38 -transfer txid: c84794743ace45d932f8d6ee5e063e27797892ef17100d7e7e24619dec5360df, consignment: 41 -transfer txid: 606f0fc715b2c7a0e27e4ae5399121e563c88a7b99b4a91c1cdd749bb1e6ddff, consignment: 39 -transfer txid: 5f638aafdf2e4261a811622d271b0a5dfa10e94d86224b7acc8c195e26ed90e2, consignment: 40 -transfer txid: b53398068e54ea4d74acb0afa4b0d6dbded2d5ae51927274d7f93985f53e9625, consignment: 42 -transfer txid: c005f7fba2f8d3694f1f573840972b1336093d8d752857be30b1756bb4c74963, consignment: 43 -transfer txid: b93a5edfcdf91d332e877a8f0e26c9297eb04b2c365aa39621ff38e5ce78df05, consignment: 45 -transfer txid: 0a583e16e58b1d3b98ccf22f57b43ea230c72e048790bc852b6f6bff72745e02, consignment: 44 -transfer txid: 6370419e089e94afdb960198a5c590ef4af67b42af628897dcb62cae1e184e5b, consignment: 46 -[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(5b31306bed3f28e13590d1081d9bcbd4684ce6be2bcbe4e9869da2dfcf8da582), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(c1252ce1747030aa12c4d789023f4381429cea6a5bebb1190b55a4e70de81ecd), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 111, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(d9bbd6856212642394341486fa4b17ed67b3edeb5b60ff1278fbe86c0b4dff9b), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(bee77f26ac6b44af531f12bdf31f13e6386b396b36b1a6bf5e4890f0af2254fc), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 867, - ), - ), - }, - }, - }, - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(5c5e1396753ab6d64031ad79554259d9ba4dea8bb27ce599bcb75c7e99cf929d), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(ee6ffdc6f1bb1fc04b7c72b51182eb34a56aca8a61a25ba5bff7a3c1d1ff710c), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(a26a48962e0ea4f47463f5b45c7e4649d7de68f517c80bbd6f2f4cf5e68b9660), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(bee77f26ac6b44af531f12bdf31f13e6386b396b36b1a6bf5e4890f0af2254fc), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - }, - }, -] -[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(a064ae6cf4d98415cec7be52c3ffd3e4e9cf174377b09a79d4c6c05c98a4972a), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(900288520864289efbd0d8a604af9cc4d25182e1ebb5064b58a7e1e5b8575abb), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(a8db0cbcbd960aef723a9afb0588ba18fa853d80c5ae13e96fc0cfc332cd3b64), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(c8107905d86a1f9f68466bce46233bfcfcda49b29ab03169f74b8b774627bb44), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - }, - }, - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(6aae48b92b6a0a018699d80bc149f3fea124e808bd9d8268e048900243c34de4), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(900288520864289efbd0d8a604af9cc4d25182e1ebb5064b58a7e1e5b8575abb), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 867, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(70bdcadb4c3ce99592737353bc4f62b9a717ed05e25f5801d6643306c6d31718), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(840608def10c6747bec77e6cc614a4e68e16081efd798a3aabad9aad4d8a926b), - vout: Vout( - 0, - ), - }, - data: Number( - Uint( - 111, - ), - ), - }, - }, - }, -] -test transfer_loop::case_09 has been running for over 60 seconds -test transfer_loop::case_10 has been running for over 60 seconds -transfer txid: bb5d25f95d0ce13db29a6892e99bc02f18833f1821a4f5197e998639990e6713, consignment: 49 -transfer txid: 2855d899c87314a74877d5f68a571c8d72425b02118c9dcd78b0299168e90125, consignment: 48 -transfer txid: c3bf69e92182d1e3e93e0ab105810682e0514205e3163cdc7b19f93307421527, consignment: 47 -[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(6863afc3d8e25308042d56aae7ce08e86d4c9b9f851251a072f40e89e5f0f38c), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(d82f1d8807da8288e2060a123f6d178e08b97722f798a781755436581b163bf5), - vout: Vout( - 0, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(c6159f6a7f58ee05c6d6be7ba8a71bfb94078085b7e41b10fc83b3f832735ebf), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(86448b4d1c93b875a009c70a3ed793ecdf0a077c7810eaca513ea127df3357f7), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - }, - }, - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(e06e555d565898c31fff2febd753b1c7fefa2e58be2a4a284d36ab1aa87607fa), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(9f9c2b9ffe2b335897d676b13b3c0d6252df05ac9f26a5ff8b0b10c3fe20157a), - vout: Vout( - 0, - ), - }, - data: Number( - Uint( - 111, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(e3cb747c2f553eb017d0d64bc236e5391a2a8643eaebf8e1a8f0b922717b86d0), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(86448b4d1c93b875a009c70a3ed793ecdf0a077c7810eaca513ea127df3357f7), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 867, - ), - ), - }, - }, - }, -] -test transfer_loop::case_11 has been running for over 60 seconds -transfer txid: e076018c18a723574583af1ebcae93e03d76ef6ecea7e60ff97bbb9b8047a373, consignment: 50 -[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(63622a49d1f8a779ba2b4e740bbabc375731a278404ea641e656a8b18961f395), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(2855d899c87314a74877d5f68a571c8d72425b02118c9dcd78b0299168e90125), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(a8db0cbcbd960aef723a9afb0588ba18fa853d80c5ae13e96fc0cfc332cd3b64), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(c8107905d86a1f9f68466bce46233bfcfcda49b29ab03169f74b8b774627bb44), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - }, - }, - { - VariantName( - "owned", - ): {}, - }, -] -thread 'transfer_loop::case_10' panicked at tests/utils/helpers.rs:914:17: -assertion `left == right` failed - left: [11, 644] - right: [655] -[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): {}, - }, - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(5c5e1396753ab6d64031ad79554259d9ba4dea8bb27ce599bcb75c7e99cf929d), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(ee6ffdc6f1bb1fc04b7c72b51182eb34a56aca8a61a25ba5bff7a3c1d1ff710c), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(a1d102045c3fb4f3822d62b0f994b9637c388ac9f7fad4d0eb021dce96d230bb), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(c3bf69e92182d1e3e93e0ab105810682e0514205e3163cdc7b19f93307421527), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - }, - }, -] -thread 'transfer_loop::case_09' panicked at tests/utils/helpers.rs:914:17: -assertion `left == right` failed - left: [11, 644] - right: [655] -[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(60d126dafdfca72926d32187509a0ae03b7cabcf8dd7116a6f0427ca40aa3e1e), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(e076018c18a723574583af1ebcae93e03d76ef6ecea7e60ff97bbb9b8047a373), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(6863afc3d8e25308042d56aae7ce08e86d4c9b9f851251a072f40e89e5f0f38c), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(d82f1d8807da8288e2060a123f6d178e08b97722f798a781755436581b163bf5), - vout: Vout( - 0, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - }, - }, - { - VariantName( - "owned", - ): {}, - }, -] -thread 'transfer_loop::case_11' panicked at tests/utils/helpers.rs:914:17: -assertion `left == right` failed - left: [11, 644] - right: [655] -transfer txid: 14176fd58d2d56a9f66414e314666d59cc7c08c3b036bd408eb7cb321148ae89, consignment: 52 -transfer txid: da5369f1bfdf9c9068caeabe5b0325a5d2a24c523a1eaf700db7bdb5f1f99dd6, consignment: 51 -transfer txid: f4641d46f284e542aedb69c3515b1876c5ff4c94b71a19dc13f465521381a066, consignment: 53 -transfer txid: 697e2dcec845e593e0c3ffdfa65ba59cd6829c36995bf8470fcf9e2927f8ce64, consignment: 54 -[tests/transfer.rs:422:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(207ec47bb8f85d23cc630027f2355884a35f4e8645d52a9f2a2bdf282d44867c), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(c4512d6e4e0db3e7eb5f4b3204a74583e0e1eee5f7dc43dc7efe29f475cbd403), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(37072c6093b3e3026b87eeece3f23d0531a55702e790e04865b8cdb8b056ea2e), - ), - pos: 1, - }: Assignment { - seal: Outpoint { - txid: Array<32>(0a583e16e58b1d3b98ccf22f57b43ea230c72e048790bc852b6f6bff72745e02), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - }, - }, - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(674273677b864e0f92ec399012e4bc1bf6f112a5649aef8e3870544431224e24), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(0a583e16e58b1d3b98ccf22f57b43ea230c72e048790bc852b6f6bff72745e02), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 867, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(fa32075db4b159ea4467ec1e20538715254566555c2e15fefca71f274757fc6c), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(5d0c848b907391acde837244305935a826f000df53a46829825c9b96f02d43c4), - vout: Vout( - 0, - ), - }, - data: Number( - Uint( - 111, - ), - ), - }, - }, - }, -] -test transfer_loop::case_10 ... ok -test transfer_loop::case_09 ... ok -test transfer_loop::case_12 has been running for over 60 seconds -transfer txid: 44332505f8aad577eae3f83d1c12bf5b39186f4d6b186c8f660b3c3e4a7da665, consignment: 55 -test transfer_loop::case_11 ... ok -[tests/transfer.rs:444:9] wlt_1_contract_2_state.collect::>() = [ - { - VariantName( - "owned", - ): { - CellAddr { - opid: Opid( - Array<32>(207ec47bb8f85d23cc630027f2355884a35f4e8645d52a9f2a2bdf282d44867c), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(c4512d6e4e0db3e7eb5f4b3204a74583e0e1eee5f7dc43dc7efe29f475cbd403), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 11, - ), - ), - }, - CellAddr { - opid: Opid( - Array<32>(c89fd96b42db7d11ba35f8c4ef84c518fe0f1cec10ef559f24d4330782fe9b72), - ), - pos: 0, - }: Assignment { - seal: Outpoint { - txid: Array<32>(44332505f8aad577eae3f83d1c12bf5b39186f4d6b186c8f660b3c3e4a7da665), - vout: Vout( - 1, - ), - }, - data: Number( - Uint( - 644, - ), - ), - }, - }, - }, - { - VariantName( - "owned", - ): {}, - }, -] -thread 'transfer_loop::case_12' panicked at tests/utils/helpers.rs:914:17: -assertion `left == right` failed - left: [11, 644] - right: [655] -transfer txid: 6881a0b4b1723a71af7748e767c77823b7e5e15f538d7cfca0c3368b0ea72aef, consignment: 56 -test transfer_loop::case_12 ... ok - -failures: - -failures: - rbf_transfer - same_transfer_twice_no_update_witnesses::case_1 - same_transfer_twice_no_update_witnesses::case_2 - tapret_wlt_receiving_opret - transfer_loop::case_01 - transfer_loop::case_02 - transfer_loop::case_03 - transfer_loop::case_04 - transfer_loop::case_05 - transfer_loop::case_06 - transfer_loop::case_07 - transfer_loop::case_08 - -test result: FAILED. 9 passed; 12 failed; 15 ignored; 0 measured; 0 filtered out; finished in 290.95s - -error: test failed, to rerun pass `--test transfer` From 955cc8ad7347d3f40c06d2c052a2a24742fc5434 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 7 Mar 2025 23:29:45 +0800 Subject: [PATCH 32/90] feat(tests): Implement targeted attack types for RGB consignment testing Signed-off-by: will-bitlightlabs --- Cargo.lock | 4 + Cargo.toml | 11 +- tests/utils/consignment_utils.rs | 490 +++++++++++++++++++++++++++++++ tests/utils/mod.rs | 1 + tests/validation.rs | 2 + 5 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 tests/utils/consignment_utils.rs create mode 100644 tests/validation.rs diff --git a/Cargo.lock b/Cargo.lock index 3e8e95b..705da04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1760,6 +1760,7 @@ name = "rgb-tests" version = "0.1.0" dependencies = [ "amplify", + "amplify_derive", "bitcoin_hashes", "bp-core", "bp-electrum", @@ -1770,6 +1771,7 @@ dependencies = [ "commit_verify", "descriptors", "file-format", + "hypersonic", "once_cell", "psbt", "rand", @@ -1778,9 +1780,11 @@ dependencies = [ "rgb-std", "rstest", "rstest_reuse", + "serde", "serde_json", "serde_yaml", "serial_test", + "single_use_seals", "strict_encoding", "strict_types", "strum", diff --git a/Cargo.toml b/Cargo.toml index e56b6fe..c980a56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ once_cell = "1.19.0" rand = "0.8.5" rstest = "0.19.0" rstest_reuse = "0.6.0" +serde = "1.0.215" serde_yaml = "0.9" serde_json = "1.0" serial_test = "3.2.0" @@ -57,15 +58,21 @@ rgb-psbt = { path = "./rgb/psbt", features = ["bp"] } rgb-std = { path = "./rgb-std", features = ["fs"] } ## rust-amplify amplify = { path = "./rust-amplify" } +amplify_derive = { path = "./amplify-derive" } ## strict-encoding -strict_encoding = { path = "./strict-encoding/rust" } +strict_encoding = { path = "./strict-encoding/rust", features = ["serde"] } ## strict-types strict_types = { path = "./strict-types" } ## commit_verify commit_verify = { path = "./client_side_validation/commit_verify" } +## sonic +hypersonic = { path = "./sonic" } +## single_use_seals +single_use_seals = { path = "./client_side_validation/single_use_seals", features = ["strict_encoding"] } tabled = "0.18.0" + [patch.crates-io] # patching all RGB-related deps, to measure code coverage ## rust-amplify @@ -99,7 +106,7 @@ bp-wallet = { path = "./bp-wallet" } ## client_side_validation commit_verify = { path = "./client_side_validation/commit_verify" } commit_encoding_derive = { path = "./client_side_validation/commit_verify/derive" } -single_use_seals = { path = "./client_side_validation/single_use_seals" } +single_use_seals = { path = "./client_side_validation/single_use_seals"} ## rgb rgb-runtime = { path = "./rgb" } rgb-psbt = { path = "./rgb/psbt" } diff --git a/tests/utils/consignment_utils.rs b/tests/utils/consignment_utils.rs new file mode 100644 index 0000000..2dd641d --- /dev/null +++ b/tests/utils/consignment_utils.rs @@ -0,0 +1,490 @@ +use std::collections::BTreeMap; +use std::fs::{self, File}; +use std::io::{self, Read, Write}; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use amplify::confinement::SmallOrdMap; +use amplify::hex::ToHex; +use amplify::{Bytes16, Display, From}; +use bp::seals::WTxoSeal; +use commit_verify::ReservedBytes; +use hypersonic::aora::Aora; +use hypersonic::{Articles, ContractId, FileSupply, Operation}; +use rgb::sigs::ContentSigs; +use rgb::{ + Contract, FilePile, Index, MoundConsumeError, Pile, PublishedWitness, RgbSealDef, Schema, + SealWitness, SingleUseSeal, Stockpile, MAGIC_BYTES_CONSIGNMENT, +}; +use serde::{Deserialize, Serialize}; +use strict_encoding::{ + DecodeError, StreamReader, StreamWriter, StrictDecode, StrictEncode, StrictReader, StrictWriter, +}; + +#[derive(Debug, Display, From)] +#[display(doc_comments)] +pub enum ConsignmentParseError { + /// I/O error: {0} + #[from] + Io(io::Error), + + /// Strict encoding error: {0} + #[from] + Decoding(DecodeError), + + /// Unrecognized magic bytes in consignment stream ({0}) + UnrecognizedMagic(String), + + /// Unknown contract {0} can't be consumed; please import contract articles first. + UnknownContract(ContractId), + + // Because MoundConsumeError does not implement Debug, + // It affects the Debug and Error implementation of the entire structure, + // So here we store the string representation of the MoundConsumeError error + MoundConsume(String), + + /// Serialization error: {0} + SerializationError(String), + + /// Invalid witness count: {0} + InvalidWitnessCount(u64), + + /// Serde YAML error: {0} + #[from] + SerdeYaml(serde_yaml::Error), + + /// Invalid data: {0} + InvalidData(String), +} + +impl std::error::Error for ConsignmentParseError {} + +/// Parse consignment data into a directory +/// This function follows the logic of dump_consignment in rgb-std/cli/src/dump.rs +pub fn parse_consignment(src: &Path, dst: &Path) -> Result<(), ConsignmentParseError> +where + SealDef: RgbSealDef + Serialize, + SealDef::Src: Serialize, + ::CliWitness: + Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, + ::PubWitness: + Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, + <::PubWitness as PublishedWitness>::PubId: + Ord + From<[u8; 32]> + Into<[u8; 32]> + Serialize, +{ + fs::create_dir_all(dst)?; + + let file = File::open(src)?; + let mut stream = StrictReader::with(StreamReader::new::<{ usize::MAX }>(file)); + + let magic_bytes = Bytes16::strict_decode(&mut stream)?; + if magic_bytes.to_byte_array() != MAGIC_BYTES_CONSIGNMENT { + return Err(ConsignmentParseError::UnrecognizedMagic( + magic_bytes.to_hex(), + )); + } + + // Version + ReservedBytes::<2>::strict_decode(&mut stream)?; + + let contract_id = ContractId::strict_decode(&mut stream)?; + println!( + "Parsing consignment for {} into '{}'", + contract_id, + dst.display() + ); + + let mut op_count = 1; + let mut seal_count = 0; + let mut witness_count = 0; + + print!("Processing contract articles ... "); + let articles = Articles::strict_decode(&mut stream)?; + + // Save genesis + let out = File::create(dst.join(format!( + "0000-genesis.{}.yaml", + articles.contract.genesis_opid() + )))?; + serde_yaml::to_writer(&out, &articles.contract.genesis)?; + + // Save codex + let out = File::create(dst.join(format!("codex.{}.yaml", articles.schema.codex.codex_id())))?; + serde_yaml::to_writer(&out, &articles.schema.codex)?; + + // Save schema + let out = File::create(dst.join("schema.yaml"))?; + serde_yaml::to_writer(&out, &articles.schema)?; + + // Save contract + let out = File::create(dst.join("contract.yaml"))?; + serde_yaml::to_writer(&out, &articles.contract)?; + + // Save contract signatures + let out = File::create(dst.join("contract_sigs.yaml"))?; + serde_yaml::to_writer(&out, &articles.contract_sigs)?; + + // Save seals + let out = File::create(dst.join("0000-seals.yml"))?; + let defined_seals = SmallOrdMap::::strict_decode(&mut stream) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; + serde_yaml::to_writer(&out, &defined_seals)?; + seal_count += defined_seals.len(); + + let count = u64::strict_decode(&mut stream) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; + if count != 0 { + println!("error"); + return Err(ConsignmentParseError::InvalidWitnessCount(count)); + } + println!("success"); + + // Create operations directory + let operations_dir = dst.join("operations"); + fs::create_dir_all(&operations_dir)?; + + println!(); + loop { + match Operation::strict_decode(&mut stream) { + Ok(operation) => { + let opid = operation.opid(); + + // save operation + let out = + File::create(operations_dir.join(format!("{op_count:04}-op.{opid}.yaml")))?; + serde_yaml::to_writer(&out, &operation)?; + + // save seals + let out = File::create(operations_dir.join(format!("{op_count:04}-seals.yml")))?; + let defined_seals = SmallOrdMap::::strict_decode(&mut stream) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; + serde_yaml::to_writer(&out, &defined_seals)?; + seal_count += defined_seals.len(); + + // save witnesses + let len = u64::strict_decode(&mut stream) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; + for no in 0..len { + let out = File::create( + operations_dir.join(format!("{op_count:04}-witness-{:02}.yml", no + 1)), + )?; + let witness = SealWitness::::strict_decode(&mut stream) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; + serde_yaml::to_writer(&out, &witness)?; + } + + witness_count += len as usize; + op_count += 1; + } + Err(DecodeError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => break, + Err(e) => return Err(ConsignmentParseError::Decoding(e)), + } + print!( + "\rParsing stream ... {op_count} operations, {seal_count} seals, {witness_count} \ + witnesses processed", + ); + } + println!(); + Ok(()) +} + +#[test] +fn test_parse_and_rebuild_consignment() { + let src = Path::new("test-data/integration/00d99ed6/consignment-551.rgb"); + let dst = Path::new("test-data/integration/00d99ed6/output").to_owned(); + parse_consignment::(src, dst.as_path()).unwrap(); + + let rebuild = dst.join("rebuild.rgb").as_path().to_owned(); + rebuild_consignment::(dst.as_path(), rebuild.as_path()).unwrap(); + + let dst_rebuild = Path::new("test-data/integration/00d99ed6/rebuild_output"); + parse_consignment::(rebuild.as_path(), dst_rebuild).unwrap(); +} + +/// Modify file content +pub fn modify_file(path: &Path, pattern: &str, replacement: &str) -> io::Result<()> { + let content = fs::read_to_string(path)?; + let modified = content.replace(pattern, replacement); + fs::write(path, modified)?; + Ok(()) +} + +/// Rebuild consignment from parsed files +/// This function follows the logic of mound.rs(fn consign), stockpile.rs(fn consign) and stock.rs(fn export_aux) +pub fn rebuild_consignment( + src_dir: &Path, + dst_path: &Path, +) -> Result<(), ConsignmentParseError> +where + SealDef: RgbSealDef + Serialize + for<'de> Deserialize<'de>, + SealDef::Src: Serialize + for<'de> Deserialize<'de>, + ::CliWitness: + Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, + ::PubWitness: + Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, + <::PubWitness as PublishedWitness>::PubId: + Ord + From<[u8; 32]> + Into<[u8; 32]> + Serialize, +{ + // Create output file + let file = File::create(dst_path)?; + let mut writer = StrictWriter::with(StreamWriter::new::<{ usize::MAX }>(file)); + + // Write magic bytes + writer = MAGIC_BYTES_CONSIGNMENT.strict_encode(writer)?; + writer = 0x00u16.strict_encode(writer)?; + + // Load contract ID + let contract_id_file = src_dir.join("contract_id.yaml"); + let contract_id: ContractId = if contract_id_file.exists() { + serde_yaml::from_reader(File::open(contract_id_file)?)? + } else { + // Try to extract from other files + let contract_file = src_dir.join("contract.yaml"); + if contract_file.exists() { + let contract: Contract = serde_yaml::from_reader(File::open(contract_file)?)?; + contract.contract_id() + } else { + return Err(ConsignmentParseError::InvalidData( + "Contract ID not found".to_string(), + )); + } + }; + + // Write contract ID + writer = contract_id.strict_encode(writer)?; + + // Load and write articles + let schema_file = src_dir.join("schema.yaml"); + let contract_file = src_dir.join("contract.yaml"); + let contract_sigs_file = src_dir.join("contract_sigs.yaml"); + + if !schema_file.exists() || !contract_file.exists() || !contract_sigs_file.exists() { + return Err(ConsignmentParseError::InvalidData( + "Missing required article files".to_string(), + )); + } + + let schema: Schema = serde_yaml::from_reader(File::open(schema_file)?)?; + let contract: Contract = serde_yaml::from_reader(File::open(contract_file)?)?; + let contract_sigs: ContentSigs = serde_yaml::from_reader(File::open(contract_sigs_file)?)?; + + let articles = Articles { + schema, + contract, + contract_sigs, + }; + + // Write articles + writer = articles.strict_encode(writer)?; + + println!("Writing genesis seals"); + // Load and write genesis seals + let genesis_seals_file = src_dir.join("0000-seals.yml"); + if !genesis_seals_file.exists() { + return Err(ConsignmentParseError::InvalidData( + "Missing genesis seals file".to_string(), + )); + } + + let genesis_seals_file = File::open(genesis_seals_file)?; + + let genesis_seals: SmallOrdMap = + serde_yaml::from_reader(genesis_seals_file).map_err(|e| dbg!(e))?; + writer = genesis_seals.strict_encode(writer)?; + + // Write 0 witnesses for genesis + writer = (0u64).strict_encode(writer)?; + + println!("Writing operations"); + // Load and write operations + let operations_dir = src_dir.join("operations"); + if !operations_dir.exists() || !operations_dir.is_dir() { + return Err(ConsignmentParseError::InvalidData( + "Operations directory not found".to_string(), + )); + } + + // Get all operation files + let mut operation_files = Vec::new(); + for entry in fs::read_dir(&operations_dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_file() && path.extension().map_or(false, |ext| ext == "yaml") { + operation_files.push(path); + } + } + + // Sort operation files by name to ensure correct order + operation_files.sort_by(|a, b| { + let a_name = a.file_name().unwrap().to_string_lossy(); + let b_name = b.file_name().unwrap().to_string_lossy(); + a_name.cmp(&b_name) + }); + + // Process each operation + for (op_index, op_file) in operation_files.iter().enumerate() { + let op_count = op_index + 1; // Operation count starts from 1 + + // Load and write operation + let operation: Operation = serde_yaml::from_reader(File::open(op_file)?)?; + writer = operation.strict_encode(writer)?; + + // Load and write operation seals + let seals_file = operations_dir.join(format!("{op_count:04}-seals.yml")); + if !seals_file.exists() { + return Err(ConsignmentParseError::InvalidData(format!( + "Missing seals file for operation {}", + op_count + ))); + } + + let seals_file = File::open(seals_file)?; + let seals: SmallOrdMap = + serde_yaml::from_reader(seals_file).map_err(|e| dbg!(e))?; + writer = seals.strict_encode(writer)?; + + // Count witness files for this operation + let mut witness_count = 0; + let mut witness_files = Vec::new(); + for i in 1..100 { + // Assuming maximum 99 witnesses per operation + let witness_file = operations_dir.join(format!("{op_count:04}-witness-{:02}.yml", i)); + if witness_file.exists() { + witness_count += 1; + witness_files.push(witness_file); + } else { + break; + } + } + + // Write witness count + writer = (witness_count as u64).strict_encode(writer)?; + + // Load and write witnesses + for witness_file in witness_files { + let witness = + serde_yaml::from_reader::<_, SealWitness>(File::open(witness_file)?)?; + writer = witness.strict_encode(writer)?; + } + } + + println!( + "Rebuilt consignment from {} to {}", + src_dir.display(), + dst_path.display() + ); + Ok(()) +} + +/// Create an attacked consignment +pub fn create_attack_consignment( + src: &Path, + attack_type: &str, +) -> Result { + // Create a temporary directory for parsing + let temp_dir_path = PathBuf::from("tests/fixtures/temp"); + fs::create_dir_all(&temp_dir_path)?; + + // Parse the consignment + parse_consignment::(src, &temp_dir_path)?; + + // Create the attack path + let attack_path = PathBuf::from(format!("tests/fixtures/attack_{}.yaml", attack_type)); + + // Modify files based on attack type + match attack_type { + "chain" => { + // Attack type: chain + // Modify consensus from bitcoin to liquid in contract.yaml + let contract_path = temp_dir_path.join("contract.yaml"); + if contract_path.exists() { + modify_file(&contract_path, "consensus: bitcoin", "consensus: liquid")?; + println!("Modified contract.yaml: changed consensus from bitcoin to liquid"); + } else { + return Err(ConsignmentParseError::InvalidData( + "contract.yaml not found".to_string(), + )); + } + } + "genesis_schema_id" => { + // Attack type: genesis_schema_id + // Modify codexId in contract.yaml and schema.yaml + let contract_path = temp_dir_path.join("contract.yaml"); + let schema_path = temp_dir_path.join("schema.yaml"); + + if contract_path.exists() && schema_path.exists() { + // Read files to find the original codexId pattern + let contract_content = fs::read_to_string(&contract_path)?; + if let Some(line) = contract_content + .lines() + .find(|line| line.contains("codexId:")) + { + let original_codex_id = line.trim(); + modify_file(&contract_path, original_codex_id, "codexId: xxx#yyy")?; + modify_file(&schema_path, original_codex_id, "codexId: xxx#yyy")?; + println!("Modified codexId in contract.yaml and schema.yaml"); + } else { + return Err(ConsignmentParseError::InvalidData( + "codexId not found in contract.yaml".to_string(), + )); + } + } else { + return Err(ConsignmentParseError::InvalidData( + "contract.yaml or schema.yaml not found".to_string(), + )); + } + } + "genesis_testnet" => { + // Attack type: genesis_testnet + // Modify testnet flag from true to false in contract.yaml + let contract_path = temp_dir_path.join("contract.yaml"); + if contract_path.exists() { + modify_file(&contract_path, "testnet: true", "testnet: false")?; + println!("Modified contract.yaml: changed testnet from true to false"); + } else { + return Err(ConsignmentParseError::InvalidData( + "contract.yaml not found".to_string(), + )); + } + } + "bundles_pubWitness_data_input_sequence" => { + // Attack type: bundles_pubWitness_data_input_sequence + // Modify sequence from 0 to 1 in operations/0001-witness-01.yml + let witness_path = temp_dir_path.join("operations").join("0001-witness-01.yml"); + if witness_path.exists() { + modify_file(&witness_path, "sequence: 0", "sequence: 1")?; + println!("Modified operations/0001-witness-01.yml: changed sequence from 0 to 1"); + } else { + return Err(ConsignmentParseError::InvalidData( + "operations/0001-witness-01.yml not found".to_string(), + )); + } + } + "resolver_error" => { + // Attack type: resolver_error + // This attack is handled by switching the esplora instance in the wallet + // No modification to the consignment is needed + println!("Resolver error attack: No modification to consignment needed."); + println!("This attack is handled by switching the esplora instance in the wallet."); + + // Just copy the original file to the attack path + fs::copy(src, &attack_path)?; + return Ok(attack_path); + } + _ => { + return Err(ConsignmentParseError::InvalidData(format!( + "Unknown attack type: {}", + attack_type + ))); + } + } + + // Rebuild consignment from modified files + rebuild_consignment::(&temp_dir_path, &attack_path)?; + + // Clean up temporary directory + fs::remove_dir_all(&temp_dir_path)?; + + println!("Created attack consignment at {}", attack_path.display()); + Ok(attack_path) +} diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 5d73ca3..2a73e21 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -1,4 +1,5 @@ pub mod chain; +pub mod consignment_utils; pub mod helpers; pub const TEST_DATA_DIR: &str = "test-data"; diff --git a/tests/validation.rs b/tests/validation.rs new file mode 100644 index 0000000..6aae14d --- /dev/null +++ b/tests/validation.rs @@ -0,0 +1,2 @@ +// TODO: +// consignment_utils.rs has completed the basic functions of attack simulation, ready to implement specific test cases later From eb968065fb8223cee404d09e13f61afa088a30ef Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Mar 2025 12:54:57 +0800 Subject: [PATCH 33/90] feat(tests): Enhance consignment utils and add unit tests Signed-off-by: will-bitlightlabs --- tests/utils/consignment_utils.rs | 65 +++++++++++++++++++++++++++----- tests/utils/helpers.rs | 2 +- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/tests/utils/consignment_utils.rs b/tests/utils/consignment_utils.rs index 2dd641d..17a62b6 100644 --- a/tests/utils/consignment_utils.rs +++ b/tests/utils/consignment_utils.rs @@ -250,6 +250,8 @@ where } }; + println!("rebuild_consignment: contract_id: {}", contract_id); + // Write contract ID writer = contract_id.strict_encode(writer)?; @@ -323,6 +325,7 @@ where // Process each operation for (op_index, op_file) in operation_files.iter().enumerate() { + println!("Processing operation: {}", op_file.display()); let op_count = op_index + 1; // Operation count starts from 1 // Load and write operation @@ -382,14 +385,33 @@ pub fn create_attack_consignment( attack_type: &str, ) -> Result { // Create a temporary directory for parsing - let temp_dir_path = PathBuf::from("tests/fixtures/temp"); - fs::create_dir_all(&temp_dir_path)?; + let temp_dir_path = PathBuf::from("tests/fixtures/v0.12/temp").join(attack_type); + + // If the directory exists, clear it; otherwise, create a new directory + if temp_dir_path.exists() { + // Check if the directory is empty + if temp_dir_path.read_dir()?.next().is_some() { + // The directory is not empty, clear it + for entry in fs::read_dir(&temp_dir_path)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + fs::remove_dir_all(path)?; + } else { + fs::remove_file(path)?; + } + } + } + } else { + // The directory does not exist, create it + fs::create_dir_all(&temp_dir_path)?; + } // Parse the consignment parse_consignment::(src, &temp_dir_path)?; // Create the attack path - let attack_path = PathBuf::from(format!("tests/fixtures/attack_{}.yaml", attack_type)); + let attack_path = PathBuf::from(format!("tests/fixtures/attack_{}.rgb", attack_type)); // Modify files based on attack type match attack_type { @@ -419,9 +441,13 @@ pub fn create_attack_consignment( .lines() .find(|line| line.contains("codexId:")) { - let original_codex_id = line.trim(); - modify_file(&contract_path, original_codex_id, "codexId: xxx#yyy")?; - modify_file(&schema_path, original_codex_id, "codexId: xxx#yyy")?; + // let original_codex_id = line.trim(); + let original_codex_id = line.split("codexId:").nth(1).unwrap().trim(); + let mut modified_codex_id = original_codex_id.to_owned(); + modified_codex_id.push('1'); + + modify_file(&contract_path, &original_codex_id, &modified_codex_id)?; + modify_file(&schema_path, &original_codex_id, &modified_codex_id)?; println!("Modified codexId in contract.yaml and schema.yaml"); } else { return Err(ConsignmentParseError::InvalidData( @@ -447,8 +473,8 @@ pub fn create_attack_consignment( )); } } - "bundles_pubWitness_data_input_sequence" => { - // Attack type: bundles_pubWitness_data_input_sequence + "bundles_pubwitness_data_input_sequence" => { + // Attack type: bundles_pubwitness_data_input_sequence // Modify sequence from 0 to 1 in operations/0001-witness-01.yml let witness_path = temp_dir_path.join("operations").join("0001-witness-01.yml"); if witness_path.exists() { @@ -483,8 +509,29 @@ pub fn create_attack_consignment( rebuild_consignment::(&temp_dir_path, &attack_path)?; // Clean up temporary directory - fs::remove_dir_all(&temp_dir_path)?; + // fs::remove_dir_all(&temp_dir_path)?; println!("Created attack consignment at {}", attack_path.display()); Ok(attack_path) } + +#[test] +fn test_create_attack_consignment() { + let src = Path::new("test-data/integration/00d99ed6/consignment-551.rgb"); + let chain_attack_path = create_attack_consignment(src, "chain").unwrap(); + assert!(chain_attack_path.exists()); + + let genesis_schema_id_attack_path = + create_attack_consignment(src, "genesis_schema_id").unwrap(); + assert!(genesis_schema_id_attack_path.exists()); + + let genesis_testnet_attack_path = create_attack_consignment(src, "genesis_testnet").unwrap(); + assert!(genesis_testnet_attack_path.exists()); + + let bundles_pubwitness_data_input_sequence_attack_path = + create_attack_consignment(src, "bundles_pubwitness_data_input_sequence").unwrap(); + assert!(bundles_pubwitness_data_input_sequence_attack_path.exists()); + + let resolver_error_attack_path = create_attack_consignment(src, "resolver_error").unwrap(); + assert!(resolver_error_attack_path.exists()); +} diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 315508d..52950b7 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -248,7 +248,7 @@ pub enum ReorgType { Revert, } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum TransferType { Blinded, Witness, From 9d418bd9b69924a6fa773b6e515b57235193abbc Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Mar 2025 12:57:21 +0800 Subject: [PATCH 34/90] feat(tests): Remove obsolete validation and backup stress test files Signed-off-by: will-bitlightlabs --- tests/stress.rs.bak | 96 ---------- tests/validation.rs | 2 - tests/validation.rs.bak | 401 ---------------------------------------- 3 files changed, 499 deletions(-) delete mode 100644 tests/stress.rs.bak delete mode 100644 tests/validation.rs delete mode 100644 tests/validation.rs.bak diff --git a/tests/stress.rs.bak b/tests/stress.rs.bak deleted file mode 100644 index e266758..0000000 --- a/tests/stress.rs.bak +++ /dev/null @@ -1,96 +0,0 @@ -pub mod utils; - -use utils::*; - -type TT = TransferType; -type DT = DescriptorType; - -#[rstest] -// blinded -#[case(TT::Blinded, DT::Wpkh, DT::Wpkh)] -#[case(TT::Blinded, DT::Wpkh, DT::Tr)] -#[case(TT::Blinded, DT::Tr, DT::Tr)] -// witness -#[case(TT::Witness, DT::Wpkh, DT::Wpkh)] -#[case(TT::Witness, DT::Wpkh, DT::Tr)] -#[case(TT::Witness, DT::Tr, DT::Tr)] -#[ignore = "run a single case if desired"] -fn back_and_forth( - #[case] transfer_type: TransferType, - #[case] wlt_1_desc: DescriptorType, - #[case] wlt_2_desc: DescriptorType, -) { - println!("transfer_type {transfer_type:?} wlt_1_desc {wlt_1_desc:?} wlt_2_desc {wlt_2_desc:?}"); - - initialize(); - - let stress_tests_dir = PathBuf::from(TEST_DATA_DIR).join(STRESS_DATA_DIR); - std::fs::create_dir_all(&stress_tests_dir).unwrap(); - let fname = OffsetDateTime::unix_timestamp(OffsetDateTime::now_utc()).to_string(); - let mut fpath = stress_tests_dir.join(fname); - fpath.set_extension("csv"); - println!("report path: {}", fpath.to_string_lossy()); - let report = Report { report_path: fpath }; - report.write_header(&[ - "wlt_1_pay", - "wlt_2_validate", - "wlt_2_accept", - "wlt_2_pay", - "wlt_1_validate", - "wlt_1_accept", - "send_1_tot", - "send_2_tot", - ]); - - let mut wlt_1 = get_wallet(&wlt_1_desc); - let mut wlt_2 = get_wallet(&wlt_2_desc); - - let issued_supply = u64::MAX; - - let (contract_id, iface_type_name) = wlt_1.issue_nia(issued_supply, wlt_1.close_method(), None); - - let loops = match std::env::var("LOOPS") { - Ok(val) if u16::from_str(&val).is_ok() => u16::from_str(&val).unwrap(), - Err(VarError::NotPresent) => 50, - _ => { - panic!("invalid loops value: must be a u16 number") - } - }; - - let sats_base = 3000; - let mut sats_send = sats_base * loops as u64; - let now = Instant::now(); - for i in 1..=loops { - println!("loop {i}/{loops}"); - sats_send -= DEFAULT_FEE_ABS * 2; - let wlt_1_send_start = Instant::now(); - wlt_1.send( - &mut wlt_2, - transfer_type, - contract_id, - &iface_type_name, - issued_supply - i as u64, - sats_send, - Some(&report), - ); - let wlt_1_send_duration = wlt_1_send_start.elapsed(); - sats_send -= DEFAULT_FEE_ABS * 2; - let wlt_2_send_start = Instant::now(); - wlt_2.send( - &mut wlt_1, - transfer_type, - contract_id, - &iface_type_name, - issued_supply - i as u64 - 1, - sats_send, - Some(&report), - ); - let wlt_2_send_duration = wlt_2_send_start.elapsed(); - - report.write_duration(wlt_1_send_duration); - report.write_duration(wlt_2_send_duration); - report.end_line(); - } - let elapsed = now.elapsed(); - println!("elapsed: {:.2?}", elapsed); -} diff --git a/tests/validation.rs b/tests/validation.rs deleted file mode 100644 index 6aae14d..0000000 --- a/tests/validation.rs +++ /dev/null @@ -1,2 +0,0 @@ -// TODO: -// consignment_utils.rs has completed the basic functions of attack simulation, ready to implement specific test cases later diff --git a/tests/validation.rs.bak b/tests/validation.rs.bak deleted file mode 100644 index 6049d92..0000000 --- a/tests/validation.rs.bak +++ /dev/null @@ -1,401 +0,0 @@ -pub mod utils; - -use utils::*; - -enum MockResolvePubWitness { - Success(Tx), - Error(WitnessResolverError), -} - -enum MockResolvePubWitnessOrd { - Success(WitnessOrd), - Error(WitnessResolverError), -} - -struct MockResolver { - pub_witnesses: HashMap, - pub_witness_ords: HashMap, -} - -impl ResolveWitness for MockResolver { - fn resolve_pub_witness( - &self, - witness_id: XWitnessId, - ) -> Result { - if let Some(res) = self.pub_witnesses.get(&witness_id) { - match res { - MockResolvePubWitness::Success(tx) => Ok(XChain::Bitcoin(tx.clone())), - MockResolvePubWitness::Error(err) => Err(err.clone()), - } - } else { - Err(WitnessResolverError::Unknown(witness_id)) - } - } - - fn resolve_pub_witness_ord( - &self, - witness_id: XWitnessId, - ) -> Result { - if let Some(res) = self.pub_witness_ords.get(&witness_id) { - match res { - MockResolvePubWitnessOrd::Success(witness_ord) => Ok(*witness_ord), - MockResolvePubWitnessOrd::Error(err) => Err(err.clone()), - } - } else { - Err(WitnessResolverError::Unknown(witness_id)) - } - } -} - -#[derive(Debug, EnumIter, Copy, Clone, PartialEq)] -enum Scenario { - A, - B, -} - -impl fmt::Display for Scenario { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -impl Scenario { - fn resolver(&self) -> MockResolver { - match self { - Self::A => { - let (tx_1, witness_id_1) = - get_tx("bc:a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce"); - let (tx_2, witness_id_2) = - get_tx("bc:d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248"); - let (tx_3, witness_id_3) = - get_tx("bc:3652d9fea802cb051f671455cbd7472e3bce2c440a4e54fa4321107037dfaff0"); - MockResolver { - pub_witnesses: map![ - witness_id_1 => MockResolvePubWitness::Success(tx_1), - witness_id_2 => MockResolvePubWitness::Success(tx_2), - witness_id_3 => MockResolvePubWitness::Success(tx_3), - ], - pub_witness_ords: map![ - witness_id_1 => MockResolvePubWitnessOrd::Success(WitnessOrd::Mined(WitnessPos::bitcoin(NonZeroU32::new(106).unwrap(), 1726062111).unwrap())), - witness_id_2 => MockResolvePubWitnessOrd::Success(WitnessOrd::Mined(WitnessPos::bitcoin(NonZeroU32::new(108).unwrap(), 1726062111).unwrap())), - witness_id_3 => MockResolvePubWitnessOrd::Success(WitnessOrd::Mined(WitnessPos::bitcoin(NonZeroU32::new(110).unwrap(), 1726062112).unwrap())), - ], - } - } - Self::B => { - let (tx_1, witness_id_1) = - get_tx("bc:c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9"); - let (tx_2, witness_id_2) = - get_tx("bc:d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3"); - let (tx_3, witness_id_3) = - get_tx("bc:0bc3024ce6404cd7aea387debde687d9e8731228e16b04b4eefda7283069f1c3"); - MockResolver { - pub_witnesses: map![ - witness_id_1 => MockResolvePubWitness::Success(tx_1), - witness_id_2 => MockResolvePubWitness::Success(tx_2), - witness_id_3 => MockResolvePubWitness::Success(tx_3), - ], - pub_witness_ords: map![ - witness_id_1 => MockResolvePubWitnessOrd::Success(WitnessOrd::Mined(WitnessPos::bitcoin(NonZeroU32::new(105).unwrap(), 1726062423).unwrap())), - witness_id_2 => MockResolvePubWitnessOrd::Success(WitnessOrd::Mined(WitnessPos::bitcoin(NonZeroU32::new(106).unwrap(), 1726062423).unwrap())), - witness_id_3 => MockResolvePubWitnessOrd::Success(WitnessOrd::Mined(WitnessPos::bitcoin(NonZeroU32::new(106).unwrap(), 1726062423).unwrap())), - ], - } - } - } - } -} - -fn get_consignment(scenario: Scenario) -> (Transfer, Vec) { - initialize(); - - let transfer_type = match scenario { - Scenario::A => TransferType::Blinded, - Scenario::B => TransferType::Witness, - }; - - let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); - let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); - - let issued_supply_1 = 999; - let issued_supply_2 = 666; - - let sats = 9000; - - let utxo = wlt_1.get_utxo(None); - let (contract_id_1, iface_type_name_1) = - wlt_1.issue_nia(issued_supply_1, wlt_1.close_method(), Some(&utxo)); - let (contract_id_2, iface_type_name_2) = - wlt_1.issue_nia(issued_supply_2, wlt_1.close_method(), Some(&utxo)); - - let mut txes = vec![]; - - let (_consignment, tx) = wlt_1.send( - &mut wlt_2, - transfer_type, - contract_id_1, - &iface_type_name_1, - 66, - sats, - None, - ); - txes.push(tx); - - // spend asset moved with blank transition - let (_consignment, tx) = wlt_1.send( - &mut wlt_2, - transfer_type, - contract_id_2, - &iface_type_name_2, - 50, - sats, - None, - ); - txes.push(tx); - - // spend change of previous send - let (consignment, tx) = wlt_1.send( - &mut wlt_2, - transfer_type, - contract_id_2, - &iface_type_name_2, - 77, - sats, - None, - ); - txes.push(tx); - - (consignment, txes) -} - -// run once to generate tests/fixtures/consignemnt_.yaml -// for example: -// SCENARIO=B cargo test --test validation validate_consignment_generate -- --ignored --show-output -// -// then copy the generated consignemnt file to tests/fixtures/attack_.yaml -// manually change tests/fixtures/attack_.yaml files to simulate attacks -#[test] -#[ignore = "one-shot"] -fn validate_consignment_generate() { - let scenario = match std::env::var("SCENARIO") { - Ok(val) if val.to_uppercase() == Scenario::A.to_string() => Scenario::A, - Ok(val) if val.to_uppercase() == Scenario::B.to_string() => Scenario::B, - Err(VarError::NotPresent) => Scenario::A, - _ => panic!("invalid scenario"), - }; - let (consignment, txes) = get_consignment(scenario); - println!(); - let cons_path = format!("tests/fixtures/consignment_{scenario}.yaml"); - let yaml = serde_yaml::to_string(&consignment).unwrap(); - std::fs::write(&cons_path, yaml).unwrap(); - println!("written consignment in: {cons_path}"); - for tx in txes { - let txid = tx.txid().to_string(); - let witness_id = XWitnessId::from_str(&txid).unwrap(); - let normalized_witness_id = witness_id.to_string().replace(":", "_"); - let yaml = serde_yaml::to_string(&tx).unwrap(); - let yaml_path = format!("tests/fixtures/{normalized_witness_id}.yaml"); - std::fs::write(&yaml_path, yaml).unwrap(); - println!("written tx: {witness_id}"); - } -} - -fn get_consignment_from_yaml(fname: &str) -> Transfer { - let cons_path = format!("tests/fixtures/{fname}.yaml"); - println!("loading {cons_path}"); - let file = std::fs::File::open(cons_path).unwrap(); - let consignment: Transfer = serde_yaml::from_reader(file).unwrap(); - consignment -} - -fn get_tx(witness_id: &str) -> (Tx, XWitnessId) { - let normalized_witness_id = witness_id.replace(":", "_"); - let yaml_path = format!("tests/fixtures/{normalized_witness_id}.yaml"); - let file = std::fs::File::open(yaml_path).unwrap(); - let tx: Tx = serde_yaml::from_reader(file).unwrap(); - let xwitness_id = XWitnessId::from_str(witness_id).unwrap(); - (tx, xwitness_id) -} - -#[test] -fn validate_consignment_success() { - for scenario in Scenario::iter() { - let resolver = scenario.resolver(); - let consignment = get_consignment_from_yaml(&format!("consignment_{scenario}")); - let res = consignment.validate(&resolver, true); - assert!(res.is_ok()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - dbg!(&validation_status); - assert!(validation_status.failures.is_empty()); - assert!(validation_status.warnings.is_empty()); - assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Valid); - } -} - -#[test] -fn validate_consignment_chain_fail() { - let resolver = Scenario::A.resolver(); - - // liquid - let consignment = get_consignment_from_yaml("attack_chain"); - let res = consignment.validate(&resolver, true); - assert!(res.is_err()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - dbg!(&validation_status); - assert!(validation_status.warnings.is_empty()); - assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); -} - -#[test] -fn validate_consignment_genesis_fail() { - let resolver = Scenario::B.resolver(); - - // schema ID: change genesis[schemaId] with CFA schema ID - let consignment = get_consignment_from_yaml("attack_genesis_schema_id"); - let res = consignment.validate(&resolver, true); - assert!(res.is_err()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - dbg!(&validation_status); - assert_eq!(validation_status.failures.len(), 5); - assert!(matches!( - validation_status.failures[0], - Failure::OperationAbsent(_) - )); - assert!(matches!( - validation_status.failures[1], - Failure::MpcInvalid(_, _, _) - )); - assert!(matches!( - validation_status.failures[2], - Failure::BundleExtraTransition(_, _) - )); - assert!(matches!( - validation_status.failures[3], - Failure::MpcInvalid(_, _, _) - )); - assert!(matches!( - validation_status.failures[4], - Failure::MpcInvalid(_, _, _) - )); - assert!(validation_status.warnings.is_empty()); - assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); - - // genesis testnet: change from true to false - let consignment = get_consignment_from_yaml("attack_genesis_testnet"); - let res = consignment.validate(&resolver, true); - assert!(res.is_err()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - dbg!(&validation_status); - assert_eq!(validation_status.failures.len(), 1); - assert!(matches!( - validation_status.failures[0], - Failure::NetworkMismatch(_) - )); - assert!(validation_status.warnings.is_empty()); - assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); -} - -#[test] -fn validate_consignment_bundles_fail() { - let resolver = Scenario::A.resolver(); - - // bundles pubWitness data inputs[0] sequence: change from 0 to 1 - let consignment = get_consignment_from_yaml("attack_bundles_pubWitness_data_input_sequence"); - let res = consignment.validate(&resolver, true); - assert!(res.is_err()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - dbg!(&validation_status); - assert_eq!(validation_status.failures.len(), 3); - assert!(matches!( - validation_status.failures[0], - Failure::SealsInvalid(_, _, _) - )); - assert!(matches!( - validation_status.failures[1], - Failure::BundleInvalidCommitment(_, _, _, _) - )); - assert!(matches!( - validation_status.failures[2], - Failure::SealNoPubWitness(_, _, _) - )); - assert!(validation_status.warnings.is_empty()); - assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); -} - -#[test] -fn validate_consignment_resolver_error() { - let scenario = Scenario::A; - let mut resolver = scenario.resolver(); - let txid = - Txid::from_str("d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248").unwrap(); - let xwitness_id = XChain::Bitcoin(txid); - - // resolve_pub_witness error - *resolver.pub_witnesses.get_mut(&xwitness_id).unwrap() = MockResolvePubWitness::Error( - WitnessResolverError::Other(xwitness_id, s!("unexpected error")), - ); - let consignment = get_consignment_from_yaml("attack_resolver_error"); - let res = consignment.validate(&resolver, true); - assert!(res.is_err()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - dbg!(&validation_status); - assert_eq!(validation_status.failures.len(), 1); - assert!(matches!( - validation_status.failures[0], - Failure::SealNoPubWitness(_, _, _) - )); - assert!(validation_status.warnings.is_empty()); - assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); - - // resolve_pub_witness_ord error - *resolver.pub_witness_ords.get_mut(&xwitness_id).unwrap() = MockResolvePubWitnessOrd::Error( - WitnessResolverError::Other(xwitness_id, s!("unexpected error")), - ); - let consignment = get_consignment_from_yaml("attack_resolver_error"); - let res = consignment.validate(&resolver, true); - assert!(res.is_err()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - dbg!(&validation_status); - assert_eq!(validation_status.failures.len(), 1); - assert!(matches!( - validation_status.failures[0], - Failure::SealNoPubWitness(_, _, _) - )); - assert!(validation_status.warnings.is_empty()); - assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); -} From 5c4329c04dc019a04b0d2c88b6e0682138f2b71f Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Mar 2025 13:04:08 +0800 Subject: [PATCH 35/90] refactor(tests): Clean up unused variables and improve code readability Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 5 +++-- tests/stress.rs | 1 - tests/transfer.rs | 22 ++++++++++---------- tests/utils/chain.rs | 2 ++ tests/utils/consignment_utils.rs | 15 ++++++-------- tests/utils/helpers.rs | 35 +++++++++++--------------------- tests/utils/mod.rs | 6 ------ 7 files changed, 34 insertions(+), 52 deletions(-) diff --git a/tests/issuance.rs b/tests/issuance.rs index 8b577d3..6004b11 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -7,6 +7,7 @@ use utils::{ DescriptorType, *, }; +#[allow(dead_code)] const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; #[template] @@ -121,7 +122,7 @@ fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { let mut params = CFAIssueParams::new("Multi_UTXO_CFA", "centiMilli", 999); // Get multiple UTXOs and add allocations - let amounts = vec![222, 444, 333]; + let amounts = [222, 444, 333]; for amount in amounts.iter() { let outpoint = wallet.get_utxo(None); params.add_allocation(outpoint, *amount); @@ -163,7 +164,7 @@ fn issue_nia_multiple_utxos(wallet_desc: DescriptorType) { let mut params = NIAIssueParams::new("Multi_UTXO_NIA", "MUTX", "centiMilli", 999); // Get multiple UTXOs and add allocations - let amounts = vec![333, 333, 333]; + let amounts = [333, 333, 333]; for amount in amounts.iter() { let outpoint = wallet.get_utxo(None); params.add_allocation(outpoint, *amount); diff --git a/tests/stress.rs b/tests/stress.rs index f115820..c9b9287 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -36,7 +36,6 @@ use utils::{ pub mod utils; // Aliases for shorter test case definitions -type TT = TransferType; type DT = DescriptorType; #[rstest] diff --git a/tests/transfer.rs b/tests/transfer.rs index ae4e781..10c2246 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -80,7 +80,7 @@ fn simple_transfer(wout: bool) { let (consignment_1, tx) = wlt_1.transfer(invoice, Some(3000), Some(500), true, None); // Receiver accepts the transfer - wlt_2.accept_transfer(&consignment_1, None); + wlt_2.accept_transfer(&consignment_1, None).unwrap(); // Broadcast and confirm transaction wlt_1.mine_tx(&tx.txid(), true); @@ -101,7 +101,7 @@ fn simple_transfer(wout: bool) { ); // Sats cost: 500 fee + 2000 sats(default) = 2500 let (consignment_2, tx) = wlt_2.transfer(invoice, None, Some(500), true, None); - wlt_1.accept_transfer(&consignment_2, None); + wlt_1.accept_transfer(&consignment_2, None).unwrap(); wlt_2.mine_tx(&tx.txid(), true); // // Sync both wallets @@ -159,7 +159,7 @@ fn rbf_transfer() { let (consignment_1, _) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); // Receiver accepts the transfer - wlt_2.accept_transfer(&consignment_1, None); + wlt_2.accept_transfer(&consignment_1, None).unwrap(); // Verify block height hasn't changed (transaction not confirmed) let mid_height = get_height(); @@ -176,7 +176,7 @@ fn rbf_transfer() { wlt_1.mine_tx(&tx.txid(), true); // Receiver accepts final transfer - wlt_2.accept_transfer(&consignment_2, None); + wlt_2.accept_transfer(&consignment_2, None).unwrap(); // Sync both wallets wlt_1.sync(); @@ -558,7 +558,7 @@ fn transfer_loop( #[case(TransferType::Blinded)] #[ignore = "Awaiting new rollback procedure API in RGB v0.12"] #[case(TransferType::Witness)] -fn same_transfer_twice_update_witnesses(#[case] transfer_type: TransferType) {} +fn same_transfer_twice_update_witnesses(#[case] _transfer_type: TransferType) {} // Complex test cases - Implementation deferred to final phase // These test cases will be implemented last, after evaluating: @@ -620,12 +620,12 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) dbg!(wlt_1 .runtime() .state_all(None) - .map(|(c, s)| { s.owned }) + .map(|(_, s)| { s.owned }) .collect::>()); dbg!(wlt_1 .runtime() .state_own(None) - .map(|(c, s)| { s.owned }) + .map(|(_, s)| { s.owned }) .collect::>()); // dbg!(wlt_2 @@ -642,7 +642,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) // TODO: called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) let (consignment, _) = wlt_1.transfer(invoice, None, Some(1000), true, None); - wlt_2.accept_transfer(&consignment, None); + wlt_2.accept_transfer(&consignment, None).unwrap(); let wlt_2_contract_state = wlt_2.runtime().state_own(None).map(|s| s.1.owned); dbg!(wlt_2_contract_state.collect::>()); @@ -702,7 +702,7 @@ fn accept_0conf() { let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, None, true, None); let txid = tx.txid(); - wlt_2.accept_transfer(&consignment, None); + wlt_2.accept_transfer(&consignment, None).unwrap(); // wlt_2 sees the allocation even if TX has not been mined wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amt]); @@ -819,7 +819,7 @@ fn send_to_oneself() { let invoice = wlt.invoice(contract_id, amt, true, Some(0), None); let (consignment, tx) = wlt.transfer(invoice.clone(), None, None, true, None); wlt.mine_tx(&tx.txid(), false); - wlt.accept_transfer(&consignment, None); + wlt.accept_transfer(&consignment, None).unwrap(); wlt.sync(); // debug contract state @@ -1438,7 +1438,7 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { let invoice = wlt_2.invoice(contract_id, 100, false, None, Some(utxo)); // Create transfer but do not broadcast its TX - let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + let (_consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); let txid = tx.txid(); // Note: The following code needs to be redesigned in RGB v0.12 diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index bb4649a..723c547 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -7,7 +7,9 @@ pub static INDEXER: OnceLock = OnceLock::new(); // Node addresses const NODE2_ADDR: &str = "172.30.2.205:18444"; const NODE3_ADDR: &str = "172.30.2.206:18444"; +#[allow(dead_code)] const NODE2_IP: &str = "172.30.2.205"; +#[allow(dead_code)] const NODE3_IP: &str = "172.30.2.206"; #[derive(Clone, Default, PartialEq, Eq, Debug)] diff --git a/tests/utils/consignment_utils.rs b/tests/utils/consignment_utils.rs index 17a62b6..b2df428 100644 --- a/tests/utils/consignment_utils.rs +++ b/tests/utils/consignment_utils.rs @@ -1,20 +1,17 @@ -use std::collections::BTreeMap; use std::fs::{self, File}; -use std::io::{self, Read, Write}; +use std::io; use std::path::{Path, PathBuf}; -use std::str::FromStr; use amplify::confinement::SmallOrdMap; use amplify::hex::ToHex; use amplify::{Bytes16, Display, From}; use bp::seals::WTxoSeal; use commit_verify::ReservedBytes; -use hypersonic::aora::Aora; -use hypersonic::{Articles, ContractId, FileSupply, Operation}; +use hypersonic::{Articles, ContractId, Operation}; use rgb::sigs::ContentSigs; use rgb::{ - Contract, FilePile, Index, MoundConsumeError, Pile, PublishedWitness, RgbSealDef, Schema, - SealWitness, SingleUseSeal, Stockpile, MAGIC_BYTES_CONSIGNMENT, + Contract, PublishedWitness, RgbSealDef, Schema, SealWitness, SingleUseSeal, + MAGIC_BYTES_CONSIGNMENT, }; use serde::{Deserialize, Serialize}; use strict_encoding::{ @@ -446,8 +443,8 @@ pub fn create_attack_consignment( let mut modified_codex_id = original_codex_id.to_owned(); modified_codex_id.push('1'); - modify_file(&contract_path, &original_codex_id, &modified_codex_id)?; - modify_file(&schema_path, &original_codex_id, &modified_codex_id)?; + modify_file(&contract_path, original_codex_id, &modified_codex_id)?; + modify_file(&schema_path, original_codex_id, &modified_codex_id)?; println!("Modified codexId in contract.yaml and schema.yaml"); } else { return Err(ConsignmentParseError::InvalidData( diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 52950b7..f6508e3 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -8,7 +8,6 @@ use std::sync::OnceLock; use std::time::Duration; use std::time::Instant; -use bp::Weight; use bp::{seals::WTxoSeal, Outpoint}; use commit_verify::{Digest, DigestExt, Sha256}; use psbt::TxParams; @@ -17,8 +16,8 @@ use rgb::invoice::{RgbBeneficiary, RgbInvoice}; use rgb::popls::bp::file::{BpDirMound, DirBarrow}; use rgb::popls::bp::{Coinselect, OpRequestSet, WalletProvider}; use rgb::{ - Assignment, AuthToken, CallScope, CellAddr, CodexId, Consensus, ContractId, ContractInfo, - CreateParams, EitherSeal, MethodName, NamedState, RgbSealDef, StateAtom, StateCalc, + Assignment, AuthToken, CellAddr, CodexId, Consensus, ContractId, ContractInfo, CreateParams, + EitherSeal, NamedState, RgbSealDef, StateAtom, StateCalc, }; use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbWallet}; use rgbp::{CoinselectStrategy, PayError}; @@ -34,11 +33,8 @@ use super::{ *, }; -use tabled::settings::{ - object::{Columns, Rows}, - Alignment, Modify, Style, -}; -use tabled::{builder::Builder, Table, Tabled}; +use tabled::settings::{object::Columns, Alignment, Modify, Style}; +use tabled::{Table, Tabled}; /// RGB Asset creation parameters builder #[derive(Clone)] @@ -427,10 +423,7 @@ impl Report { /// Get file handle fn get_file(&mut self) -> Result<&mut File, ReportError> { if self.file.is_none() { - let file = OpenOptions::new() - .write(true) - .append(true) - .open(&self.report_path)?; + let file = OpenOptions::new().append(true).open(&self.report_path)?; self.file = Some(file); } @@ -730,7 +723,7 @@ impl Report { json.push_str(&format!("{}", value)); } - json.push_str("]"); + json.push(']'); } json.push_str("\n}"); @@ -942,7 +935,7 @@ fn make_runtime(descriptor: &RgbDescr, network: Network, wallet_dir: &PathBuf) - let wallet = RgbWallet::create(provider, descriptor.clone(), network, true) .expect("Unable to create wallet"); - let mound = BpDirMound::load_testnet(Consensus::Bitcoin, &wallet_dir, false); + let mound = BpDirMound::load_testnet(Consensus::Bitcoin, wallet_dir, false); RgbDirRuntime::from(DirBarrow::with(wallet, mound)) } @@ -1007,12 +1000,11 @@ fn broadcast_tx(tx: &Tx, indexer_url: &str) { AnyIndexer::Esplora(inner) => { inner .broadcast(tx) - .map_err(|e| { + .inspect_err(|e| { dbg!( tx.inputs.iter().map(|i| i.prev_output).collect::>(), - &e + e ); - e }) .unwrap(); } @@ -1236,10 +1228,7 @@ impl TestWallet { mut report: Option<&mut Report>, ) -> (PathBuf, Tx) { // We need to handle the report parameter carefully to avoid moving it - let transfer_report = match &mut report { - Some(r) => Some(&mut **r), - None => None, - }; + let transfer_report = report.as_deref_mut(); let (consignment, tx) = self.transfer(invoice, sats, fee, true, transfer_report); broadcast_tx_and_mine(&tx, self.instance); @@ -1535,7 +1524,7 @@ impl TestWallet { /// Get contract state with parsed data structures pub fn contract_state(&mut self, contract_id: ContractId) -> Option { self.contract_state_internal(contract_id) - .map(|(immutable, owned, computed)| { + .map(|(immutable, owned, _)| { // Parse immutable state let name = immutable .get(&VariantName::from_str("name").unwrap()) @@ -1568,7 +1557,7 @@ impl TestWallet { let circulating_supply = immutable .get(&VariantName::from_str("circulating").unwrap()) .and_then(|m: &BTreeMap| m.values().next()) - .and_then(|v| Some(v.verified.unwrap_num().unwrap_uint::())) + .map(|v| v.verified.unwrap_num().unwrap_uint::()) .unwrap_or_default(); // Parse ownership state diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 2a73e21..6deb392 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -49,7 +49,6 @@ pub use amplify::{ confinement::{Confined, U16}, map, s, ByteArray, Wrapper, }; -use bitcoin_hashes::{sha256, Hash}; pub use bp::{ // seals::txout::{BlindSeal, CloseMethod, ExplicitSeal}, ConsensusDecode, @@ -97,11 +96,6 @@ pub use psbt::{ // BlindingFactor, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, // RgbWallet, TapretKey, TransferParams, Transition, WalletProvider, XOutpoint, XWitnessId, // }; -use rgb::invoice::{RgbBeneficiary, RgbInvoice}; -use rgb::popls::bp::file::{BpDirMound, DirBarrow}; -use rgb::Consensus; -use rgb::{CallScope, ContractId, CreateParams}; -use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbRuntime, RgbWallet}; // pub use rgbstd::{ // containers::{ // BuilderSeal, ConsignmentExt, Fascia, FileContent, IndexedConsignment, Kit, Transfer, From dd564654ad41d7840bbbfc73099a838a899e96d2 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Mar 2025 17:54:11 +0800 Subject: [PATCH 36/90] feat(tests): Remove obsolete fixture YAML files Signed-off-by: will-bitlightlabs --- ...undles_pubWitness_data_input_sequence.yaml | 1138 ---------------- tests/fixtures/attack_chain.yaml | 1138 ---------------- tests/fixtures/attack_genesis_schema_id.yaml | 1149 ----------------- tests/fixtures/attack_genesis_testnet.yaml | 1149 ----------------- tests/fixtures/attack_resolver_error.yaml | 1127 ---------------- ...687d9e8731228e16b04b4eefda7283069f1c3.yaml | 16 - ...7472e3bce2c440a4e54fa4321107037dfaff0.yaml | 14 - ...f90cdcac27c0af496c4de1a2fd9659948ffce.yaml | 14 - ...408172cb84d8fc6af0ded42d8a8cbea6712e9.yaml | 16 - ...03fda0f50619893e4aee0ba70b014e6d63248.yaml | 14 - ...0505bed9b3a3723a4445dd1289dc708bc80b3.yaml | 16 - tests/fixtures/consignment_A.yaml | 1138 ---------------- tests/fixtures/consignment_B.yaml | 1149 ----------------- 13 files changed, 8078 deletions(-) delete mode 100644 tests/fixtures/attack_bundles_pubWitness_data_input_sequence.yaml delete mode 100644 tests/fixtures/attack_chain.yaml delete mode 100644 tests/fixtures/attack_genesis_schema_id.yaml delete mode 100644 tests/fixtures/attack_genesis_testnet.yaml delete mode 100644 tests/fixtures/attack_resolver_error.yaml delete mode 100644 tests/fixtures/bc_0bc3024ce6404cd7aea387debde687d9e8731228e16b04b4eefda7283069f1c3.yaml delete mode 100644 tests/fixtures/bc_3652d9fea802cb051f671455cbd7472e3bce2c440a4e54fa4321107037dfaff0.yaml delete mode 100644 tests/fixtures/bc_a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce.yaml delete mode 100644 tests/fixtures/bc_c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9.yaml delete mode 100644 tests/fixtures/bc_d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248.yaml delete mode 100644 tests/fixtures/bc_d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3.yaml delete mode 100644 tests/fixtures/consignment_A.yaml delete mode 100644 tests/fixtures/consignment_B.yaml diff --git a/tests/fixtures/attack_bundles_pubWitness_data_input_sequence.yaml b/tests/fixtures/attack_bundles_pubWitness_data_input_sequence.yaml deleted file mode 100644 index e47d027..0000000 --- a/tests/fixtures/attack_bundles_pubWitness_data_input_sequence.yaml +++ /dev/null @@ -1,1138 +0,0 @@ -version: v2 -transfer: true -terminals: - 3bb2645029b3de98be6c3ed5ce3332b8591f59c693146a007b75db5cfdb7c7b8: - chain: bitcoin - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 -genesis: - ffv: 0 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - flags: null - timestamp: 1728925859 - issuer: ssi:anonymous - testnet: true - altLayers1: [] - assetTags: - 4000: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - metadata: {} - globals: - 2000: - - 074e494154434b520e4e4941206173736574206e616d650002 - 2001: - - 09004e4941207465726d7300 - 2010: - - 9a02000000000000 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0 - vout: 1 - blinding: 7704601239148887312 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null -extensions: [] -bundles: -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce:0 - sigScript: '' - sequence: 1 - witness: [] - outputs: - - value: 99999200 - scriptPubkey: 001430d944c2d49db5c315c49e13aab8cad8b9415cac - - value: 0 - scriptPubkey: 6a20669e87f4fe2acf39e58ef94c4a2f81791b7848acac344cd8a2e562f4777acc7f - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0d4042fb3c309aa40bff3159cee3a0ca87c4efc804a5347aa1a363d7244a88f7 - - e56d0e3dbadefb489899917dbc2e1dbf0c49c3ff155e178ef52feab2f351fc7c - - 4edc7f8808488b46c10bedf910818a9afbe2512c1f08a436a7b3db244f22ac85 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - knownTransitions: - 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 10251942175724995735 - state: - value: 616 - blinding: 361c123b494b218e332794a2390dc6d5cc7c332f64cf8764b6dfb3e04e56c9fc - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: bitcoin - data: 108b3912eb0b836427f235bafe449f3153c2aae08887b948a3d8529f17b19b95 - state: - value: 50 - blinding: 48626c4335335cf04b56e9dc4570b7a8b2024b4f19aef719c79eca9e3027b482 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99999600 - scriptPubkey: 00141d66111f9daca8769c3ab2b0fe14354b6198b29c - - value: 0 - scriptPubkey: 6a20a02ab7dd75b9911b540419440ebe8f5be0742f76fd9fdaf5e69ebb30f38d3f11 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0ae6caac7df078206a7af28b0a885098f743d49b92cdb3485558b804492a5be5 - - 843d661f6822486889697a7446a6a9bd1e123921c6dafdde687140cf863a9403 - - 040c8d2b550cc8f3bd210535dbf482f91e7fe62989168c1ed87eebf2b4f35be3 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - knownTransitions: - fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 65535 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 260ba748cbd95421f871fcea5b5a8dca954ed9af5fed4613def3759a33bf11b8 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 7687739675014878388 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248:0 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99998800 - scriptPubkey: 00146ab6fe162c087a01a717d2b6d4bbef87829cec24 - - value: 0 - scriptPubkey: 6a2088b706bf16e225b5d438f48c8c1abc544e807bb7fb99e6fc8ca460d4de62d1b0 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 91246094600e4cae70d42147330754f25ef710118c7bc3aa963b1a8900125b83 - - 58bb69c807310413032dd30a245738b48f1a5cb8645f55b8f089489ae16b0533 - - 500d82630b8bb4a1bcb8973500acae7114dc0d5ef77b748a60b4d93aa9375ca1 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2 - knownTransitions: - c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 9888072140771099372 - state: - value: 539 - blinding: ae89403cecbdb782ddba50b592d9590bb664bb3d4dc9f7772f7c6611f4755345 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: bitcoin - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 - state: - value: 77 - blinding: 8792d1fe5c8d6a0b556d43eca6346dc8d0c654d8c64e30294735ac5b2a17b7f8 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -schema: - ffv: 0 - flags: null - name: NonInflatableAsset - timestamp: 1713343888 - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - metaTypes: {} - globalTypes: - 2000: - reserved: null - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - maxItems: 1 - 2001: - reserved: null - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - maxItems: 1 - 2010: - reserved: null - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - maxItems: 1 - ownedTypes: - 4000: !fungible unsigned64Bit - valencyTypes: [] - genesis: - metadata: [] - globals: - 2000: once - 2001: once - 2010: once - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 9 - extensions: {} - transitions: - 10000: - metadata: [] - globals: {} - inputs: - 4000: onceOrMore - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 0 - reserved: null -ifaces: - ? version: v1 - name: RGB20Fixed - inherits: - - rgb:ifc:Vk9c4$Ny-Fv0J6tg-pDF05CE-312oCWh-fENNuia-GYbEu18#adios-alert-never - - rgb:ifc:13N6PRwT-T68!FGY-lBwX2cm-qesgJ11-j0nQkM1-WSCJFj4#ariel-gizmo-evita - - rgb:ifc:naFrAfgG-Kfu$A!c-3L!bC$4-s1LWJQV-4Iv!62u-4B3ab8Y#mailbox-dialog-iron - - rgb:ifc:w3Lk9Mt3-gKt$n5y-TYpVGg0-IDpK0p9-sHQ!hb6-m2Qr3a0#unicorn-reward-ladder - timestamp: 1711405444 - metadata: {} - globalState: - issuedSupply: - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - required: true - multiple: false - spec: - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - required: true - multiple: false - terms: - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - required: true - multiple: false - assignments: - assetOwner: - ownedState: amount - public: false - required: true - multiple: true - valencies: {} - genesis: - modifier: abstract - metadata: [] - globals: - issuedSupply: once - spec: once - terms: once - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - issuedMismatch - transitions: - transfer: - modifier: abstract - optional: false - metadata: [] - globals: {} - inputs: - assetOwner: onceOrMore - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - nonEqualAmounts - defaultAssignment: assetOwner - extensions: {} - defaultOperation: transfer - errors: - issuedMismatch: supply specified as a global parameter doesn't match the issued supply allocated to the asset owners - nonEqualAmounts: the sum of spent assets doesn't equal to the sum of assets in outputs - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - : version: v1 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - ifaceId: rgb:ifc:$iUnO9aO-1xhqUd6-1Jm5S5!-wM3ngby-5GVEylQ-ZTAMYDk#tornado-pioneer-bucket - timestamp: 1713343888 - metadata: [] - globalState: - - id: 2000 - name: spec - reserved: null - - id: 2001 - name: terms - reserved: null - - id: 2010 - name: issuedSupply - reserved: null - assignments: - - id: 4000 - name: assetOwner - reserved: null - valencies: [] - transitions: - - id: 10000 - name: transfer - reserved: null - extensions: [] - errors: - - id: 0 - name: nonEqualAmounts - reserved: null - - id: 1 - name: issuedMismatch - reserved: null - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w -supplements: [] -types: - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751: !List - - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355 - - min: 0 - max: 7 - 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01: !Tuple - - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154 - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042: !Primitive 64 - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb: !Tuple - - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90 - 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd: !Array - - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042 - - 32 - 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997 - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73: !Enum - - name: excl - tag: 33 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: amp - tag: 38 - - name: plus - tag: 43 - - name: dash - tag: 45 - - name: dot - tag: 46 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4: !Tuple - - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a: !Struct - - name: type - ty: b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660 - - name: digest - ty: 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd - 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7 - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8: !Enum - - name: space - tag: 32 - - name: excl - tag: 33 - - name: quotes - tag: 34 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: percent - tag: 37 - - name: ampersand - tag: 38 - - name: apostrophe - tag: 39 - - name: bracketL - tag: 40 - - name: bracketR - tag: 41 - - name: asterisk - tag: 42 - - name: plus - tag: 43 - - name: comma - tag: 44 - - name: minus - tag: 45 - - name: dot - tag: 46 - - name: slash - tag: 47 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: colon - tag: 58 - - name: semiColon - tag: 59 - - name: less - tag: 60 - - name: equal - tag: 61 - - name: greater - tag: 62 - - name: question - tag: 63 - - name: at - tag: 64 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: sqBracketL - tag: 91 - - name: backSlash - tag: 92 - - name: sqBracketR - tag: 93 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: backtick - tag: 96 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - - name: cBracketL - tag: 123 - - name: pipe - tag: 124 - - name: cBracketR - tag: 125 - - name: tilde - tag: 126 - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 0 - max: 65535 - 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa: !Tuple - - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f - 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7: !Struct - - name: text - ty: 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01 - - name: media - ty: e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81 - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f: !Primitive 8 - 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22: !Enum - - name: indivisible - tag: 0 - - name: deci - tag: 1 - - name: centi - tag: 2 - - name: milli - tag: 3 - - name: deciMilli - tag: 4 - - name: centiMilli - tag: 5 - - name: micro - tag: 6 - - name: deciMicro - tag: 7 - - name: centiMicro - tag: 8 - - name: nano - tag: 9 - - name: deciNano - tag: 10 - - name: centiNano - tag: 11 - - name: pico - tag: 12 - - name: deciPico - tag: 13 - - name: centiPico - tag: 14 - - name: femto - tag: 15 - - name: deciFemto - tag: 16 - - name: centiFemto - tag: 17 - - name: atto - tag: 18 - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f: !Tuple - - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2 - - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751 - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355: !Enum - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 1 - max: 255 - 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d: !Tuple - - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4 - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2: !Enum - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84: !Tuple - - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f - b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997: !Tuple - - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660: !Struct - - name: type - ty: 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - - name: subtype - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - - name: charset - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46: !List - - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73 - - min: 0 - max: 63 - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4: !Tuple - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc - caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7: !Tuple - - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4 - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90: !Tuple - - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1 - - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46 - d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01: !Struct - - name: ticker - ty: 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa - - name: name - ty: 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d - - name: details - ty: 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888 - - name: precision - ty: 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22 - d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c: !Primitive 0 - dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548: !Tuple - - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a - e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548 - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc: !List - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - min: 0 - max: 39 - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1: !Enum - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78: UnicodeChar -scripts: -- isae: - - ALU - - BPDIGEST - - RGB - code: - - 11 - - 0 - - 0 - - 0 - - 208 - - 160 - - 15 - - 1 - - 7 - - 11 - - 0 - - 1 - - 0 - - 11 - - 8 - - 0 - - 0 - - 11 - - 1 - - 2 - - 0 - - 200 - - 218 - - 7 - - 1 - - 57 - - 48 - - 0 - - 209 - - 160 - - 15 - - 1 - - 7 - data: - - 0 - - 1 - - 0 - - 0 - libs: [] -attachments: {} -signatures: {} diff --git a/tests/fixtures/attack_chain.yaml b/tests/fixtures/attack_chain.yaml deleted file mode 100644 index 21e9889..0000000 --- a/tests/fixtures/attack_chain.yaml +++ /dev/null @@ -1,1138 +0,0 @@ -version: v2 -transfer: true -terminals: - 3bb2645029b3de98be6c3ed5ce3332b8591f59c693146a007b75db5cfdb7c7b8: - chain: liquid - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 -genesis: - ffv: 0 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - flags: null - timestamp: 1728925859 - issuer: ssi:anonymous - testnet: true - altLayers1: [] - assetTags: - 4000: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - metadata: {} - globals: - 2000: - - 074e494154434b520e4e4941206173736574206e616d650002 - 2001: - - 09004e4941207465726d7300 - 2010: - - 9a02000000000000 - assignments: - 4000: - type: fungible - items: - - seal: - chain: liquid - data: - method: opretFirst - txid: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0 - vout: 1 - blinding: 7704601239148887312 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null -extensions: [] -bundles: -- pubWitness: - chain: liquid - data: !tx - version: 2 - inputs: - - prevOutput: a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce:0 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99999200 - scriptPubkey: 001430d944c2d49db5c315c49e13aab8cad8b9415cac - - value: 0 - scriptPubkey: 6a20669e87f4fe2acf39e58ef94c4a2f81791b7848acac344cd8a2e562f4777acc7f - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0d4042fb3c309aa40bff3159cee3a0ca87c4efc804a5347aa1a363d7244a88f7 - - e56d0e3dbadefb489899917dbc2e1dbf0c49c3ff155e178ef52feab2f351fc7c - - 4edc7f8808488b46c10bedf910818a9afbe2512c1f08a436a7b3db244f22ac85 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - knownTransitions: - 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: liquid - data: - method: opretFirst - txid: null - vout: 0 - blinding: 10251942175724995735 - state: - value: 616 - blinding: 361c123b494b218e332794a2390dc6d5cc7c332f64cf8764b6dfb3e04e56c9fc - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: liquid - data: 108b3912eb0b836427f235bafe449f3153c2aae08887b948a3d8529f17b19b95 - state: - value: 50 - blinding: 48626c4335335cf04b56e9dc4570b7a8b2024b4f19aef719c79eca9e3027b482 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: liquid - data: !tx - version: 2 - inputs: - - prevOutput: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99999600 - scriptPubkey: 00141d66111f9daca8769c3ab2b0fe14354b6198b29c - - value: 0 - scriptPubkey: 6a20a02ab7dd75b9911b540419440ebe8f5be0742f76fd9fdaf5e69ebb30f38d3f11 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0ae6caac7df078206a7af28b0a885098f743d49b92cdb3485558b804492a5be5 - - 843d661f6822486889697a7446a6a9bd1e123921c6dafdde687140cf863a9403 - - 040c8d2b550cc8f3bd210535dbf482f91e7fe62989168c1ed87eebf2b4f35be3 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - knownTransitions: - fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 65535 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 260ba748cbd95421f871fcea5b5a8dca954ed9af5fed4613def3759a33bf11b8 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: liquid - data: - method: opretFirst - txid: null - vout: 0 - blinding: 7687739675014878388 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: liquid - data: !tx - version: 2 - inputs: - - prevOutput: d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248:0 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99998800 - scriptPubkey: 00146ab6fe162c087a01a717d2b6d4bbef87829cec24 - - value: 0 - scriptPubkey: 6a2088b706bf16e225b5d438f48c8c1abc544e807bb7fb99e6fc8ca460d4de62d1b0 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 91246094600e4cae70d42147330754f25ef710118c7bc3aa963b1a8900125b83 - - 58bb69c807310413032dd30a245738b48f1a5cb8645f55b8f089489ae16b0533 - - 500d82630b8bb4a1bcb8973500acae7114dc0d5ef77b748a60b4d93aa9375ca1 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2 - knownTransitions: - c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: liquid - data: - method: opretFirst - txid: null - vout: 0 - blinding: 9888072140771099372 - state: - value: 539 - blinding: ae89403cecbdb782ddba50b592d9590bb664bb3d4dc9f7772f7c6611f4755345 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: liquid - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 - state: - value: 77 - blinding: 8792d1fe5c8d6a0b556d43eca6346dc8d0c654d8c64e30294735ac5b2a17b7f8 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -schema: - ffv: 0 - flags: null - name: NonInflatableAsset - timestamp: 1713343888 - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - metaTypes: {} - globalTypes: - 2000: - reserved: null - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - maxItems: 1 - 2001: - reserved: null - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - maxItems: 1 - 2010: - reserved: null - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - maxItems: 1 - ownedTypes: - 4000: !fungible unsigned64Bit - valencyTypes: [] - genesis: - metadata: [] - globals: - 2000: once - 2001: once - 2010: once - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 9 - extensions: {} - transitions: - 10000: - metadata: [] - globals: {} - inputs: - 4000: onceOrMore - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 0 - reserved: null -ifaces: - ? version: v1 - name: RGB20Fixed - inherits: - - rgb:ifc:Vk9c4$Ny-Fv0J6tg-pDF05CE-312oCWh-fENNuia-GYbEu18#adios-alert-never - - rgb:ifc:13N6PRwT-T68!FGY-lBwX2cm-qesgJ11-j0nQkM1-WSCJFj4#ariel-gizmo-evita - - rgb:ifc:naFrAfgG-Kfu$A!c-3L!bC$4-s1LWJQV-4Iv!62u-4B3ab8Y#mailbox-dialog-iron - - rgb:ifc:w3Lk9Mt3-gKt$n5y-TYpVGg0-IDpK0p9-sHQ!hb6-m2Qr3a0#unicorn-reward-ladder - timestamp: 1711405444 - metadata: {} - globalState: - issuedSupply: - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - required: true - multiple: false - spec: - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - required: true - multiple: false - terms: - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - required: true - multiple: false - assignments: - assetOwner: - ownedState: amount - public: false - required: true - multiple: true - valencies: {} - genesis: - modifier: abstract - metadata: [] - globals: - issuedSupply: once - spec: once - terms: once - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - issuedMismatch - transitions: - transfer: - modifier: abstract - optional: false - metadata: [] - globals: {} - inputs: - assetOwner: onceOrMore - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - nonEqualAmounts - defaultAssignment: assetOwner - extensions: {} - defaultOperation: transfer - errors: - issuedMismatch: supply specified as a global parameter doesn't match the issued supply allocated to the asset owners - nonEqualAmounts: the sum of spent assets doesn't equal to the sum of assets in outputs - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - : version: v1 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - ifaceId: rgb:ifc:$iUnO9aO-1xhqUd6-1Jm5S5!-wM3ngby-5GVEylQ-ZTAMYDk#tornado-pioneer-bucket - timestamp: 1713343888 - metadata: [] - globalState: - - id: 2000 - name: spec - reserved: null - - id: 2001 - name: terms - reserved: null - - id: 2010 - name: issuedSupply - reserved: null - assignments: - - id: 4000 - name: assetOwner - reserved: null - valencies: [] - transitions: - - id: 10000 - name: transfer - reserved: null - extensions: [] - errors: - - id: 0 - name: nonEqualAmounts - reserved: null - - id: 1 - name: issuedMismatch - reserved: null - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w -supplements: [] -types: - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751: !List - - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355 - - min: 0 - max: 7 - 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01: !Tuple - - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154 - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042: !Primitive 64 - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb: !Tuple - - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90 - 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd: !Array - - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042 - - 32 - 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997 - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73: !Enum - - name: excl - tag: 33 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: amp - tag: 38 - - name: plus - tag: 43 - - name: dash - tag: 45 - - name: dot - tag: 46 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4: !Tuple - - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a: !Struct - - name: type - ty: b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660 - - name: digest - ty: 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd - 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7 - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8: !Enum - - name: space - tag: 32 - - name: excl - tag: 33 - - name: quotes - tag: 34 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: percent - tag: 37 - - name: ampersand - tag: 38 - - name: apostrophe - tag: 39 - - name: bracketL - tag: 40 - - name: bracketR - tag: 41 - - name: asterisk - tag: 42 - - name: plus - tag: 43 - - name: comma - tag: 44 - - name: minus - tag: 45 - - name: dot - tag: 46 - - name: slash - tag: 47 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: colon - tag: 58 - - name: semiColon - tag: 59 - - name: less - tag: 60 - - name: equal - tag: 61 - - name: greater - tag: 62 - - name: question - tag: 63 - - name: at - tag: 64 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: sqBracketL - tag: 91 - - name: backSlash - tag: 92 - - name: sqBracketR - tag: 93 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: backtick - tag: 96 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - - name: cBracketL - tag: 123 - - name: pipe - tag: 124 - - name: cBracketR - tag: 125 - - name: tilde - tag: 126 - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 0 - max: 65535 - 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa: !Tuple - - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f - 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7: !Struct - - name: text - ty: 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01 - - name: media - ty: e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81 - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f: !Primitive 8 - 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22: !Enum - - name: indivisible - tag: 0 - - name: deci - tag: 1 - - name: centi - tag: 2 - - name: milli - tag: 3 - - name: deciMilli - tag: 4 - - name: centiMilli - tag: 5 - - name: micro - tag: 6 - - name: deciMicro - tag: 7 - - name: centiMicro - tag: 8 - - name: nano - tag: 9 - - name: deciNano - tag: 10 - - name: centiNano - tag: 11 - - name: pico - tag: 12 - - name: deciPico - tag: 13 - - name: centiPico - tag: 14 - - name: femto - tag: 15 - - name: deciFemto - tag: 16 - - name: centiFemto - tag: 17 - - name: atto - tag: 18 - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f: !Tuple - - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2 - - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751 - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355: !Enum - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 1 - max: 255 - 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d: !Tuple - - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4 - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2: !Enum - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84: !Tuple - - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f - b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997: !Tuple - - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660: !Struct - - name: type - ty: 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - - name: subtype - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - - name: charset - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46: !List - - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73 - - min: 0 - max: 63 - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4: !Tuple - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc - caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7: !Tuple - - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4 - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90: !Tuple - - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1 - - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46 - d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01: !Struct - - name: ticker - ty: 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa - - name: name - ty: 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d - - name: details - ty: 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888 - - name: precision - ty: 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22 - d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c: !Primitive 0 - dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548: !Tuple - - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a - e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548 - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc: !List - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - min: 0 - max: 39 - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1: !Enum - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78: UnicodeChar -scripts: -- isae: - - ALU - - BPDIGEST - - RGB - code: - - 11 - - 0 - - 0 - - 0 - - 208 - - 160 - - 15 - - 1 - - 7 - - 11 - - 0 - - 1 - - 0 - - 11 - - 8 - - 0 - - 0 - - 11 - - 1 - - 2 - - 0 - - 200 - - 218 - - 7 - - 1 - - 57 - - 48 - - 0 - - 209 - - 160 - - 15 - - 1 - - 7 - data: - - 0 - - 1 - - 0 - - 0 - libs: [] -attachments: {} -signatures: {} diff --git a/tests/fixtures/attack_genesis_schema_id.yaml b/tests/fixtures/attack_genesis_schema_id.yaml deleted file mode 100644 index 94cc24c..0000000 --- a/tests/fixtures/attack_genesis_schema_id.yaml +++ /dev/null @@ -1,1149 +0,0 @@ -version: v2 -transfer: true -terminals: {} -genesis: - ffv: 0 - schemaId: rgb:sch:cJjPZfUpkOqIWhpCTqYJtFYzLfz$AB3JNxIEOJZYn28#circus-version-silence - flags: null - timestamp: 1728926035 - issuer: ssi:anonymous - testnet: true - altLayers1: [] - assetTags: - 4000: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - metadata: {} - globals: - 2000: - - 074e494154434b520e4e4941206173736574206e616d650002 - 2001: - - 09004e4941207465726d7300 - 2010: - - 9a02000000000000 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: 39f4d1888d1d994a2649397d34bfcaf8a9f7de2d6369dd1d42e0c61a26b4384b - vout: 1 - blinding: 7943510731595037200 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null -extensions: [] -bundles: -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99981200 - scriptPubkey: 0014ceb732c6400f984d3258c202811ef439234ff028 - - value: 0 - scriptPubkey: 6a20efce72c00a4dafa508d223854191b9bc534505d7b40841136ea57454bcd8f62e - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - 59fb64885c9d21d566c630261ebaf61e6fdfb90fd755734580e2853606e04468 - - 972bd31741970dcfdcb1fd6e1e0cb86b43a95cdf9be16e26b20f7efb55b8815a - - 59c4bea42d613b9b4d9190c70713db38fcb1213e1384390305c9f41b105e7ad7 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6 - knownTransitions: - 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 10355153668244730300 - state: - value: 50 - blinding: 6ba480e64c69b4e53fe7c76e5c79bb79e8d1a442ba405e9b568612b0014dc452 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 4411272172758969930 - state: - value: 616 - blinding: 12d9fd983214c9993e96b7102204c30495acda3bc43e1fe327f86bce7d30ba2c - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99971800 - scriptPubkey: 0014b63cbe65e66aaec213d9e25a2ff8cd4e4f3c47d0 - - value: 0 - scriptPubkey: 6a2036831c40589897909e67d439cba95004d53280635e2ca66b6e53da52551f957c - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - ade25d6370736e013b7148b4e223030112c4dff704d992e0a8d92073df669c2f - - f478b2c344da010822be93fb7405c56c0b95867ce56582a6c4f647b678fba56e - - 9461109d34187938798bf29433c2b3f11f08ed7f7c8831fcceeab43874f11689 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 295cbd02dbfeddee5c9691cfcc2b5c59b284c8130ad1c9e2cfb867b45dc24dec - knownTransitions: - 295cbd02dbfeddee5c9691cfcc2b5c59b284c8130ad1c9e2cfb867b45dc24dec: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6 - ty: 4000 - no: 1 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 5517491780835545414 - state: - value: 77 - blinding: ab9ad5d441db401474f2f15c2d7940cec37d8b1c962dc20752256f95fdfd1634 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 17151752316201612509 - state: - value: 539 - blinding: 673f27c3f0398984c9a3c5b3f48b82348cde2c05dd58fe1795a55ac54f69e539 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: 39f4d1888d1d994a2649397d34bfcaf8a9f7de2d6369dd1d42e0c61a26b4384b:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99990600 - scriptPubkey: 00147c22e5543af0a3dca1c89ae5ffbf6cadd03a1bb3 - - value: 0 - scriptPubkey: 6a209f6aed701fb9da0762a238d96e0b203220a609a9afaba47ea71ba96e08065458 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - 09a4be7f9ba65f3e4588a93061fe429c8e257de6cb5194a82c1e4dc5d6ff48fd - - cdc9e7844302abff47462927f67cfc6b350a5023dcceb1798eeea250dcce7052 - - 6ef2b8c22960c49c7be94ea27b5909ac60dbbd69fe057d5475795a35802bf24a - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3 - knownTransitions: - 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 65535 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 3fdcbc7e3da71e3ca1c5b6c54aff496fac55cf7aa7fe56975fc37a8733619474 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 16141698382146724670 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -schema: - ffv: 0 - flags: null - name: NonInflatableAsset - timestamp: 1713343888 - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - metaTypes: {} - globalTypes: - 2000: - reserved: null - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - maxItems: 1 - 2001: - reserved: null - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - maxItems: 1 - 2010: - reserved: null - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - maxItems: 1 - ownedTypes: - 4000: !fungible unsigned64Bit - valencyTypes: [] - genesis: - metadata: [] - globals: - 2000: once - 2001: once - 2010: once - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 9 - extensions: {} - transitions: - 10000: - metadata: [] - globals: {} - inputs: - 4000: onceOrMore - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 0 - reserved: null -ifaces: - ? version: v1 - name: RGB20Fixed - inherits: - - rgb:ifc:Vk9c4$Ny-Fv0J6tg-pDF05CE-312oCWh-fENNuia-GYbEu18#adios-alert-never - - rgb:ifc:13N6PRwT-T68!FGY-lBwX2cm-qesgJ11-j0nQkM1-WSCJFj4#ariel-gizmo-evita - - rgb:ifc:naFrAfgG-Kfu$A!c-3L!bC$4-s1LWJQV-4Iv!62u-4B3ab8Y#mailbox-dialog-iron - - rgb:ifc:w3Lk9Mt3-gKt$n5y-TYpVGg0-IDpK0p9-sHQ!hb6-m2Qr3a0#unicorn-reward-ladder - timestamp: 1711405444 - metadata: {} - globalState: - issuedSupply: - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - required: true - multiple: false - spec: - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - required: true - multiple: false - terms: - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - required: true - multiple: false - assignments: - assetOwner: - ownedState: amount - public: false - required: true - multiple: true - valencies: {} - genesis: - modifier: abstract - metadata: [] - globals: - issuedSupply: once - spec: once - terms: once - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - issuedMismatch - transitions: - transfer: - modifier: abstract - optional: false - metadata: [] - globals: {} - inputs: - assetOwner: onceOrMore - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - nonEqualAmounts - defaultAssignment: assetOwner - extensions: {} - defaultOperation: transfer - errors: - issuedMismatch: supply specified as a global parameter doesn't match the issued supply allocated to the asset owners - nonEqualAmounts: the sum of spent assets doesn't equal to the sum of assets in outputs - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - : version: v1 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - ifaceId: rgb:ifc:$iUnO9aO-1xhqUd6-1Jm5S5!-wM3ngby-5GVEylQ-ZTAMYDk#tornado-pioneer-bucket - timestamp: 1713343888 - metadata: [] - globalState: - - id: 2000 - name: spec - reserved: null - - id: 2001 - name: terms - reserved: null - - id: 2010 - name: issuedSupply - reserved: null - assignments: - - id: 4000 - name: assetOwner - reserved: null - valencies: [] - transitions: - - id: 10000 - name: transfer - reserved: null - extensions: [] - errors: - - id: 0 - name: nonEqualAmounts - reserved: null - - id: 1 - name: issuedMismatch - reserved: null - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w -supplements: [] -types: - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751: !List - - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355 - - min: 0 - max: 7 - 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01: !Tuple - - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154 - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042: !Primitive 64 - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb: !Tuple - - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90 - 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd: !Array - - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042 - - 32 - 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997 - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73: !Enum - - name: excl - tag: 33 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: amp - tag: 38 - - name: plus - tag: 43 - - name: dash - tag: 45 - - name: dot - tag: 46 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4: !Tuple - - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a: !Struct - - name: type - ty: b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660 - - name: digest - ty: 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd - 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7 - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8: !Enum - - name: space - tag: 32 - - name: excl - tag: 33 - - name: quotes - tag: 34 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: percent - tag: 37 - - name: ampersand - tag: 38 - - name: apostrophe - tag: 39 - - name: bracketL - tag: 40 - - name: bracketR - tag: 41 - - name: asterisk - tag: 42 - - name: plus - tag: 43 - - name: comma - tag: 44 - - name: minus - tag: 45 - - name: dot - tag: 46 - - name: slash - tag: 47 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: colon - tag: 58 - - name: semiColon - tag: 59 - - name: less - tag: 60 - - name: equal - tag: 61 - - name: greater - tag: 62 - - name: question - tag: 63 - - name: at - tag: 64 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: sqBracketL - tag: 91 - - name: backSlash - tag: 92 - - name: sqBracketR - tag: 93 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: backtick - tag: 96 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - - name: cBracketL - tag: 123 - - name: pipe - tag: 124 - - name: cBracketR - tag: 125 - - name: tilde - tag: 126 - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 0 - max: 65535 - 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa: !Tuple - - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f - 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7: !Struct - - name: text - ty: 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01 - - name: media - ty: e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81 - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f: !Primitive 8 - 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22: !Enum - - name: indivisible - tag: 0 - - name: deci - tag: 1 - - name: centi - tag: 2 - - name: milli - tag: 3 - - name: deciMilli - tag: 4 - - name: centiMilli - tag: 5 - - name: micro - tag: 6 - - name: deciMicro - tag: 7 - - name: centiMicro - tag: 8 - - name: nano - tag: 9 - - name: deciNano - tag: 10 - - name: centiNano - tag: 11 - - name: pico - tag: 12 - - name: deciPico - tag: 13 - - name: centiPico - tag: 14 - - name: femto - tag: 15 - - name: deciFemto - tag: 16 - - name: centiFemto - tag: 17 - - name: atto - tag: 18 - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f: !Tuple - - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2 - - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751 - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355: !Enum - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 1 - max: 255 - 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d: !Tuple - - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4 - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2: !Enum - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84: !Tuple - - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f - b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997: !Tuple - - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660: !Struct - - name: type - ty: 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - - name: subtype - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - - name: charset - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46: !List - - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73 - - min: 0 - max: 63 - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4: !Tuple - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc - caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7: !Tuple - - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4 - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90: !Tuple - - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1 - - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46 - d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01: !Struct - - name: ticker - ty: 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa - - name: name - ty: 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d - - name: details - ty: 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888 - - name: precision - ty: 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22 - d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c: !Primitive 0 - dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548: !Tuple - - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a - e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548 - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc: !List - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - min: 0 - max: 39 - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1: !Enum - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78: UnicodeChar -scripts: -- isae: - - ALU - - BPDIGEST - - RGB - code: - - 11 - - 0 - - 0 - - 0 - - 208 - - 160 - - 15 - - 1 - - 7 - - 11 - - 0 - - 1 - - 0 - - 11 - - 8 - - 0 - - 0 - - 11 - - 1 - - 2 - - 0 - - 200 - - 218 - - 7 - - 1 - - 57 - - 48 - - 0 - - 209 - - 160 - - 15 - - 1 - - 7 - data: - - 0 - - 1 - - 0 - - 0 - libs: [] -attachments: {} -signatures: {} diff --git a/tests/fixtures/attack_genesis_testnet.yaml b/tests/fixtures/attack_genesis_testnet.yaml deleted file mode 100644 index caf0a80..0000000 --- a/tests/fixtures/attack_genesis_testnet.yaml +++ /dev/null @@ -1,1149 +0,0 @@ -version: v2 -transfer: true -terminals: {} -genesis: - ffv: 0 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - flags: null - timestamp: 1728926035 - issuer: ssi:anonymous - testnet: false - altLayers1: [] - assetTags: - 4000: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - metadata: {} - globals: - 2000: - - 074e494154434b520e4e4941206173736574206e616d650002 - 2001: - - 09004e4941207465726d7300 - 2010: - - 9a02000000000000 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: 39f4d1888d1d994a2649397d34bfcaf8a9f7de2d6369dd1d42e0c61a26b4384b - vout: 1 - blinding: 7943510731595037200 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null -extensions: [] -bundles: -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99981200 - scriptPubkey: 0014ceb732c6400f984d3258c202811ef439234ff028 - - value: 0 - scriptPubkey: 6a20efce72c00a4dafa508d223854191b9bc534505d7b40841136ea57454bcd8f62e - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - 59fb64885c9d21d566c630261ebaf61e6fdfb90fd755734580e2853606e04468 - - 972bd31741970dcfdcb1fd6e1e0cb86b43a95cdf9be16e26b20f7efb55b8815a - - 59c4bea42d613b9b4d9190c70713db38fcb1213e1384390305c9f41b105e7ad7 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6 - knownTransitions: - 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 10355153668244730300 - state: - value: 50 - blinding: 6ba480e64c69b4e53fe7c76e5c79bb79e8d1a442ba405e9b568612b0014dc452 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 4411272172758969930 - state: - value: 616 - blinding: 12d9fd983214c9993e96b7102204c30495acda3bc43e1fe327f86bce7d30ba2c - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99971800 - scriptPubkey: 0014b63cbe65e66aaec213d9e25a2ff8cd4e4f3c47d0 - - value: 0 - scriptPubkey: 6a2036831c40589897909e67d439cba95004d53280635e2ca66b6e53da52551f957c - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - ade25d6370736e013b7148b4e223030112c4dff704d992e0a8d92073df669c2f - - f478b2c344da010822be93fb7405c56c0b95867ce56582a6c4f647b678fba56e - - 9461109d34187938798bf29433c2b3f11f08ed7f7c8831fcceeab43874f11689 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 295cbd02dbfeddee5c9691cfcc2b5c59b284c8130ad1c9e2cfb867b45dc24dec - knownTransitions: - 295cbd02dbfeddee5c9691cfcc2b5c59b284c8130ad1c9e2cfb867b45dc24dec: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6 - ty: 4000 - no: 1 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 5517491780835545414 - state: - value: 77 - blinding: ab9ad5d441db401474f2f15c2d7940cec37d8b1c962dc20752256f95fdfd1634 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 17151752316201612509 - state: - value: 539 - blinding: 673f27c3f0398984c9a3c5b3f48b82348cde2c05dd58fe1795a55ac54f69e539 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: 39f4d1888d1d994a2649397d34bfcaf8a9f7de2d6369dd1d42e0c61a26b4384b:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99990600 - scriptPubkey: 00147c22e5543af0a3dca1c89ae5ffbf6cadd03a1bb3 - - value: 0 - scriptPubkey: 6a209f6aed701fb9da0762a238d96e0b203220a609a9afaba47ea71ba96e08065458 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - 09a4be7f9ba65f3e4588a93061fe429c8e257de6cb5194a82c1e4dc5d6ff48fd - - cdc9e7844302abff47462927f67cfc6b350a5023dcceb1798eeea250dcce7052 - - 6ef2b8c22960c49c7be94ea27b5909ac60dbbd69fe057d5475795a35802bf24a - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3 - knownTransitions: - 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 65535 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 3fdcbc7e3da71e3ca1c5b6c54aff496fac55cf7aa7fe56975fc37a8733619474 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 16141698382146724670 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -schema: - ffv: 0 - flags: null - name: NonInflatableAsset - timestamp: 1713343888 - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - metaTypes: {} - globalTypes: - 2000: - reserved: null - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - maxItems: 1 - 2001: - reserved: null - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - maxItems: 1 - 2010: - reserved: null - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - maxItems: 1 - ownedTypes: - 4000: !fungible unsigned64Bit - valencyTypes: [] - genesis: - metadata: [] - globals: - 2000: once - 2001: once - 2010: once - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 9 - extensions: {} - transitions: - 10000: - metadata: [] - globals: {} - inputs: - 4000: onceOrMore - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 0 - reserved: null -ifaces: - ? version: v1 - name: RGB20Fixed - inherits: - - rgb:ifc:Vk9c4$Ny-Fv0J6tg-pDF05CE-312oCWh-fENNuia-GYbEu18#adios-alert-never - - rgb:ifc:13N6PRwT-T68!FGY-lBwX2cm-qesgJ11-j0nQkM1-WSCJFj4#ariel-gizmo-evita - - rgb:ifc:naFrAfgG-Kfu$A!c-3L!bC$4-s1LWJQV-4Iv!62u-4B3ab8Y#mailbox-dialog-iron - - rgb:ifc:w3Lk9Mt3-gKt$n5y-TYpVGg0-IDpK0p9-sHQ!hb6-m2Qr3a0#unicorn-reward-ladder - timestamp: 1711405444 - metadata: {} - globalState: - issuedSupply: - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - required: true - multiple: false - spec: - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - required: true - multiple: false - terms: - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - required: true - multiple: false - assignments: - assetOwner: - ownedState: amount - public: false - required: true - multiple: true - valencies: {} - genesis: - modifier: abstract - metadata: [] - globals: - issuedSupply: once - spec: once - terms: once - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - issuedMismatch - transitions: - transfer: - modifier: abstract - optional: false - metadata: [] - globals: {} - inputs: - assetOwner: onceOrMore - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - nonEqualAmounts - defaultAssignment: assetOwner - extensions: {} - defaultOperation: transfer - errors: - issuedMismatch: supply specified as a global parameter doesn't match the issued supply allocated to the asset owners - nonEqualAmounts: the sum of spent assets doesn't equal to the sum of assets in outputs - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - : version: v1 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - ifaceId: rgb:ifc:$iUnO9aO-1xhqUd6-1Jm5S5!-wM3ngby-5GVEylQ-ZTAMYDk#tornado-pioneer-bucket - timestamp: 1713343888 - metadata: [] - globalState: - - id: 2000 - name: spec - reserved: null - - id: 2001 - name: terms - reserved: null - - id: 2010 - name: issuedSupply - reserved: null - assignments: - - id: 4000 - name: assetOwner - reserved: null - valencies: [] - transitions: - - id: 10000 - name: transfer - reserved: null - extensions: [] - errors: - - id: 0 - name: nonEqualAmounts - reserved: null - - id: 1 - name: issuedMismatch - reserved: null - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w -supplements: [] -types: - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751: !List - - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355 - - min: 0 - max: 7 - 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01: !Tuple - - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154 - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042: !Primitive 64 - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb: !Tuple - - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90 - 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd: !Array - - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042 - - 32 - 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997 - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73: !Enum - - name: excl - tag: 33 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: amp - tag: 38 - - name: plus - tag: 43 - - name: dash - tag: 45 - - name: dot - tag: 46 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4: !Tuple - - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a: !Struct - - name: type - ty: b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660 - - name: digest - ty: 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd - 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7 - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8: !Enum - - name: space - tag: 32 - - name: excl - tag: 33 - - name: quotes - tag: 34 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: percent - tag: 37 - - name: ampersand - tag: 38 - - name: apostrophe - tag: 39 - - name: bracketL - tag: 40 - - name: bracketR - tag: 41 - - name: asterisk - tag: 42 - - name: plus - tag: 43 - - name: comma - tag: 44 - - name: minus - tag: 45 - - name: dot - tag: 46 - - name: slash - tag: 47 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: colon - tag: 58 - - name: semiColon - tag: 59 - - name: less - tag: 60 - - name: equal - tag: 61 - - name: greater - tag: 62 - - name: question - tag: 63 - - name: at - tag: 64 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: sqBracketL - tag: 91 - - name: backSlash - tag: 92 - - name: sqBracketR - tag: 93 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: backtick - tag: 96 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - - name: cBracketL - tag: 123 - - name: pipe - tag: 124 - - name: cBracketR - tag: 125 - - name: tilde - tag: 126 - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 0 - max: 65535 - 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa: !Tuple - - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f - 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7: !Struct - - name: text - ty: 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01 - - name: media - ty: e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81 - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f: !Primitive 8 - 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22: !Enum - - name: indivisible - tag: 0 - - name: deci - tag: 1 - - name: centi - tag: 2 - - name: milli - tag: 3 - - name: deciMilli - tag: 4 - - name: centiMilli - tag: 5 - - name: micro - tag: 6 - - name: deciMicro - tag: 7 - - name: centiMicro - tag: 8 - - name: nano - tag: 9 - - name: deciNano - tag: 10 - - name: centiNano - tag: 11 - - name: pico - tag: 12 - - name: deciPico - tag: 13 - - name: centiPico - tag: 14 - - name: femto - tag: 15 - - name: deciFemto - tag: 16 - - name: centiFemto - tag: 17 - - name: atto - tag: 18 - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f: !Tuple - - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2 - - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751 - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355: !Enum - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 1 - max: 255 - 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d: !Tuple - - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4 - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2: !Enum - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84: !Tuple - - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f - b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997: !Tuple - - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660: !Struct - - name: type - ty: 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - - name: subtype - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - - name: charset - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46: !List - - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73 - - min: 0 - max: 63 - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4: !Tuple - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc - caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7: !Tuple - - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4 - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90: !Tuple - - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1 - - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46 - d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01: !Struct - - name: ticker - ty: 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa - - name: name - ty: 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d - - name: details - ty: 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888 - - name: precision - ty: 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22 - d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c: !Primitive 0 - dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548: !Tuple - - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a - e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548 - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc: !List - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - min: 0 - max: 39 - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1: !Enum - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78: UnicodeChar -scripts: -- isae: - - ALU - - BPDIGEST - - RGB - code: - - 11 - - 0 - - 0 - - 0 - - 208 - - 160 - - 15 - - 1 - - 7 - - 11 - - 0 - - 1 - - 0 - - 11 - - 8 - - 0 - - 0 - - 11 - - 1 - - 2 - - 0 - - 200 - - 218 - - 7 - - 1 - - 57 - - 48 - - 0 - - 209 - - 160 - - 15 - - 1 - - 7 - data: - - 0 - - 1 - - 0 - - 0 - libs: [] -attachments: {} -signatures: {} diff --git a/tests/fixtures/attack_resolver_error.yaml b/tests/fixtures/attack_resolver_error.yaml deleted file mode 100644 index 00f696b..0000000 --- a/tests/fixtures/attack_resolver_error.yaml +++ /dev/null @@ -1,1127 +0,0 @@ -version: v2 -transfer: true -terminals: - 3bb2645029b3de98be6c3ed5ce3332b8591f59c693146a007b75db5cfdb7c7b8: - chain: bitcoin - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 -genesis: - ffv: 0 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - flags: null - timestamp: 1728925859 - issuer: ssi:anonymous - testnet: true - altLayers1: [] - assetTags: - 4000: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - metadata: {} - globals: - 2000: - - 074e494154434b520e4e4941206173736574206e616d650002 - 2001: - - 09004e4941207465726d7300 - 2010: - - 9a02000000000000 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0 - vout: 1 - blinding: 7704601239148887312 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null -extensions: [] -bundles: -- pubWitness: - chain: bitcoin - data: !txid - d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0d4042fb3c309aa40bff3159cee3a0ca87c4efc804a5347aa1a363d7244a88f7 - - e56d0e3dbadefb489899917dbc2e1dbf0c49c3ff155e178ef52feab2f351fc7c - - 4edc7f8808488b46c10bedf910818a9afbe2512c1f08a436a7b3db244f22ac85 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - knownTransitions: - 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 10251942175724995735 - state: - value: 616 - blinding: 361c123b494b218e332794a2390dc6d5cc7c332f64cf8764b6dfb3e04e56c9fc - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: bitcoin - data: 108b3912eb0b836427f235bafe449f3153c2aae08887b948a3d8529f17b19b95 - state: - value: 50 - blinding: 48626c4335335cf04b56e9dc4570b7a8b2024b4f19aef719c79eca9e3027b482 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99999600 - scriptPubkey: 00141d66111f9daca8769c3ab2b0fe14354b6198b29c - - value: 0 - scriptPubkey: 6a20a02ab7dd75b9911b540419440ebe8f5be0742f76fd9fdaf5e69ebb30f38d3f11 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0ae6caac7df078206a7af28b0a885098f743d49b92cdb3485558b804492a5be5 - - 843d661f6822486889697a7446a6a9bd1e123921c6dafdde687140cf863a9403 - - 040c8d2b550cc8f3bd210535dbf482f91e7fe62989168c1ed87eebf2b4f35be3 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - knownTransitions: - fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 65535 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 260ba748cbd95421f871fcea5b5a8dca954ed9af5fed4613def3759a33bf11b8 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 7687739675014878388 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248:0 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99998800 - scriptPubkey: 00146ab6fe162c087a01a717d2b6d4bbef87829cec24 - - value: 0 - scriptPubkey: 6a2088b706bf16e225b5d438f48c8c1abc544e807bb7fb99e6fc8ca460d4de62d1b0 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 91246094600e4cae70d42147330754f25ef710118c7bc3aa963b1a8900125b83 - - 58bb69c807310413032dd30a245738b48f1a5cb8645f55b8f089489ae16b0533 - - 500d82630b8bb4a1bcb8973500acae7114dc0d5ef77b748a60b4d93aa9375ca1 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2 - knownTransitions: - c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 9888072140771099372 - state: - value: 539 - blinding: ae89403cecbdb782ddba50b592d9590bb664bb3d4dc9f7772f7c6611f4755345 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: bitcoin - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 - state: - value: 77 - blinding: 8792d1fe5c8d6a0b556d43eca6346dc8d0c654d8c64e30294735ac5b2a17b7f8 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -schema: - ffv: 0 - flags: null - name: NonInflatableAsset - timestamp: 1713343888 - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - metaTypes: {} - globalTypes: - 2000: - reserved: null - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - maxItems: 1 - 2001: - reserved: null - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - maxItems: 1 - 2010: - reserved: null - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - maxItems: 1 - ownedTypes: - 4000: !fungible unsigned64Bit - valencyTypes: [] - genesis: - metadata: [] - globals: - 2000: once - 2001: once - 2010: once - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 9 - extensions: {} - transitions: - 10000: - metadata: [] - globals: {} - inputs: - 4000: onceOrMore - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 0 - reserved: null -ifaces: - ? version: v1 - name: RGB20Fixed - inherits: - - rgb:ifc:Vk9c4$Ny-Fv0J6tg-pDF05CE-312oCWh-fENNuia-GYbEu18#adios-alert-never - - rgb:ifc:13N6PRwT-T68!FGY-lBwX2cm-qesgJ11-j0nQkM1-WSCJFj4#ariel-gizmo-evita - - rgb:ifc:naFrAfgG-Kfu$A!c-3L!bC$4-s1LWJQV-4Iv!62u-4B3ab8Y#mailbox-dialog-iron - - rgb:ifc:w3Lk9Mt3-gKt$n5y-TYpVGg0-IDpK0p9-sHQ!hb6-m2Qr3a0#unicorn-reward-ladder - timestamp: 1711405444 - metadata: {} - globalState: - issuedSupply: - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - required: true - multiple: false - spec: - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - required: true - multiple: false - terms: - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - required: true - multiple: false - assignments: - assetOwner: - ownedState: amount - public: false - required: true - multiple: true - valencies: {} - genesis: - modifier: abstract - metadata: [] - globals: - issuedSupply: once - spec: once - terms: once - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - issuedMismatch - transitions: - transfer: - modifier: abstract - optional: false - metadata: [] - globals: {} - inputs: - assetOwner: onceOrMore - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - nonEqualAmounts - defaultAssignment: assetOwner - extensions: {} - defaultOperation: transfer - errors: - issuedMismatch: supply specified as a global parameter doesn't match the issued supply allocated to the asset owners - nonEqualAmounts: the sum of spent assets doesn't equal to the sum of assets in outputs - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - : version: v1 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - ifaceId: rgb:ifc:$iUnO9aO-1xhqUd6-1Jm5S5!-wM3ngby-5GVEylQ-ZTAMYDk#tornado-pioneer-bucket - timestamp: 1713343888 - metadata: [] - globalState: - - id: 2000 - name: spec - reserved: null - - id: 2001 - name: terms - reserved: null - - id: 2010 - name: issuedSupply - reserved: null - assignments: - - id: 4000 - name: assetOwner - reserved: null - valencies: [] - transitions: - - id: 10000 - name: transfer - reserved: null - extensions: [] - errors: - - id: 0 - name: nonEqualAmounts - reserved: null - - id: 1 - name: issuedMismatch - reserved: null - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w -supplements: [] -types: - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751: !List - - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355 - - min: 0 - max: 7 - 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01: !Tuple - - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154 - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042: !Primitive 64 - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb: !Tuple - - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90 - 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd: !Array - - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042 - - 32 - 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997 - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73: !Enum - - name: excl - tag: 33 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: amp - tag: 38 - - name: plus - tag: 43 - - name: dash - tag: 45 - - name: dot - tag: 46 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4: !Tuple - - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a: !Struct - - name: type - ty: b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660 - - name: digest - ty: 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd - 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7 - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8: !Enum - - name: space - tag: 32 - - name: excl - tag: 33 - - name: quotes - tag: 34 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: percent - tag: 37 - - name: ampersand - tag: 38 - - name: apostrophe - tag: 39 - - name: bracketL - tag: 40 - - name: bracketR - tag: 41 - - name: asterisk - tag: 42 - - name: plus - tag: 43 - - name: comma - tag: 44 - - name: minus - tag: 45 - - name: dot - tag: 46 - - name: slash - tag: 47 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: colon - tag: 58 - - name: semiColon - tag: 59 - - name: less - tag: 60 - - name: equal - tag: 61 - - name: greater - tag: 62 - - name: question - tag: 63 - - name: at - tag: 64 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: sqBracketL - tag: 91 - - name: backSlash - tag: 92 - - name: sqBracketR - tag: 93 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: backtick - tag: 96 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - - name: cBracketL - tag: 123 - - name: pipe - tag: 124 - - name: cBracketR - tag: 125 - - name: tilde - tag: 126 - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 0 - max: 65535 - 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa: !Tuple - - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f - 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7: !Struct - - name: text - ty: 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01 - - name: media - ty: e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81 - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f: !Primitive 8 - 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22: !Enum - - name: indivisible - tag: 0 - - name: deci - tag: 1 - - name: centi - tag: 2 - - name: milli - tag: 3 - - name: deciMilli - tag: 4 - - name: centiMilli - tag: 5 - - name: micro - tag: 6 - - name: deciMicro - tag: 7 - - name: centiMicro - tag: 8 - - name: nano - tag: 9 - - name: deciNano - tag: 10 - - name: centiNano - tag: 11 - - name: pico - tag: 12 - - name: deciPico - tag: 13 - - name: centiPico - tag: 14 - - name: femto - tag: 15 - - name: deciFemto - tag: 16 - - name: centiFemto - tag: 17 - - name: atto - tag: 18 - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f: !Tuple - - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2 - - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751 - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355: !Enum - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 1 - max: 255 - 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d: !Tuple - - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4 - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2: !Enum - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84: !Tuple - - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f - b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997: !Tuple - - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660: !Struct - - name: type - ty: 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - - name: subtype - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - - name: charset - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46: !List - - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73 - - min: 0 - max: 63 - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4: !Tuple - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc - caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7: !Tuple - - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4 - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90: !Tuple - - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1 - - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46 - d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01: !Struct - - name: ticker - ty: 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa - - name: name - ty: 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d - - name: details - ty: 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888 - - name: precision - ty: 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22 - d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c: !Primitive 0 - dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548: !Tuple - - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a - e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548 - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc: !List - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - min: 0 - max: 39 - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1: !Enum - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78: UnicodeChar -scripts: -- isae: - - ALU - - BPDIGEST - - RGB - code: - - 11 - - 0 - - 0 - - 0 - - 208 - - 160 - - 15 - - 1 - - 7 - - 11 - - 0 - - 1 - - 0 - - 11 - - 8 - - 0 - - 0 - - 11 - - 1 - - 2 - - 0 - - 200 - - 218 - - 7 - - 1 - - 57 - - 48 - - 0 - - 209 - - 160 - - 15 - - 1 - - 7 - data: - - 0 - - 1 - - 0 - - 0 - libs: [] -attachments: {} -signatures: {} diff --git a/tests/fixtures/bc_0bc3024ce6404cd7aea387debde687d9e8731228e16b04b4eefda7283069f1c3.yaml b/tests/fixtures/bc_0bc3024ce6404cd7aea387debde687d9e8731228e16b04b4eefda7283069f1c3.yaml deleted file mode 100644 index 4e1fb30..0000000 --- a/tests/fixtures/bc_0bc3024ce6404cd7aea387debde687d9e8731228e16b04b4eefda7283069f1c3.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2 -inputs: -- prevOutput: d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3:1 - sigScript: '' - sequence: 0 - witness: - - 3044022031154900dd3db440c9d286fc6714ce73a63d3b70131fa61372dc830d63d8feb8022061376e25cc7e8850d0070d982092ecd1e715404b2185428a0950b24a410f98be01 - - 027884e03cdcf5f3ce603ff95bfa16d527d3078c7b48e31695a3d4ef6e552b175d -outputs: -- value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 -- value: 99971800 - scriptPubkey: 0014b63cbe65e66aaec213d9e25a2ff8cd4e4f3c47d0 -- value: 0 - scriptPubkey: 6a2036831c40589897909e67d439cba95004d53280635e2ca66b6e53da52551f957c -lockTime: 0 diff --git a/tests/fixtures/bc_3652d9fea802cb051f671455cbd7472e3bce2c440a4e54fa4321107037dfaff0.yaml b/tests/fixtures/bc_3652d9fea802cb051f671455cbd7472e3bce2c440a4e54fa4321107037dfaff0.yaml deleted file mode 100644 index e924c61..0000000 --- a/tests/fixtures/bc_3652d9fea802cb051f671455cbd7472e3bce2c440a4e54fa4321107037dfaff0.yaml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -inputs: -- prevOutput: d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248:0 - sigScript: '' - sequence: 0 - witness: - - 3045022100980c27acde83d1583762873f8bb8b11ead3eb72831e0bb12b9f17b9445fc63fd0220528bb1fbe5ad8b0e7ab272e4648003f3ab235e24421e97d46adff70d280316c401 - - 02d40f2a8d89f52a92d1b2f1b1047bff2e00f6847dd4243a8adea0253cc3b94591 -outputs: -- value: 99998800 - scriptPubkey: 00146ab6fe162c087a01a717d2b6d4bbef87829cec24 -- value: 0 - scriptPubkey: 6a2088b706bf16e225b5d438f48c8c1abc544e807bb7fb99e6fc8ca460d4de62d1b0 -lockTime: 0 diff --git a/tests/fixtures/bc_a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce.yaml b/tests/fixtures/bc_a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce.yaml deleted file mode 100644 index ca5ff5c..0000000 --- a/tests/fixtures/bc_a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce.yaml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -inputs: -- prevOutput: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0:1 - sigScript: '' - sequence: 0 - witness: - - 3044022017ded71ced861ea4e548ce9deeb69a556717911a644fb88369d12269cd25281302200cc72396108b905e8235362a953387f2195d51ea0376b0870cbfe90cbada9a9e01 - - 029376e491db9dde1d42ed68100e1bf069cf89a735d9175738f4238f9d617ed834 -outputs: -- value: 99999600 - scriptPubkey: 00141d66111f9daca8769c3ab2b0fe14354b6198b29c -- value: 0 - scriptPubkey: 6a20a02ab7dd75b9911b540419440ebe8f5be0742f76fd9fdaf5e69ebb30f38d3f11 -lockTime: 0 diff --git a/tests/fixtures/bc_c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9.yaml b/tests/fixtures/bc_c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9.yaml deleted file mode 100644 index 6ad6bc7..0000000 --- a/tests/fixtures/bc_c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2 -inputs: -- prevOutput: 39f4d1888d1d994a2649397d34bfcaf8a9f7de2d6369dd1d42e0c61a26b4384b:1 - sigScript: '' - sequence: 0 - witness: - - 3044022040589e75b92bd9a9cb725edbbb06d7fe5ee24432f94f758e36dd929841e3701d02206c83c8d7673ee10c9deef90aaad3b71587484cda6ade3eae51e44f32430cb0db01 - - 023b7da09b05da276d729b004663767db536967bc782d14b3d87baba73f1e7de94 -outputs: -- value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 -- value: 99990600 - scriptPubkey: 00147c22e5543af0a3dca1c89ae5ffbf6cadd03a1bb3 -- value: 0 - scriptPubkey: 6a209f6aed701fb9da0762a238d96e0b203220a609a9afaba47ea71ba96e08065458 -lockTime: 0 diff --git a/tests/fixtures/bc_d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248.yaml b/tests/fixtures/bc_d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248.yaml deleted file mode 100644 index 9d770ae..0000000 --- a/tests/fixtures/bc_d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248.yaml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -inputs: -- prevOutput: a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce:0 - sigScript: '' - sequence: 0 - witness: - - 30450221008ed3d3ce756c894485a9bf761add8cd58dfe5a3ee844226b8d09db9760e32a800220678c467e6923976550ce485ebbac7861dcfa2193c18d687c8b25863ad6331f7b01 - - 030508210e85f58443ad57f66f75dacc76ab84fca7879f10a7325eeeef942e3e84 -outputs: -- value: 99999200 - scriptPubkey: 001430d944c2d49db5c315c49e13aab8cad8b9415cac -- value: 0 - scriptPubkey: 6a20669e87f4fe2acf39e58ef94c4a2f81791b7848acac344cd8a2e562f4777acc7f -lockTime: 0 diff --git a/tests/fixtures/bc_d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3.yaml b/tests/fixtures/bc_d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3.yaml deleted file mode 100644 index bed65f8..0000000 --- a/tests/fixtures/bc_d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2 -inputs: -- prevOutput: c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9:1 - sigScript: '' - sequence: 0 - witness: - - 3044022073070da9946fab45dbc02010cacc6e3e89c0539e1741c8abadb1e9aaa7831b190220561c8270ce63fe44af34624a0aa93f6c1fa28cec14f39d92c16e205fe6e1778401 - - 020e8dd627ba520d0c209b7859c1e7cbe4d01bd609d0a28dbcd9be2583692786a0 -outputs: -- value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 -- value: 99981200 - scriptPubkey: 0014ceb732c6400f984d3258c202811ef439234ff028 -- value: 0 - scriptPubkey: 6a20efce72c00a4dafa508d223854191b9bc534505d7b40841136ea57454bcd8f62e -lockTime: 0 diff --git a/tests/fixtures/consignment_A.yaml b/tests/fixtures/consignment_A.yaml deleted file mode 100644 index bbda5fe..0000000 --- a/tests/fixtures/consignment_A.yaml +++ /dev/null @@ -1,1138 +0,0 @@ -version: v2 -transfer: true -terminals: - 3bb2645029b3de98be6c3ed5ce3332b8591f59c693146a007b75db5cfdb7c7b8: - chain: bitcoin - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 -genesis: - ffv: 0 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - flags: null - timestamp: 1728925859 - issuer: ssi:anonymous - testnet: true - altLayers1: [] - assetTags: - 4000: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - metadata: {} - globals: - 2000: - - 074e494154434b520e4e4941206173736574206e616d650002 - 2001: - - 09004e4941207465726d7300 - 2010: - - 9a02000000000000 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0 - vout: 1 - blinding: 7704601239148887312 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null -extensions: [] -bundles: -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: a5c3085efe8dfdba0fa0e11d81bf90cdcac27c0af496c4de1a2fd9659948ffce:0 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99999200 - scriptPubkey: 001430d944c2d49db5c315c49e13aab8cad8b9415cac - - value: 0 - scriptPubkey: 6a20669e87f4fe2acf39e58ef94c4a2f81791b7848acac344cd8a2e562f4777acc7f - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0d4042fb3c309aa40bff3159cee3a0ca87c4efc804a5347aa1a363d7244a88f7 - - e56d0e3dbadefb489899917dbc2e1dbf0c49c3ff155e178ef52feab2f351fc7c - - 4edc7f8808488b46c10bedf910818a9afbe2512c1f08a436a7b3db244f22ac85 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - knownTransitions: - 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 10251942175724995735 - state: - value: 616 - blinding: 361c123b494b218e332794a2390dc6d5cc7c332f64cf8764b6dfb3e04e56c9fc - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: bitcoin - data: 108b3912eb0b836427f235bafe449f3153c2aae08887b948a3d8529f17b19b95 - state: - value: 50 - blinding: 48626c4335335cf04b56e9dc4570b7a8b2024b4f19aef719c79eca9e3027b482 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: 22f0538e189f32922e55daf6fa0b7120bc01de8520a9a4c80655fdaf70272ac0:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99999600 - scriptPubkey: 00141d66111f9daca8769c3ab2b0fe14354b6198b29c - - value: 0 - scriptPubkey: 6a20a02ab7dd75b9911b540419440ebe8f5be0742f76fd9fdaf5e69ebb30f38d3f11 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 0ae6caac7df078206a7af28b0a885098f743d49b92cdb3485558b804492a5be5 - - 843d661f6822486889697a7446a6a9bd1e123921c6dafdde687140cf863a9403 - - 040c8d2b550cc8f3bd210535dbf482f91e7fe62989168c1ed87eebf2b4f35be3 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e - knownTransitions: - fb58c747eec9c44a05ec907ec9d14e0e72572f75db0a3f9aa47f0673702e760e: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 65535 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 260ba748cbd95421f871fcea5b5a8dca954ed9af5fed4613def3759a33bf11b8 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 7687739675014878388 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: d077ea7e3a55a215893a18e82cb03fda0f50619893e4aee0ba70b014e6d63248:0 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 99998800 - scriptPubkey: 00146ab6fe162c087a01a717d2b6d4bbef87829cec24 - - value: 0 - scriptPubkey: 6a2088b706bf16e225b5d438f48c8c1abc544e807bb7fb99e6fc8ca460d4de62d1b0 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 1 - cofactor: 1 - path: - - 91246094600e4cae70d42147330754f25ef710118c7bc3aa963b1a8900125b83 - - 58bb69c807310413032dd30a245738b48f1a5cb8645f55b8f089489ae16b0533 - - 500d82630b8bb4a1bcb8973500acae7114dc0d5ef77b748a60b4d93aa9375ca1 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2 - knownTransitions: - c04da8609a2a8ddf7e0e9847f4ebd6758b1091bceeda10094b24352c97840ea2: - ffv: 0 - contractId: rgb:JgunSMvZ-VCH4cfz-qW1qNyp-VO2a9f7-UYT3vN1-mjO$Ebg - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 9b50df314989fe006013a96d2ded4b508e5f32ef2b29e7245abfb3d9a35888e3 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 9888072140771099372 - state: - value: 539 - blinding: ae89403cecbdb782ddba50b592d9590bb664bb3d4dc9f7772f7c6611f4755345 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - - seal: - chain: bitcoin - data: e1c963ea4a2d4e21f870c713a76d0397a0cc197aece1f53a66ae9febf122bb50 - state: - value: 77 - blinding: 8792d1fe5c8d6a0b556d43eca6346dc8d0c654d8c64e30294735ac5b2a17b7f8 - tag: 603a2b302aac8d1cd7c8adc3acd72f31ce652128f96218fa5b519fd5e9930f6d - lock: null - valencies: [] - validator: null - witness: null -schema: - ffv: 0 - flags: null - name: NonInflatableAsset - timestamp: 1713343888 - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - metaTypes: {} - globalTypes: - 2000: - reserved: null - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - maxItems: 1 - 2001: - reserved: null - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - maxItems: 1 - 2010: - reserved: null - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - maxItems: 1 - ownedTypes: - 4000: !fungible unsigned64Bit - valencyTypes: [] - genesis: - metadata: [] - globals: - 2000: once - 2001: once - 2010: once - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 9 - extensions: {} - transitions: - 10000: - metadata: [] - globals: {} - inputs: - 4000: onceOrMore - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 0 - reserved: null -ifaces: - ? version: v1 - name: RGB20Fixed - inherits: - - rgb:ifc:Vk9c4$Ny-Fv0J6tg-pDF05CE-312oCWh-fENNuia-GYbEu18#adios-alert-never - - rgb:ifc:13N6PRwT-T68!FGY-lBwX2cm-qesgJ11-j0nQkM1-WSCJFj4#ariel-gizmo-evita - - rgb:ifc:naFrAfgG-Kfu$A!c-3L!bC$4-s1LWJQV-4Iv!62u-4B3ab8Y#mailbox-dialog-iron - - rgb:ifc:w3Lk9Mt3-gKt$n5y-TYpVGg0-IDpK0p9-sHQ!hb6-m2Qr3a0#unicorn-reward-ladder - timestamp: 1711405444 - metadata: {} - globalState: - issuedSupply: - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - required: true - multiple: false - spec: - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - required: true - multiple: false - terms: - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - required: true - multiple: false - assignments: - assetOwner: - ownedState: amount - public: false - required: true - multiple: true - valencies: {} - genesis: - modifier: abstract - metadata: [] - globals: - issuedSupply: once - spec: once - terms: once - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - issuedMismatch - transitions: - transfer: - modifier: abstract - optional: false - metadata: [] - globals: {} - inputs: - assetOwner: onceOrMore - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - nonEqualAmounts - defaultAssignment: assetOwner - extensions: {} - defaultOperation: transfer - errors: - issuedMismatch: supply specified as a global parameter doesn't match the issued supply allocated to the asset owners - nonEqualAmounts: the sum of spent assets doesn't equal to the sum of assets in outputs - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - : version: v1 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - ifaceId: rgb:ifc:$iUnO9aO-1xhqUd6-1Jm5S5!-wM3ngby-5GVEylQ-ZTAMYDk#tornado-pioneer-bucket - timestamp: 1713343888 - metadata: [] - globalState: - - id: 2000 - name: spec - reserved: null - - id: 2001 - name: terms - reserved: null - - id: 2010 - name: issuedSupply - reserved: null - assignments: - - id: 4000 - name: assetOwner - reserved: null - valencies: [] - transitions: - - id: 10000 - name: transfer - reserved: null - extensions: [] - errors: - - id: 0 - name: nonEqualAmounts - reserved: null - - id: 1 - name: issuedMismatch - reserved: null - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w -supplements: [] -types: - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751: !List - - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355 - - min: 0 - max: 7 - 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01: !Tuple - - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154 - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042: !Primitive 64 - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb: !Tuple - - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90 - 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd: !Array - - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042 - - 32 - 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997 - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73: !Enum - - name: excl - tag: 33 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: amp - tag: 38 - - name: plus - tag: 43 - - name: dash - tag: 45 - - name: dot - tag: 46 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4: !Tuple - - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a: !Struct - - name: type - ty: b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660 - - name: digest - ty: 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd - 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7 - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8: !Enum - - name: space - tag: 32 - - name: excl - tag: 33 - - name: quotes - tag: 34 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: percent - tag: 37 - - name: ampersand - tag: 38 - - name: apostrophe - tag: 39 - - name: bracketL - tag: 40 - - name: bracketR - tag: 41 - - name: asterisk - tag: 42 - - name: plus - tag: 43 - - name: comma - tag: 44 - - name: minus - tag: 45 - - name: dot - tag: 46 - - name: slash - tag: 47 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: colon - tag: 58 - - name: semiColon - tag: 59 - - name: less - tag: 60 - - name: equal - tag: 61 - - name: greater - tag: 62 - - name: question - tag: 63 - - name: at - tag: 64 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: sqBracketL - tag: 91 - - name: backSlash - tag: 92 - - name: sqBracketR - tag: 93 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: backtick - tag: 96 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - - name: cBracketL - tag: 123 - - name: pipe - tag: 124 - - name: cBracketR - tag: 125 - - name: tilde - tag: 126 - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 0 - max: 65535 - 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa: !Tuple - - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f - 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7: !Struct - - name: text - ty: 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01 - - name: media - ty: e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81 - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f: !Primitive 8 - 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22: !Enum - - name: indivisible - tag: 0 - - name: deci - tag: 1 - - name: centi - tag: 2 - - name: milli - tag: 3 - - name: deciMilli - tag: 4 - - name: centiMilli - tag: 5 - - name: micro - tag: 6 - - name: deciMicro - tag: 7 - - name: centiMicro - tag: 8 - - name: nano - tag: 9 - - name: deciNano - tag: 10 - - name: centiNano - tag: 11 - - name: pico - tag: 12 - - name: deciPico - tag: 13 - - name: centiPico - tag: 14 - - name: femto - tag: 15 - - name: deciFemto - tag: 16 - - name: centiFemto - tag: 17 - - name: atto - tag: 18 - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f: !Tuple - - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2 - - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751 - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355: !Enum - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 1 - max: 255 - 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d: !Tuple - - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4 - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2: !Enum - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84: !Tuple - - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f - b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997: !Tuple - - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660: !Struct - - name: type - ty: 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - - name: subtype - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - - name: charset - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46: !List - - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73 - - min: 0 - max: 63 - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4: !Tuple - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc - caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7: !Tuple - - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4 - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90: !Tuple - - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1 - - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46 - d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01: !Struct - - name: ticker - ty: 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa - - name: name - ty: 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d - - name: details - ty: 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888 - - name: precision - ty: 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22 - d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c: !Primitive 0 - dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548: !Tuple - - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a - e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548 - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc: !List - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - min: 0 - max: 39 - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1: !Enum - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78: UnicodeChar -scripts: -- isae: - - ALU - - BPDIGEST - - RGB - code: - - 11 - - 0 - - 0 - - 0 - - 208 - - 160 - - 15 - - 1 - - 7 - - 11 - - 0 - - 1 - - 0 - - 11 - - 8 - - 0 - - 0 - - 11 - - 1 - - 2 - - 0 - - 200 - - 218 - - 7 - - 1 - - 57 - - 48 - - 0 - - 209 - - 160 - - 15 - - 1 - - 7 - data: - - 0 - - 1 - - 0 - - 0 - libs: [] -attachments: {} -signatures: {} diff --git a/tests/fixtures/consignment_B.yaml b/tests/fixtures/consignment_B.yaml deleted file mode 100644 index bd61796..0000000 --- a/tests/fixtures/consignment_B.yaml +++ /dev/null @@ -1,1149 +0,0 @@ -version: v2 -transfer: true -terminals: {} -genesis: - ffv: 0 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - flags: null - timestamp: 1728926035 - issuer: ssi:anonymous - testnet: true - altLayers1: [] - assetTags: - 4000: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - metadata: {} - globals: - 2000: - - 074e494154434b520e4e4941206173736574206e616d650002 - 2001: - - 09004e4941207465726d7300 - 2010: - - 9a02000000000000 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: 39f4d1888d1d994a2649397d34bfcaf8a9f7de2d6369dd1d42e0c61a26b4384b - vout: 1 - blinding: 7943510731595037200 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null -extensions: [] -bundles: -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: c269055b7750a234087c11acd7a408172cb84d8fc6af0ded42d8a8cbea6712e9:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99981200 - scriptPubkey: 0014ceb732c6400f984d3258c202811ef439234ff028 - - value: 0 - scriptPubkey: 6a20efce72c00a4dafa508d223854191b9bc534505d7b40841136ea57454bcd8f62e - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - 59fb64885c9d21d566c630261ebaf61e6fdfb90fd755734580e2853606e04468 - - 972bd31741970dcfdcb1fd6e1e0cb86b43a95cdf9be16e26b20f7efb55b8815a - - 59c4bea42d613b9b4d9190c70713db38fcb1213e1384390305c9f41b105e7ad7 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6 - knownTransitions: - 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 10355153668244730300 - state: - value: 50 - blinding: 6ba480e64c69b4e53fe7c76e5c79bb79e8d1a442ba405e9b568612b0014dc452 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 4411272172758969930 - state: - value: 616 - blinding: 12d9fd983214c9993e96b7102204c30495acda3bc43e1fe327f86bce7d30ba2c - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: d84c37b6c6616184c454c815d970505bed9b3a3723a4445dd1289dc708bc80b3:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99971800 - scriptPubkey: 0014b63cbe65e66aaec213d9e25a2ff8cd4e4f3c47d0 - - value: 0 - scriptPubkey: 6a2036831c40589897909e67d439cba95004d53280635e2ca66b6e53da52551f957c - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - ade25d6370736e013b7148b4e223030112c4dff704d992e0a8d92073df669c2f - - f478b2c344da010822be93fb7405c56c0b95867ce56582a6c4f647b678fba56e - - 9461109d34187938798bf29433c2b3f11f08ed7f7c8831fcceeab43874f11689 - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 295cbd02dbfeddee5c9691cfcc2b5c59b284c8130ad1c9e2cfb867b45dc24dec - knownTransitions: - 295cbd02dbfeddee5c9691cfcc2b5c59b284c8130ad1c9e2cfb867b45dc24dec: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 10000 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 93ff8f77c5f41ebdfb417b9f30a603e2b48a0db75d5a0e520495954e564f62f6 - ty: 4000 - no: 1 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 0 - blinding: 5517491780835545414 - state: - value: 77 - blinding: ab9ad5d441db401474f2f15c2d7940cec37d8b1c962dc20752256f95fdfd1634 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 17151752316201612509 - state: - value: 539 - blinding: 673f27c3f0398984c9a3c5b3f48b82348cde2c05dd58fe1795a55ac54f69e539 - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -- pubWitness: - chain: bitcoin - data: !tx - version: 2 - inputs: - - prevOutput: 39f4d1888d1d994a2649397d34bfcaf8a9f7de2d6369dd1d42e0c61a26b4384b:1 - sigScript: '' - sequence: 0 - witness: [] - outputs: - - value: 9000 - scriptPubkey: 0014a39902b742ace887eeef8b91463f30893f777a12 - - value: 99990600 - scriptPubkey: 00147c22e5543af0a3dca1c89ae5ffbf6cadd03a1bb3 - - value: 0 - scriptPubkey: 6a209f6aed701fb9da0762a238d96e0b203220a609a9afaba47ea71ba96e08065458 - lockTime: 0 - anchoredBundles: !opret - mpcProof: - pos: 4 - cofactor: 1 - path: - - 09a4be7f9ba65f3e4588a93061fe429c8e257de6cb5194a82c1e4dc5d6ff48fd - - cdc9e7844302abff47462927f67cfc6b350a5023dcceb1798eeea250dcce7052 - - 6ef2b8c22960c49c7be94ea27b5909ac60dbbd69fe057d5475795a35802bf24a - dbcProof: null - bundle: - closeMethod: opretFirst - inputMap: - 0: 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3 - knownTransitions: - 76fc3455d84d793361211daa2a85be764b9bebc559dd2958833bf6ab153fa9a3: - ffv: 0 - contractId: rgb:P9y8fj2n-Hjyhxbb-FSv9Jb6-xVz3qn$-laXX8N6-hzNhlHQ - nonce: 18446744073709551615 - transitionType: 65535 - metadata: {} - globals: {} - inputs: - - prevOut: - op: 3fdcbc7e3da71e3ca1c5b6c54aff496fac55cf7aa7fe56975fc37a8733619474 - ty: 4000 - no: 0 - assignments: - 4000: - type: fungible - items: - - seal: - chain: bitcoin - data: - method: opretFirst - txid: null - vout: 1 - blinding: 16141698382146724670 - state: - value: 666 - blinding: 7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e - tag: 182bcffc792b3b0b5ea98515b0babbf1650db23f30e508eb8637000d8ad590db - lock: null - valencies: [] - validator: null - witness: null -schema: - ffv: 0 - flags: null - name: NonInflatableAsset - timestamp: 1713343888 - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - metaTypes: {} - globalTypes: - 2000: - reserved: null - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - maxItems: 1 - 2001: - reserved: null - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - maxItems: 1 - 2010: - reserved: null - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - maxItems: 1 - ownedTypes: - 4000: !fungible unsigned64Bit - valencyTypes: [] - genesis: - metadata: [] - globals: - 2000: once - 2001: once - 2010: once - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 9 - extensions: {} - transitions: - 10000: - metadata: [] - globals: {} - inputs: - 4000: onceOrMore - assignments: - 4000: onceOrMore - valencies: [] - validator: - lib: abf099d28bed50df5e065715327f3a9b329f777cb0b9fefff634c193a03cb626 - pos: 0 - reserved: null -ifaces: - ? version: v1 - name: RGB20Fixed - inherits: - - rgb:ifc:Vk9c4$Ny-Fv0J6tg-pDF05CE-312oCWh-fENNuia-GYbEu18#adios-alert-never - - rgb:ifc:13N6PRwT-T68!FGY-lBwX2cm-qesgJ11-j0nQkM1-WSCJFj4#ariel-gizmo-evita - - rgb:ifc:naFrAfgG-Kfu$A!c-3L!bC$4-s1LWJQV-4Iv!62u-4B3ab8Y#mailbox-dialog-iron - - rgb:ifc:w3Lk9Mt3-gKt$n5y-TYpVGg0-IDpK0p9-sHQ!hb6-m2Qr3a0#unicorn-reward-ladder - timestamp: 1711405444 - metadata: {} - globalState: - issuedSupply: - semId: 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84 - required: true - multiple: false - spec: - semId: d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01 - required: true - multiple: false - terms: - semId: 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7 - required: true - multiple: false - assignments: - assetOwner: - ownedState: amount - public: false - required: true - multiple: true - valencies: {} - genesis: - modifier: abstract - metadata: [] - globals: - issuedSupply: once - spec: once - terms: once - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - issuedMismatch - transitions: - transfer: - modifier: abstract - optional: false - metadata: [] - globals: {} - inputs: - assetOwner: onceOrMore - assignments: - assetOwner: onceOrMore - valencies: [] - errors: - - nonEqualAmounts - defaultAssignment: assetOwner - extensions: {} - defaultOperation: transfer - errors: - issuedMismatch: supply specified as a global parameter doesn't match the issued supply allocated to the asset owners - nonEqualAmounts: the sum of spent assets doesn't equal to the sum of assets in outputs - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w - : version: v1 - schemaId: rgb:sch:RDYhMTR!9gv8Y2GLv9UNBEK1hcrCmdLDFk9Qd5fnO8k#brave-dinner-banana - ifaceId: rgb:ifc:$iUnO9aO-1xhqUd6-1Jm5S5!-wM3ngby-5GVEylQ-ZTAMYDk#tornado-pioneer-bucket - timestamp: 1713343888 - metadata: [] - globalState: - - id: 2000 - name: spec - reserved: null - - id: 2001 - name: terms - reserved: null - - id: 2010 - name: issuedSupply - reserved: null - assignments: - - id: 4000 - name: assetOwner - reserved: null - valencies: [] - transitions: - - id: 10000 - name: transfer - reserved: null - extensions: [] - errors: - - id: 0 - name: nonEqualAmounts - reserved: null - - id: 1 - name: issuedMismatch - reserved: null - developer: ssi:LZS1ux-gjD9nXPF-OcetUUkW-6r3uSCS6-aQhs9W5f-8JE7w -supplements: [] -types: - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751: !List - - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355 - - min: 0 - max: 7 - 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01: !Tuple - - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154 - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042: !Primitive 64 - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb: !Tuple - - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90 - 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd: !Array - - 1cabbfc3d826c0bfd1e9770a889efacc8b6716ad014a3eec10b6591530229042 - - 32 - 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997 - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73: !Enum - - name: excl - tag: 33 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: amp - tag: 38 - - name: plus - tag: 43 - - name: dash - tag: 45 - - name: dot - tag: 46 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4: !Tuple - - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a: !Struct - - name: type - ty: b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660 - - name: digest - ty: 2a5baaac5089ff098d150b482cfed8bcd01a91c0d7b45d32216ed576ab71ebdd - 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7 - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8: !Enum - - name: space - tag: 32 - - name: excl - tag: 33 - - name: quotes - tag: 34 - - name: hash - tag: 35 - - name: dollar - tag: 36 - - name: percent - tag: 37 - - name: ampersand - tag: 38 - - name: apostrophe - tag: 39 - - name: bracketL - tag: 40 - - name: bracketR - tag: 41 - - name: asterisk - tag: 42 - - name: plus - tag: 43 - - name: comma - tag: 44 - - name: minus - tag: 45 - - name: dot - tag: 46 - - name: slash - tag: 47 - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: colon - tag: 58 - - name: semiColon - tag: 59 - - name: less - tag: 60 - - name: equal - tag: 61 - - name: greater - tag: 62 - - name: question - tag: 63 - - name: at - tag: 64 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: sqBracketL - tag: 91 - - name: backSlash - tag: 92 - - name: sqBracketR - tag: 93 - - name: caret - tag: 94 - - name: lodash - tag: 95 - - name: backtick - tag: 96 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - - name: cBracketL - tag: 123 - - name: pipe - tag: 124 - - name: cBracketR - tag: 125 - - name: tilde - tag: 126 - 560d96f7a47924b2c3df040e6463398fd65fd591652c294342bfa5f939155154: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 0 - max: 65535 - 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa: !Tuple - - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f - 5b8bc7543832054a1d22be94226be7538b133a26881cba4613027878e05c6cf7: !Struct - - name: text - ty: 18cb946f1293cf180e9d78dcc65bc59b472ffffeadfbf58db198cc8328f64b01 - - name: media - ty: e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81 - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f: !Primitive 8 - 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22: !Enum - - name: indivisible - tag: 0 - - name: deci - tag: 1 - - name: centi - tag: 2 - - name: milli - tag: 3 - - name: deciMilli - tag: 4 - - name: centiMilli - tag: 5 - - name: micro - tag: 6 - - name: deciMicro - tag: 7 - - name: centiMicro - tag: 8 - - name: nano - tag: 9 - - name: deciNano - tag: 10 - - name: centiNano - tag: 11 - - name: pico - tag: 12 - - name: deciPico - tag: 13 - - name: centiPico - tag: 14 - - name: femto - tag: 15 - - name: deciFemto - tag: 16 - - name: centiFemto - tag: 17 - - name: atto - tag: 18 - 5e5ec8924f73cd72c4225c96ab47796658ef1b729ca306e260bca42b25891d0f: !Tuple - - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2 - - 0af65fd62581de85cbd14e23e2db9a92bbef8b7974ffe1b50c4c74db8f86e751 - 5f5e26e5c5053c1b4544515bc6a0653da02a0791fb31116d71a4fad916e15355: !Enum - - name: zero - tag: 48 - - name: one - tag: 49 - - name: two - tag: 50 - - name: three - tag: 51 - - name: four - tag: 52 - - name: five - tag: 53 - - name: six - tag: 54 - - name: seven - tag: 55 - - name: eight - tag: 56 - - name: nine - tag: 57 - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 63aa2314e8b147c8b284dfb39a9e10d19caad5faea848e3cb9849d9167d6344a: !List - - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78 - - min: 1 - max: 255 - 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d: !Tuple - - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4 - 822380f475f0edb4b5dc517991de7390ada2dbb3752c4c066851aa01630296c2: !Enum - - name: _A - tag: 65 - - name: _B - tag: 66 - - name: _C - tag: 67 - - name: _D - tag: 68 - - name: _E - tag: 69 - - name: _F - tag: 70 - - name: _G - tag: 71 - - name: _H - tag: 72 - - name: _I - tag: 73 - - name: _J - tag: 74 - - name: _K - tag: 75 - - name: _L - tag: 76 - - name: _M - tag: 77 - - name: _N - tag: 78 - - name: _O - tag: 79 - - name: _P - tag: 80 - - name: _Q - tag: 81 - - name: _R - tag: 82 - - name: _S - tag: 83 - - name: _T - tag: 84 - - name: _U - tag: 85 - - name: _V - tag: 86 - - name: _W - tag: 87 - - name: _X - tag: 88 - - name: _Y - tag: 89 - - name: _Z - tag: 90 - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - 888c5865633af13b95b7cd1a8d8af2dac1dc140b977251d9d4daf3c7511c8e84: !Tuple - - 5ca149585de534ee91b3e3a030b7efd4cdb79abea9152f101f3759b4c7210e1f - b070d38ff6d20c5ae5d80715ca31541d5a52bbdecbd3529d38e6ddb672200997: !Tuple - - 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - b10ddefe8020add8a0ca08292150abb13c514d76de5168c1c97105a27e676660: !Struct - - name: type - ty: 1cb0758e14c2008c0f008ce6d2d41e9e1937e1cd0f9914c59a7e29e1ce7ba0bb - - name: subtype - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - - name: charset - ty: 2fd8f27a172712903e6a3e96f0f85c0480b4211a17acd13059fc51d4a4bbde2c - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46: !List - - 3cd1a29dccad9b917b26305f89a8a4fb2118302a4e73c5ac0a780de6ab005e73 - - min: 0 - max: 63 - c43a7d9eb9b3027973c98f5dd6e1ac04f5cbd34240c0bebc0a0fb808140094d4: !Tuple - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc - caff8faeb38a00a04e3621538f8e61d75a85a465cb0a0e48c3593e7eaa6c5fc7: !Tuple - - 3f2b72b7c4af1a630cb6d3ff088baf351093ee465b9e7d472a610082e449d7e4 - ccc272928f793803d91f5dad8d51cc986b4332380f9224f7c7c1514d768ebb90: !Tuple - - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1 - - bf8fcbe9c5395731a6b4cd61fb00dfe7a5d629365339c55aeae087a3b90aaa46 - d7fcbee31ef0a85d5f973bda1b0b8c9e7efbcbc5572577382cacd3bdb4218a01: !Struct - - name: ticker - ty: 5b772c8eb15fd74700c79241f60f8fda37e736b3fd462ab017ce4d454efa81aa - - name: name - ty: 805ec5bc5312c84190445da16aa1c08a09e300e8323acfae6a23420a29ad003d - - name: details - ty: 45b780258601c526b23b5b4861460a9050e13f35fbbe8305a8001157e4013888 - - name: precision - ty: 5d03c4178da98e7e3f3af343e3997d74201d11f42732cfbea2b04b8e3ff15f22 - d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c: !Primitive 0 - dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548: !Tuple - - 43aa7fc5f6f5644fe5a2ae5e1aa99042cdeb879442e34c723ff5827fb133de8a - e087a83496338799afc48a9211683a427d2bd33e2ea7ebb8a8b880ea4ab4eb81: !Union - ? name: none - tag: 0 - : d83fbee02f0de5b46cf80fe11ef7fdf061c78d975d31ade9eea2bc4099339e6c - ? name: some - tag: 1 - : dc1e2f52567f725fd730ad84867f0da4c9ba9af0813311dfe4ef3e3c4a612548 - f5ad172144ccd2dd62ece74ff0fb14641d936a80c1a0c93ebf97727184897cbc: !List - - 48be23172ae884459ae78334a0063f09fa0e317bea8b233ce782a38875e796b8 - - min: 0 - max: 39 - f9170804ddae0479f8d5af74ab3bd202e6ea4172d9a9b93707151adb7fc40ca1: !Enum - - name: a - tag: 97 - - name: b - tag: 98 - - name: c - tag: 99 - - name: d - tag: 100 - - name: e - tag: 101 - - name: f - tag: 102 - - name: g - tag: 103 - - name: h - tag: 104 - - name: i - tag: 105 - - name: j - tag: 106 - - name: k - tag: 107 - - name: l - tag: 108 - - name: m - tag: 109 - - name: n - tag: 110 - - name: o - tag: 111 - - name: p - tag: 112 - - name: q - tag: 113 - - name: r - tag: 114 - - name: s - tag: 115 - - name: t - tag: 116 - - name: u - tag: 117 - - name: v - tag: 118 - - name: w - tag: 119 - - name: x - tag: 120 - - name: y - tag: 121 - - name: z - tag: 122 - fba958721a3d335406b368c36f5a82790960cce239febcafe189ba9839d5da78: UnicodeChar -scripts: -- isae: - - ALU - - BPDIGEST - - RGB - code: - - 11 - - 0 - - 0 - - 0 - - 208 - - 160 - - 15 - - 1 - - 7 - - 11 - - 0 - - 1 - - 0 - - 11 - - 8 - - 0 - - 0 - - 11 - - 1 - - 2 - - 0 - - 200 - - 218 - - 7 - - 1 - - 57 - - 48 - - 0 - - 209 - - 160 - - 15 - - 1 - - 7 - data: - - 0 - - 1 - - 0 - - 0 - libs: [] -attachments: {} -signatures: {} From 92082eb82935785d4830d71f94216e5799ac708a Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Mar 2025 18:31:15 +0800 Subject: [PATCH 37/90] feat(tests): Add sync_and_rollback_state method for future rollback support Signed-off-by: will-bitlightlabs --- tests/utils/helpers.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index f6508e3..5217211 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1068,8 +1068,16 @@ impl TestWallet { self.instance = instance; } + // TODO: Dr. Maxim mentioned in the meeting that + // He will support rollback state related APIs in the reorg and rbf scenarios + // Because it is not implemented at the moment, only sync is included for now + pub fn sync_and_rollback_state(&mut self) { + self.sync(); + } + pub fn switch_to_instance(&mut self, instance: u8) { self.change_instance(instance); + self.sync_and_rollback_state(); } pub fn indexer_url(&self) -> String { From 855a55359da3b5050dc59151386561a2d5a1e96a Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 11 Mar 2025 20:46:23 +0800 Subject: [PATCH 38/90] test: Update receive_from_unbroadcasted_transfer_to_blinded for RGB v0.12 API changes Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 113 ++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 73 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 10c2246..ee543fb 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -23,7 +23,6 @@ pub mod utils; -use bp::Tx; use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -1411,8 +1410,16 @@ fn sync_mainnet_wlt() { } #[test] -#[ignore = "Needs to be updated to accommodate API changes to RGB v0.12"] #[serial] +// TODO: This test case cannot pass currently +// +// The background is as follows: +// wallet 1 first transfers RGB assets to wallet 2, where wallet 2 receives the assets +// in a blinded manner (using an existing UTXO create rgb-invoice). +// The witness transaction generated between them has not been broadcasted to the network, +// wallet 2 accepts the consignment, use the received assets to transfer to wallet 3 +// finally, the transfer is completed, the asset results of wallet 2 and wallet 3 are correct, +// but the asset result of wallet 1 is incorrect fn receive_from_unbroadcasted_transfer_to_blinded() { initialize(); @@ -1432,87 +1439,47 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { // Get UTXO and create invoice let utxo = wlt_2.get_utxo(None); - broadcast_tx_and_mine(&Tx::from_str(&utxo.txid.to_string()).unwrap(), 0); // In RGB v0.12, the invoice API has been changed let invoice = wlt_2.invoice(contract_id, 100, false, None, Some(utxo)); // Create transfer but do not broadcast its TX - let (_consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); - let txid = tx.txid(); - - // Note: The following code needs to be redesigned in RGB v0.12 - // The original test used a custom OffchainResolver to handle unbroadcasted transactions - // In RGB v0.12, the validation and parsing mechanisms may have changed - - // TODO: Implement a custom resolver for RGB v0.12 - // The original code: - /* - struct OffchainResolver<'a, 'cons, const TRANSFER: bool> { - witness_id: XWitnessId, - consignment: &'cons IndexedConsignment<'cons, TRANSFER>, - fallback: &'a AnyResolver, - } - impl ResolveWitness for OffchainResolver<'_, '_, TRANSFER> { - fn resolve_pub_witness( - &self, - witness_id: XWitnessId, - ) -> Result { - self.consignment - .pub_witness(witness_id) - .and_then(|p| p.map_ref(|pw| pw.tx().cloned()).transpose()) - .ok_or(WitnessResolverError::Unknown(witness_id)) - .or_else(|_| self.fallback.resolve_pub_witness(witness_id)) - } - fn resolve_pub_witness_ord( - &self, - witness_id: XWitnessId, - ) -> Result { - if witness_id != self.witness_id { - return self.fallback.resolve_pub_witness_ord(witness_id); - } - Ok(WitnessOrd::Tentative) - } - } + let (consignment, _tx) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + wlt_2.accept_transfer(&consignment, None).unwrap(); - let resolver = OffchainResolver { - witness_id: XChain::Bitcoin(txid), - consignment: &IndexedConsignment::new(&consignment), - fallback: &wlt_2.get_resolver(), - }; - */ + // The following three lines are debug code, + // used to debug the transfer under normal broadcast logic - // In RGB v0.12, the API for accepting transfers may have changed - // The original code: - // wlt_2.accept_transfer_custom_resolver(consignment.clone(), None, &resolver); + // wlt_1.broadcast_tx(&tx); + // wlt_1.mine_tx(&tx.txid(), false); + // wlt_1.sync(); - // Due to API changes, this test is temporarily ignored - println!("The test needs to be updated to adapt to the API changes in RGB v0.12"); - println!("Transaction ID: {}", txid); + dbg!(wlt_2 + .runtime() + .state_own(Some(contract_id)) + .map(|s| s.1.owned) + .collect::>()); - // The following steps are from the original test, need to be adjusted according to the API changes in RGB v0.12 - /* - let invoice = wlt_3.invoice( - contract_id, - &iface_type_name, - 50, - wlt_2.close_method(), - InvoiceType::Witness, - ); + let invoice = wlt_3.invoice(contract_id, 50, true, None, None); let (consignment, tx) = wlt_2.transfer(invoice, Some(2000), None, true, None); wlt_2.mine_tx(&tx.txid(), false); + wlt_2.sync(); + wlt_1.sync(); + let res = wlt_3.accept_transfer(&consignment, None); + let wlt_3_states = wlt_3 + .runtime() + .state_own(Some(contract_id)) + .map(|s| s.1.owned) + .collect::>(); + let wlt_2_states = wlt_2 + .runtime() + .state_own(Some(contract_id)) + .map(|s| s.1.owned) + .collect::>(); + assert!(res.is_ok(), "accept transfer failed"); + dbg!(wlt_3_states, wlt_2_states); - // consignment validation fails because it notices an unbroadcasted TX in the history - let res = consignment.validate(&wlt_3.get_resolver(), wlt_3.testnet()); - assert!(res.is_err()); - let validation_status = match res { - Ok(validated_consignment) => validated_consignment.validation_status().clone(), - Err((status, _consignment)) => status, - }; - assert_eq!(validation_status.failures.len(), 1); - assert!(matches!( - validation_status.failures[0], - Failure::SealNoPubWitness(_, _, _) - )); - */ + wlt_3.check_allocations(contract_id, AssetSchema::Nia, vec![50]); + wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![50]); + wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![500]); } From 5437d5f32a9e8228b4b463d8bc1534479881bf3f Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 20 Mar 2025 18:48:05 +0800 Subject: [PATCH 39/90] feat(tests): Integrate new issuer NIA/FUA issuance and transfer API tests Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 24 ++- ...CollectibleFungibleAsset.yaml => FUA.yaml} | 10 +- .../{NonInflatableAsset.yaml => NFA.yaml} | 10 +- tests/templates/schemata/RGB20-NFA.issuer | Bin 0 -> 3387 bytes tests/templates/schemata/RGB21-FAC.issuer | Bin 0 -> 3718 bytes tests/templates/schemata/RGB21-UAC.issuer | Bin 0 -> 3448 bytes tests/templates/schemata/RGB21-UDA.issuer | Bin 0 -> 3419 bytes tests/templates/schemata/RGB25-FUA.issuer | Bin 0 -> 3382 bytes tests/transfer.rs | 184 +++++++++--------- tests/utils/helpers.rs | 61 ++++-- tests/utils/mod.rs | 6 +- 11 files changed, 159 insertions(+), 136 deletions(-) rename tests/templates/issuance/{CollectibleFungibleAsset.yaml => FUA.yaml} (60%) rename tests/templates/issuance/{NonInflatableAsset.yaml => NFA.yaml} (62%) create mode 100644 tests/templates/schemata/RGB20-NFA.issuer create mode 100644 tests/templates/schemata/RGB21-FAC.issuer create mode 100644 tests/templates/schemata/RGB21-UAC.issuer create mode 100644 tests/templates/schemata/RGB21-UDA.issuer create mode 100644 tests/templates/schemata/RGB25-FUA.issuer diff --git a/tests/issuance.rs b/tests/issuance.rs index 6004b11..4a01a56 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -3,7 +3,7 @@ pub mod utils; use rstest_reuse::{self, *}; use utils::{ chain::initialize, - helpers::{get_wallet, CFAIssueParams, NIAIssueParams}, + helpers::{get_wallet, CFAIssueParams, FUAIssueParams, NIAIssueParams}, DescriptorType, *, }; @@ -69,10 +69,14 @@ fn issue_nia(wallet_desc: DescriptorType) { .allocations .iter() .any(|(outpoint, amount)| *outpoint == fake_outpoint_one && *amount == 500_000)); + dbg!(wallet + .runtime() + .state_all(Some(contract_id)) + .collect::>()); } #[apply(descriptor_and_close_method)] -fn issue_cfa(wallet_desc: DescriptorType) { +fn issue_fua(wallet_desc: DescriptorType) { println!("wallet_desc {wallet_desc:?}"); initialize(); @@ -80,7 +84,7 @@ fn issue_cfa(wallet_desc: DescriptorType) { let mut wallet = get_wallet(&wallet_desc); // Create CFA issuance parameters - let mut params = CFAIssueParams::new("DemoCFA", "centiMilli", 10_000); + let mut params = FUAIssueParams::new("DemoCFA", "details", "centiMilli", 10_000); // Add initial allocation let fake_outpoint = @@ -89,7 +93,7 @@ fn issue_cfa(wallet_desc: DescriptorType) { params.add_allocation(fake_outpoint, 10_000); // Issue the contract - let contract_id = wallet.issue_cfa_with_params(params); + let contract_id = wallet.issue_fua_with_params(params); // Verify contract state let state = wallet @@ -108,18 +112,22 @@ fn issue_cfa(wallet_desc: DescriptorType) { .allocations .iter() .any(|(outpoint, amount)| *outpoint == fake_outpoint && *amount == 10_000)); + dbg!(wallet + .runtime() + .state_all(Some(contract_id)) + .collect::>()); } #[apply(descriptor_and_close_method)] -fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { +fn issue_fua_multiple_utxos(wallet_desc: DescriptorType) { println!("wallet_desc {wallet_desc:?}"); initialize(); let mut wallet = get_wallet(&wallet_desc); - // Create CFA issuance parameters with multiple allocations - let mut params = CFAIssueParams::new("Multi_UTXO_CFA", "centiMilli", 999); + // Create FUA issuance parameters with multiple allocations + let mut params = FUAIssueParams::new("Multi_UTXO_CFA", "details", "centiMilli", 999); // Get multiple UTXOs and add allocations let amounts = [222, 444, 333]; @@ -129,7 +137,7 @@ fn issue_cfa_multiple_utxos(wallet_desc: DescriptorType) { } // Issue the contract - let contract_id = wallet.issue_cfa_with_params(params); + let contract_id = wallet.issue_fua_with_params(params); // Verify contract state let state = wallet diff --git a/tests/templates/issuance/CollectibleFungibleAsset.yaml b/tests/templates/issuance/FUA.yaml similarity index 60% rename from tests/templates/issuance/CollectibleFungibleAsset.yaml rename to tests/templates/issuance/FUA.yaml index a51c770..ac9e3fc 100644 --- a/tests/templates/issuance/CollectibleFungibleAsset.yaml +++ b/tests/templates/issuance/FUA.yaml @@ -1,19 +1,19 @@ consensus: bitcoin testnet: true -codexId: 6bl9LdZ_-BU8Skh9-f~4UazR-TFwyotq-ac4yebi-zodXJnw#weather-motif-patriot -name: DemoCFA +codexId: V7PSoqY~-Ki2PmBY-mNH~fq6-dQDDaDf-M0l09jz-8ThY4LI#diagram-fantasy-bazaar +name: DemoFUA method: issue -timestamp: "2024-12-18T10:32:00-02:00" +timestamp: "2025-03-17T10:32:00-02:00" global: - name: name - verified: DemoCFA + verified: FUA - name: precision verified: centiMilli - name: circulating verified: 10000 owned: - - name: owned + - name: amount seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 data: 10000 diff --git a/tests/templates/issuance/NonInflatableAsset.yaml b/tests/templates/issuance/NFA.yaml similarity index 62% rename from tests/templates/issuance/NonInflatableAsset.yaml rename to tests/templates/issuance/NFA.yaml index 0a3582c..441489d 100644 --- a/tests/templates/issuance/NonInflatableAsset.yaml +++ b/tests/templates/issuance/NFA.yaml @@ -1,21 +1,21 @@ consensus: bitcoin testnet: true -codexId: znwQGVhW-rfRa8el-pNaAsUW-UWxXsB_-4UlC~Tf-TERhBm4#mirage-queen-delphi +codexId: dLmJMaGC-A4CjS2t-cauJxL1-3f1_osG-0kuj~XB-n8KCQ1k#ranger-beast-puma name: DemoToken method: issue -timestamp: "2024-12-18T10:32:00-02:00" +timestamp: "2025-03-17T10:32:00-02:00" global: - name: name - verified: Demo Token + verified: NFA - name: ticker - verified: DEMO + verified: NFA - name: precision verified: centiMilli - name: circulating verified: 10000 owned: - - name: owned + - name: amount seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 data: 10000 diff --git a/tests/templates/schemata/RGB20-NFA.issuer b/tests/templates/schemata/RGB20-NFA.issuer new file mode 100644 index 0000000000000000000000000000000000000000..796392b53daba0e99c3ac7e47856d93ea0629913 GIT binary patch literal 3387 zcmdT`d2kd}8h`Ii_hcqWhHIffgTt}1#6Sqag~S}qBmn}s!;wJ7PG{y#rb$otOdmN= zAVi8lb_2<-0!EGyEO(*A4FwiQWrG3T6fTyo%jy~hNi@ZZawtaSkobDYz&|d%Rc>w7 zepNH`tM}dC`@Z)L0Fl{}IE@!Q0;h7N0=9cJv5eONrzlt*3EZNR;O9iQBy)b5_u=U- z?~9pfWq{E1+XDl42L3%k0D%br_SJXSTrNF0R*afFW9+nwhx%u4U`m_H_BX_DTLy2{ zTmVGONG1jh{0B06P&z>X)MJ}s_tctd_AV+fUfCOnaenf_rRaw0(a|X1iGAAk?EJHKrlQdDiYaak=h>Mq98YvntmTmlPA$BEv_2lzM-X7Ob z|8;lg$D@X9lk+}2+kL$&?~%>x|C!QpA!cabVc~mQ&-m|txW;ugY;(pQ`20$1JM%)^ zE&-AvJ&-7o^Wo@s>*}c!Ulu%aDt&p>$bTF^P0cc)QkdvK} zIv0Qla=>gyj0`{>a#SIv5zTF6S|DQD$Y+EdFr5*=4IINz9Yi)jzVw4Qq8B{0G5Y-d zEP`{IzZ?JNa(koT0dytdj}a;7)_PWzvFHXYv{|Bvpf zPz(cuz-ZWM_(sC&UB?cgYUT76=leacQ2l@XyMuYXqdnYq)G`V@ch+dOXn2wv-nYBA zxiZ3hx#Q(ATaurxKWEvocjRXoZMomBXgXfGpkvaQsDG_bZ@&2KtQK>M^=3ru)0ciT zDe+?M-i_MDtw&8Pt@t??wo|yuB}^~}G)cwEM9Rx4-brS+BnX^5In0k`7Z%lDS~(wq z3fUx&g>!yMQDw>R#ZxS$GDn^QHS<>?lt0zNDJqtEr96uA3!3sc?UH;xE}Hi7qNYqU zxg~Wvtq8J^S{N z=8k>8h#B_i?4rY66Cxf37NebH8aad)-FyXEVC3Hmpxk7aL0WG;9+A!w1m0xT&$4t# zg$EfyOcSn4mdt}(0>eUFf-PkCijvi$t7a1vZVhVca0n@fOL{2C$|Y#%U6u|bXb<+O zk}YU+o(_lIwHd_2DNa?T5$scs^}R_aKAfJGx8g4?IH@Hntm#(la9`l1n;(wuDOh4k z{yFXaziQO~ZnM=+s`*B{cKPsYALms!omUzUw0?9*i_SEA^Y%j*+IrG7>;E$^qdy=t zG@1aT*P2E~wYzZ#|M}(HRh$st`v>u*>r0Qa$whaj9>qNq-pkJ!QMb@&qtM7`BlI5_ zGa>EFd*@2OyqI(C)+l%6?^o7zwwz8ru}u!F-}Fqo5#M6uAhaf@3<9H+EJia12MvV{ M{u=G+kUSCp5f6rZ*8l(j literal 0 HcmV?d00001 diff --git a/tests/templates/schemata/RGB21-FAC.issuer b/tests/templates/schemata/RGB21-FAC.issuer new file mode 100644 index 0000000000000000000000000000000000000000..60641dabb826e488f024801a73c1863ce2e84dc7 GIT binary patch literal 3718 zcmdT`c~n%_8Nc_=yjeg76)VSmREl*ML?a0J96&%pHa8UVc+6a!Co}I2@4aC&ZfIOc zQK(T96oX4`G@;@_tMO2bTdmtkVo4ftX~sxNV%(zEqE>omU}FDhc|E5+J*W4NncunJ zcE8{E-S=Gp2Fwsyv&;!RYcsNvgk_^yu-UL@D*#w{DZ;_>7C~ekB4@|r%+~Emv5Ns& z<6d-hyzKbb3jzpK00f6;^}HHsf|IgVS}%rvFdsfk8N82q)PovZmqVig0f49}=_~>r z|AvnHQ0@f*=vNXmr=cu)%QwHjyd_}G*~|*Vl_A;lkDVD9+}<%E^SH~K1Nf&ILMlDp z6dD3`vdHpM9u}cKuZtw9GXwx?tp&?0XOq61*7VhQzt+RHzxuldKmFSS_FTob?2x)| z@9l1+-<`PAmK>RV^3t?Rd&n$9zRwtV zI&R^pfI|oB=G64VhP&_CW8zlaTify{#V86v03{3gm{(2C-*@Nc!G48Lw!fJzSBTc} zpVw=Q{BMGMcRjGjm2OU)T9*_Y#((-*@t31({m*Z@f4X(-(}au6iHCPHm$pV9fuy&( zUH?!tcI)H|d1b4p%Z9`wV88JFz=mFn*N+ke51(^;&agyZ30KDo8 zcdvE7#z;=PQOGlLyu&F=Mou#Ff^5VEPIBF3!Pq4goU&U?T&V!m%*{xdofs1jfPrk# zq-Z8RTIUxCRzu`B7We}?*9c5jL|3BeJLp=7=z56!!CE?(_H5@80}h!kkbP7}Bsq$w zRHCx`6v>U7QvG!B*`U_lw@=4r-B=;Q>e(&vtWZ{(pM7m!`_4m!-keIha;iboE9qgx z?K1n)A!IOLIO#R=%$eTv=P7*PJTS9GWjFf z$`ENr5(PrVDdO}^kKqmjnCSJZF@qc;=zb~HQi&y`#6t76=EJ{qB{m&j?t1@vtGKsE zyP+|3^LE>%DjnCbBx#$Mr7Zxgf@mc~>yW4VIu9TY&_`NaQvO{&s&PUF*>?{()WylXCjvE{HOty zNar_Yf8qL2{p8{wO!UW1jXwUzbbY|v&8D25>ZqGjYL54>@IQUxkMI2YeBU4L*FVYo z=(~_3IW61m6gH*`Dp1l&%nPyNfHs^dioO~V66eX}O6 zx@~n>t!A43nIUB9cW(`kY%ANd-r2VGn2Mn!2W!SgH7+*WhH46&f{dkMYAY*Qhifck zAhTkS)`3Mc=H;L2Sv!Fe8Oy;wtV57wQE*uC2wg52Qu$a;`k5D{kJPb}j73h$AEkEK zoYH8@EZFVr7|PD^PHC*lBFN(?$ws1#SC?W@n4l7P9HNqogiuPhiWpB+=Lt?ROr6IS z;z=rrE1pbAxDfNNQJ7n7m8YnAj>qA|t4-h|^b)pnF>W|jZNrijNqN3=QQE~KX2~(4 zbp=i=x!)So5G&J&nLZscCKF;}Vh|G>id{>2nE18SaF$UTvpmQ)X7g^6MI#U?Cz#=hl)rbAAqFS(uv(&1Pt^K#XBt9$dT_ zTCI@d;F2XUKOfp`&~Ar34+Q}_9I&7OiXxOGD9h04goTB$s0bDp!;%tMTBT|43E{pQO@tDE-!WPHyduVo%S zH`Fi$=(1I30xR}!Ts|%0QOwuxE|ZOedOaQy`bpF7`dJ&NJ!FQd0(?2%!WD87mutg7 zZNX*^QtsB{5a}G7jZ^8}d&zF7_VEZjm?BcMC}_H*1Zurff_3D1!3%nw+jKTTK6;O( z8~PGD%t8;3D3u_;PLUfLs61?!1%Hpv8E)9K)29dbQnRuw^k!ZUZaqsy4v33QTlBkH z9926?TlGAom%U)`v#Whw8FN+9|4DoQuNw8g+iYdSS3Y(=xO@1>^|X?zn^I-n?rROs zF-aP0+5u=rTTiLN{y+0t|MLad9Px1KmZO*ZSCs$Ia`Ji~-)&;r)#jE*=h6mlTth*n z8=&;HrjQbM?Jx0f_q`})ZQ-|m#qWJI?-&!E`Eukj>>7F{J*D@$nMxCdLP`_iNnPO3 z*h^P#Zp8;weGol*erm>kgslv2_u-7)XuK-=X| LX-<3fiTd9GN4uzZ literal 0 HcmV?d00001 diff --git a/tests/templates/schemata/RGB21-UAC.issuer b/tests/templates/schemata/RGB21-UAC.issuer new file mode 100644 index 0000000000000000000000000000000000000000..5df9d3925c71caad70c563d2685751dfab81a43d GIT binary patch literal 3448 zcmdT`X;c(f7Jlz_S1%A~1tSM1nnoE7ZUiMR$Wk_-pzMnQg%m~iYr3Sns;R1GGe#wj z3keF71QP^ZBuYp0|_`WcZcn>Y@ipf)Nj|wnV0?ACy zh602Cg^lx4PJsY;on05ci2IZ*s_nYXr=E!0aVVqY+!KC3@R|Pm-aInO;pPB-mLVk4 z78_=TK#j=LtYF4G)S7wPRS{t*1prF535zsi6+Vk<`zqM0?~wIhy50%5|9y?_tlE|v z(tPP^Q!Dw}>>bv`@Z9#(cb~em=3HZK$@syX`ulMuVsmpw>hK1AA4VU-4-3Y=IVy-f5>K$NdgFwE5xi~PT}s$J^THOZ*BiWu2{ue zfDjjeJ$GKS#g@Mmzo0o`awz-ZN2Q-lYt(gZ9q8zraXapP>iG35*{k{@4@0T9 zMwFjC8eKc*l(}LZamG8o!jtsTHtq^M*>ZBLGCf+OpS9QXs@xL*pn%jMAQ(Y#U;rNW zg|pX2mg$1SrsvFhhP69HLC*+!mJ{{3$RQ1y$mxf*oI`Y~rBDb!Rc3l}QhYQGfVXr& zN{?pHBCrv8D0E&^Kqcv;2VN0?%$Lp?qrtd13As z%kJzrQ0!*=3IOXMS_{!ekYy#_{#MV%X z$P*rF!zpzH&?*h5hDt#;pqOgX%SD;=8FHuu8y-4nB?lI0RX@g;9BRn%NX3F*Um>}f z13CcI`=))=P`YdO*uj*q;KZH@ox!=)AJqS;X`r|IkBJvrgEaT{Wbxx7W@o4lS~|Gp z6=mAI(--DHXx-nt`Pi%TKj|)Yzro-zkeguwz8AK7$J+-{nb5U0_gwEj<*oPsZXi#z zwR-4|YQ}(<&l>VZDI8pR~8vFe~%PsTU--aB{>)vi7;JftbzSl3* zm3XVJwC(oW8u@(Xc}@K;-;41rDL<^JIaU(aHpy@5Ki9|B^*4c489l{KS zi4$iMf>p{AtSrYo_oRYjafm`J;bsw{g~xcd(#$#dP^FnE#!o2(rgRP=;9|_qB`{N9 z5$7pchQ;%xs8)^*(+b$eL_6UEr4ji}|zJ%l2|aAj6#^Q97{I|=7JJWk6c zj5LqMXH-_sB&jHk(@JEFg?W&sVSYX|8llMqF@|O{EGU2$3uG9$awRM*gjOrG*&xe8 zj)QhPEGmLL4+Q~=B6K)laWO0@fu*IetPGZyYmM%UtWw$;JAU@ZgS6Fz$XHGIIk^={ zK)C_Q*%_ae+ZTGZ=HSO_Gp@*5&Dho>DoC+#@bkiiEs|R8Htk zn6XXdbgr0-oN&}oOcx%lq(zbQp`MxCcajMIU2IJ1ioZ4Dh{mbvntLImZAEX~{d{b1 zdZr@s*R=Qlt5N^A%~mmK?M=tED~Aq$nOauUBUCpxeR0q+Jwatj-3yJV_FYBjZ>D?h9i<|(9|Rr6y#XJmCHrh#BDYZpB)1W6HTwm`oc{QH{&)S!*Y1rmjelw7 u+V;k-$m84iqV=1fZI#n&fwNLd)jR;ng0jzO?>zO literal 0 HcmV?d00001 diff --git a/tests/templates/schemata/RGB21-UDA.issuer b/tests/templates/schemata/RGB21-UDA.issuer new file mode 100644 index 0000000000000000000000000000000000000000..3555102c181c545a8e4ea81f83df6b0be1cc6032 GIT binary patch literal 3419 zcmdT`dsGzH8Nc`L&aw*y6s#Prk5#A^PzgwkBH+4!u*w@Tppap9_ri|s&MY&tuwaae z1e6wq#$bY=2st)dsd&_?9Ew3gITAg2)TD+)Dn?3;!AF!>AC=DXi20*sdQN+CPVZm8 z^L_Vw{J#5r^9=w~QW-kWhSf$ohZZQan&NpZcmgBChgd1b$a0jGqb+!m!L%Dr8NhR|d4_td!cYcq3Moe#1*HO2!+AA$x%vK;?le!ZP zhW~>*j-(t10x*4kb7_cwGjjuXRu8h@#f4XTZw_+Ocb{#_xTU+<;y2C#{7Z(ANRHM9 z1wy63Q4F7rIjG9!D1$(=3_ltI0J)P93lweUudHah7U0@{()@S#zF80dahK|<*qa&H zbn|vYtLE*+`^|Bone7)JzxZg&XZ6(uGlw&t-rBXNHnh*u)m*w^XG(bu6w{sXJdZu? z)?e#9tucM+Z2Q2?#AD9J_I%R!hKJ8@7y3UK$jT^?N(G_`1Bs*<%7PbsR8}rO_f5)- zj;Qs1p2v?gt*x7e-3AX>BBHk3F75e?WE6=YfDqVR%*dAH9=g?gY+C-%zSlE_3eFVp zX|qDj{NBgq;9W~p(HpwuO|kQWnU6lUU-7SZzp(pGNB_cyF&~iU?hU4I>JL8!#on6m z{NT~3>LuOT#oLHWZn|O@jfbkf(WkSybGJMtLa7cq;&NN+2>_5mau^Ua&)YBn&-=pB zYZIRZyv?F!v(+?XwF$hM=G6=u3lg}M6L^gJJ9IWKx;ypO0=?8QxB1*86tO3s?lpk#Cp+yM%r#sj*1-`_bkag zrHVN*Npa?u);yfm>C@kEqa!lo>J|>x#P>u~Y;jR;<`?T8?LVGB&gxA7wn4NNqB1nX zOgREXKBGWnphV-GG*Gimb5L_!WQ-uta1iVOCD2*suC*i0d(KYUZl^Gyl54w1OQ5Mk zk(C-(qzDtM<}qqe4oaUJs6+z>s1)D(7Y(X3Gm(M;(iM`bfYfY>?*^QX`hQ$!Z(KZe zIPn^s+dHc(AhYtr+IJi7^i}>k?s}`Q^2y;eZhF|_wTcs_4t9NUp(^X*^<~dmkM-?r zd289HJ@)Y=hR1-^tP=43kj?wgog1Do4)>~cj!QI;||+E^%)sS@K(xz z)pBe%nCB?+Y^;F!xpEW5o4gf9)@-IYA15p3444squA(d=g<3#ZXvW4blo?rJ5y6|qC;{>!%&{-X zSOy2mgaS5*5KJ7#i{;s@jSH4%)A{&C8Bg1n5IoMu%u58Ob4rl%uv{d#9UPdiqb4Jy4@q7(<=jOXIyOu|5MSa?NYW{skXR61@6 zv>`VOQWVtdp}_!+Mu;)Y&W1TT&}4!%4L5Ftxw+76h87EC7|62FYK3`ukmDfFLqUKx z8_ds#1qIMR&j0=kle~HEoA~8Zc@0OX(-O=D5uU%1qh&UKNLTy|yCce#BRAZx+-uCqI}U^kG{= z^O{{N?vZn4o-Q)|)Yq8?k|ggroInBzBJ3Ov_XbS)2pPoktWSm=LuFj#Z3l zMd&oH6|quWoeZl|I!xn5L>G@$D9vf%$uUORr3h7BS2mcM!W()5b* zZ+qImoZ_;VOZxnB&;72X8M{gdC^Z36UuyzM)$Y+V{D(tN?UZ@h_1`e>++TNw3{QXN zdj|K-`6M~PqinU*Mj?>YMi^@HniF~PldJk~1`_T*nPQyz#>TDf^%ug=?d9@HcD~vw hrB_M?7+;g~$AAT3Ih5MdO`%XK;uQr6n!Yvp?CW6${@JCs%B`*1uWBa0 zdf)NB?|a`jzW@+1UEz35kR?uZ>5@>cV;85YSQ`L5k{a*lB#*3cens%%3B32&jMP#< zWWueUp4&bDULb(L0s#BUhbt}=?;9*dj+!`ld`0hTQ`RxX4W)bP;kn#LUbl z3iSL3Hbzp0Kmg{qo^0Ng965f|)-Y@>@>>BpVKQ40}bz2If_x|l-a~tza%nlKf zCf!$T9;|VKsG0@JOej2Z{Kn+#D?e@8TsgF7@vXmad}>=lm#?E`-J%WowT+N8=DtEn zoDYxtu%?ze{6qeON7EKY4%oM6@0{&}arlMjd?{%wFRttS+AIsROMt_#U|vwkv=v(3 zj;PzcaYb_c)s%0ZS+2Q;_WNnfqz~GgTV`)ezQT?$y$ap895M;PcQbn;)0}|?vORzn zR8_|S+?xwy*6uIkRNd#2OI(8F*EQ88s4hv?T)12(tES1WpjOs3Lrp>Tdq_XzJqAD;3z7)j5NcS1&Cq{Bqv)9s4Rm***=xlMt*mj@MgJwR&t*;ip|MQ`g@A*v-7z-WKLOXdeikI^{0vOC_F}y8Y0Q zI_J^DpKX2R*q|RTwOlKC{rl+GiaMY5(eN#Fd)mHj=YVh1 zTXKG0)NrVBX8Xv9$nVysHJ)D++hk34+z5|;;`=|0OgO)K=X(A8=7ScNR{b20T@+d1MAns9szj*3lP#)H^(d|43M@^bu~6#Orc#n1;W!dil%;rwihV+g0Ux78 ztf~ogU^f$Or3&Uq8cBA-hN{7h$%xY!#7>)rShpLoDJh6eO+{>48e*qUN9>Flh@CkT zvFYiEoiz)wvu7hVBLlISnTXBGLTq+6Vsmm3o12T+ygbC_=OcE`9K_C@i`aSd5IcW9 zVhaioyI=ug7cLA_%iY1wEOHc+7UdfSFTQu2S4i`mg0;u3qU<3m)^1p70$)}HISv*V zL!O5o55yRjl)%zb==DNDfJ>IZvN9-&(C34a1Z5fe{jj_oDhgCpsA*8wVMPV3tb|on zu(}#9UFzUNi9A911wUSP_aJXMtqGzBuP`GX8k#N0;^)%~3cF)3Hne`zH1WWtQzs5I zw(tI3RNsfDEZE;MJp3VGH{%M+fL?;+5h@6=6pI*89>Ot@HbzfCWO77NusDpfOaoG3 z0Yw1QM9V9(HK--f7Sa-IC!8qB4!hx+MNpU{;Ay~Kq#eB6JD|!TsLvgh0mJDM?9*gt zAm(%f_PrA`fcsILrpf);$47U+Lnl0tmYTch-6ova6lrU?8QsrU{=$tf26g4nwIuzP z@%~>8>VJ3GR*ziulYaTa{@1?Bt!_A@*6(fpvQ;0KVfE(jfjrv$mL>N8vo5oLKxk;T z0cO9}G&1Ym_1pN3UAL+@G49-p(hFDT9b}Uh+#Y)ncMU(8m)*Z+mKmea$cz!L?Tr|o zdi><+;vdduU%oleGxX0(Rvl?NmUMWFQoeS>vNkil-Ry!8O^yiyvy$v)I|hS+Y{9=~ KJRPzp=KloiM11%F literal 0 HcmV?d00001 diff --git a/tests/transfer.rs b/tests/transfer.rs index ee543fb..5ef3c8a 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -27,7 +27,7 @@ use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; -use utils::helpers::CustomCoinselectStrategy; +use utils::helpers::{CustomCoinselectStrategy, FUAIssueParams}; use utils::{ chain::{ connect_reorg_nodes, disconnect_reorg_nodes, get_height, get_height_custom, initialize, @@ -88,8 +88,8 @@ fn simple_transfer(wout: bool) { wlt_1.sync(); wlt_2.sync(); - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![supply - assign]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![supply - assign]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![assign]); let assign_wlt1 = 200; let invoice = wlt_1.invoice(contract_id, assign_wlt1, wout, Some(0), None); @@ -121,10 +121,10 @@ fn simple_transfer(wout: bool) { wlt_1.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![supply - assign, assign_wlt1], ); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![assign - assign_wlt1]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![assign - assign_wlt1]); } #[test] @@ -182,8 +182,8 @@ fn rbf_transfer() { wlt_2.sync(); // Verify asset allocations in both wallets - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![200]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![400]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![200]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![400]); // Transfer assets back to sender wlt_2.send( @@ -200,28 +200,20 @@ fn rbf_transfer() { #[rstest] // blinded: nia - nia -#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::Nia, AS::Nia)] -#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::Nia, AS::Nia)] -#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::Nia, AS::Nia)] -#[case(TT::Blinded, DT::Tr, DT::Tr, AS::Nia, AS::Nia)] +#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::RGB20, AS::RGB20)] +#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::RGB20, AS::RGB20)] +#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::RGB20, AS::RGB20)] +#[case(TT::Blinded, DT::Tr, DT::Tr, AS::RGB20, AS::RGB20)] // blinded: nia - cfa -#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::Nia, AS::Cfa)] -#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::Nia, AS::Cfa)] -#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::Nia, AS::Cfa)] -#[case(TT::Blinded, DT::Tr, DT::Tr, AS::Nia, AS::Cfa)] +#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::RGB20, AS::RGB25)] +#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::RGB20, AS::RGB25)] +#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::RGB20, AS::RGB25)] +#[case(TT::Blinded, DT::Tr, DT::Tr, AS::RGB20, AS::RGB25)] // blinded: cfa - cfa -#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::Cfa, AS::Cfa)] -#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::Cfa, AS::Cfa)] -#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::Cfa, AS::Cfa)] -#[case(TT::Blinded, DT::Tr, DT::Tr, AS::Cfa, AS::Cfa)] -// FIXME: `calling to method absent in Codex API` -// When using the same utxo for issue, the transfer will report an error -// -// There is also a strange phenomenon that when all assets issued using the same utxo are CFA types, no errors are reported. -// rgb-test cmd: cargo test transfer_loop::case_09 -// If both are NIA or the first asset NIA, an error will occur. -// rgb-test cmd: cargo test transfer_loop::case_01 -// +#[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::RGB25, AS::RGB25)] +#[case(TT::Blinded, DT::Wpkh, DT::Tr, AS::RGB25, AS::RGB25)] +#[case(TT::Blinded, DT::Tr, DT::Wpkh, AS::RGB25, AS::RGB25)] +#[case(TT::Blinded, DT::Tr, DT::Tr, AS::RGB25, AS::RGB25)] // TODO: UDA related asset feature, RGB core library is being improved, // And the test case for UDA assets will be added later @@ -252,18 +244,19 @@ fn transfer_loop( // Issue first asset let contract_id_1 = match asset_schema_1 { - AssetSchema::Nia => { + AssetSchema::RGB20 => { let mut params = NIAIssueParams::new("TestAsset1", "TEST1", "centiMilli", issued_supply_1); params.add_allocation(utxo, issued_supply_1); wlt_1.issue_nia_with_params(params) } - AssetSchema::Cfa => { - let mut params = CFAIssueParams::new("TestAsset1", "centiMilli", issued_supply_1); + AssetSchema::RGB25 => { + let mut params = + FUAIssueParams::new("TestAsset1", "details", "centiMilli", issued_supply_1); params.add_allocation(utxo, issued_supply_1); - wlt_1.issue_cfa_with_params(params) + wlt_1.issue_fua_with_params(params) } - AssetSchema::Uda => { + AssetSchema::RGB21 => { // TODO: UDA is not supported yet panic!("UDA is not supported yet"); } @@ -271,18 +264,19 @@ fn transfer_loop( // Issue second asset let contract_id_2 = match asset_schema_2 { - AssetSchema::Nia => { + AssetSchema::RGB20 => { let mut params = NIAIssueParams::new("TestAsset2", "TEST2", "centiMilli", issued_supply_2); params.add_allocation(utxo, issued_supply_2); wlt_1.issue_nia_with_params(params) } - AssetSchema::Cfa => { - let mut params = CFAIssueParams::new("TestAsset2", "centiMilli", issued_supply_2); + AssetSchema::RGB25 => { + let mut params = + FUAIssueParams::new("TestAsset2", "details", "centiMilli", issued_supply_2); params.add_allocation(utxo, issued_supply_2); - wlt_1.issue_cfa_with_params(params) + wlt_1.issue_fua_with_params(params) } - AssetSchema::Uda => { + AssetSchema::RGB21 => { // TODO: UDA is not supported yet panic!("UDA is not supported yet"); } @@ -298,7 +292,7 @@ fn transfer_loop( wlt_1.check_allocations(contract_id_2, asset_schema_2, vec![issued_supply_2]); // wlt_1 spends asset 1 - let amount_1 = if asset_schema_1 != AssetSchema::Uda { + let amount_1 = if asset_schema_1 != AssetSchema::RGB21 { 99 } else { 1 @@ -328,7 +322,7 @@ fn transfer_loop( wlt_2.check_allocations(contract_id_1, asset_schema_1, vec![amount_1]); // wlt_1 spends asset 1 change (only if possible) - if asset_schema_1 != AssetSchema::Uda { + if asset_schema_1 != AssetSchema::RGB21 { let amount_2 = 33; wlt_1.send( &mut wlt_2, @@ -350,7 +344,7 @@ fn transfer_loop( } // wlt_1 spends asset 2 - let amount_3 = if asset_schema_2 != AssetSchema::Uda { + let amount_3 = if asset_schema_2 != AssetSchema::RGB21 { 22 } else { 1 @@ -367,7 +361,7 @@ fn transfer_loop( ); // Verify final allocations - if asset_schema_1 != AssetSchema::Uda { + if asset_schema_1 != AssetSchema::RGB21 { let amount_2 = 33; wlt_1.check_allocations( contract_id_1, @@ -389,12 +383,12 @@ fn transfer_loop( wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3]); // wlt_2 spends received allocation(s) of asset 1 - let amount_4 = if asset_schema_1 != AssetSchema::Uda { + let amount_4 = if asset_schema_1 != AssetSchema::RGB21 { 111 } else { 1 }; - let amount_2 = if asset_schema_1 != AssetSchema::Uda { + let amount_2 = if asset_schema_1 != AssetSchema::RGB21 { 33 } else { 0 @@ -428,7 +422,7 @@ fn transfer_loop( wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3]); // wlt_2 spends asset 2 - let amount_5 = if asset_schema_2 != AssetSchema::Uda { + let amount_5 = if asset_schema_2 != AssetSchema::RGB21 { 11 } else { 1 @@ -469,7 +463,7 @@ fn transfer_loop( wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3 - amount_5]); // wlt_1 spends asset 1, received back - let amount_6 = if asset_schema_1 != AssetSchema::Uda { + let amount_6 = if asset_schema_1 != AssetSchema::RGB21 { issued_supply_1 - amount_1 - amount_2 + amount_4 } else { 1 @@ -520,7 +514,7 @@ fn transfer_loop( wlt_2.check_allocations(contract_id_2, asset_schema_2, vec![amount_3 - amount_5]); // wlt_1 spends asset 2, received back - let amount_7 = if asset_schema_2 != AssetSchema::Uda { + let amount_7 = if asset_schema_2 != AssetSchema::RGB21 { issued_supply_2 - amount_3 + amount_5 } else { 1 @@ -646,7 +640,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) let wlt_2_contract_state = wlt_2.runtime().state_own(None).map(|s| s.1.owned); dbg!(wlt_2_contract_state.collect::>()); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amount]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount]); wlt_2.send( &mut wlt_1, @@ -704,7 +698,7 @@ fn accept_0conf() { wlt_2.accept_transfer(&consignment, None).unwrap(); // wlt_2 sees the allocation even if TX has not been mined - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amt]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amt]); wlt_1.sync(); @@ -717,7 +711,7 @@ fn accept_0conf() { // after mining, wlt_1 doesn't need to get tentative allocations to see the change wlt_1.mine_tx(&txid, false); wlt_1.sync(); - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_change_amt]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_change_amt]); } #[test] @@ -751,8 +745,8 @@ fn tapret_wlt_receiving_opret() { // Fifth transfer: wlt_1 -> wlt_2, transfer 570 wlt_1.send(&mut wlt_2, false, contract_id, 570, 1000, None, None, None); - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![30, 570]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![30, 570]); } #[test] @@ -797,8 +791,8 @@ fn check_fungible_history() { .collect::>()); // check allocations - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![issue_supply - amt]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amt]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![issue_supply - amt]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amt]); } #[test] @@ -829,17 +823,17 @@ fn send_to_oneself() { .collect::>()); // check allocations - wlt.check_allocations(contract_id, AssetSchema::Nia, vec![amt, issue_supply - amt]); + wlt.check_allocations( + contract_id, + AssetSchema::RGB20, + vec![amt, issue_supply - amt], + ); } #[rstest] -#[ignore = "fix needed (calling to method absent in Codex API)"] #[case(DescriptorType::Tr, DescriptorType::Tr)] -#[ignore = "fix needed (calling to method absent in Codex API)"] #[case(DescriptorType::Tr, DescriptorType::Wpkh)] -#[ignore = "fix needed (calling to method absent in Codex API)"] #[case(DescriptorType::Wpkh, DescriptorType::Tr)] -#[ignore = "fix needed (calling to method absent in Codex API)"] #[case(DescriptorType::Wpkh, DescriptorType::Wpkh)] fn blank_tapret_opret( #[case] descriptor_type_0: DescriptorType, @@ -891,10 +885,10 @@ fn blank_tapret_opret( ); // Verify final allocations - wlt_1.check_allocations(contract_id_0, AssetSchema::Nia, vec![]); - wlt_1.check_allocations(contract_id_1, AssetSchema::Nia, vec![]); - wlt_2.check_allocations(contract_id_0, AssetSchema::Nia, vec![200]); - wlt_2.check_allocations(contract_id_1, AssetSchema::Nia, vec![100]); + wlt_1.check_allocations(contract_id_0, AssetSchema::RGB20, vec![]); + wlt_1.check_allocations(contract_id_1, AssetSchema::RGB20, vec![]); + wlt_2.check_allocations(contract_id_0, AssetSchema::RGB20, vec![200]); + wlt_2.check_allocations(contract_id_1, AssetSchema::RGB20, vec![100]); } #[rstest] @@ -1063,12 +1057,12 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let wlt_2_alloc_2 = 80; wlt_1.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_1_alloc_1, wlt_1_alloc_2], ); wlt_2.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_2_alloc_1, wlt_2_alloc_2], ); } @@ -1078,8 +1072,8 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_1.switch_to_instance(INSTANCE_3); wlt_2.switch_to_instance(INSTANCE_3); let wlt_1_alloc_1 = 600; - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); } (HistoryType::Branching, ReorgType::ChangeOrder) => { broadcast_tx_and_mine(&txs[1], INSTANCE_3); @@ -1092,10 +1086,10 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let wlt_2_alloc_1 = 1; wlt_1.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_1_alloc_1, wlt_1_alloc_2], ); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_2_alloc_1]); } (HistoryType::Merging, ReorgType::ChangeOrder) => { broadcast_tx_and_mine(&txs[1], INSTANCE_3); @@ -1105,8 +1099,8 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_2.switch_to_instance(INSTANCE_3); let wlt_1_alloc_1 = 599; let wlt_2_alloc_1 = 1; - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_2_alloc_1]); } (HistoryType::Merging, ReorgType::Revert) => { broadcast_tx_and_mine(&txs[1], INSTANCE_3); @@ -1115,8 +1109,8 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_2.switch_to_instance(INSTANCE_3); let wlt_1_alloc_1 = 400; let wlt_2_alloc_1 = 200; - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_2_alloc_1]); } } @@ -1138,12 +1132,12 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let wlt_2_amt = wlt_2_alloc_1 + wlt_2_alloc_2; wlt_1.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_1_alloc_1, wlt_1_alloc_2], ); wlt_2.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_2_alloc_1, wlt_2_alloc_2], ); @@ -1170,9 +1164,9 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp None, None, ); - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); - wlt_3.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_amt, wlt_2_amt]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_amt, wlt_2_amt]); } HistoryType::Branching => { let wlt_1_alloc_1 = 200; @@ -1181,10 +1175,10 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let wlt_2_alloc_1 = 1; wlt_1.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_1_alloc_1, wlt_1_alloc_2], ); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_2_alloc_1]); // Test spending the final allocations wlt_1.send_contract("TestAsset", &mut wlt_3); @@ -1209,19 +1203,19 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp None, None, ); - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); wlt_3.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_1_amt, wlt_2_alloc_1], ); } HistoryType::Merging => { let wlt_1_alloc_1 = 599; let wlt_2_alloc_1 = 1; - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_1_alloc_1]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![wlt_2_alloc_1]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_2_alloc_1]); // Test spending the final allocations wlt_1.send_contract("TestAsset", &mut wlt_3); @@ -1246,11 +1240,11 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp None, None, ); - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); wlt_3.check_allocations( contract_id, - AssetSchema::Nia, + AssetSchema::RGB20, vec![wlt_1_alloc_1, wlt_2_alloc_1], ); } @@ -1280,7 +1274,7 @@ fn revert_genesis(#[case] with_transfers: bool) { params.add_allocation(utxo, issued_supply); let contract_id = wlt.issue_nia_with_params(params); - wlt.check_allocations(contract_id, AssetSchema::Nia, vec![issued_supply]); + wlt.check_allocations(contract_id, AssetSchema::RGB20, vec![issued_supply]); if with_transfers { let mut recv_wlt = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); @@ -1297,7 +1291,7 @@ fn revert_genesis(#[case] with_transfers: bool) { None, None, ); - wlt.check_allocations(contract_id, AssetSchema::Nia, vec![issued_supply - amt]); + wlt.check_allocations(contract_id, AssetSchema::RGB20, vec![issued_supply - amt]); } // TODO: The following code uses APIs that have been removed in RGB v0.12 @@ -1312,7 +1306,7 @@ fn revert_genesis(#[case] with_transfers: bool) { // // wlt.check_allocations( // contract_id, - // AssetSchema::Nia, + // AssetSchema::RGB20, // vec![], // ); } @@ -1385,8 +1379,8 @@ fn invoice_reuse(#[case] transfer_type: TransferType) { // or should they correspond to two transfers? // Check asset allocations - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![100, 200]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![amount, amount]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![100, 200]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount, amount]); // FIXME: The following code needs to be redesigned in RGB v0.12 // Note: In RGB v0.12, the type of consignment has been changed to PathBuf, no longer directly containing the bundles field @@ -1479,7 +1473,7 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { assert!(res.is_ok(), "accept transfer failed"); dbg!(wlt_3_states, wlt_2_states); - wlt_3.check_allocations(contract_id, AssetSchema::Nia, vec![50]); - wlt_2.check_allocations(contract_id, AssetSchema::Nia, vec![50]); - wlt_1.check_allocations(contract_id, AssetSchema::Nia, vec![500]); + wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![50]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![50]); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![500]); } diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 5217211..d806bb3 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -50,10 +50,10 @@ impl AssetParamsBuilder { } } - /// Create a new builder instance for collectible fungible asset - pub fn default_cfa() -> Self { + /// Create a new builder instance for fractional unique asset + pub fn default_fua() -> Self { Self { - params: Self::from_file(COLLECTIBLE_FUNGIBLE_ASSET_TEMPLATE_PATH), + params: Self::from_file(FRACTIONAL_UNIQUE_ASSET_TEMPLATE_PATH), } } @@ -108,6 +108,20 @@ impl AssetParamsBuilder { self } + /// Update details state in global states + pub fn update_details_state(mut self, value: &str) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "details".into()) + { + state.state.verified = StrictVal::Unit; + state.state.unverified = Some(value.into()); + } + self + } + /// Update ticker state in global states pub fn update_ticker_state(mut self, value: &str) -> Self { if let Some(state) = self @@ -181,7 +195,7 @@ impl AssetParamsBuilder { /// Add owned state pub fn add_owned_state(mut self, seal: Outpoint, val: u64) -> Self { self.params.owned.push(NamedState { - name: "owned".into(), + name: "amount".into(), state: Assignment { seal: EitherSeal::Alt(seal), data: val.into(), @@ -297,9 +311,9 @@ pub struct ColoringInfo { #[derive(Debug, EnumIter, Copy, Clone, PartialEq)] pub enum AssetSchema { - Nia, - Uda, - Cfa, + RGB20, + RGB21, + RGB25, } impl fmt::Display for AssetSchema { @@ -1369,11 +1383,13 @@ impl TestWallet { mut expected_fungible_allocations: Vec, ) { match asset_schema { - AssetSchema::Nia | AssetSchema::Cfa => { + AssetSchema::RGB20 | AssetSchema::RGB25 => { + // For fungible assets, we need to check the "amount" allocation let state = self.runtime.state_own(Some(contract_id)).next().unwrap().1; + let allocation_field = "amount"; let mut actual_fungible_allocations = state .owned - .get("owned") + .get(allocation_field) .unwrap() .iter() .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) @@ -1382,7 +1398,8 @@ impl TestWallet { expected_fungible_allocations.sort(); assert_eq!(actual_fungible_allocations, expected_fungible_allocations); } - AssetSchema::Uda => { + AssetSchema::RGB21 => { + // TODO: Implement UDA asset allocation checking once RGB core library support is ready todo!() } } @@ -1570,7 +1587,7 @@ impl TestWallet { // Parse ownership state let mut allocations = vec![]; - if let Some(owned_map) = owned.get(&VariantName::from_str("owned").unwrap()) { + if let Some(owned_map) = owned.get(&VariantName::from_str("amount").unwrap()) { for assignment in owned_map.values() { allocations.push(( assignment.seal, @@ -1592,11 +1609,13 @@ impl TestWallet { } } -/// Parameters for CFA (Collectible Fungible Asset) issuance +/// Parameters for FUA (Fractional unique asset) issuance #[derive(Clone)] -pub struct CFAIssueParams { +pub struct FUAIssueParams { /// Asset name pub name: String, + /// Asset details + pub details: String, /// Decimal precision for the asset pub precision: String, /// Total circulating supply @@ -1605,10 +1624,11 @@ pub struct CFAIssueParams { pub initial_allocations: Vec<(Outpoint, u64)>, } -impl Default for CFAIssueParams { +impl Default for FUAIssueParams { fn default() -> Self { Self { - name: "Demo CFA".to_string(), + name: "DemoFUA".to_string(), + details: "Demo FUA details".to_string(), precision: "centiMilli".to_string(), circulating_supply: 10_000, initial_allocations: vec![], @@ -1616,15 +1636,17 @@ impl Default for CFAIssueParams { } } -impl CFAIssueParams { +impl FUAIssueParams { /// Create new CFA issuance parameters pub fn new( name: impl Into, + details: impl Into, precision: impl Into, circulating_supply: u64, ) -> Self { Self { name: name.into(), + details: details.into(), precision: precision.into(), circulating_supply, initial_allocations: vec![], @@ -1639,11 +1661,12 @@ impl CFAIssueParams { } impl TestWallet { - /// Issue a CFA contract with custom parameters - pub fn issue_cfa_with_params(&mut self, params: CFAIssueParams) -> ContractId { - let mut builder = AssetParamsBuilder::default_cfa() + /// Issue a FUA contract with custom parameters + pub fn issue_fua_with_params(&mut self, params: FUAIssueParams) -> ContractId { + let mut builder = AssetParamsBuilder::default_fua() .name(params.name.as_str()) .update_name_state(params.name.as_str()) + .update_details_state(params.details.as_str()) .update_precision_state(params.precision.as_str()) .update_circulating_state(params.circulating_supply) .clear_owned_state(); diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 6deb392..ac6c5ec 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -5,10 +5,8 @@ pub mod helpers; pub const TEST_DATA_DIR: &str = "test-data"; pub const SCHEMATA_DIR: &str = "tests/templates/schemata"; pub const ISSUANCE_DIR: &str = "tests/templates/issuance"; -pub const NON_INFLATABLE_ASSET_TEMPLATE_PATH: &str = - "tests/templates/issuance/NonInflatableAsset.yaml"; -pub const COLLECTIBLE_FUNGIBLE_ASSET_TEMPLATE_PATH: &str = - "tests/templates/issuance/CollectibleFungibleAsset.yaml"; +pub const NON_INFLATABLE_ASSET_TEMPLATE_PATH: &str = "tests/templates/issuance/NFA.yaml"; +pub const FRACTIONAL_UNIQUE_ASSET_TEMPLATE_PATH: &str = "tests/templates/issuance/FUA.yaml"; pub const INTEGRATION_DATA_DIR: &str = "integration"; pub const STRESS_DATA_DIR: &str = "stress"; From 81830823c2534c0a9977a7f0b7aea49873f801eb Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 24 Mar 2025 11:46:52 +0800 Subject: [PATCH 40/90] chore: remove useless CFAIssueParams Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 2 +- tests/transfer.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/issuance.rs b/tests/issuance.rs index 4a01a56..b25809e 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -3,7 +3,7 @@ pub mod utils; use rstest_reuse::{self, *}; use utils::{ chain::initialize, - helpers::{get_wallet, CFAIssueParams, FUAIssueParams, NIAIssueParams}, + helpers::{get_wallet, FUAIssueParams, NIAIssueParams}, DescriptorType, *, }; diff --git a/tests/transfer.rs b/tests/transfer.rs index 5ef3c8a..633e343 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -35,7 +35,7 @@ use utils::{ }, helpers::{ broadcast_tx_and_mine, get_mainnet_wallet, get_wallet, get_wallet_custom, AssetSchema, - CFAIssueParams, HistoryType, NIAIssueParams, ReorgType, TransferType, + HistoryType, NIAIssueParams, ReorgType, TransferType, }, DescriptorType, INSTANCE_2, INSTANCE_3, *, }; From c6c2d078407fce555789d4f11591eee0042da9e8 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 24 Mar 2025 11:50:52 +0800 Subject: [PATCH 41/90] chore: ignore consignment tests Signed-off-by: will-bitlightlabs --- tests/utils/consignment_utils.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/utils/consignment_utils.rs b/tests/utils/consignment_utils.rs index b2df428..9bb5813 100644 --- a/tests/utils/consignment_utils.rs +++ b/tests/utils/consignment_utils.rs @@ -186,6 +186,7 @@ where } #[test] +#[ignore] fn test_parse_and_rebuild_consignment() { let src = Path::new("test-data/integration/00d99ed6/consignment-551.rgb"); let dst = Path::new("test-data/integration/00d99ed6/output").to_owned(); @@ -513,6 +514,7 @@ pub fn create_attack_consignment( } #[test] +#[ignore] fn test_create_attack_consignment() { let src = Path::new("test-data/integration/00d99ed6/consignment-551.rgb"); let chain_attack_path = create_attack_consignment(src, "chain").unwrap(); From 61bc340e6605b5234b759eab37135fb351ac4090 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 25 Mar 2025 19:33:10 +0800 Subject: [PATCH 42/90] feat(tests): Added new FAC issuance test templates and related features Signed-off-by: will-bitlightlabs --- .gitmodules | 2 +- Cargo.toml | 2 + strict-types | 2 +- tests/issuance.rs | 53 ++++++++++++++++++++-- tests/templates/issuance/FAC.yaml | 30 ++++++++++++ tests/templates/schemata/RGB21-FAC.issuer | Bin 3718 -> 7612 bytes tests/templates/schemata/RGB21-UAC.issuer | Bin 3448 -> 0 bytes tests/templates/schemata/RGB21-UDA.issuer | Bin 3419 -> 0 bytes tests/utils/helpers.rs | 9 +++- tests/utils/mod.rs | 1 + 10 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 tests/templates/issuance/FAC.yaml delete mode 100644 tests/templates/schemata/RGB21-UAC.issuer delete mode 100644 tests/templates/schemata/RGB21-UDA.issuer diff --git a/.gitmodules b/.gitmodules index 5798a64..9ab3432 100644 --- a/.gitmodules +++ b/.gitmodules @@ -24,7 +24,7 @@ url = https://github.com/RGB-WG/rgb-schemata [submodule "strict-types"] path = strict-types - url = https://github.com/strict-types/strict-types + url = https://github.com/will-bitlightlabs/strict-types.git [submodule "strict-encoding"] path = strict-encoding url = https://github.com/strict-types/strict-encoding diff --git a/Cargo.toml b/Cargo.toml index c980a56..8c5858f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -125,4 +125,6 @@ sonic-callreq = { path = "./sonic/callreq" } strict_encoding = { path = "./strict-encoding/rust" } strict_encoding_derive = { path = "./strict-encoding/rust/derive" } ## strict-types +# Temporarily use the `fix/value-type-order-mismatch` branch of `will-bitlightlabs/strict-types` +# After the upstream PR is merged, switch back to `strict-types/strict-types` strict_types = { path = "./strict-types" } diff --git a/strict-types b/strict-types index 302acf4..6618c6d 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit 302acf4b1c4a5b128e9af6a3433c94a1b0774073 +Subproject commit 6618c6dfcc5d3d7e28d6f94943e06a697f953190 diff --git a/tests/issuance.rs b/tests/issuance.rs index b25809e..0ccb9f7 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -1,9 +1,13 @@ pub mod utils; use rstest_reuse::{self, *}; +use strict_types::{ + value::{Blob, StrictNum}, + VariantName, +}; use utils::{ chain::initialize, - helpers::{get_wallet, FUAIssueParams, NIAIssueParams}, + helpers::{get_wallet, AssetParamsBuilder, FUAIssueParams, NIAIssueParams}, DescriptorType, *, }; @@ -13,8 +17,6 @@ const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; #[template] #[rstest] #[case(DescriptorType::Wpkh)] -#[case(DescriptorType::Wpkh)] -#[case(DescriptorType::Tr)] #[case(DescriptorType::Tr)] fn descriptor_and_close_method(#[case] wallet_desc: DescriptorType) {} @@ -203,6 +205,51 @@ fn issue_nia_multiple_utxos(wallet_desc: DescriptorType) { assert_eq!(total_allocated, 999); } +#[apply(descriptor_and_close_method)] +fn issue_fac(wallet_desc: DescriptorType) { + println!("wallet_desc {wallet_desc:?}"); + + initialize(); + + // TODO: + let mut wallet = get_wallet(&wallet_desc); + let mut default_fac = AssetParamsBuilder::default_fac().build(); + + for name_state in default_fac.global.iter_mut() { + let name = VariantName::from_str("token").unwrap(); + if name_state.name == name { + let token = &mut name_state.state.verified; + if let StrictVal::Struct(s) = token { + let reserved_name = FieldName::from_str("reserved").unwrap(); + let reserved = s.get_mut(&reserved_name).unwrap(); + *reserved = StrictVal::Bytes(Blob(vec![0; 26])); + } + } + } + + for name_state in default_fac.owned.iter_mut() { + let name = VariantName::from_str("fractions").unwrap(); + if name_state.name == name { + let fractions = &mut name_state.state; + let fractions_data = &mut fractions.data; + *fractions_data = StrictVal::Tuple(vec![ + StrictVal::Number(StrictNum::from(0u32)), + StrictVal::Number(StrictNum::from(10000u64)), + ]); + } + } + + let contract_id = wallet.issue_with_params(default_fac); + + dbg!( + wallet.contracts_info(), + wallet + .runtime() + .state_all(Some(contract_id)) + .collect::>() + ); +} + // TODO: RGB official is improving the feature of uda asset, will add test after it's ready // #[apply(descriptor_and_close_method)] // fn issue_uda(wallet_desc: DescriptorType) { diff --git a/tests/templates/issuance/FAC.yaml b/tests/templates/issuance/FAC.yaml new file mode 100644 index 0000000..95b8d5b --- /dev/null +++ b/tests/templates/issuance/FAC.yaml @@ -0,0 +1,30 @@ +consensus: bitcoin +testnet: true +codexId: rlRZvs8I-GisCpaD-0L9GTZc-SHPBkK8-S0xp24p-eSZ3iNo#distant-recycle-paprika + +# This is the correct codexId +# codexId: rlRZvs8I-GisCpaD-0L9GTZc-SHPBkK8-S0xp24p-eSZ3iNo#distant-recycle-paprika +name: DemoFAC +method: issue +timestamp: "2025-03-17T10:32:00-02:00" + +global: + - name: name + verified: FractionableAssetCollection + - name: fractions + verified: 10000 + - name: token + verified: + index: 0 + amount: 10000 + # TODO: `reserved` is a 26-sized U8 array, + # Need to rewrite to bytes in code + reserved: +owned: + - name: fractions + seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 + data: + # TODO: Expected to be parsed as tuple, but parsed as union, need to convert in code + - 0 + - 10000 + diff --git a/tests/templates/schemata/RGB21-FAC.issuer b/tests/templates/schemata/RGB21-FAC.issuer index 60641dabb826e488f024801a73c1863ce2e84dc7..b03efedc70466b695fb8f63ac9686088d5008e22 100644 GIT binary patch literal 7612 zcmdT|dpK3;{$KCfd+og`boWaoMnja`YDm(yF;OD-h?Z^dg`It~*4k_}A~h*p=yFn0 zi6-Sznsk$r%6Nn>x~r6OnQk~5-Biw^%=~`mIj47e&OGONe(xW=&%3_w<$K+q&lf?) zd`}8Rv_v5nN)3b*MbHK!g;YxPFAYb;a>`yQl#3OlP)SN;#1v7~4iA?|gc(!b_x675 z{r3YP0AV4B#uF>{(F4n|rM9yNJ)CDG+VZpd@r948_EVL$1?4g7R|q2plUa!L{t21B zNA(SWAP4<|&Rpi{O+tUl{>|d*X5vDM!)VRFn_K0{P2-K@RyPdjfc#4h0p>GXU~L6> zG%1u*5d;Y|B0d|5`g8??u(@J_7D}Yl?OA6YT4=SDNZ;r*>A(KaDXdzb5o%TRq&=sM zzujh+be=xnCTA+&%hP>(1dy zx27OPMcb44hcv|%vAAjTun7g`lYVOp3yFh01)yKNh*3%|lo6A!q@=RTpZktI?;312 z{BVAe-_Fs5_KV#zXV=8`RSgfIw?HmIFj^5!$XVY-?|asGXmo7%jvqtm^<2PIX$x`4;onZZ&xM-(LhRZE-vbnArN__+L&F zZvF0JMDlX1PTM_s5Pz6PcJ74A;>t9(uQSiUI)6|*%moO-0(dWiNhnH1Ajlta(HCo9 z9+N4R%s>%gAdxFoG-V*64CD&hfQV5s=|(FIK7UoH=)TX)Q7i;-{C&MV-JRVLM4MUQ zGfop|peb6q$O?dJnIk#~KimKjM4|k2)G3Rf4N!hDKy{E+{BVB%ayYX=f(kA&>u7S{ z7o9NZJ7LEBvXV^B*=4@gubj}5(|q0~ z{GF&%I{zEy*c7e_qo*#jDn#CZW@!VPfpa+`B#im+6c1qUm(kgkLr!#-_D zMfxrMX@dr{L5^r}em|etu#rCw<;WQe!YuS<`yvPm6PV7V0HiW-SeQgECe#E7aBg;6 z_wx0KsUZH=x4%y8Iy?8hQ|%0sSD06WEj5lu5)?tk65>V^-D&!Fk2{2y7^xe`@+~9k zPi?Yw$>`d?Y#9HB?FuuFP^M7HX;^vX+#EhQN!w|Mjqw~--j!Y_PuJ|K&A-@^BbLos zrDZj@3oL|hv1t={VI#l^vhZMb2^&RH_dxgX3Fb1uz=K? zY2(K^5_Mh?oE)zaR{LoB$Ff6BYf86GztNx`@Kx{UiI$n$Y^`hu=R$5uoYu}is288drV6X}t@8e0QPGR& z->PrtC*2vAwJt6uxd-;0gR<#(C2?4*@ne!f(e3PuJX6E@1&1BH=fyU9M^#kEU^&Yo zBf{8XAua4GoscwYSAxCU2gK5R{DY*EkB6p#oQ3;T<_VXVckt}A>-A=g{_#yWuGd>- zJkEc7biv#%PTd8!4>cLbFSu#cF?XqGwc^*s{JM~D-=2Q7vRCrcQ0qLWNrwKXwF8D# zls{hix3EeMrX&@L2-sz?Xv09r9`^;IEmPY!9(kN?dA#F#-SNyb2S!>98E+d@Qe~(; zer!Sc`P;^4%db9((_FplUG3V)QAJ>m#ytY z8g1KDr?Y)TW#%%|rb|n+Php_;9Jwhi-i~!=d}z^n@7itA&enE1nvOGn%aohdYXeRWc^0jEZ-0#u7p8_D zVzw~9aQ>QJjrAi3xlR6fyX=bI#O&y;EEoZyW>wp_Qk-L*v5WLUc6V#lqWZ$j8fC5C#sg;y<%f`oY01x49!PTKSC&_Bqv9bIoU`UF-d0q=80;!_}OfwM9ENE;Y8q z*X-ZhWB5OoW}Z}Kp{81^wE$T}vCP?oS|l}OM+vDYBaWDX>_Tz^ODIzsvz1a6HHis$ zD$1NCR?t(}O9)b7$ztk?6^o8jSYvb)Nf0*d2!)EA%8ro464O|eMExB`5wV2a79%8) zQM4UfE|C+{F_DlY=tUf>RxUAcPB^q>_oK`>ZO)4``*hPB zSESzOW#tZUb}yd)YT?GxIOqJt%2(ZDua=yHi}Vhp3+kSwY!N*6AZK+aCmyzGO#PG9 zfg_eg5)=)KGq*EFx@Nzwbj@sAF*TbrOXHok)zYVHjU3vNb62a{ww_?&7^M`72!l_) z;l!vEG(mmye|^MN5~PSJeBWv?<*PAy>wlLZyPDNrf_sFyVzWR3n<8Jthv!d`x*l ziY7=26>av(xtK^HlL;qdGKpM8eR48JNf`%O{Aa#aNELE>4T_LSocpFT*iwR`9I$@0 zI+Gho5<=z~j=UHZV=RU-&O(JWAH|)VP+TBDac5@~cX2^+S63AO{(BUkJsZW{+)&)z z9mVI&LGihBQQX4=#plgKaZgVa_wqvV`SVfS+Z)Awd{Eri7sdVjP~6`i#RCFRJTMT& z7c4;Wpdb_v4%Vb%1fMOlP$Qf%k#C>EA%86Ug#J^o^7^D`i6}bkuMJxb(ZEBNvXv4g z@x$*6J_#5tk&20BF!I9T{W%E3>3cpw-ZOmSbac@m$ASZ7p!dC&vbf;$A=~bn_--!P zJ!@iXjc-41gMo_y!n)bIak^#TzB6(|pKHsyNDEQ>j|Csw6S`)Ym^cP(tZ3#cNg`H4 z#J$!hHspECn&z2x=BB}eaV`e_HYKn9FRwAV)Hd>^*q@Eb2(d)?FlGPLtu`s!4_!#z zG&IUykTB_*__FZ>S=;AcaH2DOFL|TF#y;oIbFMZ+~69&OTFeVCsbeeuPA&f*idmuzBYwi$P0kJV6F%-(l*Mm72RvmF1EeE)A{?q8dI zFfNawFz5+GUaXOPrQVG(pO-%& zW?w~{TWVREYms$!Z_VgXPqUr*?e~grGz&HzzyH?t4hKag;<(N$3AIN~`RrZMm|pR# z&xUMI_F%Sdvai$FWPL;1G*N#Efn^2k5Cp*9iUAnNPBu#VP1X6LGNJdQr~Z zBdW`48Mm;q`*kq^t3I&m#e-p)0ir+RGxy6)7QC#vb@j@gVGZk> z!Yl%=zfovkxDZ=;HY&(tE}ICz01Q3Bhyucffnp562n~z|a#;Or5q1ohQib=iN*Lzn zilT%h(=vz2l_jz>ZhmMDo;c-7>z)QYY*|9<=>*)AT#v>6O7xAExA<)Xe{$2O|svTz=N)2@F|dC@c}*ek4xsd#@Hs zr$5S*?|m6?0(T7hXnKNZGOYLU8kRB#MyN0p7K7bIx`r;b_4mV{w|RB;j1Z68yf~>M zyV|ilgN#|Z=7%yEp3sEVD;RwkFxo&8z}PZ|zSZTi?;m8xzqxUUE|^h|wmx+t?;JR3 z%N?nAH}S&YJupAQIzI?of6Icfi1F*gYtjolM zbyo&Ly!UgH50-P#AC7?oO+HUxG~(;L2dkv8{A20;wP+Mp1fdXq;CGh$*<7%m?0`HY F{trV6#w-8; delta 600 zcmdmE-6lIBsb0-8M&PE66QgNNL&j;N)!~f4{NxV<0Pq z!AXFLEtw%QWn14~M3 zawa2da%x^lCKGFJW=>8fGbc#Q7sO=Y0!x6|tU%f1qI@=}ERe|#lLfLlSn?9{@;Nzz zL3;gwOfF8aRuGe$r64mopN9h^6#!)MLZm=UKGw9<+>(5Lu%T`srU1lHFk6r%v7{tl zXmX;g!sLB|UnWaSC`{fYvO}SxCn7c3>ZA44?PsNWyFT4Ict?bLdQsrbE4Mx$50vR^ anLLYAY4Us?g~^fZBuYp0|_`WcZcn>Y@ipf)Nj|wnV0?ACy zh602Cg^lx4PJsY;on05ci2IZ*s_nYXr=E!0aVVqY+!KC3@R|Pm-aInO;pPB-mLVk4 z78_=TK#j=LtYF4G)S7wPRS{t*1prF535zsi6+Vk<`zqM0?~wIhy50%5|9y?_tlE|v z(tPP^Q!Dw}>>bv`@Z9#(cb~em=3HZK$@syX`ulMuVsmpw>hK1AA4VU-4-3Y=IVy-f5>K$NdgFwE5xi~PT}s$J^THOZ*BiWu2{ue zfDjjeJ$GKS#g@Mmzo0o`awz-ZN2Q-lYt(gZ9q8zraXapP>iG35*{k{@4@0T9 zMwFjC8eKc*l(}LZamG8o!jtsTHtq^M*>ZBLGCf+OpS9QXs@xL*pn%jMAQ(Y#U;rNW zg|pX2mg$1SrsvFhhP69HLC*+!mJ{{3$RQ1y$mxf*oI`Y~rBDb!Rc3l}QhYQGfVXr& zN{?pHBCrv8D0E&^Kqcv;2VN0?%$Lp?qrtd13As z%kJzrQ0!*=3IOXMS_{!ekYy#_{#MV%X z$P*rF!zpzH&?*h5hDt#;pqOgX%SD;=8FHuu8y-4nB?lI0RX@g;9BRn%NX3F*Um>}f z13CcI`=))=P`YdO*uj*q;KZH@ox!=)AJqS;X`r|IkBJvrgEaT{Wbxx7W@o4lS~|Gp z6=mAI(--DHXx-nt`Pi%TKj|)Yzro-zkeguwz8AK7$J+-{nb5U0_gwEj<*oPsZXi#z zwR-4|YQ}(<&l>VZDI8pR~8vFe~%PsTU--aB{>)vi7;JftbzSl3* zm3XVJwC(oW8u@(Xc}@K;-;41rDL<^JIaU(aHpy@5Ki9|B^*4c489l{KS zi4$iMf>p{AtSrYo_oRYjafm`J;bsw{g~xcd(#$#dP^FnE#!o2(rgRP=;9|_qB`{N9 z5$7pchQ;%xs8)^*(+b$eL_6UEr4ji}|zJ%l2|aAj6#^Q97{I|=7JJWk6c zj5LqMXH-_sB&jHk(@JEFg?W&sVSYX|8llMqF@|O{EGU2$3uG9$awRM*gjOrG*&xe8 zj)QhPEGmLL4+Q~=B6K)laWO0@fu*IetPGZyYmM%UtWw$;JAU@ZgS6Fz$XHGIIk^={ zK)C_Q*%_ae+ZTGZ=HSO_Gp@*5&Dho>DoC+#@bkiiEs|R8Htk zn6XXdbgr0-oN&}oOcx%lq(zbQp`MxCcajMIU2IJ1ioZ4Dh{mbvntLImZAEX~{d{b1 zdZr@s*R=Qlt5N^A%~mmK?M=tED~Aq$nOauUBUCpxeR0q+Jwatj-3yJV_FYBjZ>D?h9i<|(9|Rr6y#XJmCHrh#BDYZpB)1W6HTwm`oc{QH{&)S!*Y1rmjelw7 u+V;k-$m84iqV=1fZI#n&fwNLd)jR;ng0jzO?>zO diff --git a/tests/templates/schemata/RGB21-UDA.issuer b/tests/templates/schemata/RGB21-UDA.issuer deleted file mode 100644 index 3555102c181c545a8e4ea81f83df6b0be1cc6032..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3419 zcmdT`dsGzH8Nc`L&aw*y6s#Prk5#A^PzgwkBH+4!u*w@Tppap9_ri|s&MY&tuwaae z1e6wq#$bY=2st)dsd&_?9Ew3gITAg2)TD+)Dn?3;!AF!>AC=DXi20*sdQN+CPVZm8 z^L_Vw{J#5r^9=w~QW-kWhSf$ohZZQan&NpZcmgBChgd1b$a0jGqb+!m!L%Dr8NhR|d4_td!cYcq3Moe#1*HO2!+AA$x%vK;?le!ZP zhW~>*j-(t10x*4kb7_cwGjjuXRu8h@#f4XTZw_+Ocb{#_xTU+<;y2C#{7Z(ANRHM9 z1wy63Q4F7rIjG9!D1$(=3_ltI0J)P93lweUudHah7U0@{()@S#zF80dahK|<*qa&H zbn|vYtLE*+`^|Bone7)JzxZg&XZ6(uGlw&t-rBXNHnh*u)m*w^XG(bu6w{sXJdZu? z)?e#9tucM+Z2Q2?#AD9J_I%R!hKJ8@7y3UK$jT^?N(G_`1Bs*<%7PbsR8}rO_f5)- zj;Qs1p2v?gt*x7e-3AX>BBHk3F75e?WE6=YfDqVR%*dAH9=g?gY+C-%zSlE_3eFVp zX|qDj{NBgq;9W~p(HpwuO|kQWnU6lUU-7SZzp(pGNB_cyF&~iU?hU4I>JL8!#on6m z{NT~3>LuOT#oLHWZn|O@jfbkf(WkSybGJMtLa7cq;&NN+2>_5mau^Ua&)YBn&-=pB zYZIRZyv?F!v(+?XwF$hM=G6=u3lg}M6L^gJJ9IWKx;ypO0=?8QxB1*86tO3s?lpk#Cp+yM%r#sj*1-`_bkag zrHVN*Npa?u);yfm>C@kEqa!lo>J|>x#P>u~Y;jR;<`?T8?LVGB&gxA7wn4NNqB1nX zOgREXKBGWnphV-GG*Gimb5L_!WQ-uta1iVOCD2*suC*i0d(KYUZl^Gyl54w1OQ5Mk zk(C-(qzDtM<}qqe4oaUJs6+z>s1)D(7Y(X3Gm(M;(iM`bfYfY>?*^QX`hQ$!Z(KZe zIPn^s+dHc(AhYtr+IJi7^i}>k?s}`Q^2y;eZhF|_wTcs_4t9NUp(^X*^<~dmkM-?r zd289HJ@)Y=hR1-^tP=43kj?wgog1Do4)>~cj!QI;||+E^%)sS@K(xz z)pBe%nCB?+Y^;F!xpEW5o4gf9)@-IYA15p3444squA(d=g<3#ZXvW4blo?rJ5y6|qC;{>!%&{-X zSOy2mgaS5*5KJ7#i{;s@jSH4%)A{&C8Bg1n5IoMu%u58Ob4rl%uv{d#9UPdiqb4Jy4@q7(<=jOXIyOu|5MSa?NYW{skXR61@6 zv>`VOQWVtdp}_!+Mu;)Y&W1TT&}4!%4L5Ftxw+76h87EC7|62FYK3`ukmDfFLqUKx z8_ds#1qIMR&j0=kle~HEoA~8Zc@0OX(-O=D5uU%1qh&UKNLTy|yCce#BRAZx+-uCqI}U^kG{= z^O{{N?vZn4o-Q)|)Yq8?k|ggroInBzBJ3Ov_XbS)2pPoktWSm=LuFj#Z3l zMd&oH6|quWoeZl|I!xn5L>G@$D9vf%$uUORr3h7BS2mcM!W()5b* zZ+qImoZ_;VOZxnB&;72X8M{gdC^Z36UuyzM)$Y+V{D(tN?UZ@h_1`e>++TNw3{QXN zdj|K-`6M~PqinU*Mj?>YMi^@HniF~PldJk~1`_T*nPQyz#>TDf^%ug=?d9@HcD~vw hrB_M?7+;g~$AAT3Ih5Md Self { + Self { + params: Self::from_file(FRACTIONABLE_ASSET_COLLECTION_TEMPLATE_PATH), + } + } + /// Load parameters from YAML file pub fn from_file>(path: P) -> CreateParams { let file = File::open(path).expect("Unable to open file"); @@ -1676,6 +1683,6 @@ impl TestWallet { builder = builder.add_owned_state(outpoint, amount); } - self.issue_with_params(builder.build()) + self.issue_with_params(dbg!(builder.build())) } } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index ac6c5ec..085477a 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -7,6 +7,7 @@ pub const SCHEMATA_DIR: &str = "tests/templates/schemata"; pub const ISSUANCE_DIR: &str = "tests/templates/issuance"; pub const NON_INFLATABLE_ASSET_TEMPLATE_PATH: &str = "tests/templates/issuance/NFA.yaml"; pub const FRACTIONAL_UNIQUE_ASSET_TEMPLATE_PATH: &str = "tests/templates/issuance/FUA.yaml"; +pub const FRACTIONABLE_ASSET_COLLECTION_TEMPLATE_PATH: &str = "tests/templates/issuance/FAC.yaml"; pub const INTEGRATION_DATA_DIR: &str = "integration"; pub const STRESS_DATA_DIR: &str = "stress"; From 1109bd2ce61f73cb869e8a5e412e461e0574a33f Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 26 Mar 2025 01:07:36 +0800 Subject: [PATCH 43/90] feat(tests): Implement RGB21 complex specification type conversion and basic issue Signed-off-by: will-bitlightlabs --- .gitmodules | 6 - Cargo.lock | 31 +++ Cargo.toml | 5 + tests/issuance.rs | 97 +++++-- tests/templates/issuance/FAC.yaml | 44 ++++ tests/utils/helpers.rs | 406 +++++++++++++++++++++++++++++- 6 files changed, 555 insertions(+), 34 deletions(-) diff --git a/.gitmodules b/.gitmodules index 9ab3432..e4a8c38 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,9 +19,6 @@ [submodule "bp-std"] path = bp-std url = https://github.com/BP-WG/bp-std -[submodule "rgb-schemata"] - path = rgb-schemata - url = https://github.com/RGB-WG/rgb-schemata [submodule "strict-types"] path = strict-types url = https://github.com/will-bitlightlabs/strict-types.git @@ -46,9 +43,6 @@ [submodule "amplify-derive"] path = amplify-derive url = https://github.com/rust-amplify/amplify-derive.git -[submodule "ascii-armor"] - path = ascii-armor - url = https://github.com/UBIDECO/ascii-armor.git [submodule "bp-esplora-client"] path = bp-esplora-client url = https://github.com/BP-WG/bp-esplora-client.git diff --git a/Cargo.lock b/Cargo.lock index 705da04..b8d5e2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,6 +110,19 @@ dependencies = [ "serde", ] +[[package]] +name = "ascii-armor" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0269eb842ec952b027df0fc33184b6a0dea5ea473160b36992274eb53758461e" +dependencies = [ + "amplify", + "baid64", + "base85", + "sha2", + "strict_encoding", +] + [[package]] name = "autocfg" version = "1.2.0" @@ -271,6 +284,7 @@ dependencies = [ "secp256k1", "serde", "strict_encoding", + "strict_types", ] [[package]] @@ -1689,6 +1703,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "rgb-interfaces" +version = "0.12.0-beta.5" +dependencies = [ + "amplify", + "bp-consensus", + "commit_verify", + "getrandom", + "serde", + "strict_encoding", + "strict_types", + "wasm-bindgen", +] + [[package]] name = "rgb-invoice" version = "0.12.0-beta.5" @@ -1772,9 +1800,11 @@ dependencies = [ "descriptors", "file-format", "hypersonic", + "indexmap 2.7.0", "once_cell", "psbt", "rand", + "rgb-interfaces", "rgb-psbt", "rgb-runtime", "rgb-std", @@ -2294,6 +2324,7 @@ name = "strict_types" version = "2.8.2" dependencies = [ "amplify", + "ascii-armor", "baid64", "indexmap 2.7.0", "serde", diff --git a/Cargo.toml b/Cargo.toml index 8c5858f..d745af7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ serial_test = "3.2.0" strum = { version = "0.26.2", features = ["derive"] } strum_macros = "0.26.2" time = { version = "0.3.34", features = ["formatting"] } +indexmap = "2.7.0" # RGB-related deps ## bp-core @@ -56,6 +57,8 @@ rgb-runtime = { path = "./rgb", features = [ rgb-psbt = { path = "./rgb/psbt", features = ["bp"] } ## rgb-std rgb-std = { path = "./rgb-std", features = ["fs"] } +## rgb-interfaces +rgb-interfaces = { path = "./rgb-interfaces", features = ["serde"] } ## rust-amplify amplify = { path = "./rust-amplify" } amplify_derive = { path = "./amplify-derive" } @@ -114,6 +117,8 @@ rgb-psbt = { path = "./rgb/psbt" } rgb-core = { path = "./rgb-core" } ## rgb-std rgb-std = { path = "./rgb-std" } +## rgb-interfaces +rgb-interfaces = { path = "./rgb-interfaces", features = ["serde"] } ## rust-aluvm aluvm = { path = "./rust-aluvm" } zk-aluvm = { path = "./zk-aluvm" } diff --git a/tests/issuance.rs b/tests/issuance.rs index 0ccb9f7..a70cafe 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -1,5 +1,6 @@ pub mod utils; +use ifaces::{EmbeddedMedia, MediaType, ProofOfReserves}; use rstest_reuse::{self, *}; use strict_types::{ value::{Blob, StrictNum}, @@ -7,7 +8,10 @@ use strict_types::{ }; use utils::{ chain::initialize, - helpers::{get_wallet, AssetParamsBuilder, FUAIssueParams, NIAIssueParams}, + helpers::{ + attachment_from_fpath, get_wallet, nft_spec, AssetParamsBuilder, FACIssueParams, + FUAIssueParams, NIAIssueParams, + }, DescriptorType, *, }; @@ -211,36 +215,77 @@ fn issue_fac(wallet_desc: DescriptorType) { initialize(); - // TODO: let mut wallet = get_wallet(&wallet_desc); - let mut default_fac = AssetParamsBuilder::default_fac().build(); - - for name_state in default_fac.global.iter_mut() { - let name = VariantName::from_str("token").unwrap(); - if name_state.name == name { - let token = &mut name_state.state.verified; - if let StrictVal::Struct(s) = token { - let reserved_name = FieldName::from_str("reserved").unwrap(); - let reserved = s.get_mut(&reserved_name).unwrap(); - *reserved = StrictVal::Bytes(Blob(vec![0; 26])); - } - } - } - for name_state in default_fac.owned.iter_mut() { - let name = VariantName::from_str("fractions").unwrap(); - if name_state.name == name { - let fractions = &mut name_state.state; - let fractions_data = &mut fractions.data; - *fractions_data = StrictVal::Tuple(vec![ - StrictVal::Number(StrictNum::from(0u32)), - StrictVal::Number(StrictNum::from(10000u64)), - ]); - } + // Create FAC asset parameters + let mut fac_params = FACIssueParams::new( + "DigitalCollection", + "A collection of digital assets", + 10_000, + ); + + let ticker = "TCKR"; + let name = "asset name"; + let details = "some details"; + let terms_text = "Ricardian contract"; + let terms_media_fpath = Some(MEDIA_FPATH); + let data = vec![1u8, 3u8, 9u8]; + let preview_ty = "image/jpeg"; + let token_data_preview = EmbeddedMedia { + ty: MediaType::with(preview_ty), + data: Confined::try_from(data.clone()).unwrap(), + }; + let proof = vec![2u8, 4u8, 6u8, 10u8]; + let token_data_reserves = ProofOfReserves { + utxo: Outpoint::from_str(FAKE_TXID).unwrap(), + proof: Confined::try_from(proof.clone()).unwrap(), + }; + let token_data_ticker = "TDTCKR"; + let token_data_name = "token data name"; + let token_data_details = "token data details"; + let token_data_attachment = attachment_from_fpath(MEDIA_FPATH); + let mut token_data_attachments = BTreeMap::new(); + for (idx, attachment_fpath) in ["README.md", "Cargo.toml"].iter().enumerate() { + token_data_attachments.insert(idx as u8, attachment_from_fpath(attachment_fpath)); } - let contract_id = wallet.issue_with_params(default_fac); + let nft_spec = nft_spec( + ticker, + name, + details, + token_data_preview, + token_data_attachment, + token_data_attachments, + token_data_reserves, + ); + + // Create allocation + let outpoint = wallet.get_utxo(None); + fac_params.with_allocation(outpoint, 10_000); + fac_params.with_nft_spec(nft_spec); + // Issue the contract + let contract_id = wallet.issue_fac_with_params(fac_params); + println!("FAC contract issued with ID: {}", contract_id); + + // Verify contract state + let state = wallet + .contract_state(contract_id) + .expect("Contract state does not exist"); + // Verify immutable state + assert_eq!(state.immutable.name, "DigitalCollection"); + + // Verify ownership state + // TODO: This needs to be refactored, + // the owned state of RGB21 is different from RGB20 and RGB25 + // assert_eq!(state.owned.allocations.len(), 1); + // assert!(state + // .owned + // .allocations + // .iter() + // .any(|(op, amount)| *op == outpoint && *amount == 10_000)); + + // Output contract state information dbg!( wallet.contracts_info(), wallet diff --git a/tests/templates/issuance/FAC.yaml b/tests/templates/issuance/FAC.yaml index 95b8d5b..8b42def 100644 --- a/tests/templates/issuance/FAC.yaml +++ b/tests/templates/issuance/FAC.yaml @@ -20,6 +20,50 @@ global: # TODO: `reserved` is a 26-sized U8 array, # Need to rewrite to bytes in code reserved: + unverified: + index: 0 + ticker: TCKR + name: asset name + details: some details + preview: + type: + type: image + subtype: jpeg + charset: null + data: + - 1 + - 3 + - 9 + media: + type: + type: image + subtype: jpeg + charset: null + digest: 02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a + attachments: + # TODO: the following fields cannot be recognized by strict-types directly, + # need to be converted in code + # 0: + # type: + # type: text + # subtype: plain + # charset: + # digest: 4bdf15cfc812b9c6d7a7b335daeb73dea8bef0e69c88b69e15db37c016c0737a + # 1: + # type: + # type: text + # subtype: plain + # charset: + # digest: dd0d0ed1a817858d4597336e4faa1061b81dc95b3ca77d4ecd352b6e940555d7 + reserves: + utxo: + txid: e5a3e577309df31bd606f48049049d2e1e02b048206ba232944fcc053a176ccb + vout: 0 + proof: + - 2 + - 4 + - 6 + - 10 owned: - name: fractions seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 03342ac..8c3e3ef 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1,7 +1,10 @@ +use bitcoin_hashes::{sha256, Hash}; +use indexmap::IndexMap; use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::fs::{File, OpenOptions}; use std::io::Write; +use std::ops::Deref; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::OnceLock; @@ -10,6 +13,10 @@ use std::time::Instant; use bp::{seals::WTxoSeal, Outpoint}; use commit_verify::{Digest, DigestExt, Sha256}; +use ifaces::{ + AssetName, Attachment, Details, EmbeddedMedia, MediaType, NftSpec, ProofOfReserves, Ticker, + TokenIndex, +}; use psbt::TxParams; use rand::RngCore; use rgb::invoice::{RgbBeneficiary, RgbInvoice}; @@ -22,8 +29,8 @@ use rgb::{ use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbWallet}; use rgbp::{CoinselectStrategy, PayError}; use rgpsbt::ScriptResolver; -use strict_types::value::EnumTag; -use strict_types::{TypeName, VariantName}; +use strict_types::value::{Blob, EnumTag, StrictNum}; +use strict_types::{FieldName, StrictEncode, TypeName, VariantName}; use crate::utils::chain::fund_wallet; @@ -1686,3 +1693,398 @@ impl TestWallet { self.issue_with_params(dbg!(builder.build())) } } + +/// Parameters for FAC (Fractionable Asset Collection) issuance +#[derive(Clone)] +pub struct FACIssueParams { + /// Collection name + pub name: String, + /// Collection details + pub details: String, + /// Total number of fractions + pub total_fractions: u64, + /// Token index + pub index: u32, + /// Initial token allocation (outpoint, amount) + pub initial_allocation: Option<(Outpoint, u64)>, + /// NFT specification + pub nft_spec: Option, +} + +impl Default for FACIssueParams { + fn default() -> Self { + Self { + name: "FAC".to_string(), + details: "Demo FAC details".to_string(), + total_fractions: 10_000, + index: UDA_FIXED_INDEX, + initial_allocation: None, + nft_spec: None, + } + } +} + +impl FACIssueParams { + /// Create new FAC issuance parameters + pub fn new(name: impl Into, details: impl Into, total_fractions: u64) -> Self { + Self { + name: name.into(), + details: details.into(), + index: UDA_FIXED_INDEX, + total_fractions, + initial_allocation: None, + nft_spec: None, + } + } + + /// Set token allocation + pub fn with_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { + self.initial_allocation = Some((outpoint, amount)); + self + } + + /// Set NFT specification + pub fn with_nft_spec(&mut self, nft_spec: NftSpec) -> &mut Self { + self.nft_spec = Some(nft_spec); + self + } +} + +fn nft_spec_minimal() -> NftSpec { + NftSpec { + index: TokenIndex::from(UDA_FIXED_INDEX), + ..Default::default() + } +} + +pub fn nft_spec( + ticker: &str, + name: &str, + details: &str, + preview: EmbeddedMedia, + media: Attachment, + attachments: BTreeMap, + reserves: ProofOfReserves, +) -> NftSpec { + let mut nft_spec = nft_spec_minimal(); + nft_spec.preview = Some(preview); + nft_spec.media = Some(media); + nft_spec.attachments = Confined::try_from(attachments.clone()).unwrap(); + nft_spec.reserves = Some(reserves); + nft_spec.ticker = Some(Ticker::try_from(ticker.to_string()).unwrap()); + nft_spec.name = Some(AssetName::try_from(name.to_string()).unwrap()); + nft_spec.details = Some(Details::from_str(details).unwrap()); + nft_spec +} + +// Function to create a file attachment from a file path +pub fn attachment_from_fpath(fpath: &str) -> Attachment { + let file_bytes = std::fs::read(fpath).unwrap(); + let file_hash: sha256::Hash = Hash::hash(&file_bytes[..]); + let digest = file_hash.to_byte_array().into(); + let mime = FileFormat::from_file(fpath) + .unwrap() + .media_type() + .to_string(); + let media_ty: &'static str = Box::leak(mime.clone().into_boxed_str()); + let media_type = MediaType::with(media_ty); + Attachment { + ty: media_type, + digest, + } +} + +impl TestWallet { + // TODO: Need to optimize the following code + /// Issue a FAC contract with custom parameters + pub fn issue_fac_with_params(&mut self, params: FACIssueParams) -> ContractId { + let mut create_params = AssetParamsBuilder::default_fac() + .name(params.name.as_str()) + .update_name_state(params.name.as_str()) + .update_details_state(params.details.as_str()) + .build(); + + for name_state in create_params.global.iter_mut() { + let name = VariantName::from_str("token").unwrap(); + if name_state.name == name { + let token = &mut name_state.state.verified; + if let StrictVal::Struct(s) = token { + let reserved_name = FieldName::from_str("reserved").unwrap(); + let reserved = s.get_mut(&reserved_name).unwrap(); + *reserved = StrictVal::Bytes(Blob(vec![0; 26])); + + let index_name = FieldName::from_str("index").unwrap(); + let index = s.get_mut(&index_name).unwrap(); + *index = StrictVal::Number(StrictNum::from(params.index as u32)); + + let amount_name = FieldName::from_str("amount").unwrap(); + let amount = s.get_mut(&amount_name).unwrap(); + *amount = StrictVal::Number(StrictNum::from(params.total_fractions as u64)); + } + + if let Some(ref nft_spec) = params.nft_spec { + let nft_spec_strict_val = name_state.state.unverified.as_mut().unwrap(); + + match nft_spec_strict_val { + StrictVal::Struct(s) => { + // pub index: TokenIndex, + // pub ticker: Option, + // pub name: Option, + // pub details: Option
, + // pub preview: Option, + // pub media: Option, + // pub attachments: Confined, 0, 20>, + // pub reserves: Option, + let index_name = FieldName::from_str("index").unwrap(); + let index = s.get_mut(&index_name).unwrap(); + *index = StrictVal::Number(StrictNum::from(params.index as u32)); + + if let Some(ref ticker) = nft_spec.ticker { + let ticker_name = FieldName::from_str("ticker").unwrap(); + let ticker = s.get_mut(&ticker_name).unwrap(); + *ticker = StrictVal::String(ticker.to_string()); + } + + if let Some(ref name) = nft_spec.name { + let name_name = FieldName::from_str("name").unwrap(); + let name = s.get_mut(&name_name).unwrap(); + *name = StrictVal::String(name.to_string()); + } + + if let Some(ref details) = nft_spec.details { + let details_name = FieldName::from_str("details").unwrap(); + let details = s.get_mut(&details_name).unwrap(); + *details = StrictVal::String(details.to_string()); + } + + if let Some(ref preview_params) = nft_spec.preview { + let preview_name = FieldName::from_str("preview").unwrap(); + let preview = s.get_mut(&preview_name).unwrap(); + match preview { + StrictVal::Struct(s) => { + let preview_type_name = + FieldName::from_str("type").unwrap(); + let preview_type = s.get_mut(&preview_type_name).unwrap(); + match preview_type { + StrictVal::Struct(ty) => { + let ty_name = FieldName::from_str("type").unwrap(); + let ty_type = ty.get_mut(&ty_name).unwrap(); + *ty_type = StrictVal::String( + preview_params.ty.ty.to_string(), + ); + + let subtype_name = + FieldName::from_str("subtype").unwrap(); + let subtype = ty.get_mut(&subtype_name).unwrap(); + + if let Some(ref subtype_params) = + preview_params.ty.subtype + { + *subtype = StrictVal::String( + subtype_params.to_string(), + ); + } else { + *subtype = StrictVal::Unit; + } + + let charset_name = + FieldName::from_str("charset").unwrap(); + let charset = ty.get_mut(&charset_name).unwrap(); + if let Some(ref charset_params) = + preview_params.ty.charset + { + *charset = StrictVal::String( + charset_params.to_string(), + ); + } else { + *charset = StrictVal::Unit; + } + } + _ => { + panic!("Invalid preview type"); + } + } + + let data_name = FieldName::from_str("data").unwrap(); + let data = s.get_mut(&data_name).unwrap(); + *data = + StrictVal::Bytes(Blob(preview_params.data.to_vec())); + } + _ => { + panic!("Invalid preview"); + } + } + } + + if let Some(ref media_params) = nft_spec.media { + let media_name = FieldName::from_str("media").unwrap(); + let media = s.get_mut(&media_name).unwrap(); + match media { + StrictVal::Struct(s) => { + let media_type_name = FieldName::from_str("type").unwrap(); + let media_type = s.get_mut(&media_type_name).unwrap(); + match media_type { + StrictVal::Struct(ty) => { + let ty_name = FieldName::from_str("type").unwrap(); + let ty_type = ty.get_mut(&ty_name).unwrap(); + *ty_type = StrictVal::String( + media_params.ty.ty.to_string(), + ); + + let subtype_name = + FieldName::from_str("subtype").unwrap(); + let subtype = ty.get_mut(&subtype_name).unwrap(); + if let Some(ref subtype_params) = + media_params.ty.subtype + { + *subtype = StrictVal::String( + subtype_params.to_string(), + ); + } else { + *subtype = StrictVal::Unit; + } + + let charset_name = + FieldName::from_str("charset").unwrap(); + let charset = ty.get_mut(&charset_name).unwrap(); + if let Some(ref charset_params) = + media_params.ty.charset + { + *charset = StrictVal::String( + charset_params.to_string(), + ); + } else { + *charset = StrictVal::Unit; + } + } + _ => { + panic!("Invalid media type"); + } + } + + let data_name = FieldName::from_str("digest").unwrap(); + let data = s.get_mut(&data_name).unwrap(); + *data = + StrictVal::Bytes(Blob(media_params.digest.to_vec())); + } + _ => { + panic!("Invalid media"); + } + } + } + + let mut map_inner = vec![]; + let attachments = nft_spec.attachments.deref(); + for (id, attachment) in attachments { + let attachments_name = FieldName::from_str("attachments").unwrap(); + let attachments = s.get_mut(&attachments_name).unwrap(); + + // let mut attachment = StrictVal::Struct(IndexMap::new()); + let mut attachmet_inner: IndexMap = + IndexMap::new(); + let mut ty_inner: IndexMap = IndexMap::new(); + ty_inner.insert( + FieldName::from("type"), + StrictVal::String(attachment.ty.ty.to_string()), + ); + ty_inner.insert( + FieldName::from("subtype"), + if let Some(ref subtype_params) = attachment.ty.subtype { + StrictVal::String(subtype_params.to_string()) + } else { + StrictVal::Unit + }, + ); + ty_inner.insert( + FieldName::from("charset"), + if let Some(ref charset_params) = attachment.ty.charset { + StrictVal::String(charset_params.to_string()) + } else { + StrictVal::Unit + }, + ); + + attachmet_inner + .insert(FieldName::from("type"), StrictVal::Struct(ty_inner)); + attachmet_inner.insert( + FieldName::from("digest"), + StrictVal::Bytes(Blob(attachment.digest.to_vec())), + ); + + map_inner.push(( + StrictVal::Number(StrictNum::from(*id as u8)), + StrictVal::Struct(attachmet_inner), + )); + } + + let attachments_name = FieldName::from_str("attachments").unwrap(); + let attachments_val = s.get_mut(&attachments_name).unwrap(); + *attachments_val = StrictVal::Map(map_inner); + + if let Some(ref reserves_params) = nft_spec.reserves { + let reserves_name = FieldName::from_str("reserves").unwrap(); + let reserves = s.get_mut(&reserves_name).unwrap(); + match reserves { + StrictVal::Struct(s) => { + let utxo_name = FieldName::from_str("utxo").unwrap(); + let utxo = s.get_mut(&utxo_name).unwrap(); + match utxo { + StrictVal::Struct(s) => { + let txid_name = + FieldName::from_str("txid").unwrap(); + let txid = s.get_mut(&txid_name).unwrap(); + *txid = StrictVal::Bytes(Blob( + reserves_params.utxo.txid.to_inner().to_vec(), + )); + + let vout_name = + FieldName::from_str("vout").unwrap(); + let vout = s.get_mut(&vout_name).unwrap(); + *vout = StrictVal::Number(StrictNum::from( + reserves_params.utxo.vout.into_u32(), + )); + } + _ => { + panic!("Invalid utxo"); + } + } + + let proof_name = FieldName::from_str("proof").unwrap(); + let proof = s.get_mut(&proof_name).unwrap(); + *proof = + StrictVal::Bytes(Blob(reserves_params.proof.to_vec())); + } + _ => { + panic!("Invalid reserves"); + } + } + } + } + _ => { + panic!("Invalid NFT spec"); + } + } + + // let nft_s = serde_yaml::to_string(&nft_spec).unwrap(); + // println!("{nft_s}"); + // *name_state.state.verified = StrictVal::Bytes(Blob(writer)); + } + } + } + + for name_state in create_params.owned.iter_mut() { + let name = VariantName::from_str("fractions").unwrap(); + if name_state.name == name { + let fractions = &mut name_state.state; + let fractions_data = &mut fractions.data; + *fractions_data = StrictVal::Tuple(vec![ + StrictVal::Number(StrictNum::from(params.index as u32)), + StrictVal::Number(StrictNum::from(params.total_fractions as u64)), + ]); + } + } + + let contract_id = self.issue_with_params(create_params); + contract_id + } +} From 39fa3d1388e7a62adbc83ac9cccc39d2d61a209d Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 26 Mar 2025 23:00:47 +0800 Subject: [PATCH 44/90] feat(tests): Add RGB21 contract state parsing functionality Signed-off-by: will-bitlightlabs --- strict-types | 2 +- tests/issuance.rs | 28 +-- tests/utils/helpers.rs | 499 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 488 insertions(+), 41 deletions(-) diff --git a/strict-types b/strict-types index 6618c6d..9246d37 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit 6618c6dfcc5d3d7e28d6f94943e06a697f953190 +Subproject commit 9246d37ff2b4d6df851a963e9287e94ea4e13d01 diff --git a/tests/issuance.rs b/tests/issuance.rs index a70cafe..21c640c 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -2,15 +2,10 @@ pub mod utils; use ifaces::{EmbeddedMedia, MediaType, ProofOfReserves}; use rstest_reuse::{self, *}; -use strict_types::{ - value::{Blob, StrictNum}, - VariantName, -}; use utils::{ chain::initialize, helpers::{ - attachment_from_fpath, get_wallet, nft_spec, AssetParamsBuilder, FACIssueParams, - FUAIssueParams, NIAIssueParams, + attachment_from_fpath, get_wallet, nft_spec, FACIssueParams, FUAIssueParams, NIAIssueParams, }, DescriptorType, *, }; @@ -227,8 +222,6 @@ fn issue_fac(wallet_desc: DescriptorType) { let ticker = "TCKR"; let name = "asset name"; let details = "some details"; - let terms_text = "Ricardian contract"; - let terms_media_fpath = Some(MEDIA_FPATH); let data = vec![1u8, 3u8, 9u8]; let preview_ty = "image/jpeg"; let token_data_preview = EmbeddedMedia { @@ -240,9 +233,6 @@ fn issue_fac(wallet_desc: DescriptorType) { utxo: Outpoint::from_str(FAKE_TXID).unwrap(), proof: Confined::try_from(proof.clone()).unwrap(), }; - let token_data_ticker = "TDTCKR"; - let token_data_name = "token data name"; - let token_data_details = "token data details"; let token_data_attachment = attachment_from_fpath(MEDIA_FPATH); let mut token_data_attachments = BTreeMap::new(); for (idx, attachment_fpath) in ["README.md", "Cargo.toml"].iter().enumerate() { @@ -286,13 +276,15 @@ fn issue_fac(wallet_desc: DescriptorType) { // .any(|(op, amount)| *op == outpoint && *amount == 10_000)); // Output contract state information - dbg!( - wallet.contracts_info(), - wallet - .runtime() - .state_all(Some(contract_id)) - .collect::>() - ); + // dbg!( + // wallet.contracts_info(), + // wallet + // .runtime() + // .state_all(Some(contract_id)) + // .collect::>() + // ); + + dbg!(wallet.contract_state_rgb21(contract_id)); } // TODO: RGB official is improving the feature of uda asset, will add test after it's ready diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 8c3e3ef..6e699c7 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -30,7 +30,7 @@ use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbWallet}; use rgbp::{CoinselectStrategy, PayError}; use rgpsbt::ScriptResolver; use strict_types::value::{Blob, EnumTag, StrictNum}; -use strict_types::{FieldName, StrictEncode, TypeName, VariantName}; +use strict_types::{FieldName, TypeName, VariantName}; use crate::utils::chain::fund_wallet; @@ -1827,34 +1827,26 @@ impl TestWallet { match nft_spec_strict_val { StrictVal::Struct(s) => { - // pub index: TokenIndex, - // pub ticker: Option, - // pub name: Option, - // pub details: Option
, - // pub preview: Option, - // pub media: Option, - // pub attachments: Confined, 0, 20>, - // pub reserves: Option, let index_name = FieldName::from_str("index").unwrap(); let index = s.get_mut(&index_name).unwrap(); *index = StrictVal::Number(StrictNum::from(params.index as u32)); - if let Some(ref ticker) = nft_spec.ticker { + if let Some(ref ticker_params) = nft_spec.ticker { let ticker_name = FieldName::from_str("ticker").unwrap(); let ticker = s.get_mut(&ticker_name).unwrap(); - *ticker = StrictVal::String(ticker.to_string()); + *ticker = StrictVal::String(ticker_params.to_string()); } - if let Some(ref name) = nft_spec.name { + if let Some(ref name_params) = nft_spec.name { let name_name = FieldName::from_str("name").unwrap(); let name = s.get_mut(&name_name).unwrap(); - *name = StrictVal::String(name.to_string()); + *name = StrictVal::String(name_params.to_string()); } - if let Some(ref details) = nft_spec.details { + if let Some(ref details_params) = nft_spec.details { let details_name = FieldName::from_str("details").unwrap(); let details = s.get_mut(&details_name).unwrap(); - *details = StrictVal::String(details.to_string()); + *details = StrictVal::String(details_params.to_string()); } if let Some(ref preview_params) = nft_spec.preview { @@ -1976,9 +1968,6 @@ impl TestWallet { let mut map_inner = vec![]; let attachments = nft_spec.attachments.deref(); for (id, attachment) in attachments { - let attachments_name = FieldName::from_str("attachments").unwrap(); - let attachments = s.get_mut(&attachments_name).unwrap(); - // let mut attachment = StrictVal::Struct(IndexMap::new()); let mut attachmet_inner: IndexMap = IndexMap::new(); @@ -2064,10 +2053,6 @@ impl TestWallet { panic!("Invalid NFT spec"); } } - - // let nft_s = serde_yaml::to_string(&nft_spec).unwrap(); - // println!("{nft_s}"); - // *name_state.state.verified = StrictVal::Bytes(Blob(writer)); } } } @@ -2088,3 +2073,473 @@ impl TestWallet { contract_id } } + +/// Immutable state part of RGB21 contract +#[derive(Debug, Clone)] +pub struct RGB21ContractImmutableState { + pub name: String, + pub total_fractions: u64, + pub token: Option, +} + +/// NFT metadata in RGB21 contract +#[derive(Debug, Clone)] +pub struct NFTMetadata { + pub index: u32, + pub amount: u64, + pub ticker: Option, + pub name: Option, + pub details: Option, + pub preview: Option, + pub media: Option, + pub attachments: BTreeMap, + pub reserves: Option, +} + +/// Media data with full content +#[derive(Debug, Clone)] +pub struct MediaData { + pub media_type: MediaTypeData, + pub data: Vec, +} + +/// Media type information +#[derive(Debug, Clone)] +pub struct MediaTypeData { + pub r#type: String, + pub subtype: Option, + pub charset: Option, +} + +/// Media digest (reference only) +#[derive(Debug, Clone)] +pub struct MediaDigest { + pub media_type: MediaTypeData, + pub digest: Vec, +} + +/// Reserve proof data +#[derive(Debug, Clone)] +pub struct ReserveData { + pub utxo: Outpoint, + pub proof: Vec, +} + +/// Owned state part of RGB21 contract +#[derive(Debug, Clone)] +pub struct RGB21ContractOwnedState { + pub fractions: Vec<(Outpoint, u32, u64)>, // (outpoint, index, amount) +} + +/// Complete RGB21 contract state +#[derive(Debug, Clone)] +pub struct RGB21ContractState { + pub immutable: RGB21ContractImmutableState, + pub owned: RGB21ContractOwnedState, +} + +/// Extract the first element from a tuple +fn extract_from_tuple(v: &StrictVal) -> Option { + if let StrictVal::Tuple(s) = v { + if !s.is_empty() { + Some(s[0].clone()) + } else { + None + } + } else { + None + } +} + +/// Extract the first element from a two-layer tuple +fn extract_from_2_layer_tuple(v: &StrictVal) -> Option { + if let StrictVal::Tuple(t) = v { + if let Some(inner) = t.get(0) { + extract_from_tuple(inner) + } else { + None + } + } else { + None + } +} + +/// Extract value from Union (for Option type) +fn extract_from_union(v: &StrictVal) -> Option { + if let StrictVal::Union(tag, t) = v { + if let EnumTag::Name(name) = tag { + if ***name == "some" { + Some(t.as_ref().clone()) + } else { + None + } + } else { + None + } + } else { + None + } +} + +/// Extract value from Union and single-layer Tuple +fn extract_from_union_and_tuple(v: &StrictVal) -> Option { + extract_from_union(v).and_then(|s| extract_from_tuple(&s)) +} + +/// Extract value from Union and two-layer Tuple +fn extract_from_union_and_2_layer_tuple(v: &StrictVal) -> Option { + extract_from_union(v).and_then(|s| extract_from_2_layer_tuple(&s)) +} + +impl TestWallet { + /// Get RGB21 contract state + pub fn contract_state_rgb21(&mut self, contract_id: ContractId) -> Option { + self.contract_state_internal(contract_id) + .map(|(immutable, owned, _)| { + // Parse immutable state + let name = immutable + .get(&VariantName::from_str("name").unwrap()) + .and_then(|m| m.values().next()) + .map(|v| v.verified.unwrap_string()) + .unwrap_or_default(); + + let total_fractions = immutable + .get(&VariantName::from_str("fractions").unwrap()) + .and_then(|m| m.values().next()) + .map(|v| v.verified.unwrap_num().unwrap_uint::()) + .unwrap_or_default(); + + // Parse token/NFT metadata + let token = immutable + .get(&VariantName::from_str("token").unwrap()) + .and_then(|m| m.values().next()) + .map(|v| { + let mut index = 0u32; + let mut amount = 0u64; + + // Parse verified token data + if let StrictVal::Struct(ref s) = v.verified { + if let Some(StrictVal::Number(n)) = + s.get(&FieldName::from_str("index").unwrap()) + { + index = n.unwrap_uint::(); + } + if let Some(StrictVal::Number(n)) = + s.get(&FieldName::from_str("amount").unwrap()) + { + amount = n.unwrap_uint::(); + } + } + + // Parse unverified token metadata + let mut ticker = None; + let mut name = None; + let mut details = None; + let mut preview = None; + let mut media = None; + let mut attachments = BTreeMap::new(); + let mut reserves = None; + + if let Some(ref unverified) = v.unverified { + if let StrictVal::Struct(ref s) = unverified { + if let Some(StrictVal::Union(_, t)) = + s.get(&FieldName::from_str("ticker").unwrap()) + { + ticker = + extract_from_2_layer_tuple(t).map(|s| s.unwrap_string()); + } + + if let Some(StrictVal::Union(_, t)) = + s.get(&FieldName::from_str("name").unwrap()) + { + name = extract_from_2_layer_tuple(t).map(|s| s.unwrap_string()); + } + + if let Some(StrictVal::Union(_, t)) = + s.get(&FieldName::from_str("details").unwrap()) + { + details = + extract_from_2_layer_tuple(t).map(|s| s.unwrap_string()); + } + + // Parse preview + let preview_struct = s + .get(&FieldName::from_str("preview").unwrap()) + .and_then(|v| extract_from_union_and_tuple(v)); + + if let Some(StrictVal::Struct(ref p)) = preview_struct { + let media_type = if let Some(StrictVal::Struct(ref t)) = + p.get(&FieldName::from_str("type").unwrap()) + { + let type_value = t + .get(&FieldName::from_str("type").unwrap()) + .and_then(|v| { + extract_from_tuple(v).map(|s| s.unwrap_string()) + }) + .unwrap_or_default(); + + let subtype = t + .get(&FieldName::from_str("subtype").unwrap()) + .and_then(|v| { + extract_from_union_and_2_layer_tuple(v) + .map(|s| s.unwrap_string()) + }); + + let charset = t + .get(&FieldName::from_str("charset").unwrap()) + .and_then(|v| { + extract_from_union_and_2_layer_tuple(v) + .map(|s| s.unwrap_string()) + }); + + MediaTypeData { + r#type: type_value, + subtype, + charset, + } + } else { + MediaTypeData { + r#type: "".to_string(), + subtype: None, + charset: None, + } + }; + + let data = if let Some(StrictVal::Bytes(Blob(d))) = + p.get(&FieldName::from_str("data").unwrap()) + { + d.clone() + } else { + vec![] + }; + + preview = Some(MediaData { media_type, data }); + } + + // Parse media + let media_struct = s + .get(&FieldName::from_str("media").unwrap()) + .and_then(|v| extract_from_union_and_tuple(v)); + + if let Some(StrictVal::Struct(ref m)) = media_struct { + let media_type = if let Some(StrictVal::Struct(ref t)) = + m.get(&FieldName::from_str("type").unwrap()) + { + let type_value = t + .get(&FieldName::from_str("type").unwrap()) + .and_then(|v| { + extract_from_tuple(v).map(|s| s.unwrap_string()) + }) + .unwrap_or_default(); + + let subtype = t + .get(&FieldName::from_str("subtype").unwrap()) + .and_then(|v| { + extract_from_union_and_2_layer_tuple(v) + .map(|s| s.unwrap_string()) + }); + + let charset = t + .get(&FieldName::from_str("charset").unwrap()) + .and_then(|v| { + extract_from_union_and_2_layer_tuple(v) + .map(|s| s.unwrap_string()) + }); + + MediaTypeData { + r#type: type_value, + subtype, + charset, + } + } else { + MediaTypeData { + r#type: "".to_string(), + subtype: None, + charset: None, + } + }; + + let digest = if let Some(StrictVal::Bytes(Blob(d))) = + m.get(&FieldName::from_str("digest").unwrap()) + { + d.clone() + } else { + vec![] + }; + + media = Some(MediaDigest { media_type, digest }); + } + + // Parse attachments + if let Some(StrictVal::Map(ref atts)) = + s.get(&FieldName::from_str("attachments").unwrap()) + { + for (key, value) in atts { + if let ( + StrictVal::Number(idx), + StrictVal::Struct(ref att), + ) = (key, value) + { + let media_type = if let Some(StrictVal::Struct(ref t)) = + att.get(&FieldName::from_str("type").unwrap()) + { + let type_value = t + .get(&FieldName::from_str("type").unwrap()) + .and_then(|v| { + extract_from_tuple(v) + .map(|s| s.unwrap_string()) + }) + .unwrap_or_default(); + + let subtype = t + .get(&FieldName::from_str("subtype").unwrap()) + .and_then(|v| { + extract_from_union_and_2_layer_tuple(v) + .map(|s| s.unwrap_string()) + }); + + let charset = t + .get(&FieldName::from_str("charset").unwrap()) + .and_then(|v| { + extract_from_union_and_2_layer_tuple(v) + .map(|s| s.unwrap_string()) + }); + + MediaTypeData { + r#type: type_value, + subtype, + charset, + } + } else { + MediaTypeData { + r#type: "".to_string(), + subtype: None, + charset: None, + } + }; + + let digest = if let Some(StrictVal::Bytes(Blob(d))) = + att.get(&FieldName::from_str("digest").unwrap()) + { + d.clone() + } else { + vec![] + }; + + let attachment = MediaDigest { media_type, digest }; + + attachments.insert(idx.unwrap_uint::(), attachment); + } + } + } + + // Parse reserves + let reserves_struct = s + .get(&FieldName::from_str("reserves").unwrap()) + .and_then(|v| extract_from_union_and_tuple(v)); + + if let Some(StrictVal::Struct(ref r)) = reserves_struct { + if let Some(StrictVal::Struct(ref u)) = + r.get(&FieldName::from_str("utxo").unwrap()) + { + let txid_bytes = u + .get(&FieldName::from_str("txid").unwrap()) + .and_then(|v| extract_from_tuple(v)) + .and_then(|v| { + if let StrictVal::Bytes(Blob(tx)) = v { + Some(tx) + } else { + None + } + }) + .unwrap_or_default(); + + let vout = u + .get(&FieldName::from_str("vout").unwrap()) + .and_then(|v| extract_from_tuple(v)) + .and_then(|v| { + if let StrictVal::Number(n) = v { + Some(n.unwrap_uint::()) + } else { + None + } + }) + .unwrap_or_default(); + + let txid = if txid_bytes.len() == 32 { + let mut arr = [0u8; 32]; + arr.copy_from_slice(&txid_bytes); + Txid::from_byte_array(arr) + } else { + // default txid + Txid::coinbase() + }; + + let outpoint = Outpoint::new(txid, vout); + + let proof = if let Some(StrictVal::Bytes(Blob(p))) = + r.get(&FieldName::from_str("proof").unwrap()) + { + p.clone() + } else { + vec![] + }; + + reserves = Some(ReserveData { + utxo: outpoint, + proof, + }); + } + } + } + } + + NFTMetadata { + index, + amount, + ticker, + name, + details, + preview, + media, + attachments, + reserves, + } + }); + + // Parse ownership state (fractions) + let mut fractions = vec![]; + if let Some(owned_map) = owned.get(&VariantName::from_str("fractions").unwrap()) { + for assignment in owned_map.values() { + if let StrictVal::Tuple(ref tuple) = assignment.data { + if tuple.len() >= 2 { + let idx_val = extract_from_tuple(&tuple[0]); + let amt_val = extract_from_tuple(&tuple[1]); + + if let ( + Some(StrictVal::Number(idx)), + Some(StrictVal::Number(amount)), + ) = (idx_val, amt_val) + { + fractions.push(( + assignment.seal, + idx.unwrap_uint::(), + amount.unwrap_uint::(), + )); + } + } + } + } + } + + RGB21ContractState { + immutable: RGB21ContractImmutableState { + name, + total_fractions, + token, + }, + owned: RGB21ContractOwnedState { fractions }, + } + }) + } +} From 7064433b0a03ba2cedf6480059ed22d3ed3ecc30 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 31 Mar 2025 13:35:42 +0800 Subject: [PATCH 45/90] feat: enhance RGB21-FAC contract tests and update dependencies Signed-off-by: will-bitlightlabs --- .gitmodules | 8 +- Cargo.lock | 2 +- Cargo.toml | 2 +- client_side_validation | 2 +- rgb-interfaces | 1 + strict-types | 2 +- tests/issuance.rs | 156 +++++------------ tests/templates/issuance/FAC.yaml | 13 +- tests/templates/schemata/RGB21-FAC.issuer | Bin 7612 -> 8380 bytes tests/transfer_rgb21.rs | 198 ++++++++++++++++++++++ tests/utils/helpers.rs | 70 +++----- 11 files changed, 281 insertions(+), 173 deletions(-) create mode 160000 rgb-interfaces create mode 100644 tests/transfer_rgb21.rs diff --git a/.gitmodules b/.gitmodules index e4a8c38..ff87905 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "rust-aluvm"] path = rust-aluvm url = https://github.com/aluvm/rust-aluvm -[submodule "rgb-interfaces"] - path = rgb-interfaces - url = https://github.com/RGB-WG/rgb-interfaces [submodule "client_side_validation"] path = client_side_validation url = https://github.com/LNP-BP/client_side_validation/ @@ -21,7 +18,7 @@ url = https://github.com/BP-WG/bp-std [submodule "strict-types"] path = strict-types - url = https://github.com/will-bitlightlabs/strict-types.git + url = https://github.com/strict-types/strict-types [submodule "strict-encoding"] path = strict-encoding url = https://github.com/strict-types/strict-encoding @@ -64,3 +61,6 @@ [submodule "sonic"] path = sonic url = https://github.com/AluVM/sonic +[submodule "rgb-interfaces"] + path = rgb-interfaces + url = https://github.com/RGB-WG/rgb-interfaces.git diff --git a/Cargo.lock b/Cargo.lock index b8d5e2d..f01eb88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1197,7 +1197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d745af7..aa555b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -118,7 +118,7 @@ rgb-core = { path = "./rgb-core" } ## rgb-std rgb-std = { path = "./rgb-std" } ## rgb-interfaces -rgb-interfaces = { path = "./rgb-interfaces", features = ["serde"] } +rgb-interfaces = { path = "./rgb-interfaces" } ## rust-aluvm aluvm = { path = "./rust-aluvm" } zk-aluvm = { path = "./zk-aluvm" } diff --git a/client_side_validation b/client_side_validation index 76b3cde..e22c5e0 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit 76b3cdec2f82b5c9cbed32a9b80124b8602f397e +Subproject commit e22c5e0491fbbad29b537e5c7d0e807793f49006 diff --git a/rgb-interfaces b/rgb-interfaces new file mode 160000 index 0000000..4156451 --- /dev/null +++ b/rgb-interfaces @@ -0,0 +1 @@ +Subproject commit 4156451411a66e3db35bf03e02bb95de5a93c81c diff --git a/strict-types b/strict-types index 9246d37..c1def3a 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit 9246d37ff2b4d6df851a963e9287e94ea4e13d01 +Subproject commit c1def3a5efb9ef92de883427eac61afbc6cda8f3 diff --git a/tests/issuance.rs b/tests/issuance.rs index 21c640c..969ce74 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -243,10 +243,10 @@ fn issue_fac(wallet_desc: DescriptorType) { ticker, name, details, - token_data_preview, - token_data_attachment, - token_data_attachments, - token_data_reserves, + token_data_preview.clone(), + token_data_attachment.clone(), + token_data_attachments.clone(), + token_data_reserves.clone(), ); // Create allocation @@ -257,117 +257,43 @@ fn issue_fac(wallet_desc: DescriptorType) { let contract_id = wallet.issue_fac_with_params(fac_params); println!("FAC contract issued with ID: {}", contract_id); - // Verify contract state - let state = wallet - .contract_state(contract_id) - .expect("Contract state does not exist"); + let state = wallet.contract_state_rgb21(contract_id).unwrap(); + let token = state.immutable.token.unwrap(); + assert_eq!(state.immutable.name.as_str(), "DigitalCollection"); + assert_eq!(state.immutable.total_fractions, 10_000); + assert_eq!(token.ticker.unwrap().to_string(), ticker); + assert_eq!(token.name.unwrap().to_string(), name); + assert_eq!(token.details.unwrap().to_string(), details); + assert_eq!( + token.preview.as_ref().unwrap().media_type.r#type.as_str(), + token_data_preview.ty.ty.as_str() + ); - // Verify immutable state - assert_eq!(state.immutable.name, "DigitalCollection"); + assert_eq!( + token.preview.as_ref().unwrap().data.as_slice(), + token_data_preview.data.as_slice() + ); + assert_eq!( + token.media.as_ref().unwrap().digest.as_slice(), + token_data_attachment.digest.as_slice() + ); + // token_data_attachments + for (idx, attachment) in token.attachments.iter() { + assert_eq!( + attachment.digest.as_slice(), + token_data_attachments[idx].digest.as_slice() + ); + } + assert_eq!( + token.reserves.as_ref().unwrap().utxo.to_string(), + token_data_reserves.utxo.to_string() + ); + assert_eq!( + token.reserves.as_ref().unwrap().proof.as_slice(), + token_data_reserves.proof.as_slice() + ); - // Verify ownership state - // TODO: This needs to be refactored, - // the owned state of RGB21 is different from RGB20 and RGB25 - // assert_eq!(state.owned.allocations.len(), 1); - // assert!(state - // .owned - // .allocations - // .iter() - // .any(|(op, amount)| *op == outpoint && *amount == 10_000)); - - // Output contract state information - // dbg!( - // wallet.contracts_info(), - // wallet - // .runtime() - // .state_all(Some(contract_id)) - // .collect::>() - // ); - - dbg!(wallet.contract_state_rgb21(contract_id)); + assert_eq!(state.owned.fractions.len(), 1); + assert_eq!(state.owned.fractions[0].0.to_string(), outpoint.to_string()); + assert_eq!(state.owned.fractions[0].1, 10_000); } - -// TODO: RGB official is improving the feature of uda asset, will add test after it's ready -// #[apply(descriptor_and_close_method)] -// fn issue_uda(wallet_desc: DescriptorType) { -// println!("wallet_desc {wallet_desc:?} "); - -// initialize(); - -// let mut wallet = get_wallet(&wallet_desc); - -// let ticker = "TCKR"; -// let name = "asset name"; -// let details = Some("some details"); -// let terms_text = "Ricardian contract"; -// let terms_media_fpath = Some(MEDIA_FPATH); -// let data = vec![1u8, 3u8, 9u8]; -// let preview_ty = "image/jpeg"; -// let token_data_preview = EmbeddedMedia { -// ty: MediaType::with(preview_ty), -// data: Confined::try_from(data.clone()).unwrap(), -// }; -// let proof = vec![2u8, 4u8, 6u8, 10u8]; -// let token_data_reserves = ProofOfReserves { -// utxo: Outpoint::from_str(FAKE_TXID).unwrap(), -// proof: Confined::try_from(proof.clone()).unwrap(), -// }; -// let token_data_ticker = "TDTCKR"; -// let token_data_name = "token data name"; -// let token_data_details = "token data details"; -// let token_data_attachment = attachment_from_fpath(MEDIA_FPATH); -// let mut token_data_attachments = BTreeMap::new(); -// for (idx, attachment_fpath) in ["README.md", "Cargo.toml"].iter().enumerate() { -// token_data_attachments.insert(idx as u8, attachment_from_fpath(attachment_fpath)); -// } -// let token_data = uda_token_data( -// token_data_ticker, -// token_data_name, -// token_data_details, -// token_data_preview.clone(), -// token_data_attachment.clone(), -// token_data_attachments.clone(), -// token_data_reserves.clone(), -// ); -// let asset_info = AssetInfo::uda( -// ticker, -// name, -// details, -// terms_text, -// terms_media_fpath, -// token_data, -// ); -// let (contract_id, iface_type_name) = wallet.issue_with_info(asset_info, close_method, vec![]); - -// let contract = wallet.contract_iface_class::(contract_id); -// let spec = contract.spec(); -// assert_eq!(spec.ticker.to_string(), ticker.to_string()); -// assert_eq!(spec.name.to_string(), name.to_string()); -// assert_eq!(spec.precision.decimals(), 0); -// let terms = contract.contract_terms(); -// assert_eq!(terms.text.to_string(), terms_text.to_string()); -// let terms_media = terms.media.unwrap(); -// assert_eq!(terms_media.ty.to_string(), "image/jpeg"); -// assert_eq!( -// terms_media.digest.to_string(), -// "02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a" -// ); -// let token_data = contract.token_data(); -// assert_eq!(token_data.index, TokenIndex::from(0)); -// assert_eq!(token_data.ticker.unwrap().to_string(), token_data_ticker); -// assert_eq!(token_data.name.unwrap().to_string(), token_data_name); -// assert_eq!(token_data.details.unwrap().to_string(), token_data_details); -// assert_eq!(token_data.preview.unwrap(), token_data_preview); -// assert_eq!(token_data.media.unwrap(), token_data_attachment); -// assert_eq!( -// token_data.attachments.to_unconfined(), -// token_data_attachments -// ); -// assert_eq!(token_data.reserves.unwrap(), token_data_reserves); - -// let allocations = wallet.contract_data_allocations(contract_id, &iface_type_name); -// assert_eq!(allocations.len(), 1); -// let allocation = &allocations[0]; -// assert_eq!(allocation.seal.method(), close_method); -// assert_eq!(allocation.state.to_string(), "000000000100000000000000"); -// } diff --git a/tests/templates/issuance/FAC.yaml b/tests/templates/issuance/FAC.yaml index 8b42def..9629bb3 100644 --- a/tests/templates/issuance/FAC.yaml +++ b/tests/templates/issuance/FAC.yaml @@ -15,11 +15,11 @@ global: verified: 10000 - name: token verified: - index: 0 - amount: 10000 - # TODO: `reserved` is a 26-sized U8 array, + tokenIndex: 0 + fraction: 10000 + # TODO: `align` is a 26-sized U8 array, # Need to rewrite to bytes in code - reserved: + align: unverified: index: 0 ticker: TCKR @@ -67,8 +67,5 @@ global: owned: - name: fractions seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 - data: - # TODO: Expected to be parsed as tuple, but parsed as union, need to convert in code - - 0 - - 10000 + data: 10000 diff --git a/tests/templates/schemata/RGB21-FAC.issuer b/tests/templates/schemata/RGB21-FAC.issuer index b03efedc70466b695fb8f63ac9686088d5008e22..b29d875bd0b3d6d51e5de31ae04013e8cb93d84f 100644 GIT binary patch delta 992 zcmdmEy~lAw6_diNWvpr&x!Y?`y`J~;vrNO}vrL+iH~++E-TI&O)&96O$K+W|K9kon zDljrm7GzP}tihbg%-iNXn+X3>BxE2&10Ta= zJrO0RiZ4=krX1KL%IBMQ{`H1D35BG7CZiXp8SmY_Fm2kysTWxp@9ImfZ<)cpVd=TV zjORspi#6OPJUMna)_x0C%{cZ9~qZq8G? zf;4Ow)aOp{s(snCchc1@oxFM+uB?pr)WuEZZg00q+M-->t7!iekxRQLnY&E?G_y`< z5<9EY-HmKdSMHX-#PLGjGx?8Hlucf@pNy3`<|@h0PR;Y2T+Oed&zhK%nVv_;{TyjUiOD6I`FWrmw7E{&jtKyG|G?(} delta 281 zcmdnvxW{@!6_Wz9S@yEm_ts06eVyGJThd#Up?`G)n?l|;74C%}a$Tz?PoBl(qnJ3& z>{MD)BkNf{&n9jMA#N7PSypqXratf0lNGojK!luUr=5%nLnEXOU zVe=*~F~-eYJW}jRgxti+1Tr728AP8H{x!KyM1hHcadVbvF3aTm0t%BYr8ZACkX4xM RC%tL&F&P=g&2@5iOaRbwXUhNp diff --git a/tests/transfer_rgb21.rs b/tests/transfer_rgb21.rs new file mode 100644 index 0000000..4df16d9 --- /dev/null +++ b/tests/transfer_rgb21.rs @@ -0,0 +1,198 @@ +pub mod utils; + +use ifaces::{EmbeddedMedia, MediaType, ProofOfReserves}; +use utils::helpers::{attachment_from_fpath, nft_spec, FACIssueParams}; + +use rstest_reuse::{self, *}; +use std::str::FromStr; +use utils::{ + chain::initialize, + helpers::{get_wallet, AssetSchema}, + DescriptorType, *, +}; + +#[template] +#[rstest] +#[case(true)] +#[case(false)] +fn wout(#[case] wout: bool) {} + +#[allow(dead_code)] +const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; + +#[apply(wout)] +fn simple_fac_transfer(wout: bool) { + initialize(); + + // Create two wallet instances + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + let total_fractions = 10_000; + let asset_name = "DigitalCollection"; + + // Create FAC asset parameters + let mut fac_params = FACIssueParams::new( + asset_name, + "A collection of digital assets", + total_fractions, + ); + + // Prepare NFT data + let ticker = "DCOLL"; + let name = "Digital Collection #1"; + let details = "First item in the digital collection"; + + // Create preview data + let data = vec![1u8, 3u8, 9u8]; + let preview_ty = "image/jpeg"; + let token_data_preview = EmbeddedMedia { + ty: MediaType::with(preview_ty), + data: Confined::try_from(data.clone()).unwrap(), + }; + + // Create reserves proof + let proof = vec![2u8, 4u8, 6u8, 10u8]; + let token_data_reserves = ProofOfReserves { + utxo: Outpoint::from_str(FAKE_TXID).unwrap(), + proof: Confined::try_from(proof.clone()).unwrap(), + }; + + // Create attachment + let token_data_attachment = attachment_from_fpath(MEDIA_FPATH); + + // Create additional attachments + let mut token_data_attachments = BTreeMap::new(); + for (idx, attachment_fpath) in ["README.md", "Cargo.toml"].iter().enumerate() { + token_data_attachments.insert(idx as u8, attachment_from_fpath(attachment_fpath)); + } + + // Create NFT spec + let nft_spec = nft_spec( + ticker, + name, + details, + token_data_preview.clone(), + token_data_attachment.clone(), + token_data_attachments, + token_data_reserves.clone(), + ); + + // Get an outpoint for allocation + let outpoint = wlt_1.get_utxo(None); + fac_params.with_allocation(outpoint, total_fractions); + fac_params.with_nft_spec(nft_spec); + + // Issue the contract + let contract_id = wlt_1.issue_fac_with_params(fac_params); + println!("FAC contract issued with ID: {}", contract_id); + + // Share contract with wallet 2 + wlt_1.send_contract(asset_name, &mut wlt_2); + wlt_2.reload_runtime(); + + // Verify initial state + let state = wlt_1.contract_state_rgb21(contract_id).unwrap(); + assert_eq!(state.immutable.name.as_str(), asset_name); + assert_eq!(state.immutable.total_fractions, total_fractions); + assert_eq!(state.owned.fractions.len(), 1); + assert_eq!(state.owned.fractions[0].1, total_fractions); + + dbg!( + wlt_1 + .runtime() + .state_own(Some(contract_id)) + .next() + .unwrap() + .1 + .owned + ); + dbg!( + wlt_2 + .runtime() + .state_own(Some(contract_id)) + .next() + .unwrap() + .1 + .owned + ); + + // Transfer some fractions to wallet 2 + let transfer_amount = 1001; + let invoice = wlt_2.invoice(contract_id, transfer_amount, wout, Some(0), None); + let (consignment_1, tx) = wlt_1.transfer(invoice, Some(9000), Some(500), true, None); + + // Receiver accepts the transfer + wlt_2.accept_transfer(&consignment_1, None).unwrap(); + + // Broadcast and confirm transaction + wlt_1.mine_tx(&tx.txid(), true); + + // Sync both wallets + wlt_1.sync(); + wlt_2.sync(); + + dbg!( + wlt_1 + .runtime() + .state_own(Some(contract_id)) + .next() + .unwrap() + .1 + .owned + ); + dbg!( + wlt_2 + .runtime() + .state_own(Some(contract_id)) + .next() + .unwrap() + .1 + .owned + ); + + // Verify allocations after transfer + wlt_1.check_allocations( + contract_id, + AssetSchema::RGB21, + vec![total_fractions - transfer_amount], + ); + wlt_2.check_allocations(contract_id, AssetSchema::RGB21, vec![transfer_amount]); + + // Check that NFT data is preserved in both wallets + let state_1 = wlt_1.contract_state_rgb21(contract_id).unwrap(); + let token_1 = state_1.immutable.token.unwrap(); + assert_eq!(token_1.ticker.unwrap().to_string(), ticker); + assert_eq!(token_1.name.unwrap().to_string(), name); + + let state_2 = wlt_2.contract_state_rgb21(contract_id).unwrap(); + let token_2 = state_2.immutable.token.unwrap(); + assert_eq!(token_2.ticker.unwrap().to_string(), ticker); + assert_eq!(token_2.name.unwrap().to_string(), name); + + // Test transferring some fractions back to wallet 1 + let return_amount = 1000; + let invoice = wlt_1.invoice(contract_id, return_amount, wout, Some(0), None); + let (consignment_2, tx) = wlt_2.transfer(invoice, Some(3000), Some(500), true, None); + + // Wallet 1 accepts the transfer + wlt_1.accept_transfer(&consignment_2, None).unwrap(); + + // Broadcast and confirm transaction + wlt_2.mine_tx(&tx.txid(), true); + + // Sync both wallets + wlt_1.sync(); + wlt_2.sync(); + + // Verify final allocations + wlt_1.check_allocations( + contract_id, + AssetSchema::RGB21, + vec![total_fractions - transfer_amount, return_amount], + ); + wlt_2.check_allocations( + contract_id, + AssetSchema::RGB21, + vec![transfer_amount - return_amount], + ); +} diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 6e699c7..372ad45 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1396,27 +1396,29 @@ impl TestWallet { asset_schema: AssetSchema, mut expected_fungible_allocations: Vec, ) { - match asset_schema { + let allocation_field = match asset_schema { AssetSchema::RGB20 | AssetSchema::RGB25 => { // For fungible assets, we need to check the "amount" allocation - let state = self.runtime.state_own(Some(contract_id)).next().unwrap().1; - let allocation_field = "amount"; - let mut actual_fungible_allocations = state - .owned - .get(allocation_field) - .unwrap() - .iter() - .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) - .collect::>(); - actual_fungible_allocations.sort(); - expected_fungible_allocations.sort(); - assert_eq!(actual_fungible_allocations, expected_fungible_allocations); + "amount" } AssetSchema::RGB21 => { - // TODO: Implement UDA asset allocation checking once RGB core library support is ready - todo!() + // for RGB21, we need to check the "fractions" allocation + "fractions" } - } + }; + + let state = self.runtime.state_own(Some(contract_id)).next().unwrap().1; + + let mut actual_fungible_allocations = state + .owned + .get(allocation_field) + .unwrap() + .iter() + .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) + .collect::>(); + actual_fungible_allocations.sort(); + expected_fungible_allocations.sort(); + assert_eq!(actual_fungible_allocations, expected_fungible_allocations); } pub fn sign_finalize(&self, psbt: &mut Psbt) { @@ -1809,15 +1811,15 @@ impl TestWallet { if name_state.name == name { let token = &mut name_state.state.verified; if let StrictVal::Struct(s) = token { - let reserved_name = FieldName::from_str("reserved").unwrap(); + let reserved_name = FieldName::from_str("align").unwrap(); let reserved = s.get_mut(&reserved_name).unwrap(); *reserved = StrictVal::Bytes(Blob(vec![0; 26])); - let index_name = FieldName::from_str("index").unwrap(); + let index_name = FieldName::from_str("tokenIndex").unwrap(); let index = s.get_mut(&index_name).unwrap(); *index = StrictVal::Number(StrictNum::from(params.index as u32)); - let amount_name = FieldName::from_str("amount").unwrap(); + let amount_name = FieldName::from_str("fraction").unwrap(); let amount = s.get_mut(&amount_name).unwrap(); *amount = StrictVal::Number(StrictNum::from(params.total_fractions as u64)); } @@ -2061,11 +2063,11 @@ impl TestWallet { let name = VariantName::from_str("fractions").unwrap(); if name_state.name == name { let fractions = &mut name_state.state; + fractions.seal = EitherSeal::Alt(params.initial_allocation.unwrap().0); let fractions_data = &mut fractions.data; - *fractions_data = StrictVal::Tuple(vec![ - StrictVal::Number(StrictNum::from(params.index as u32)), - StrictVal::Number(StrictNum::from(params.total_fractions as u64)), - ]); + *fractions_data = StrictVal::Tuple(vec![StrictVal::Number(StrictNum::from( + params.initial_allocation.unwrap().1, + ))]); } } @@ -2128,7 +2130,7 @@ pub struct ReserveData { /// Owned state part of RGB21 contract #[derive(Debug, Clone)] pub struct RGB21ContractOwnedState { - pub fractions: Vec<(Outpoint, u32, u64)>, // (outpoint, index, amount) + pub fractions: Vec<(Outpoint, u64)>, // (outpoint, amount) } /// Complete RGB21 contract state @@ -2511,24 +2513,8 @@ impl TestWallet { let mut fractions = vec![]; if let Some(owned_map) = owned.get(&VariantName::from_str("fractions").unwrap()) { for assignment in owned_map.values() { - if let StrictVal::Tuple(ref tuple) = assignment.data { - if tuple.len() >= 2 { - let idx_val = extract_from_tuple(&tuple[0]); - let amt_val = extract_from_tuple(&tuple[1]); - - if let ( - Some(StrictVal::Number(idx)), - Some(StrictVal::Number(amount)), - ) = (idx_val, amt_val) - { - fractions.push(( - assignment.seal, - idx.unwrap_uint::(), - amount.unwrap_uint::(), - )); - } - } - } + let amt_val = assignment.data.unwrap_num().unwrap_uint::(); + fractions.push((assignment.seal, amt_val)); } } From 00168d249faa010550e38c6995f48b0c1b0ad5ff Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 2 Apr 2025 19:03:55 +0800 Subject: [PATCH 46/90] fix: resolve transaction conflicts and block height assertions in integration tests Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 24 ++++++++++++------------ tests/transfer_rgb21.rs | 4 ++-- tests/utils/helpers.rs | 3 +-- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 633e343..320c388 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -82,7 +82,7 @@ fn simple_transfer(wout: bool) { wlt_2.accept_transfer(&consignment_1, None).unwrap(); // Broadcast and confirm transaction - wlt_1.mine_tx(&tx.txid(), true); + wlt_1.mine_tx(&tx.txid(), false); // Sync both wallets wlt_1.sync(); @@ -101,7 +101,7 @@ fn simple_transfer(wout: bool) { // Sats cost: 500 fee + 2000 sats(default) = 2500 let (consignment_2, tx) = wlt_2.transfer(invoice, None, Some(500), true, None); wlt_1.accept_transfer(&consignment_2, None).unwrap(); - wlt_2.mine_tx(&tx.txid(), true); + wlt_2.mine_tx(&tx.txid(), false); // // Sync both wallets wlt_1.sync(); @@ -610,16 +610,16 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), None); let _ = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); - dbg!(wlt_1 - .runtime() - .state_all(None) - .map(|(_, s)| { s.owned }) - .collect::>()); - dbg!(wlt_1 - .runtime() - .state_own(None) - .map(|(_, s)| { s.owned }) - .collect::>()); + // dbg!(wlt_1 + // .runtime() + // .state_all(None) + // .map(|(_, s)| { s.owned }) + // .collect::>()); + // dbg!(wlt_1 + // .runtime() + // .state_own(None) + // .map(|(_, s)| { s.owned }) + // .collect::>()); // dbg!(wlt_2 // .runtime() diff --git a/tests/transfer_rgb21.rs b/tests/transfer_rgb21.rs index 4df16d9..a1d54af 100644 --- a/tests/transfer_rgb21.rs +++ b/tests/transfer_rgb21.rs @@ -125,7 +125,7 @@ fn simple_fac_transfer(wout: bool) { wlt_2.accept_transfer(&consignment_1, None).unwrap(); // Broadcast and confirm transaction - wlt_1.mine_tx(&tx.txid(), true); + wlt_1.mine_tx(&tx.txid(), false); // Sync both wallets wlt_1.sync(); @@ -178,7 +178,7 @@ fn simple_fac_transfer(wout: bool) { wlt_1.accept_transfer(&consignment_2, None).unwrap(); // Broadcast and confirm transaction - wlt_2.mine_tx(&tx.txid(), true); + wlt_2.mine_tx(&tx.txid(), false); // Sync both wallets wlt_1.sync(); diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 372ad45..e8cc23a 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1267,8 +1267,7 @@ impl TestWallet { let transfer_report = report.as_deref_mut(); let (consignment, tx) = self.transfer(invoice, sats, fee, true, transfer_report); - broadcast_tx_and_mine(&tx, self.instance); - + self.mine_tx(&tx.txid(), false); // Now use the original report parameter recv_wallet.accept_transfer(&consignment, report).unwrap(); self.sync(); From bdd01a6d0ec06858cc867a4d0f92e800a57985bd Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 2 Apr 2025 22:24:49 +0800 Subject: [PATCH 47/90] refactor: modularize helpers.rs into specialized components Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 8 +- tests/stress.rs | 7 +- tests/transfer.rs | 12 +- tests/transfer_rgb21.rs | 3 +- tests/utils/helper/asset_params.rs | 182 ++ tests/utils/helper/asset_types.rs | 286 ++++ tests/utils/helper/coinselect.rs | 93 ++ tests/utils/helper/mod.rs | 7 + tests/utils/helper/reporting.rs | 464 ++++++ tests/utils/{helpers.rs => helper/wallet.rs} | 1571 ++++-------------- tests/utils/mod.rs | 108 +- 11 files changed, 1387 insertions(+), 1354 deletions(-) create mode 100644 tests/utils/helper/asset_params.rs create mode 100644 tests/utils/helper/asset_types.rs create mode 100644 tests/utils/helper/coinselect.rs create mode 100644 tests/utils/helper/mod.rs create mode 100644 tests/utils/helper/reporting.rs rename tests/utils/{helpers.rs => helper/wallet.rs} (67%) diff --git a/tests/issuance.rs b/tests/issuance.rs index 969ce74..65e834a 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -2,13 +2,7 @@ pub mod utils; use ifaces::{EmbeddedMedia, MediaType, ProofOfReserves}; use rstest_reuse::{self, *}; -use utils::{ - chain::initialize, - helpers::{ - attachment_from_fpath, get_wallet, nft_spec, FACIssueParams, FUAIssueParams, NIAIssueParams, - }, - DescriptorType, *, -}; +use utils::{chain::initialize, helper::wallet::get_wallet, DescriptorType, *}; #[allow(dead_code)] const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; diff --git a/tests/stress.rs b/tests/stress.rs index c9b9287..4e1e98f 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -27,9 +27,11 @@ use std::time::Instant; use std::{env::VarError, fs::File}; use time::format_description::well_known::Iso8601; use time::{format_description, OffsetDateTime}; +use utils::NIAIssueParams; use utils::{ chain::initialize, - helpers::{get_wallet, MetricDefinition, MetricType, Report, TransferType}, + helper::reporting::{MetricDefinition, MetricType, Report}, + helper::wallet::{get_wallet, TransferType}, DescriptorType, DEFAULT_FEE_ABS, STRESS_DATA_DIR, TEST_DATA_DIR, }; @@ -135,8 +137,7 @@ fn back_and_forth( // In RGB v0.12, the close_method parameter is no longer required // Create and issue assets - let mut params = - utils::helpers::NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issued_supply); + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issued_supply); let utxo = wlt_1.get_utxo(None); params.add_allocation(utxo, issued_supply); let contract_id = wlt_1.issue_nia_with_params(params); diff --git a/tests/transfer.rs b/tests/transfer.rs index 320c388..25e34a4 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -27,19 +27,19 @@ use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; -use utils::helpers::{CustomCoinselectStrategy, FUAIssueParams}; +use utils::helper::wallet::{ + broadcast_tx_and_mine, get_mainnet_wallet, get_wallet, get_wallet_custom, AssetSchema, +}; use utils::{ chain::{ connect_reorg_nodes, disconnect_reorg_nodes, get_height, get_height_custom, initialize, mine_custom, stop_mining, }, - helpers::{ - broadcast_tx_and_mine, get_mainnet_wallet, get_wallet, get_wallet_custom, AssetSchema, - HistoryType, NIAIssueParams, ReorgType, TransferType, - }, DescriptorType, INSTANCE_2, INSTANCE_3, *, }; +use crate::utils::helper::wallet::{HistoryType, ReorgType}; + type TT = TransferType; type DT = DescriptorType; type AS = AssetSchema; @@ -974,7 +974,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp HistoryType::Linear => { // Set the coin selection strategy to true small size // This setting is very important, it avoids selecting the output of the revert transaction as input - wlt_1.set_coinselect_strategy(helpers::CustomCoinselectStrategy::TrueSmallSize); + wlt_1.set_coinselect_strategy(CustomCoinselectStrategy::TrueSmallSize); let amt_0 = 590; // Create blinded invoice with specific UTXO let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); diff --git a/tests/transfer_rgb21.rs b/tests/transfer_rgb21.rs index a1d54af..bc9910c 100644 --- a/tests/transfer_rgb21.rs +++ b/tests/transfer_rgb21.rs @@ -1,13 +1,12 @@ pub mod utils; use ifaces::{EmbeddedMedia, MediaType, ProofOfReserves}; -use utils::helpers::{attachment_from_fpath, nft_spec, FACIssueParams}; use rstest_reuse::{self, *}; use std::str::FromStr; use utils::{ chain::initialize, - helpers::{get_wallet, AssetSchema}, + helper::wallet::{get_wallet, AssetSchema}, DescriptorType, *, }; diff --git a/tests/utils/helper/asset_params.rs b/tests/utils/helper/asset_params.rs new file mode 100644 index 0000000..ded35ab --- /dev/null +++ b/tests/utils/helper/asset_params.rs @@ -0,0 +1,182 @@ +use super::*; + +/// RGB Asset creation parameters builder +#[derive(Clone)] +pub struct AssetParamsBuilder { + params: CreateParams, +} + +impl AssetParamsBuilder { + /// Create a new builder instance for non-inflatable asset + pub fn default_nia() -> Self { + Self { + params: Self::from_file(NON_INFLATABLE_ASSET_TEMPLATE_PATH), + } + } + + /// Create a new builder instance for fractional unique asset + pub fn default_fua() -> Self { + Self { + params: Self::from_file(FRACTIONAL_UNIQUE_ASSET_TEMPLATE_PATH), + } + } + + /// Create a new builder instance for fractionable asset collection + pub fn default_fac() -> Self { + Self { + params: Self::from_file(FRACTIONABLE_ASSET_COLLECTION_TEMPLATE_PATH), + } + } + + /// Load parameters from YAML file + pub fn from_file>(path: P) -> CreateParams { + let file = File::open(path).expect("Unable to open file"); + let params: CreateParams = + serde_yaml::from_reader::<_, CreateParams>(file).expect(""); + params + } + + /// Set the contract template ID + pub fn codex_id(mut self, codex_id: CodexId) -> Self { + self.params.codex_id = codex_id; + self + } + + /// Set the consensus type + pub fn consensus(mut self, consensus: Consensus) -> Self { + self.params.consensus = consensus; + self + } + + /// Set whether it is a test network + pub fn testnet(mut self, testnet: bool) -> Self { + self.params.testnet = testnet; + self + } + + /// Set the contract method name + pub fn method(mut self, method: &str) -> Self { + self.params.method = VariantName::from_str(method).unwrap(); + self + } + + /// Set the contract name + pub fn name(mut self, name: &str) -> Self { + self.params.name = TypeName::from_str(name).unwrap(); + self + } + + /// Update name state in global states + pub fn update_name_state(mut self, value: &str) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "name".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Update details state in global states + pub fn update_details_state(mut self, value: &str) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "details".into()) + { + state.state.verified = StrictVal::Unit; + state.state.unverified = Some(value.into()); + } + self + } + + /// Update ticker state in global states + pub fn update_ticker_state(mut self, value: &str) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "ticker".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Update precision state in global states + pub fn update_precision_state(mut self, value: &str) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "precision".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Update circulating state in global states + /// circulating type is "RGBContract.Amount" eq u64 in rust + pub fn update_circulating_state(mut self, value: u64) -> Self { + if let Some(state) = self + .params + .global + .iter_mut() + .find(|s| s.name == "circulating".into()) + { + state.state.verified = value.into(); + } + self + } + + /// Update owned state + pub fn update_owned_state(mut self, seal: Outpoint, val: u64) -> Self { + // check if owned state exists + if let Some(state) = self + .params + .owned + .iter_mut() + .find(|s| s.name == "owned".into()) + { + // if exists, update seal and data + state.state.seal = EitherSeal::Alt(seal); + state.state.data = val.into(); + } else { + // if not exists, create a new owned state + self.params.owned.push(NamedState { + name: "owned".into(), + state: Assignment { + seal: EitherSeal::Alt(seal), + data: val.into(), + }, + }); + } + self + } + + pub fn clear_owned_state(mut self) -> Self { + self.params.owned.clear(); + self + } + + /// Add owned state + pub fn add_owned_state(mut self, seal: Outpoint, val: u64) -> Self { + self.params.owned.push(NamedState { + name: "amount".into(), + state: Assignment { + seal: EitherSeal::Alt(seal), + data: val.into(), + }, + }); + self + } + + /// Build CreateParams instance + pub fn build(self) -> CreateParams { + self.params + } +} diff --git a/tests/utils/helper/asset_types.rs b/tests/utils/helper/asset_types.rs new file mode 100644 index 0000000..6f199a9 --- /dev/null +++ b/tests/utils/helper/asset_types.rs @@ -0,0 +1,286 @@ +use super::*; + +/// Parameters for NIA (Non-Inflatable Asset) issuance +#[derive(Clone)] +pub struct NIAIssueParams { + pub name: String, + pub ticker: String, + pub precision: String, + pub circulating_supply: u64, + pub initial_allocations: Vec<(Outpoint, u64)>, +} + +impl Default for NIAIssueParams { + fn default() -> Self { + Self { + name: "USD Tether".to_string(), + ticker: "USDT".to_string(), + precision: "centiMilli".to_string(), + circulating_supply: 1_000_000, + initial_allocations: vec![], + } + } +} + +impl NIAIssueParams { + pub fn new( + name: impl Into, + ticker: impl Into, + precision: impl Into, + circulating_supply: u64, + ) -> Self { + Self { + name: name.into(), + ticker: ticker.into(), + precision: precision.into(), + circulating_supply, + initial_allocations: vec![], + } + } + + pub fn add_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { + self.initial_allocations.push((outpoint, amount)); + self + } +} + +/// RGB Contract State representation +#[derive(Debug)] +pub struct ContractState { + /// Immutable state of the contract + pub immutable: ContractImmutableState, + /// Ownership state of the contract + pub owned: ContractOwnedState, +} + +/// Contract's immutable state +#[derive(Debug)] +pub struct ContractImmutableState { + pub name: String, + pub ticker: String, + pub precision: String, + pub circulating_supply: u64, +} + +/// Contract's ownership state +#[derive(Debug)] +pub struct ContractOwnedState { + pub allocations: Vec<(Outpoint, u64)>, +} + +/// Parameters for FUA (Fractional unique asset) issuance +#[derive(Clone)] +pub struct FUAIssueParams { + /// Asset name + pub name: String, + /// Asset details + pub details: String, + /// Decimal precision for the asset + pub precision: String, + /// Total circulating supply + pub circulating_supply: u64, + /// Initial token allocations (outpoint, amount) + pub initial_allocations: Vec<(Outpoint, u64)>, +} + +impl Default for FUAIssueParams { + fn default() -> Self { + Self { + name: "DemoFUA".to_string(), + details: "Demo FUA details".to_string(), + precision: "centiMilli".to_string(), + circulating_supply: 10_000, + initial_allocations: vec![], + } + } +} + +impl FUAIssueParams { + /// Create new CFA issuance parameters + pub fn new( + name: impl Into, + details: impl Into, + precision: impl Into, + circulating_supply: u64, + ) -> Self { + Self { + name: name.into(), + details: details.into(), + precision: precision.into(), + circulating_supply, + initial_allocations: vec![], + } + } + + /// Add a token allocation + pub fn add_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { + self.initial_allocations.push((outpoint, amount)); + self + } +} + +/// Parameters for FAC (Fractionable Asset Collection) issuance +#[derive(Clone)] +pub struct FACIssueParams { + /// Collection name + pub name: String, + /// Collection details + pub details: String, + /// Total number of fractions + pub total_fractions: u64, + /// Token index + pub index: u32, + /// Initial token allocation (outpoint, amount) + pub initial_allocation: Option<(Outpoint, u64)>, + /// NFT specification + pub nft_spec: Option, +} + +impl Default for FACIssueParams { + fn default() -> Self { + Self { + name: "FAC".to_string(), + details: "Demo FAC details".to_string(), + total_fractions: 10_000, + index: UDA_FIXED_INDEX, + initial_allocation: None, + nft_spec: None, + } + } +} + +impl FACIssueParams { + /// Create new FAC issuance parameters + pub fn new(name: impl Into, details: impl Into, total_fractions: u64) -> Self { + Self { + name: name.into(), + details: details.into(), + index: UDA_FIXED_INDEX, + total_fractions, + initial_allocation: None, + nft_spec: None, + } + } + + /// Set token allocation + pub fn with_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { + self.initial_allocation = Some((outpoint, amount)); + self + } + + /// Set NFT specification + pub fn with_nft_spec(&mut self, nft_spec: NftSpec) -> &mut Self { + self.nft_spec = Some(nft_spec); + self + } +} + +/// Create a minimal NFT spec with just index +pub fn nft_spec_minimal() -> NftSpec { + NftSpec { + index: TokenIndex::from(UDA_FIXED_INDEX), + ..Default::default() + } +} + +/// Create a complete NFT spec with all details +pub fn nft_spec( + ticker: &str, + name: &str, + details: &str, + preview: EmbeddedMedia, + media: Attachment, + attachments: BTreeMap, + reserves: ProofOfReserves, +) -> NftSpec { + let mut nft_spec = nft_spec_minimal(); + nft_spec.preview = Some(preview); + nft_spec.media = Some(media); + nft_spec.attachments = Confined::try_from(attachments.clone()).unwrap(); + nft_spec.reserves = Some(reserves); + nft_spec.ticker = Some(Ticker::try_from(ticker.to_string()).unwrap()); + nft_spec.name = Some(AssetName::try_from(name.to_string()).unwrap()); + nft_spec.details = Some(Details::from_str(details).unwrap()); + nft_spec +} + +/// Function to create a file attachment from a file path +pub fn attachment_from_fpath(fpath: &str) -> Attachment { + let file_bytes = std::fs::read(fpath).unwrap(); + let file_hash: sha256::Hash = Hash::hash(&file_bytes[..]); + let digest = file_hash.to_byte_array().into(); + let mime = FileFormat::from_file(fpath) + .unwrap() + .media_type() + .to_string(); + let media_ty: &'static str = Box::leak(mime.clone().into_boxed_str()); + let media_type = MediaType::with(media_ty); + Attachment { + ty: media_type, + digest, + } +} + +/// Immutable state part of RGB21 contract +#[derive(Debug, Clone)] +pub struct RGB21ContractImmutableState { + pub name: String, + pub total_fractions: u64, + pub token: Option, +} + +/// NFT metadata in RGB21 contract +#[derive(Debug, Clone)] +pub struct NFTMetadata { + pub index: u32, + pub amount: u64, + pub ticker: Option, + pub name: Option, + pub details: Option, + pub preview: Option, + pub media: Option, + pub attachments: BTreeMap, + pub reserves: Option, +} + +/// Media data with full content +#[derive(Debug, Clone)] +pub struct MediaData { + pub media_type: MediaTypeData, + pub data: Vec, +} + +/// Media type information +#[derive(Debug, Clone)] +pub struct MediaTypeData { + pub r#type: String, + pub subtype: Option, + pub charset: Option, +} + +/// Media digest (reference only) +#[derive(Debug, Clone)] +pub struct MediaDigest { + pub media_type: MediaTypeData, + pub digest: Vec, +} + +/// Reserve proof data +#[derive(Debug, Clone)] +pub struct ReserveData { + pub utxo: Outpoint, + pub proof: Vec, +} + +/// Owned state part of RGB21 contract +#[derive(Debug, Clone)] +pub struct RGB21ContractOwnedState { + pub fractions: Vec<(Outpoint, u64)>, // (outpoint, amount) +} + +/// Complete RGB21 contract state +#[derive(Debug, Clone)] +pub struct RGB21ContractState { + pub immutable: RGB21ContractImmutableState, + pub owned: RGB21ContractOwnedState, +} diff --git a/tests/utils/helper/coinselect.rs b/tests/utils/helper/coinselect.rs new file mode 100644 index 0000000..02a48b7 --- /dev/null +++ b/tests/utils/helper/coinselect.rs @@ -0,0 +1,93 @@ +use super::*; + +/// Custom RGB coinselection strategy for more precise control over UTXO selection +/// +/// # Usage Example +/// +/// ``` +/// // Create wallet +/// let mut wallet = get_wallet(&DescriptorType::Wpkh); +/// +/// // Set to true small size strategy (selects UTXOs with maximum values) +/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::TrueSmallSize); +/// +/// // Or use standard strategies +/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::Standard(CoinselectStrategy::Aggregate)); +/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::Standard(CoinselectStrategy::SmallSize)); +/// +/// // For transfers requiring specific UTXOs (like testing reorganization history), use: +/// let (consignment, tx) = wallet.transfer_with_specific_utxo(invoice, specific_utxo, sats, fee, broadcast, report); +/// ``` +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum CustomCoinselectStrategy { + /// Use standard RGB coinselection strategies + /// - Aggregate: Collects many small outputs until target amount is reached + /// - SmallSize: Collects minimum number of outputs but without proper value sorting + Standard(CoinselectStrategy), + + /// Enhanced coinselection strategy that truly minimizes transaction size + /// by selecting the minimum number of UTXOs with largest asset values. + /// This strategy: + /// 1. First sorts all available colored UTXOs by their asset amount + /// 2. Selects the minimum number of largest-value UTXOs needed to satisfy the transfer + /// 3. Results in smallest possible transaction size by using fewer inputs + TrueSmallSize, +} + +impl Default for CustomCoinselectStrategy { + fn default() -> Self { + Self::Standard(CoinselectStrategy::default()) + } +} + +/// Implementation of the Coinselect trait for our custom strategy +impl Coinselect for CustomCoinselectStrategy { + fn coinselect( + &mut self, + invoiced_state: &StrictVal, + calc: &mut (impl StateCalc + ?Sized), + // Sorted vector by values + owned_state: Vec<(CellAddr, &StrictVal)>, + ) -> Option> { + match self { + // For standard strategies, delegate to the original implementation + CustomCoinselectStrategy::Standard(strategy) => { + strategy.coinselect(invoiced_state, calc, owned_state) + } + + // True small size implementation - sort by value before selection + CustomCoinselectStrategy::TrueSmallSize => { + // Clone the state to allow sorting (we need to own the data) + let mut value_sorted_state: Vec<(CellAddr, &StrictVal, u64)> = owned_state + .iter() + .filter_map(|(addr, val)| { + // Extract numeric value (assuming we're dealing with u64 values) + let amount: u64 = val.unwrap_num().unwrap_uint(); + Some((*addr, *val, amount)) + }) + .collect(); + + // Sort by value in descending order (largest first) + value_sorted_state.sort_by(|a, b| b.2.cmp(&a.2)); + + // Now use the sorted state for iteration + let res = value_sorted_state + .into_iter() + .take_while(|(_, val, _)| { + if calc.is_satisfied(invoiced_state) { + return false; + } + calc.accumulate(val).is_ok() + }) + .map(|(addr, _, _)| addr) + .collect(); + + if !calc.is_satisfied(invoiced_state) { + return None; + }; + + Some(res) + } + } + } +} diff --git a/tests/utils/helper/mod.rs b/tests/utils/helper/mod.rs new file mode 100644 index 0000000..dc9fb97 --- /dev/null +++ b/tests/utils/helper/mod.rs @@ -0,0 +1,7 @@ +pub mod asset_params; +pub mod asset_types; +pub mod coinselect; +pub mod reporting; +pub mod wallet; + +use super::*; diff --git a/tests/utils/helper/reporting.rs b/tests/utils/helper/reporting.rs new file mode 100644 index 0000000..1c3f2f1 --- /dev/null +++ b/tests/utils/helper/reporting.rs @@ -0,0 +1,464 @@ +use super::*; + +/// Test metric type +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum MetricType { + /// Duration (milliseconds) + Duration, + /// Bytes value + Bytes, + /// Integer value + Integer, + /// Float value + Float, + /// Text value + Text, +} + +/// Test metric definition +#[derive(Debug, Clone)] +pub struct MetricDefinition { + /// Metric name + pub name: String, + /// Metric type + pub metric_type: MetricType, + /// Metric description + pub description: String, +} + +/// Test report structure +pub struct Report { + /// Report file path + pub report_path: PathBuf, + /// Metric definitions + metrics: Vec, + /// File handle + file: Option, + /// Buffer for rows + buffer: Vec, + /// Current row being built + current_row: HashMap, + /// Buffer flush threshold + flush_threshold: usize, +} + +/// Report error types +#[derive(Debug)] +pub enum ReportError { + /// IO error + Io(std::io::Error), + /// Format error + Format(String), + /// Metric error + Metric(String), +} + +impl From for ReportError { + fn from(err: std::io::Error) -> Self { + ReportError::Io(err) + } +} + +impl std::fmt::Display for ReportError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ReportError::Io(err) => write!(f, "IO error: {}", err), + ReportError::Format(msg) => write!(f, "Format error: {}", msg), + ReportError::Metric(msg) => write!(f, "Metric error: {}", msg), + } + } +} + +impl std::error::Error for ReportError {} + +impl Report { + /// Create new report instance + pub fn new( + path: PathBuf, + metrics: Vec, + flush_threshold: Option, + ) -> Result { + let mut report = Self { + report_path: path, + metrics, + file: None, + buffer: Vec::new(), + current_row: HashMap::new(), + flush_threshold: flush_threshold.unwrap_or(10), + }; + + // Initialize report file + report.initialize()?; + + Ok(report) + } + + /// Initialize report file + fn initialize(&mut self) -> Result<(), ReportError> { + let headers: Vec = self.metrics.iter().map(|m| m.name.clone()).collect(); + + let file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(&self.report_path)?; + + let mut file = file; + file.write_all(format!("{}\n", headers.join(";")).as_bytes())?; + + // Save file handle for subsequent use + self.file = Some(file); + + Ok(()) + } + + /// Get file handle + fn get_file(&mut self) -> Result<&mut File, ReportError> { + if self.file.is_none() { + let file = OpenOptions::new().append(true).open(&self.report_path)?; + + self.file = Some(file); + } + + Ok(self.file.as_mut().unwrap()) + } + + /// Add duration metric by name + pub fn add_duration(&mut self, name: &str, duration: Duration) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Duration)?; + self.current_row + .insert(name.to_string(), duration.as_millis().to_string()); + Ok(()) + } + + /// Add bytes metric by name + pub fn add_bytes(&mut self, name: &str, value: u64) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Bytes)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Add integer metric by name + pub fn add_integer(&mut self, name: &str, value: u64) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Integer)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Add float metric by name + pub fn add_float(&mut self, name: &str, value: f64) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Float)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Add text metric by name + pub fn add_text(&mut self, name: &str, value: &str) -> Result<(), ReportError> { + self.check_metric_name_and_type(name, MetricType::Text)?; + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Add arbitrary type metric by name (auto conversion) + pub fn add_value(&mut self, name: &str, value: T) -> Result<(), ReportError> { + if !self.metrics.iter().any(|m| m.name == name) { + return Err(ReportError::Metric(format!( + "Metric name '{}' not found", + name + ))); + } + + self.current_row.insert(name.to_string(), value.to_string()); + Ok(()) + } + + /// Helper method to check if metric name exists and has correct type + fn check_metric_name_and_type( + &self, + name: &str, + expected_type: MetricType, + ) -> Result<(), ReportError> { + let metric = self.metrics.iter().find(|m| m.name == name); + + match metric { + Some(m) if m.metric_type == expected_type => Ok(()), + Some(m) => Err(ReportError::Metric(format!( + "Metric '{}' type mismatch, expected {:?}, actual {:?}", + name, expected_type, m.metric_type + ))), + None => Err(ReportError::Metric(format!( + "Metric name '{}' not found", + name + ))), + } + } + + /// Complete current row and add to buffer + pub fn end_row(&mut self) -> Result<(), ReportError> { + // Ensure all metrics have values + for metric in &self.metrics { + if !self.current_row.contains_key(&metric.name) { + self.current_row.insert(metric.name.clone(), String::new()); + } + } + + // Create row in the same order as metrics + let row = self + .metrics + .iter() + .map(|m| self.current_row.get(&m.name).cloned().unwrap_or_default()) + .collect::>() + .join(";"); + + self.buffer.push(row); + + // Clear current row for next use + self.current_row.clear(); + + // If buffer reaches threshold, flush to file + if self.buffer.len() >= self.flush_threshold { + self.flush_buffer()?; + } + + Ok(()) + } + + /// Write buffer content to file + pub fn flush_buffer(&mut self) -> Result<(), ReportError> { + if self.buffer.is_empty() { + return Ok(()); + } + + // Clone buffer contents to avoid borrow conflict + let buffer_contents = self.buffer.clone(); + let file = self.get_file()?; + + for row in buffer_contents.iter() { + file.write_all(format!("{}\n", row).as_bytes())?; + } + + self.buffer.clear(); + + Ok(()) + } + + /// Generate summary statistics + pub fn generate_summary(&mut self) -> Result { + // Ensure all data is written to file + self.flush_buffer()?; + + // Read CSV file + let content = std::fs::read_to_string(&self.report_path)?; + let lines: Vec<&str> = content.lines().collect(); + + if lines.is_empty() { + return Err(ReportError::Format("CSV file is empty".to_string())); + } + + // Parse headers + let headers: Vec<&str> = lines[0].split(';').collect(); + + // Prepare data structure + let mut data: Vec> = vec![Vec::new(); headers.len()]; + + // Parse data rows + for line in lines.iter().skip(1) { + let values: Vec<&str> = line.split(';').collect(); + for (i, value) in values.iter().enumerate() { + if i >= headers.len() { + break; + } + + if let Ok(num) = value.parse::() { + data[i].push(num); + } + } + } + + #[derive(Tabled)] + struct MetricSummary { + #[tabled(rename = "Metric")] + metric: String, + #[tabled(rename = "Average")] + average: String, + #[tabled(rename = "Minimum")] + minimum: String, + #[tabled(rename = "Maximum")] + maximum: String, + #[tabled(rename = "Sample Count")] + count: String, + } + + let mut summaries = Vec::new(); + + for (i, header) in headers.iter().enumerate() { + if data[i].is_empty() { + continue; + } + + let values = &data[i]; + let avg = values.iter().sum::() / values.len() as f64; + let min = values.iter().fold(f64::INFINITY, |a, &b| a.min(b)); + let max = values.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b)); + + // Format output based on metric type + let metric_type = if i < self.metrics.len() { + self.metrics[i].metric_type + } else { + MetricType::Float + }; + + let (avg_str, min_str, max_str) = match metric_type { + MetricType::Duration => ( + format!("{:.2} ms", avg), + format!("{:.2} ms", min), + format!("{:.2} ms", max), + ), + MetricType::Bytes => ( + format!("{:.2} B", avg), + format!("{:.2} B", min), + format!("{:.2} B", max), + ), + MetricType::Integer | MetricType::Float => ( + format!("{:.2}", avg), + format!("{:.2}", min), + format!("{:.2}", max), + ), + MetricType::Text => ("-".to_string(), "-".to_string(), "-".to_string()), + }; + + summaries.push(MetricSummary { + metric: header.to_string(), + average: avg_str, + minimum: min_str, + maximum: max_str, + count: values.len().to_string(), + }); + } + + // Create the table and style it + let mut table = Table::new(summaries); + table + .with(Style::markdown()) + .with(Modify::new(Columns::new(1..)).with(Alignment::right())); + + // Generate the final Markdown output + let mut summary = String::new(); + summary.push_str("# Performance Test Summary\n\n"); + summary.push_str(&table.to_string()); + + Ok(summary) + } + + /// Save summary statistics to file + pub fn save_summary(&mut self, name: &str) -> Result { + let summary = self.generate_summary()?; + + let summary_path = self + .report_path + .clone() + .with_file_name(format!("{}.md", name)); + + let mut file = std::fs::File::create(&summary_path)?; + file.write_all(summary.as_bytes())?; + + Ok(summary_path) + } + + /// Generate chart data + pub fn generate_chart_data(&mut self) -> Result { + // Ensure all data is written to file + self.flush_buffer()?; + + // Read CSV file + let content = std::fs::read_to_string(&self.report_path)?; + let lines: Vec<&str> = content.lines().collect(); + + if lines.is_empty() { + return Err(ReportError::Format("CSV file is empty".to_string())); + } + + // Parse headers + let headers: Vec<&str> = lines[0].split(';').collect(); + + // Prepare data structure + let mut data: Vec> = vec![Vec::new(); headers.len()]; + + // Parse data rows + for line in lines.iter().skip(1) { + let values: Vec<&str> = line.split(';').collect(); + for (i, value) in values.iter().enumerate() { + if i >= headers.len() { + break; + } + + if let Ok(num) = value.parse::() { + data[i].push(num); + } + } + } + + // Generate JSON + let mut json = String::from("{\n"); + + for (i, header) in headers.iter().enumerate() { + if i > 0 { + json.push_str(",\n"); + } + + json.push_str(&format!(" \"{}\": [", header)); + + for (j, value) in data[i].iter().enumerate() { + if j > 0 { + json.push_str(", "); + } + json.push_str(&format!("{}", value)); + } + + json.push(']'); + } + + json.push_str("\n}"); + + // Save JSON + let mut chart_path = self.report_path.clone(); + chart_path.set_extension("json"); + + let mut file = std::fs::File::create(&chart_path)?; + file.write_all(json.as_bytes())?; + + Ok(chart_path) + } + + /// Ensure all data is written on drop + pub fn finalize(&mut self) -> Result<(), ReportError> { + self.flush_buffer() + } + + /// For backward compatibility + pub fn write_header(&self, _fields: &[&str]) { + // Do nothing, headers are now defined by metrics + } + + /// For backward compatibility + pub fn write_duration(&self, _duration: Duration) { + // Do nothing, use add_duration instead + } + + /// For backward compatibility + pub fn write_value(&self, _value: T) { + // Do nothing, use add_value instead + } + + /// For backward compatibility + pub fn end_line(&self) { + // Do nothing, use end_row instead + } +} + +impl Drop for Report { + fn drop(&mut self) { + // Try to flush buffer, ignore errors + let _ = self.flush_buffer(); + } +} diff --git a/tests/utils/helpers.rs b/tests/utils/helper/wallet.rs similarity index 67% rename from tests/utils/helpers.rs rename to tests/utils/helper/wallet.rs index e8cc23a..1a0be94 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helper/wallet.rs @@ -1,244 +1,26 @@ -use bitcoin_hashes::{sha256, Hash}; -use indexmap::IndexMap; -use std::collections::{BTreeMap, HashMap}; -use std::fmt; -use std::fs::{File, OpenOptions}; -use std::io::Write; -use std::ops::Deref; -use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicU32, Ordering}; -use std::sync::OnceLock; -use std::time::Duration; -use std::time::Instant; - -use bp::{seals::WTxoSeal, Outpoint}; -use commit_verify::{Digest, DigestExt, Sha256}; -use ifaces::{ - AssetName, Attachment, Details, EmbeddedMedia, MediaType, NftSpec, ProofOfReserves, Ticker, - TokenIndex, -}; -use psbt::TxParams; -use rand::RngCore; -use rgb::invoice::{RgbBeneficiary, RgbInvoice}; -use rgb::popls::bp::file::{BpDirMound, DirBarrow}; -use rgb::popls::bp::{Coinselect, OpRequestSet, WalletProvider}; -use rgb::{ - Assignment, AuthToken, CellAddr, CodexId, Consensus, ContractId, ContractInfo, CreateParams, - EitherSeal, NamedState, RgbSealDef, StateAtom, StateCalc, -}; -use rgbp::{descriptor::RgbDescr, RgbDirRuntime, RgbWallet}; -use rgbp::{CoinselectStrategy, PayError}; -use rgpsbt::ScriptResolver; -use strict_types::value::{Blob, EnumTag, StrictNum}; -use strict_types::{FieldName, TypeName, VariantName}; - -use crate::utils::chain::fund_wallet; - -use super::chain::is_tx_confirmed; -use super::{ - chain::{indexer_url, mine_custom, Indexer, INDEXER}, - *, -}; - -use tabled::settings::{object::Columns, Alignment, Modify, Style}; -use tabled::{Table, Tabled}; - -/// RGB Asset creation parameters builder -#[derive(Clone)] -pub struct AssetParamsBuilder { - params: CreateParams, -} - -impl AssetParamsBuilder { - /// Create a new builder instance for non-inflatable asset - pub fn default_nia() -> Self { - Self { - params: Self::from_file(NON_INFLATABLE_ASSET_TEMPLATE_PATH), - } - } - - /// Create a new builder instance for fractional unique asset - pub fn default_fua() -> Self { - Self { - params: Self::from_file(FRACTIONAL_UNIQUE_ASSET_TEMPLATE_PATH), - } - } - - /// Create a new builder instance for fractionable asset collection - pub fn default_fac() -> Self { - Self { - params: Self::from_file(FRACTIONABLE_ASSET_COLLECTION_TEMPLATE_PATH), - } - } - - /// Load parameters from YAML file - pub fn from_file>(path: P) -> CreateParams { - let file = File::open(path).expect("Unable to open file"); - let params: CreateParams = - serde_yaml::from_reader::<_, CreateParams>(file).expect(""); - params - } - - /// Set the contract template ID - pub fn codex_id(mut self, codex_id: CodexId) -> Self { - self.params.codex_id = codex_id; - self - } - - /// Set the consensus type - pub fn consensus(mut self, consensus: Consensus) -> Self { - self.params.consensus = consensus; - self - } - - /// Set whether it is a test network - pub fn testnet(mut self, testnet: bool) -> Self { - self.params.testnet = testnet; - self - } - - /// Set the contract method name - pub fn method(mut self, method: &str) -> Self { - self.params.method = VariantName::from_str(method).unwrap(); - self - } - - /// Set the contract name - pub fn name(mut self, name: &str) -> Self { - self.params.name = TypeName::from_str(name).unwrap(); - self - } - - /// Update name state in global states - pub fn update_name_state(mut self, value: &str) -> Self { - if let Some(state) = self - .params - .global - .iter_mut() - .find(|s| s.name == "name".into()) - { - state.state.verified = value.into(); - } - self - } - - /// Update details state in global states - pub fn update_details_state(mut self, value: &str) -> Self { - if let Some(state) = self - .params - .global - .iter_mut() - .find(|s| s.name == "details".into()) - { - state.state.verified = StrictVal::Unit; - state.state.unverified = Some(value.into()); - } - self - } - - /// Update ticker state in global states - pub fn update_ticker_state(mut self, value: &str) -> Self { - if let Some(state) = self - .params - .global - .iter_mut() - .find(|s| s.name == "ticker".into()) - { - state.state.verified = value.into(); - } - self - } - - /// Update precision state in global states - pub fn update_precision_state(mut self, value: &str) -> Self { - if let Some(state) = self - .params - .global - .iter_mut() - .find(|s| s.name == "precision".into()) - { - state.state.verified = value.into(); - } - self - } - - /// Update circulating state in global states - /// circulating type is "RGBContract.Amount" eq u64 in rust - pub fn update_circulating_state(mut self, value: u64) -> Self { - if let Some(state) = self - .params - .global - .iter_mut() - .find(|s| s.name == "circulating".into()) - { - state.state.verified = value.into(); - } - self - } - - /// Update owned state - pub fn update_owned_state(mut self, seal: Outpoint, val: u64) -> Self { - // check if owned state exists - if let Some(state) = self - .params - .owned - .iter_mut() - .find(|s| s.name == "owned".into()) - { - // if exists, update seal and data - state.state.seal = EitherSeal::Alt(seal); - state.state.data = val.into(); - } else { - // if not exists, create a new owned state - self.params.owned.push(NamedState { - name: "owned".into(), - state: Assignment { - seal: EitherSeal::Alt(seal), - data: val.into(), - }, - }); - } - self - } - - pub fn clear_owned_state(mut self) -> Self { - self.params.owned.clear(); - self - } - - /// Add owned state - pub fn add_owned_state(mut self, seal: Outpoint, val: u64) -> Self { - self.params.owned.push(NamedState { - name: "amount".into(), - state: Assignment { - seal: EitherSeal::Alt(seal), - data: val.into(), - }, - }); - self - } - - /// Build CreateParams instance - pub fn build(self) -> CreateParams { - self.params - } -} - -pub struct TestWallet { - runtime: RgbDirRuntime, - descriptor: RgbDescr, - signer: Option, - wallet_dir: PathBuf, - instance: u8, - coinselect_strategy: CustomCoinselectStrategy, - /// Optional wallet identifier for reporting purposes - wallet_id: Option, -} +use super::*; enum WalletAccount { Private(XprivAccount), Public(XpubAccount), } +/// Test wallet structure type +pub struct TestWallet { + /// RGB runtime for wallet operations + pub runtime: RgbDirRuntime, + /// RGB descriptor for wallet + pub descriptor: RgbDescr, + /// Signer for transaction signing + pub signer: Option, + /// Wallet directory path + pub wallet_dir: PathBuf, + /// Bitcoin node instance number + pub instance: u8, + /// Custom coinselection strategy + pub coinselect_strategy: CustomCoinselectStrategy, + /// Optional wallet identifier for reporting purposes + pub wallet_id: Option, +} pub enum AllocationFilter { Stock, @@ -336,561 +118,52 @@ impl fmt::Display for AssetSchema { } } -/// Test metric type -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum MetricType { - /// Duration (milliseconds) - Duration, - /// Bytes value - Bytes, - /// Integer value - Integer, - /// Float value - Float, - /// Text value - Text, -} - -/// Test metric definition -#[derive(Debug, Clone)] -pub struct MetricDefinition { - /// Metric name - pub name: String, - /// Metric type - pub metric_type: MetricType, - /// Metric description - pub description: String, -} - -/// Test report structure -pub struct Report { - /// Report file path - pub report_path: PathBuf, - /// Metric definitions - metrics: Vec, - /// File handle - file: Option, - /// Buffer for rows - buffer: Vec, - /// Current row being built - current_row: HashMap, - /// Buffer flush threshold - flush_threshold: usize, -} - -/// Report error types -#[derive(Debug)] -pub enum ReportError { - /// IO error - Io(std::io::Error), - /// Format error - Format(String), - /// Metric error - Metric(String), -} - -impl From for ReportError { - fn from(err: std::io::Error) -> Self { - ReportError::Io(err) - } -} - -impl std::fmt::Display for ReportError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ReportError::Io(err) => write!(f, "IO error: {}", err), - ReportError::Format(msg) => write!(f, "Format error: {}", msg), - ReportError::Metric(msg) => write!(f, "Metric error: {}", msg), - } - } +/// Create a new wallet with the specified descriptor type +pub fn get_wallet(descriptor_type: &DescriptorType) -> TestWallet { + get_wallet_custom(descriptor_type, INSTANCE_1) } -impl std::error::Error for ReportError {} - -impl Report { - /// Create new report instance - pub fn new( - path: PathBuf, - metrics: Vec, - flush_threshold: Option, - ) -> Result { - let mut report = Self { - report_path: path, - metrics, - file: None, - buffer: Vec::new(), - current_row: HashMap::new(), - flush_threshold: flush_threshold.unwrap_or(10), - }; - - // Initialize report file - report.initialize()?; - - Ok(report) - } - - /// Initialize report file - fn initialize(&mut self) -> Result<(), ReportError> { - let headers: Vec = self.metrics.iter().map(|m| m.name.clone()).collect(); - - let file = OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open(&self.report_path)?; - - let mut file = file; - file.write_all(format!("{}\n", headers.join(";")).as_bytes())?; - - // Save file handle for subsequent use - self.file = Some(file); - - Ok(()) - } - - /// Get file handle - fn get_file(&mut self) -> Result<&mut File, ReportError> { - if self.file.is_none() { - let file = OpenOptions::new().append(true).open(&self.report_path)?; - - self.file = Some(file); - } - - Ok(self.file.as_mut().unwrap()) - } - - /// Add duration metric by name - pub fn add_duration(&mut self, name: &str, duration: Duration) -> Result<(), ReportError> { - self.check_metric_name_and_type(name, MetricType::Duration)?; - self.current_row - .insert(name.to_string(), duration.as_millis().to_string()); - Ok(()) - } - - /// Add bytes metric by name - pub fn add_bytes(&mut self, name: &str, value: u64) -> Result<(), ReportError> { - self.check_metric_name_and_type(name, MetricType::Bytes)?; - self.current_row.insert(name.to_string(), value.to_string()); - Ok(()) - } - - /// Add integer metric by name - pub fn add_integer(&mut self, name: &str, value: u64) -> Result<(), ReportError> { - self.check_metric_name_and_type(name, MetricType::Integer)?; - self.current_row.insert(name.to_string(), value.to_string()); - Ok(()) - } - - /// Add float metric by name - pub fn add_float(&mut self, name: &str, value: f64) -> Result<(), ReportError> { - self.check_metric_name_and_type(name, MetricType::Float)?; - self.current_row.insert(name.to_string(), value.to_string()); - Ok(()) - } - - /// Add text metric by name - pub fn add_text(&mut self, name: &str, value: &str) -> Result<(), ReportError> { - self.check_metric_name_and_type(name, MetricType::Text)?; - self.current_row.insert(name.to_string(), value.to_string()); - Ok(()) - } - - /// Add arbitrary type metric by name (auto conversion) - pub fn add_value(&mut self, name: &str, value: T) -> Result<(), ReportError> { - if !self.metrics.iter().any(|m| m.name == name) { - return Err(ReportError::Metric(format!( - "Metric name '{}' not found", - name - ))); - } - - self.current_row.insert(name.to_string(), value.to_string()); - Ok(()) - } - - /// Helper method to check if metric name exists and has correct type - fn check_metric_name_and_type( - &self, - name: &str, - expected_type: MetricType, - ) -> Result<(), ReportError> { - let metric = self.metrics.iter().find(|m| m.name == name); - - match metric { - Some(m) if m.metric_type == expected_type => Ok(()), - Some(m) => Err(ReportError::Metric(format!( - "Metric '{}' type mismatch, expected {:?}, actual {:?}", - name, expected_type, m.metric_type - ))), - None => Err(ReportError::Metric(format!( - "Metric name '{}' not found", - name - ))), - } - } - - /// Complete current row and add to buffer - pub fn end_row(&mut self) -> Result<(), ReportError> { - // Ensure all metrics have values - for metric in &self.metrics { - if !self.current_row.contains_key(&metric.name) { - self.current_row.insert(metric.name.clone(), String::new()); - } - } - - // Create row in the same order as metrics - let row = self - .metrics - .iter() - .map(|m| self.current_row.get(&m.name).cloned().unwrap_or_default()) - .collect::>() - .join(";"); - - self.buffer.push(row); - - // Clear current row for next use - self.current_row.clear(); - - // If buffer reaches threshold, flush to file - if self.buffer.len() >= self.flush_threshold { - self.flush_buffer()?; - } - - Ok(()) - } - - /// Write buffer content to file - pub fn flush_buffer(&mut self) -> Result<(), ReportError> { - if self.buffer.is_empty() { - return Ok(()); - } - - // Clone buffer contents to avoid borrow conflict - let buffer_contents = self.buffer.clone(); - let file = self.get_file()?; - - for row in buffer_contents.iter() { - file.write_all(format!("{}\n", row).as_bytes())?; - } - - self.buffer.clear(); - - Ok(()) - } - - /// Generate summary statistics - pub fn generate_summary(&mut self) -> Result { - // Ensure all data is written to file - self.flush_buffer()?; - - // Read CSV file - let content = std::fs::read_to_string(&self.report_path)?; - let lines: Vec<&str> = content.lines().collect(); - - if lines.is_empty() { - return Err(ReportError::Format("CSV file is empty".to_string())); - } - - // Parse headers - let headers: Vec<&str> = lines[0].split(';').collect(); - - // Prepare data structure - let mut data: Vec> = vec![Vec::new(); headers.len()]; - - // Parse data rows - for line in lines.iter().skip(1) { - let values: Vec<&str> = line.split(';').collect(); - for (i, value) in values.iter().enumerate() { - if i >= headers.len() { - break; - } - - if let Ok(num) = value.parse::() { - data[i].push(num); - } - } - } - - #[derive(Tabled)] - struct MetricSummary { - #[tabled(rename = "Metric")] - metric: String, - #[tabled(rename = "Average")] - average: String, - #[tabled(rename = "Minimum")] - minimum: String, - #[tabled(rename = "Maximum")] - maximum: String, - #[tabled(rename = "Sample Count")] - count: String, - } - - let mut summaries = Vec::new(); - - for (i, header) in headers.iter().enumerate() { - if data[i].is_empty() { - continue; - } - - let values = &data[i]; - let avg = values.iter().sum::() / values.len() as f64; - let min = values.iter().fold(f64::INFINITY, |a, &b| a.min(b)); - let max = values.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b)); - - // Format output based on metric type - let metric_type = if i < self.metrics.len() { - self.metrics[i].metric_type - } else { - MetricType::Float - }; - - let (avg_str, min_str, max_str) = match metric_type { - MetricType::Duration => ( - format!("{:.2} ms", avg), - format!("{:.2} ms", min), - format!("{:.2} ms", max), - ), - MetricType::Bytes => ( - format!("{:.2} B", avg), - format!("{:.2} B", min), - format!("{:.2} B", max), - ), - MetricType::Integer | MetricType::Float => ( - format!("{:.2}", avg), - format!("{:.2}", min), - format!("{:.2}", max), - ), - MetricType::Text => ("-".to_string(), "-".to_string(), "-".to_string()), - }; - - summaries.push(MetricSummary { - metric: header.to_string(), - average: avg_str, - minimum: min_str, - maximum: max_str, - count: values.len().to_string(), - }); - } - - // Create the table and style it - let mut table = Table::new(summaries); - table - .with(Style::markdown()) - .with(Modify::new(Columns::new(1..)).with(Alignment::right())); - - // Generate the final Markdown output - let mut summary = String::new(); - summary.push_str("# Performance Test Summary\n\n"); - summary.push_str(&table.to_string()); - - Ok(summary) - } - - /// Save summary statistics to file - pub fn save_summary(&mut self, name: &str) -> Result { - let summary = self.generate_summary()?; - - let summary_path = self - .report_path - .clone() - .with_file_name(format!("{}.md", name)); - - let mut file = std::fs::File::create(&summary_path)?; - file.write_all(summary.as_bytes())?; - - Ok(summary_path) - } - - /// Generate chart data - pub fn generate_chart_data(&mut self) -> Result { - // Ensure all data is written to file - self.flush_buffer()?; - - // Read CSV file - let content = std::fs::read_to_string(&self.report_path)?; - let lines: Vec<&str> = content.lines().collect(); - - if lines.is_empty() { - return Err(ReportError::Format("CSV file is empty".to_string())); - } - - // Parse headers - let headers: Vec<&str> = lines[0].split(';').collect(); - - // Prepare data structure - let mut data: Vec> = vec![Vec::new(); headers.len()]; - - // Parse data rows - for line in lines.iter().skip(1) { - let values: Vec<&str> = line.split(';').collect(); - for (i, value) in values.iter().enumerate() { - if i >= headers.len() { - break; - } - - if let Ok(num) = value.parse::() { - data[i].push(num); - } - } - } - - // Generate JSON - let mut json = String::from("{\n"); - - for (i, header) in headers.iter().enumerate() { - if i > 0 { - json.push_str(",\n"); - } - - json.push_str(&format!(" \"{}\": [", header)); - - for (j, value) in data[i].iter().enumerate() { - if j > 0 { - json.push_str(", "); - } - json.push_str(&format!("{}", value)); - } - - json.push(']'); - } - - json.push_str("\n}"); - - // Save JSON - let mut chart_path = self.report_path.clone(); - chart_path.set_extension("json"); - - let mut file = std::fs::File::create(&chart_path)?; - file.write_all(json.as_bytes())?; - - Ok(chart_path) - } - - /// Ensure all data is written on drop - pub fn finalize(&mut self) -> Result<(), ReportError> { - self.flush_buffer() - } - - /// For backward compatibility - pub fn write_header(&self, _fields: &[&str]) { - // Do nothing, headers are now defined by metrics - } - - /// For backward compatibility - pub fn write_duration(&self, _duration: Duration) { - // Do nothing, use add_duration instead - } - - /// For backward compatibility - pub fn write_value(&self, _value: T) { - // Do nothing, use add_value instead - } - - /// For backward compatibility - pub fn end_line(&self) { - // Do nothing, use end_row instead - } -} +/// Create a new wallet with the specified descriptor type and instance +pub fn get_wallet_custom(descriptor_type: &DescriptorType, instance: u8) -> TestWallet { + let mut seed = vec![0u8; 128]; + rand::thread_rng().fill_bytes(&mut seed); -impl Drop for Report { - fn drop(&mut self) { - // Try to flush buffer, ignore errors - let _ = self.flush_buffer(); - } -} + let xpriv_account = XprivAccount::with_seed(true, &seed).derive(h![86, 1, 0]); -/// Custom RGB coinselection strategy for more precise control over UTXO selection -/// -/// # Usage Example -/// -/// ``` -/// // Create wallet -/// let mut wallet = get_wallet(&DescriptorType::Wpkh); -/// -/// // Set to true small size strategy (selects UTXOs with maximum values) -/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::TrueSmallSize); -/// -/// // Or use standard strategies -/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::Standard(CoinselectStrategy::Aggregate)); -/// wallet.set_coinselect_strategy(CustomCoinselectStrategy::Standard(CoinselectStrategy::SmallSize)); -/// -/// // For transfers requiring specific UTXOs (like testing reorganization history), use: -/// let (consignment, tx) = wallet.transfer_with_specific_utxo(invoice, specific_utxo, sats, fee, broadcast, report); -/// ``` -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum CustomCoinselectStrategy { - /// Use standard RGB coinselection strategies - /// - Aggregate: Collects many small outputs until target amount is reached - /// - SmallSize: Collects minimum number of outputs but without proper value sorting - Standard(CoinselectStrategy), - - /// Enhanced coinselection strategy that truly minimizes transaction size - /// by selecting the minimum number of UTXOs with largest asset values. - /// This strategy: - /// 1. First sorts all available colored UTXOs by their asset amount - /// 2. Selects the minimum number of largest-value UTXOs needed to satisfy the transfer - /// 3. Results in smallest possible transaction size by using fewer inputs - TrueSmallSize, -} + let fingerprint = xpriv_account.account_fp().to_string(); + let wallet_dir = PathBuf::from(TEST_DATA_DIR) + .join(INTEGRATION_DATA_DIR) + .join(fingerprint); -impl Default for CustomCoinselectStrategy { - fn default() -> Self { - Self::Standard(CoinselectStrategy::default()) - } + _get_wallet( + descriptor_type, + Network::Regtest, + wallet_dir, + WalletAccount::Private(xpriv_account), + instance, + ) } -/// Implementation of the Coinselect trait for our custom strategy -impl Coinselect for CustomCoinselectStrategy { - fn coinselect( - &mut self, - invoiced_state: &StrictVal, - calc: &mut (impl StateCalc + ?Sized), - // Sorted vector by values - owned_state: Vec<(CellAddr, &StrictVal)>, - ) -> Option> { - match self { - // For standard strategies, delegate to the original implementation - CustomCoinselectStrategy::Standard(strategy) => { - strategy.coinselect(invoiced_state, calc, owned_state) - } - - // True small size implementation - sort by value before selection - CustomCoinselectStrategy::TrueSmallSize => { - // Clone the state to allow sorting (we need to own the data) - let mut value_sorted_state: Vec<(CellAddr, &StrictVal, u64)> = owned_state - .iter() - .filter_map(|(addr, val)| { - // Extract numeric value (assuming we're dealing with u64 values) - let amount: u64 = val.unwrap_num().unwrap_uint(); - Some((*addr, *val, amount)) - }) - .collect(); - - // Sort by value in descending order (largest first) - value_sorted_state.sort_by(|a, b| b.2.cmp(&a.2)); - - // Now use the sorted state for iteration - let res = value_sorted_state - .into_iter() - .take_while(|(_, val, _)| { - if calc.is_satisfied(invoiced_state) { - return false; - } - calc.accumulate(val).is_ok() - }) - .map(|(addr, _, _)| addr) - .collect(); +/// Create a wallet for mainnet (using predefined public keys) +pub fn get_mainnet_wallet() -> TestWallet { + let xpub_account = XpubAccount::from_str( + "[c32338a7/86h/0h/0h]xpub6CmiK1xc7YwL472qm4zxeURFX8yMCSasioXujBjVMMzA3AKZr6KLQEmkzDge1Ezn2p43ZUysyx6gfajFVVnhtQ1AwbXEHrioLioXXgj2xW5" + ).unwrap(); - if !calc.is_satisfied(invoiced_state) { - return None; - }; + let wallet_dir = PathBuf::from(TEST_DATA_DIR) + .join(INTEGRATION_DATA_DIR) + .join("mainnet"); - Some(res) - } - } - } + _get_wallet( + &DescriptorType::Wpkh, + Network::Mainnet, + wallet_dir, + WalletAccount::Public(xpub_account), + INSTANCE_1, + ) } +/// Internal wallet creation function fn _get_wallet( descriptor_type: &DescriptorType, network: Network, @@ -957,6 +230,7 @@ fn _get_wallet( test_wallet } +/// Create a runtime for the wallet fn make_runtime(descriptor: &RgbDescr, network: Network, wallet_dir: &PathBuf) -> RgbDirRuntime { let name = "bp_wallet.wallet"; let provider = FsTextStore::new(wallet_dir.join(name)).unwrap(); @@ -967,48 +241,7 @@ fn make_runtime(descriptor: &RgbDescr, network: Network, wallet_dir: &PathBuf) - RgbDirRuntime::from(DirBarrow::with(wallet, mound)) } -pub fn get_wallet(descriptor_type: &DescriptorType) -> TestWallet { - get_wallet_custom(descriptor_type, INSTANCE_1) -} - -pub fn get_wallet_custom(descriptor_type: &DescriptorType, instance: u8) -> TestWallet { - let mut seed = vec![0u8; 128]; - rand::thread_rng().fill_bytes(&mut seed); - - let xpriv_account = XprivAccount::with_seed(true, &seed).derive(h![86, 1, 0]); - - let fingerprint = xpriv_account.account_fp().to_string(); - let wallet_dir = PathBuf::from(TEST_DATA_DIR) - .join(INTEGRATION_DATA_DIR) - .join(fingerprint); - - _get_wallet( - descriptor_type, - Network::Regtest, - wallet_dir, - WalletAccount::Private(xpriv_account), - instance, - ) -} - -pub fn get_mainnet_wallet() -> TestWallet { - let xpub_account = XpubAccount::from_str( - "[c32338a7/86h/0h/0h]xpub6CmiK1xc7YwL472qm4zxeURFX8yMCSasioXujBjVMMzA3AKZr6KLQEmkzDge1Ezn2p43ZUysyx6gfajFVVnhtQ1AwbXEHrioLioXXgj2xW5" - ).unwrap(); - - let wallet_dir = PathBuf::from(TEST_DATA_DIR) - .join(INTEGRATION_DATA_DIR) - .join("mainnet"); - - _get_wallet( - &DescriptorType::Wpkh, - Network::Mainnet, - wallet_dir, - WalletAccount::Public(xpub_account), - INSTANCE_1, - ) -} - +/// Get an indexer instance fn get_indexer(indexer_url: &str) -> AnyIndexer { match INDEXER.get().unwrap() { Indexer::Electrum => { @@ -1020,6 +253,7 @@ fn get_indexer(indexer_url: &str) -> AnyIndexer { } } +/// Broadcast a transaction fn broadcast_tx(tx: &Tx, indexer_url: &str) { match get_indexer(indexer_url) { AnyIndexer::Electrum(inner) => { @@ -1040,6 +274,7 @@ fn broadcast_tx(tx: &Tx, indexer_url: &str) { } } +/// Broadcast a transaction and mine a block pub fn broadcast_tx_and_mine(tx: &Tx, instance: u8) { broadcast_tx(tx, &indexer_url(instance, Network::Regtest)); mine_custom(false, instance, 1); @@ -1096,11 +331,45 @@ impl TestWallet { self.instance = instance; } - // TODO: Dr. Maxim mentioned in the meeting that - // He will support rollback state related APIs in the reorg and rbf scenarios - // Because it is not implemented at the moment, only sync is included for now - pub fn sync_and_rollback_state(&mut self) { - self.sync(); + // TODO: Dr. Maxim mentioned in the meeting that + // He will support rollback state related APIs in the reorg and rbf scenarios + // Because it is not implemented at the moment, only sync is included for now + pub fn sync_and_rollback_state(&mut self) { + self.sync(); + } + + pub fn issue_nia_with_params(&mut self, params: NIAIssueParams) -> ContractId { + let mut builder: AssetParamsBuilder = AssetParamsBuilder::default_nia() + .name(params.name.as_str()) + .update_name_state(params.name.as_str()) + .update_ticker_state(params.ticker.as_str()) + .update_precision_state(params.precision.as_str()) + .update_circulating_state(params.circulating_supply) + .clear_owned_state(); + + for (outpoint, amount) in params.initial_allocations { + builder = builder.add_owned_state(outpoint, amount); + } + + self.issue_with_params(builder.build()) + } + + /// Issue a FUA contract with custom parameters + pub fn issue_fua_with_params(&mut self, params: FUAIssueParams) -> ContractId { + let mut builder = AssetParamsBuilder::default_fua() + .name(params.name.as_str()) + .update_name_state(params.name.as_str()) + .update_details_state(params.details.as_str()) + .update_precision_state(params.precision.as_str()) + .update_circulating_state(params.circulating_supply) + .clear_owned_state(); + + // Add initial allocations + for (outpoint, amount) in params.initial_allocations { + builder = builder.add_owned_state(outpoint, amount); + } + + self.issue_with_params(dbg!(builder.build())) } pub fn switch_to_instance(&mut self, instance: u8) { @@ -1180,6 +449,33 @@ impl TestWallet { } } + /// Generates a noise engine for seal randomization + /// This is a clone of the internal noise_engine implementation from rgb-std, + /// since the original is not public and we need it for custom UTXO selection + fn noise_engine(&self) -> Sha256 { + let noise_seed = self.runtime.wallet.noise_seed(); + let mut noise_engine = Sha256::new(); + noise_engine.input_raw(noise_seed.as_ref()); + noise_engine + } + + /// Creates an auth token for a specific UTXO + /// + /// This is a custom implementation that allows specifying the UTXO to use, + /// unlike the standard rgb-std auth_token which automatically selects a UTXO. + /// We need this to support custom UTXO selection for auth tokens. + pub fn create_auth_token_with_utxo( + &mut self, + nonce: Option, + outpoint: Outpoint, + ) -> Option { + let nonce = nonce.unwrap_or_else(|| self.runtime.wallet.next_nonce()); + let seal = WTxoSeal::no_fallback(outpoint, self.noise_engine(), nonce); + let auth = seal.auth_token(); + self.runtime.wallet.register_seal(seal); + Some(auth) + } + /// Creates an RGB invoice with either a witness output or auth token beneficiary /// /// # Arguments @@ -1213,31 +509,69 @@ impl TestWallet { RgbInvoice::new(contract_id, beneficiary, Some(value)) } - /// Generates a noise engine for seal randomization - /// This is a clone of the internal noise_engine implementation from rgb-std, - /// since the original is not public and we need it for custom UTXO selection - fn noise_engine(&self) -> Sha256 { - let noise_seed = self.runtime.wallet.noise_seed(); - let mut noise_engine = Sha256::new(); - noise_engine.input_raw(noise_seed.as_ref()); - noise_engine + /// Set the coin selection strategy + pub fn set_coinselect_strategy(&mut self, strategy: CustomCoinselectStrategy) -> &mut Self { + self.coinselect_strategy = strategy; + self } - /// Creates an auth token for a specific UTXO - /// - /// This is a custom implementation that allows specifying the UTXO to use, - /// unlike the standard rgb-std auth_token which automatically selects a UTXO. - /// We need this to support custom UTXO selection for auth tokens. - pub fn create_auth_token_with_utxo( + /// Get the current coin selection strategy + pub fn coinselect_strategy(&self) -> CustomCoinselectStrategy { + self.coinselect_strategy + } + + /// Set wallet identifier for reporting purposes + pub fn with_id(mut self, id: impl Into) -> Self { + self.wallet_id = Some(id.into()); + self + } + + /// Get wallet identifier, or a default if not set + pub fn wallet_id(&self) -> String { + self.wallet_id + .clone() + .unwrap_or_else(|| format!("wallet_{}", self.instance)) + } + + pub fn sign_finalize(&self, psbt: &mut Psbt) { + let _sig_count = psbt.sign(self.signer.as_ref().unwrap()).unwrap(); + psbt.finalize(self.runtime.wallet.descriptor()); + } + + pub fn sign_finalize_extract(&self, psbt: &mut Psbt) -> Tx { + self.sign_finalize(psbt); + psbt.extract().unwrap() + } + + pub fn check_allocations( &mut self, - nonce: Option, - outpoint: Outpoint, - ) -> Option { - let nonce = nonce.unwrap_or_else(|| self.runtime.wallet.next_nonce()); - let seal = WTxoSeal::no_fallback(outpoint, self.noise_engine(), nonce); - let auth = seal.auth_token(); - self.runtime.wallet.register_seal(seal); - Some(auth) + contract_id: ContractId, + asset_schema: AssetSchema, + mut expected_fungible_allocations: Vec, + ) { + let allocation_field = match asset_schema { + AssetSchema::RGB20 | AssetSchema::RGB25 => { + // For fungible assets, we need to check the "amount" allocation + "amount" + } + AssetSchema::RGB21 => { + // for RGB21, we need to check the "fractions" allocation + "fractions" + } + }; + + let state = self.runtime.state_own(Some(contract_id)).next().unwrap().1; + + let mut actual_fungible_allocations = state + .owned + .get(allocation_field) + .unwrap() + .iter() + .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) + .collect::>(); + actual_fungible_allocations.sort(); + expected_fungible_allocations.sort(); + assert_eq!(actual_fungible_allocations, expected_fungible_allocations); } pub fn send( @@ -1388,179 +722,9 @@ impl TestWallet { } Ok(()) } - - pub fn check_allocations( - &mut self, - contract_id: ContractId, - asset_schema: AssetSchema, - mut expected_fungible_allocations: Vec, - ) { - let allocation_field = match asset_schema { - AssetSchema::RGB20 | AssetSchema::RGB25 => { - // For fungible assets, we need to check the "amount" allocation - "amount" - } - AssetSchema::RGB21 => { - // for RGB21, we need to check the "fractions" allocation - "fractions" - } - }; - - let state = self.runtime.state_own(Some(contract_id)).next().unwrap().1; - - let mut actual_fungible_allocations = state - .owned - .get(allocation_field) - .unwrap() - .iter() - .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) - .collect::>(); - actual_fungible_allocations.sort(); - expected_fungible_allocations.sort(); - assert_eq!(actual_fungible_allocations, expected_fungible_allocations); - } - - pub fn sign_finalize(&self, psbt: &mut Psbt) { - let _sig_count = psbt.sign(self.signer.as_ref().unwrap()).unwrap(); - psbt.finalize(self.runtime.wallet.descriptor()); - } - - pub fn sign_finalize_extract(&self, psbt: &mut Psbt) -> Tx { - self.sign_finalize(psbt); - psbt.extract().unwrap() - } - - /// Set the coin selection strategy - pub fn set_coinselect_strategy(&mut self, strategy: CustomCoinselectStrategy) -> &mut Self { - self.coinselect_strategy = strategy; - self - } - - /// Get the current coin selection strategy - pub fn coinselect_strategy(&self) -> CustomCoinselectStrategy { - self.coinselect_strategy - } - - /// Set wallet identifier for reporting purposes - pub fn with_id(mut self, id: impl Into) -> Self { - self.wallet_id = Some(id.into()); - self - } - - /// Get wallet identifier, or a default if not set - pub fn wallet_id(&self) -> String { - self.wallet_id - .clone() - .unwrap_or_else(|| format!("wallet_{}", self.instance)) - } -} - -/// Parameters for NIA (Non-Inflatable Asset) issuance -#[derive(Clone)] -pub struct NIAIssueParams { - pub name: String, - pub ticker: String, - pub precision: String, - pub circulating_supply: u64, - pub initial_allocations: Vec<(Outpoint, u64)>, -} - -impl Default for NIAIssueParams { - fn default() -> Self { - Self { - name: "USD Tether".to_string(), - ticker: "USDT".to_string(), - precision: "centiMilli".to_string(), - circulating_supply: 1_000_000, - initial_allocations: vec![], - } - } -} - -impl NIAIssueParams { - pub fn new( - name: impl Into, - ticker: impl Into, - precision: impl Into, - circulating_supply: u64, - ) -> Self { - Self { - name: name.into(), - ticker: ticker.into(), - precision: precision.into(), - circulating_supply, - initial_allocations: vec![], - } - } - - pub fn add_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { - self.initial_allocations.push((outpoint, amount)); - self - } -} - -/// RGB Contract State representation -#[derive(Debug)] -pub struct ContractState { - /// Immutable state of the contract - pub immutable: ContractImmutableState, - /// Ownership state of the contract - pub owned: ContractOwnedState, -} - -/// Contract's immutable state -#[derive(Debug)] -pub struct ContractImmutableState { - pub name: String, - pub ticker: String, - pub precision: String, - pub circulating_supply: u64, -} - -/// Contract's ownership state -#[derive(Debug)] -pub struct ContractOwnedState { - pub allocations: Vec<(Outpoint, u64)>, } impl TestWallet { - pub fn issue_nia_with_params(&mut self, params: NIAIssueParams) -> ContractId { - let mut builder: AssetParamsBuilder = AssetParamsBuilder::default_nia() - .name(params.name.as_str()) - .update_name_state(params.name.as_str()) - .update_ticker_state(params.ticker.as_str()) - .update_precision_state(params.precision.as_str()) - .update_circulating_state(params.circulating_supply) - .clear_owned_state(); - - for (outpoint, amount) in params.initial_allocations { - builder = builder.add_owned_state(outpoint, amount); - } - - self.issue_with_params(builder.build()) - } - - /// Get contract state (internal implementation) - fn contract_state_internal( - &mut self, - contract_id: ContractId, - ) -> Option<( - BTreeMap>, - BTreeMap>>, - BTreeMap, - )> { - self.runtime() - .state_all(Some(contract_id)) - .next() - .map(|(_, state)| { - ( - state.immutable.clone(), - state.owned.clone(), - state.computed.clone(), - ) - }) - } - /// Get contract state with parsed data structures pub fn contract_state(&mut self, contract_id: ContractId) -> Option { self.contract_state_internal(contract_id) @@ -1622,177 +786,143 @@ impl TestWallet { } }) } + /// Get contract state (internal implementation) + fn contract_state_internal( + &mut self, + contract_id: ContractId, + ) -> Option<( + BTreeMap>, + BTreeMap>>, + BTreeMap, + )> { + self.runtime() + .state_all(Some(contract_id)) + .next() + .map(|(_, state)| { + ( + state.immutable.clone(), + state.owned.clone(), + state.computed.clone(), + ) + }) + } } -/// Parameters for FUA (Fractional unique asset) issuance -#[derive(Clone)] -pub struct FUAIssueParams { - /// Asset name +/// Immutable state part of RGB21 contract +#[derive(Debug, Clone)] +pub struct RGB21ContractImmutableState { pub name: String, - /// Asset details - pub details: String, - /// Decimal precision for the asset - pub precision: String, - /// Total circulating supply - pub circulating_supply: u64, - /// Initial token allocations (outpoint, amount) - pub initial_allocations: Vec<(Outpoint, u64)>, + pub total_fractions: u64, + pub token: Option, } -impl Default for FUAIssueParams { - fn default() -> Self { - Self { - name: "DemoFUA".to_string(), - details: "Demo FUA details".to_string(), - precision: "centiMilli".to_string(), - circulating_supply: 10_000, - initial_allocations: vec![], - } - } +/// NFT metadata in RGB21 contract +#[derive(Debug, Clone)] +pub struct NFTMetadata { + pub index: u32, + pub amount: u64, + pub ticker: Option, + pub name: Option, + pub details: Option, + pub preview: Option, + pub media: Option, + pub attachments: BTreeMap, + pub reserves: Option, } -impl FUAIssueParams { - /// Create new CFA issuance parameters - pub fn new( - name: impl Into, - details: impl Into, - precision: impl Into, - circulating_supply: u64, - ) -> Self { - Self { - name: name.into(), - details: details.into(), - precision: precision.into(), - circulating_supply, - initial_allocations: vec![], - } - } +/// Media data with full content +#[derive(Debug, Clone)] +pub struct MediaData { + pub media_type: MediaTypeData, + pub data: Vec, +} - /// Add a token allocation - pub fn add_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { - self.initial_allocations.push((outpoint, amount)); - self - } +/// Media type information +#[derive(Debug, Clone)] +pub struct MediaTypeData { + pub r#type: String, + pub subtype: Option, + pub charset: Option, } -impl TestWallet { - /// Issue a FUA contract with custom parameters - pub fn issue_fua_with_params(&mut self, params: FUAIssueParams) -> ContractId { - let mut builder = AssetParamsBuilder::default_fua() - .name(params.name.as_str()) - .update_name_state(params.name.as_str()) - .update_details_state(params.details.as_str()) - .update_precision_state(params.precision.as_str()) - .update_circulating_state(params.circulating_supply) - .clear_owned_state(); +/// Media digest (reference only) +#[derive(Debug, Clone)] +pub struct MediaDigest { + pub media_type: MediaTypeData, + pub digest: Vec, +} - // Add initial allocations - for (outpoint, amount) in params.initial_allocations { - builder = builder.add_owned_state(outpoint, amount); - } +/// Reserve proof data +#[derive(Debug, Clone)] +pub struct ReserveData { + pub utxo: Outpoint, + pub proof: Vec, +} - self.issue_with_params(dbg!(builder.build())) - } +/// Owned state part of RGB21 contract +#[derive(Debug, Clone)] +pub struct RGB21ContractOwnedState { + pub fractions: Vec<(Outpoint, u64)>, // (outpoint, amount) } -/// Parameters for FAC (Fractionable Asset Collection) issuance -#[derive(Clone)] -pub struct FACIssueParams { - /// Collection name - pub name: String, - /// Collection details - pub details: String, - /// Total number of fractions - pub total_fractions: u64, - /// Token index - pub index: u32, - /// Initial token allocation (outpoint, amount) - pub initial_allocation: Option<(Outpoint, u64)>, - /// NFT specification - pub nft_spec: Option, +/// Complete RGB21 contract state +#[derive(Debug, Clone)] +pub struct RGB21ContractState { + pub immutable: RGB21ContractImmutableState, + pub owned: RGB21ContractOwnedState, } -impl Default for FACIssueParams { - fn default() -> Self { - Self { - name: "FAC".to_string(), - details: "Demo FAC details".to_string(), - total_fractions: 10_000, - index: UDA_FIXED_INDEX, - initial_allocation: None, - nft_spec: None, +/// Extract the first element from a tuple +fn extract_from_tuple(v: &StrictVal) -> Option { + if let StrictVal::Tuple(s) = v { + if !s.is_empty() { + Some(s[0].clone()) + } else { + None } + } else { + None } } -impl FACIssueParams { - /// Create new FAC issuance parameters - pub fn new(name: impl Into, details: impl Into, total_fractions: u64) -> Self { - Self { - name: name.into(), - details: details.into(), - index: UDA_FIXED_INDEX, - total_fractions, - initial_allocation: None, - nft_spec: None, +/// Extract the first element from a two-layer tuple +fn extract_from_2_layer_tuple(v: &StrictVal) -> Option { + if let StrictVal::Tuple(t) = v { + if let Some(inner) = t.get(0) { + extract_from_tuple(inner) + } else { + None } - } - - /// Set token allocation - pub fn with_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { - self.initial_allocation = Some((outpoint, amount)); - self - } - - /// Set NFT specification - pub fn with_nft_spec(&mut self, nft_spec: NftSpec) -> &mut Self { - self.nft_spec = Some(nft_spec); - self + } else { + None } } -fn nft_spec_minimal() -> NftSpec { - NftSpec { - index: TokenIndex::from(UDA_FIXED_INDEX), - ..Default::default() +/// Extract value from Union (for Option type) +fn extract_from_union(v: &StrictVal) -> Option { + if let StrictVal::Union(tag, t) = v { + if let EnumTag::Name(name) = tag { + if ***name == "some" { + Some(t.as_ref().clone()) + } else { + None + } + } else { + None + } + } else { + None } } -pub fn nft_spec( - ticker: &str, - name: &str, - details: &str, - preview: EmbeddedMedia, - media: Attachment, - attachments: BTreeMap, - reserves: ProofOfReserves, -) -> NftSpec { - let mut nft_spec = nft_spec_minimal(); - nft_spec.preview = Some(preview); - nft_spec.media = Some(media); - nft_spec.attachments = Confined::try_from(attachments.clone()).unwrap(); - nft_spec.reserves = Some(reserves); - nft_spec.ticker = Some(Ticker::try_from(ticker.to_string()).unwrap()); - nft_spec.name = Some(AssetName::try_from(name.to_string()).unwrap()); - nft_spec.details = Some(Details::from_str(details).unwrap()); - nft_spec +/// Extract value from Union and single-layer Tuple +fn extract_from_union_and_tuple(v: &StrictVal) -> Option { + extract_from_union(v).and_then(|s| extract_from_tuple(&s)) } -// Function to create a file attachment from a file path -pub fn attachment_from_fpath(fpath: &str) -> Attachment { - let file_bytes = std::fs::read(fpath).unwrap(); - let file_hash: sha256::Hash = Hash::hash(&file_bytes[..]); - let digest = file_hash.to_byte_array().into(); - let mime = FileFormat::from_file(fpath) - .unwrap() - .media_type() - .to_string(); - let media_ty: &'static str = Box::leak(mime.clone().into_boxed_str()); - let media_type = MediaType::with(media_ty); - Attachment { - ty: media_type, - digest, - } +/// Extract value from Union and two-layer Tuple +fn extract_from_union_and_2_layer_tuple(v: &StrictVal) -> Option { + extract_from_union(v).and_then(|s| extract_from_2_layer_tuple(&s)) } impl TestWallet { @@ -2073,126 +1203,7 @@ impl TestWallet { let contract_id = self.issue_with_params(create_params); contract_id } -} - -/// Immutable state part of RGB21 contract -#[derive(Debug, Clone)] -pub struct RGB21ContractImmutableState { - pub name: String, - pub total_fractions: u64, - pub token: Option, -} - -/// NFT metadata in RGB21 contract -#[derive(Debug, Clone)] -pub struct NFTMetadata { - pub index: u32, - pub amount: u64, - pub ticker: Option, - pub name: Option, - pub details: Option, - pub preview: Option, - pub media: Option, - pub attachments: BTreeMap, - pub reserves: Option, -} - -/// Media data with full content -#[derive(Debug, Clone)] -pub struct MediaData { - pub media_type: MediaTypeData, - pub data: Vec, -} - -/// Media type information -#[derive(Debug, Clone)] -pub struct MediaTypeData { - pub r#type: String, - pub subtype: Option, - pub charset: Option, -} - -/// Media digest (reference only) -#[derive(Debug, Clone)] -pub struct MediaDigest { - pub media_type: MediaTypeData, - pub digest: Vec, -} - -/// Reserve proof data -#[derive(Debug, Clone)] -pub struct ReserveData { - pub utxo: Outpoint, - pub proof: Vec, -} - -/// Owned state part of RGB21 contract -#[derive(Debug, Clone)] -pub struct RGB21ContractOwnedState { - pub fractions: Vec<(Outpoint, u64)>, // (outpoint, amount) -} - -/// Complete RGB21 contract state -#[derive(Debug, Clone)] -pub struct RGB21ContractState { - pub immutable: RGB21ContractImmutableState, - pub owned: RGB21ContractOwnedState, -} - -/// Extract the first element from a tuple -fn extract_from_tuple(v: &StrictVal) -> Option { - if let StrictVal::Tuple(s) = v { - if !s.is_empty() { - Some(s[0].clone()) - } else { - None - } - } else { - None - } -} - -/// Extract the first element from a two-layer tuple -fn extract_from_2_layer_tuple(v: &StrictVal) -> Option { - if let StrictVal::Tuple(t) = v { - if let Some(inner) = t.get(0) { - extract_from_tuple(inner) - } else { - None - } - } else { - None - } -} - -/// Extract value from Union (for Option type) -fn extract_from_union(v: &StrictVal) -> Option { - if let StrictVal::Union(tag, t) = v { - if let EnumTag::Name(name) = tag { - if ***name == "some" { - Some(t.as_ref().clone()) - } else { - None - } - } else { - None - } - } else { - None - } -} - -/// Extract value from Union and single-layer Tuple -fn extract_from_union_and_tuple(v: &StrictVal) -> Option { - extract_from_union(v).and_then(|s| extract_from_tuple(&s)) -} - -/// Extract value from Union and two-layer Tuple -fn extract_from_union_and_2_layer_tuple(v: &StrictVal) -> Option { - extract_from_union(v).and_then(|s| extract_from_2_layer_tuple(&s)) -} -impl TestWallet { /// Get RGB21 contract state pub fn contract_state_rgb21(&mut self, contract_id: ContractId) -> Option { self.contract_state_internal(contract_id) diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 085477a..6a9bcdf 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -1,6 +1,6 @@ pub mod chain; pub mod consignment_utils; -pub mod helpers; +pub mod helper; pub const TEST_DATA_DIR: &str = "test-data"; pub const SCHEMATA_DIR: &str = "tests/templates/schemata"; @@ -33,13 +33,17 @@ pub use std::{ env::VarError, ffi::OsString, fmt::{self, Display}, - fs::OpenOptions, + fs::{File, OpenOptions}, io::Write, num::NonZeroU32, - path::{PathBuf, MAIN_SEPARATOR}, + ops::Deref, + path::{Path, PathBuf, MAIN_SEPARATOR}, process::{Command, Stdio}, str::FromStr, - sync::{Mutex, Once, OnceLock, RwLock}, + sync::{ + atomic::{AtomicU32, Ordering}, + Mutex, Once, OnceLock, RwLock, + }, time::{Duration, Instant}, }; @@ -48,16 +52,9 @@ pub use amplify::{ confinement::{Confined, U16}, map, s, ByteArray, Wrapper, }; +pub use bitcoin_hashes::{sha256, Hash}; pub use bp::{ - // seals::txout::{BlindSeal, CloseMethod, ExplicitSeal}, - ConsensusDecode, - Outpoint, - Sats, - ScriptPubkey, - SeqNo, - Tx, - Txid, - Vout, + seals::WTxoSeal, ConsensusDecode, Outpoint, Sats, ScriptPubkey, SeqNo, Tx, Txid, Vout, }; pub use bpstd::{ h, signers::TestnetSigner, Address, DerivationPath, DerivationSeg, DerivedAddr, Descriptor, @@ -68,61 +65,60 @@ pub use bpwallet::{ fs::FsTextStore, indexers::esplora::Client as EsploraClient, AnyIndexer, Indexer as BpIndexer, Wallet, }; +pub use commit_verify::{Digest, DigestExt, Sha256}; pub use descriptors::Wpkh; pub use electrum::{Client as ElectrumClient, ElectrumApi, Param}; pub use file_format::FileFormat; -// pub use ifaces::{ -// rgb20, rgb21, -// rgb21::{EmbeddedMedia, TokenData}, -// rgb25, IssuerWrapper, Rgb20, Rgb21, Rgb25, -// }; -pub use helpers::DescriptorType; +pub use ifaces::{ + AssetName, Attachment, Details, EmbeddedMedia, MediaType, NftSpec, ProofOfReserves, Ticker, + TokenIndex, +}; +pub use indexmap::IndexMap; pub use once_cell::sync::Lazy; pub use psbt::{ Beneficiary as PsbtBeneficiary, Payment, Prevout, Psbt, PsbtConstructor, PsbtMeta, PsbtVer, + TxParams, +}; +pub use rand::RngCore; +pub use rgb::{ + invoice::{RgbBeneficiary, RgbInvoice}, + popls::bp::{ + file::{BpDirMound, DirBarrow}, + Coinselect, OpRequestSet, WalletProvider, + }, + AuthToken, CellAddr, CodexId, Consensus, ContractId, ContractInfo, CreateParams, EitherSeal, + RgbSealDef, StateCalc, }; -// pub use psrgbt::{RgbExt, RgbInExt, RgbPsbt, TxParams}; -// pub use rand::RngCore; -// pub use rgb::{ -// info::ContractInfo, -// interface::{AllocatedState, AssignmentsFilter, ContractOp, OpDirection}, -// invoice::Pay2Vout, -// persistence::{MemContract, MemContractState, Stock}, -// resolvers::AnyResolver, -// stl::ContractTerms, -// validation::{Failure, ResolveWitness, Scripts, Validity, WitnessResolverError}, -// vm::{WitnessOrd, WitnessPos, XWitnessTx}, -// BlindingFactor, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, -// RgbWallet, TapretKey, TransferParams, Transition, WalletProvider, XOutpoint, XWitnessId, -// }; -// pub use rgbstd::{ -// containers::{ -// BuilderSeal, ConsignmentExt, Fascia, FileContent, IndexedConsignment, Kit, Transfer, -// ValidKit, -// }, -// interface::{ -// ContractBuilder, ContractIface, DataAllocation, FilterExclude, FungibleAllocation, Iface, -// IfaceClass, IfaceId, IfaceImpl, NamedField, -// }, -// invoice::{Beneficiary, RgbInvoice, RgbInvoiceBuilder, XChainNet}, -// persistence::{fs::FsBinStore, PersistedState, SchemaIfaces, StashReadProvider}, -// schema::SchemaId, -// stl::{ -// AssetSpec, Attachment, Details, MediaType, Name, ProofOfReserves, RicardianContract, Ticker, -// }, -// Allocation, Amount, ContractId, GlobalStateType, KnownState, Layer1, Operation, -// OutputAssignment, OwnedFraction, Precision, Schema, TokenIndex, TxoSeal, XChain, -// }; +pub use rgbp::{descriptor::RgbDescr, CoinselectStrategy, PayError, RgbDirRuntime, RgbWallet}; +pub use rgpsbt::ScriptResolver; pub use rstest::rstest; -// pub use schemata::{CollectibleFungibleAsset, NonInflatableAsset, UniqueDigitalAsset}; pub use serial_test::serial; -pub use strict_encoding::{fname, tn, FieldName, StrictSerialize, TypeName}; -pub use strict_types::{StrictVal, TypeSystem}; +pub use strict_encoding::{fname, tn, StrictSerialize}; +pub use strict_types::{ + value::{Blob, StrictNum, StrictVal}, + FieldName, TypeName, TypeSystem, VariantName, +}; pub use strum::IntoEnumIterator; pub use strum_macros::EnumIter; +pub use tabled::{ + settings::{object::Columns, Alignment, Modify, Style}, + Table, Tabled, +}; pub use time::OffsetDateTime; -// pub use crate::utils::{chain::*, helpers::*}; - pub const KEY_CHAIN_RGB: u8 = 9; pub const KEY_CHAIN_TAPRET: u8 = 10; + +pub use helper::asset_params::AssetParamsBuilder; +pub use helper::asset_types::{ + attachment_from_fpath, nft_spec, nft_spec_minimal, FACIssueParams, FUAIssueParams, + NIAIssueParams, +}; +pub use helper::coinselect::CustomCoinselectStrategy; +pub use helper::reporting::Report; +pub use helper::wallet::{DescriptorType, InvoiceType, TestWallet, TransferType}; + +pub use chain::{fund_wallet, indexer_url, is_tx_confirmed, mine_custom, Indexer, INDEXER}; +pub use helper::asset_types::{ContractImmutableState, ContractOwnedState, ContractState}; +pub use rgb::{Assignment, NamedState, StateAtom}; +pub use strict_types::value::EnumTag; From 28eba4a99ecfc2dd17b480e9f18fdd4b0e18a0c6 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 3 Apr 2025 20:43:35 +0800 Subject: [PATCH 48/90] fix: resolve ChangeRequired error in stress tests Signed-off-by: will-bitlightlabs --- tests/stress.rs | 11 ++++++++--- tests/utils/helper/wallet.rs | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/stress.rs b/tests/stress.rs index 4e1e98f..26ec6d5 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -27,13 +27,13 @@ use std::time::Instant; use std::{env::VarError, fs::File}; use time::format_description::well_known::Iso8601; use time::{format_description, OffsetDateTime}; -use utils::NIAIssueParams; use utils::{ chain::initialize, helper::reporting::{MetricDefinition, MetricType, Report}, helper::wallet::{get_wallet, TransferType}, DescriptorType, DEFAULT_FEE_ABS, STRESS_DATA_DIR, TEST_DATA_DIR, }; +use utils::{fund_wallet, NIAIssueParams}; pub mod utils; @@ -138,7 +138,11 @@ fn back_and_forth( // In RGB v0.12, the close_method parameter is no longer required // Create and issue assets let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issued_supply); + // fund wlt_1 and get utxo let utxo = wlt_1.get_utxo(None); + // fund wlt_2 + let _ = wlt_2.get_utxo(None); + params.add_allocation(utxo, issued_supply); let contract_id = wlt_1.issue_nia_with_params(params); wlt_1.send_contract("TestAsset", &mut wlt_2); @@ -158,7 +162,6 @@ fn back_and_forth( for i in 1..=loops { println!("loop {i}/{loops}"); sats_send -= MIN_RELAY_FEE * 2; - // In RGB v0.12, the send method parameters have been changed wlt_1.send( &mut wlt_2, @@ -171,7 +174,9 @@ fn back_and_forth( Some(&mut report), ); - sats_send -= DEFAULT_FEE_ABS * 2; + // Here we subtract MIN_RELAY_FEE * 2 + // Because one MIN_RELAY_FEE is used for change, and one is used for fee + sats_send -= MIN_RELAY_FEE * 2; wlt_2.send( &mut wlt_1, diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 1a0be94..143adb9 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -325,6 +325,7 @@ impl TestWallet { // It needs to be reloaded at a special time, and consider submitting a PR to RGB pub fn reload_runtime(&mut self) { self.runtime = make_runtime(&self.descriptor, self.network(), &self.wallet_dir); + self.sync(); } pub fn change_instance(&mut self, instance: u8) { From ff3f06b9bceb0585ec13af8f2290b5519ce0fdbb Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 9 Apr 2025 19:50:20 +0800 Subject: [PATCH 49/90] docs: explain test behavior differences between RGB v0.11 and v0.12 Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index 25e34a4..bf804f8 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1414,6 +1414,16 @@ fn sync_mainnet_wlt() { // wallet 2 accepts the consignment, use the received assets to transfer to wallet 3 // finally, the transfer is completed, the asset results of wallet 2 and wallet 3 are correct, // but the asset result of wallet 1 is incorrect +// +// However, I observed that in the original v0.11.0-beta.9 version, this test case expected wallet 3's accept_transfer to fail. +// The main distinction likely arises from the significant differences in the critical workflow between the two versions: +// In v0.11.0-beta.9, when wallet 1 transfers assets to wallet 2, if wallet 2 wants to accept the consignment, +// it must implement a custom Resolver; otherwise, the validation cannot pass (because the transaction hasn't been broadcast to the network). +// But in v0.12 version, the resolver concept has been removed, so wallet 2 can normally accept the consignment, +// and the phenomenon of wallet 2 successfully transferring to wallet 3 occurs. +// There is a significant distinction between the test cases in these two versions. I believe the expected behavior of this test case +// remains to be determined. +// We need to wait for the completion of the latest indexer/resolver implementation with the doctor before revisiting this issue. fn receive_from_unbroadcasted_transfer_to_blinded() { initialize(); From d313a8118c35da074f1cb8ff33301489cd46ed4f Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 25 Apr 2025 00:03:29 +0800 Subject: [PATCH 50/90] chore(WIP): Adapt test framework to latest RGB v0.12 Signed-off-by: will-bitlightlabs --- Cargo.lock | 130 ++++---- amplify-num | 2 +- bp-core | 2 +- bp-electrum-client | 2 +- bp-esplora-client | 2 +- bp-std | 2 +- bp-wallet | 2 +- client_side_validation | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-std | 2 +- rust-aluvm | 2 +- rust-amplify | 2 +- rust-baid64 | 2 +- sonic | 2 +- strict-encoding | 2 +- strict-types | 2 +- tests/issuance.rs | 16 +- tests/transfer.rs | 82 +---- tests/transfer_rgb21.rs | 40 +-- tests/utils/consignment_utils.rs | 536 ------------------------------ tests/utils/helper/asset_types.rs | 2 +- tests/utils/helper/wallet.rs | 106 +++--- tests/utils/mod.rs | 19 +- ultrasonic | 2 +- vesper | 2 +- zk-aluvm | 2 +- 27 files changed, 168 insertions(+), 801 deletions(-) delete mode 100644 tests/utils/consignment_utils.rs diff --git a/Cargo.lock b/Cargo.lock index f01eb88..4e735ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,7 +42,7 @@ dependencies = [ [[package]] name = "amplify" -version = "4.8.0" +version = "4.8.1" dependencies = [ "amplify_derive", "amplify_num", @@ -95,6 +95,20 @@ dependencies = [ "libc", ] +[[package]] +name = "aora" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224dad22f0c757318ac61fbfbab2a77efabbe73696e6d95a13084db6c7367263" +dependencies = [ + "amplify", + "binfile", + "getrandom", + "indexmap 2.9.0", + "strict_encoding", + "wasm-bindgen", +] + [[package]] name = "arrayvec" version = "0.7.4" @@ -131,29 +145,25 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-lc-rs" -version = "1.7.3" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7d844e282b4b56750b2d4e893b2205581ded8709fddd2b6aa5418c150ca877" +checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" dependencies = [ "aws-lc-sys", - "mirai-annotations", - "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.18.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a2c29203f6bf296d01141cc8bb9dbd5ecd4c27843f2ee0767bcd5985a927da" +checksum = "bfa9b6986f250236c27e5a204062434a773a13243d2ffc2955f37bdba4c5c6a1" dependencies = [ "bindgen", "cc", "cmake", "dunce", "fs_extra", - "libc", - "paste", ] [[package]] @@ -210,9 +220,9 @@ checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" [[package]] name = "bindgen" -version = "0.69.4" +version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "bitflags 2.5.0", "cexpr", @@ -231,6 +241,15 @@ dependencies = [ "which", ] +[[package]] +name = "binfile" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6274ba7d40c4296332ddf908383673f96412b853337a4df0f6ecc9495ec5ff7d" +dependencies = [ + "amplify", +] + [[package]] name = "bitcoin-io" version = "0.1.2" @@ -325,7 +344,7 @@ dependencies = [ "bp-invoice", "commit_verify", "hmac", - "indexmap 2.7.0", + "indexmap 2.9.0", "serde", "sha2", ] @@ -335,7 +354,7 @@ name = "bp-electrum" version = "0.12.0-beta.5" dependencies = [ "amplify", - "bp-std", + "bp-core", "byteorder", "libc", "log", @@ -349,7 +368,7 @@ dependencies = [ [[package]] name = "bp-esplora" -version = "0.12.0-beta.5" +version = "0.12.0-beta.5.1" dependencies = [ "amplify", "bp-std", @@ -362,21 +381,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "bp-esplora" -version = "0.12.0-beta.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec6536fdc52c7be3e5d1b5204e5276f7f782225fb6fc7080411039d32bc47f4" -dependencies = [ - "amplify", - "bp-std", - "log", - "minreq", - "serde", - "serde_with 3.11.0", - "sha2", -] - [[package]] name = "bp-invoice" version = "0.12.0-beta.5" @@ -427,7 +431,7 @@ version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-electrum", - "bp-esplora 0.12.0-beta.5.1", + "bp-esplora", "bp-std", "descriptors", "nonasync", @@ -672,7 +676,7 @@ version = "0.12.0-beta.5" dependencies = [ "amplify", "bp-derive", - "indexmap 2.7.0", + "indexmap 2.9.0", "serde", ] @@ -1061,6 +1065,7 @@ version = "0.12.0-beta.5" dependencies = [ "aluvm", "amplify", + "aora", "commit_verify", "getrandom", "serde", @@ -1124,9 +1129,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.0", @@ -1197,7 +1202,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1272,12 +1277,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - [[package]] name = "mnemonic" version = "1.1.1" @@ -1540,7 +1539,7 @@ dependencies = [ "bp-derive", "commit_verify", "descriptors", - "indexmap 2.7.0", + "indexmap 2.9.0", "serde", "strict_encoding", ] @@ -1752,7 +1751,7 @@ dependencies = [ "bp-wallet", "commit_verify", "getrandom", - "indexmap 2.7.0", + "indexmap 2.9.0", "nonasync", "rgb-psbt", "rgb-std", @@ -1767,6 +1766,7 @@ name = "rgb-std" version = "0.12.0-beta.5" dependencies = [ "amplify", + "aora", "bp-core", "bp-invoice", "chrono", @@ -1792,7 +1792,7 @@ dependencies = [ "bitcoin_hashes", "bp-core", "bp-electrum", - "bp-esplora 0.12.0-beta.5", + "bp-esplora", "bp-invoice", "bp-std", "bp-wallet", @@ -1800,7 +1800,7 @@ dependencies = [ "descriptors", "file-format", "hypersonic", - "indexmap 2.7.0", + "indexmap 2.9.0", "once_cell", "psbt", "rand", @@ -1924,9 +1924,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.7" +version = "0.23.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" dependencies = [ "aws-lc-rs", "log", @@ -1949,15 +1949,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.5.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "aws-lc-rs", "ring", @@ -2139,7 +2139,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.0", + "indexmap 2.9.0", "serde", "serde_derive", "serde_json", @@ -2177,7 +2177,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.9.0", "itoa", "ryu", "serde", @@ -2285,7 +2285,7 @@ dependencies = [ "baid64", "chrono", "fluent-uri", - "indexmap 2.7.0", + "indexmap 2.9.0", "serde", "strict_encoding", "strict_types", @@ -2300,7 +2300,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "strict_encoding" -version = "2.8.1" +version = "2.8.2" dependencies = [ "amplify", "serde", @@ -2310,7 +2310,7 @@ dependencies = [ [[package]] name = "strict_encoding_derive" -version = "2.8.1" +version = "2.8.2" dependencies = [ "amplify_syn", "heck 0.5.0", @@ -2321,12 +2321,12 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.8.2" +version = "2.8.3" dependencies = [ "amplify", "ascii-armor", "baid64", - "indexmap 2.7.0", + "indexmap 2.9.0", "serde", "serde_json", "serde_yaml", @@ -2577,7 +2577,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", @@ -3054,20 +3054,6 @@ name = "zeroize" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63381fa6624bf92130a6b87c0d07380116f80b565c42cf0d754136f0238359ef" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.95", -] [[package]] name = "zk-aluvm" diff --git a/amplify-num b/amplify-num index 98cda24..be035c1 160000 --- a/amplify-num +++ b/amplify-num @@ -1 +1 @@ -Subproject commit 98cda24f2ed2d19ffaba743f59f9ad34464bb492 +Subproject commit be035c1ed260313217bd799bd47cbc9bdfdf27ec diff --git a/bp-core b/bp-core index f26f459..f1fbfbc 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit f26f45921fdf6083e09620dc05b6e990dc639c42 +Subproject commit f1fbfbc6e80360e636287d815839c040449c942c diff --git a/bp-electrum-client b/bp-electrum-client index c820723..4d433e1 160000 --- a/bp-electrum-client +++ b/bp-electrum-client @@ -1 +1 @@ -Subproject commit c820723a453c40c50db876cd9b6db1897e0e94b6 +Subproject commit 4d433e1acb52832098bcf70cfe1483e041b1cca5 diff --git a/bp-esplora-client b/bp-esplora-client index b382527..84016ca 160000 --- a/bp-esplora-client +++ b/bp-esplora-client @@ -1 +1 @@ -Subproject commit b382527a1392fff01492f69905d7cacd030169c1 +Subproject commit 84016ca377364e6759101aa8e76e9a6da3f72c6e diff --git a/bp-std b/bp-std index 1e8eb90..f8d482e 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit 1e8eb9008221e429e67f1caa6ffe9ffb54bde5e4 +Subproject commit f8d482ed765329970dafeb399a738d411b07ceea diff --git a/bp-wallet b/bp-wallet index 54102a7..0d43906 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 54102a7413da2227bcbb049998b5cbefc894ca02 +Subproject commit 0d439062ecb352d3601dee7df9d9eaebe2e27acf diff --git a/client_side_validation b/client_side_validation index e22c5e0..b502409 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit e22c5e0491fbbad29b537e5c7d0e807793f49006 +Subproject commit b5024094fb3183b1cf4376efed7e2d3e38a0e7e2 diff --git a/rgb b/rgb index 5bd42bf..c347fa1 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 5bd42bfefd2614b353505baaf95041640ac2ff82 +Subproject commit c347fa1017d3452cdc6751acb20d7d9096f5a107 diff --git a/rgb-core b/rgb-core index 6603689..57a1800 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 66036890a42604014e4388538eef943283171581 +Subproject commit 57a1800032ce126e6fd05779f08d7792a4b42a19 diff --git a/rgb-std b/rgb-std index 088f179..f288ffe 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 088f1795df9a3d3c905b6628cea7e5c31988ae4e +Subproject commit f288ffe080adc085d2c2b223ef222a76ed5d9b39 diff --git a/rust-aluvm b/rust-aluvm index 0a59555..7d3fba7 160000 --- a/rust-aluvm +++ b/rust-aluvm @@ -1 +1 @@ -Subproject commit 0a5955595de41b58e390b8d3028bd49e091a410d +Subproject commit 7d3fba7d269d799030071683479c541ea3449f90 diff --git a/rust-amplify b/rust-amplify index cc510c3..f60a5a8 160000 --- a/rust-amplify +++ b/rust-amplify @@ -1 +1 @@ -Subproject commit cc510c350e2fcc2d1f7bf7de47a59e7f4a7520a2 +Subproject commit f60a5a87002353f5e40ace0c3e332a609a17c1b3 diff --git a/rust-baid64 b/rust-baid64 index 7e6a7c3..aaa426f 160000 --- a/rust-baid64 +++ b/rust-baid64 @@ -1 +1 @@ -Subproject commit 7e6a7c36013b30df597c85e6c3f3464d928e4563 +Subproject commit aaa426fd30f812c5ff07cd72d4ddc61b74b9bc4e diff --git a/sonic b/sonic index 4af3e1b..0cedd84 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 4af3e1bcbe3aed862ce9e422f373650f3c817930 +Subproject commit 0cedd840862937d20234e7532f34992b76d6ab05 diff --git a/strict-encoding b/strict-encoding index f7be0a7..6981414 160000 --- a/strict-encoding +++ b/strict-encoding @@ -1 +1 @@ -Subproject commit f7be0a7a046fe97289bda5f0b13bd57d7108b61e +Subproject commit 698141467e12886509e2c6d0e93c96d7f6ce0cf4 diff --git a/strict-types b/strict-types index c1def3a..e445a98 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit c1def3a5efb9ef92de883427eac61afbc6cda8f3 +Subproject commit e445a989f5152548e3db632d654b5ac4729ca710 diff --git a/tests/issuance.rs b/tests/issuance.rs index 65e834a..742ed40 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -58,16 +58,13 @@ fn issue_nia(wallet_desc: DescriptorType) { .owned .allocations .iter() - .any(|(outpoint, amount)| *outpoint == fake_outpoint_zero && *amount == 500_000)); + .any(|(outpoint, amount)| outpoint.primary == fake_outpoint_zero && *amount == 500_000)); assert!(state .owned .allocations .iter() - .any(|(outpoint, amount)| *outpoint == fake_outpoint_one && *amount == 500_000)); - dbg!(wallet - .runtime() - .state_all(Some(contract_id)) - .collect::>()); + .any(|(outpoint, amount)| outpoint.primary == fake_outpoint_one && *amount == 500_000)); + dbg!(wallet.runtime().state_all(contract_id)); } #[apply(descriptor_and_close_method)] @@ -106,11 +103,8 @@ fn issue_fua(wallet_desc: DescriptorType) { .owned .allocations .iter() - .any(|(outpoint, amount)| *outpoint == fake_outpoint && *amount == 10_000)); - dbg!(wallet - .runtime() - .state_all(Some(contract_id)) - .collect::>()); + .any(|(outpoint, amount)| outpoint.primary == fake_outpoint && *amount == 10_000)); + dbg!(wallet.runtime().state_all(contract_id)); } #[apply(descriptor_and_close_method)] diff --git a/tests/transfer.rs b/tests/transfer.rs index bf804f8..a42e4e3 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -108,16 +108,8 @@ fn simple_transfer(wout: bool) { wlt_2.sync(); // owned state - dbg!(wlt_1 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); - dbg!(wlt_2 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); + dbg!(wlt_1.runtime().state_own(contract_id).owned); + dbg!(wlt_2.runtime().state_own(contract_id).owned); wlt_1.check_allocations( contract_id, @@ -449,12 +441,6 @@ fn transfer_loop( vec![issued_supply_2 - amount_3, amount_5], ); - // for debug - { - let wlt_1_contract_2_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); - dbg!(wlt_1_contract_2_state.collect::>()); - } - wlt_2.check_allocations( contract_id_1, asset_schema_1, @@ -480,11 +466,6 @@ fn transfer_loop( None, ); wlt_1.check_allocations(contract_id_1, asset_schema_1, vec![]); - // for debug - { - let wlt_1_contract_2_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); - dbg!(wlt_1_contract_2_state.collect::>()); - } // Theoretically, there should be two outputs, one for the change UTXO and one for the income UTXO. // But because the change UTXO is associated with two assets (asset 1 and asset 2), asset 1 has been fully transferred to the UTXO of wlt2. @@ -637,9 +618,6 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) wlt_2.accept_transfer(&consignment, None).unwrap(); - let wlt_2_contract_state = wlt_2.runtime().state_own(None).map(|s| s.1.owned); - dbg!(wlt_2_contract_state.collect::>()); - wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount]); wlt_2.send( @@ -653,9 +631,6 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) None, ); - let wlt_1_contract_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); - dbg!(wlt_1_contract_state.collect::>()); - let mut wlt_3 = get_wallet(&DescriptorType::Wpkh); wlt_1.send_contract("TestAsset", &mut wlt_3); wlt_3.reload_runtime(); @@ -670,8 +645,6 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) None, None, ); - let wlt_3_contract_state = wlt_3.runtime().state_own(None).map(|s| s.1.owned); - dbg!(wlt_3_contract_state.collect::>()); } #[test] @@ -704,10 +677,6 @@ fn accept_0conf() { let wlt_1_change_amt = issue_supply - amt; - // wlt_1 needs to get tentative allocations to see its change from the unmined TX - let wlt_1_contract_state = wlt_1.runtime().state_own(None).map(|s| s.1.owned); - dbg!(wlt_1_contract_state.collect::>()); - // after mining, wlt_1 doesn't need to get tentative allocations to see the change wlt_1.mine_tx(&txid, false); wlt_1.sync(); @@ -767,11 +736,7 @@ fn check_fungible_history() { // debug contract info dbg!(wlt_1.contracts_info()); - dbg!(wlt_1 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); + dbg!(wlt_1.runtime().state_own(contract_id).owned); // transfer let amt = 200; @@ -779,16 +744,8 @@ fn check_fungible_history() { let _txid = tx.txid(); // debug contract state - dbg!(wlt_1 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); - dbg!(wlt_2 - .runtime() - .state_own(Some(contract_id)) - .map(|s| { s.1.owned }) - .collect::>()); + dbg!(wlt_1.runtime().state_own(contract_id).owned); + dbg!(wlt_2.runtime().state_own(contract_id).owned); // check allocations wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![issue_supply - amt]); @@ -816,11 +773,7 @@ fn send_to_oneself() { wlt.sync(); // debug contract state - dbg!(wlt - .runtime() - .state_own(None) - .map(|s| s.1.owned) - .collect::>()); + dbg!(wlt.runtime().state_own(contract_id).owned); // check allocations wlt.check_allocations( @@ -1337,7 +1290,7 @@ fn mainnet_wlt_receiving_test_asset() { wlt_1.mine_tx(&tx.txid(), false); match wlt_2.accept_transfer(&consignment, None) { Err(e) => { - dbg!(e); + dbg!(e.to_string()); } _ => panic!("validation must fail"), } @@ -1458,29 +1411,16 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { // wlt_1.mine_tx(&tx.txid(), false); // wlt_1.sync(); - dbg!(wlt_2 - .runtime() - .state_own(Some(contract_id)) - .map(|s| s.1.owned) - .collect::>()); + dbg!(wlt_2.runtime().state_own(contract_id).owned); let invoice = wlt_3.invoice(contract_id, 50, true, None, None); let (consignment, tx) = wlt_2.transfer(invoice, Some(2000), None, true, None); wlt_2.mine_tx(&tx.txid(), false); wlt_2.sync(); wlt_1.sync(); - let res = wlt_3.accept_transfer(&consignment, None); - let wlt_3_states = wlt_3 - .runtime() - .state_own(Some(contract_id)) - .map(|s| s.1.owned) - .collect::>(); - let wlt_2_states = wlt_2 - .runtime() - .state_own(Some(contract_id)) - .map(|s| s.1.owned) - .collect::>(); - assert!(res.is_ok(), "accept transfer failed"); + wlt_3.accept_transfer(&consignment, None).unwrap(); + let wlt_3_states = wlt_3.runtime().state_own(contract_id).owned; + let wlt_2_states = wlt_2.runtime().state_own(contract_id).owned; dbg!(wlt_3_states, wlt_2_states); wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![50]); diff --git a/tests/transfer_rgb21.rs b/tests/transfer_rgb21.rs index bc9910c..bffed6e 100644 --- a/tests/transfer_rgb21.rs +++ b/tests/transfer_rgb21.rs @@ -96,24 +96,8 @@ fn simple_fac_transfer(wout: bool) { assert_eq!(state.owned.fractions.len(), 1); assert_eq!(state.owned.fractions[0].1, total_fractions); - dbg!( - wlt_1 - .runtime() - .state_own(Some(contract_id)) - .next() - .unwrap() - .1 - .owned - ); - dbg!( - wlt_2 - .runtime() - .state_own(Some(contract_id)) - .next() - .unwrap() - .1 - .owned - ); + dbg!(wlt_1.runtime().state_own(contract_id).owned); + dbg!(wlt_2.runtime().state_own(contract_id).owned); // Transfer some fractions to wallet 2 let transfer_amount = 1001; @@ -130,24 +114,8 @@ fn simple_fac_transfer(wout: bool) { wlt_1.sync(); wlt_2.sync(); - dbg!( - wlt_1 - .runtime() - .state_own(Some(contract_id)) - .next() - .unwrap() - .1 - .owned - ); - dbg!( - wlt_2 - .runtime() - .state_own(Some(contract_id)) - .next() - .unwrap() - .1 - .owned - ); + dbg!(wlt_1.runtime().state_own(contract_id).owned); + dbg!(wlt_2.runtime().state_own(contract_id).owned); // Verify allocations after transfer wlt_1.check_allocations( diff --git a/tests/utils/consignment_utils.rs b/tests/utils/consignment_utils.rs deleted file mode 100644 index 9bb5813..0000000 --- a/tests/utils/consignment_utils.rs +++ /dev/null @@ -1,536 +0,0 @@ -use std::fs::{self, File}; -use std::io; -use std::path::{Path, PathBuf}; - -use amplify::confinement::SmallOrdMap; -use amplify::hex::ToHex; -use amplify::{Bytes16, Display, From}; -use bp::seals::WTxoSeal; -use commit_verify::ReservedBytes; -use hypersonic::{Articles, ContractId, Operation}; -use rgb::sigs::ContentSigs; -use rgb::{ - Contract, PublishedWitness, RgbSealDef, Schema, SealWitness, SingleUseSeal, - MAGIC_BYTES_CONSIGNMENT, -}; -use serde::{Deserialize, Serialize}; -use strict_encoding::{ - DecodeError, StreamReader, StreamWriter, StrictDecode, StrictEncode, StrictReader, StrictWriter, -}; - -#[derive(Debug, Display, From)] -#[display(doc_comments)] -pub enum ConsignmentParseError { - /// I/O error: {0} - #[from] - Io(io::Error), - - /// Strict encoding error: {0} - #[from] - Decoding(DecodeError), - - /// Unrecognized magic bytes in consignment stream ({0}) - UnrecognizedMagic(String), - - /// Unknown contract {0} can't be consumed; please import contract articles first. - UnknownContract(ContractId), - - // Because MoundConsumeError does not implement Debug, - // It affects the Debug and Error implementation of the entire structure, - // So here we store the string representation of the MoundConsumeError error - MoundConsume(String), - - /// Serialization error: {0} - SerializationError(String), - - /// Invalid witness count: {0} - InvalidWitnessCount(u64), - - /// Serde YAML error: {0} - #[from] - SerdeYaml(serde_yaml::Error), - - /// Invalid data: {0} - InvalidData(String), -} - -impl std::error::Error for ConsignmentParseError {} - -/// Parse consignment data into a directory -/// This function follows the logic of dump_consignment in rgb-std/cli/src/dump.rs -pub fn parse_consignment(src: &Path, dst: &Path) -> Result<(), ConsignmentParseError> -where - SealDef: RgbSealDef + Serialize, - SealDef::Src: Serialize, - ::CliWitness: - Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, - ::PubWitness: - Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, - <::PubWitness as PublishedWitness>::PubId: - Ord + From<[u8; 32]> + Into<[u8; 32]> + Serialize, -{ - fs::create_dir_all(dst)?; - - let file = File::open(src)?; - let mut stream = StrictReader::with(StreamReader::new::<{ usize::MAX }>(file)); - - let magic_bytes = Bytes16::strict_decode(&mut stream)?; - if magic_bytes.to_byte_array() != MAGIC_BYTES_CONSIGNMENT { - return Err(ConsignmentParseError::UnrecognizedMagic( - magic_bytes.to_hex(), - )); - } - - // Version - ReservedBytes::<2>::strict_decode(&mut stream)?; - - let contract_id = ContractId::strict_decode(&mut stream)?; - println!( - "Parsing consignment for {} into '{}'", - contract_id, - dst.display() - ); - - let mut op_count = 1; - let mut seal_count = 0; - let mut witness_count = 0; - - print!("Processing contract articles ... "); - let articles = Articles::strict_decode(&mut stream)?; - - // Save genesis - let out = File::create(dst.join(format!( - "0000-genesis.{}.yaml", - articles.contract.genesis_opid() - )))?; - serde_yaml::to_writer(&out, &articles.contract.genesis)?; - - // Save codex - let out = File::create(dst.join(format!("codex.{}.yaml", articles.schema.codex.codex_id())))?; - serde_yaml::to_writer(&out, &articles.schema.codex)?; - - // Save schema - let out = File::create(dst.join("schema.yaml"))?; - serde_yaml::to_writer(&out, &articles.schema)?; - - // Save contract - let out = File::create(dst.join("contract.yaml"))?; - serde_yaml::to_writer(&out, &articles.contract)?; - - // Save contract signatures - let out = File::create(dst.join("contract_sigs.yaml"))?; - serde_yaml::to_writer(&out, &articles.contract_sigs)?; - - // Save seals - let out = File::create(dst.join("0000-seals.yml"))?; - let defined_seals = SmallOrdMap::::strict_decode(&mut stream) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; - serde_yaml::to_writer(&out, &defined_seals)?; - seal_count += defined_seals.len(); - - let count = u64::strict_decode(&mut stream) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; - if count != 0 { - println!("error"); - return Err(ConsignmentParseError::InvalidWitnessCount(count)); - } - println!("success"); - - // Create operations directory - let operations_dir = dst.join("operations"); - fs::create_dir_all(&operations_dir)?; - - println!(); - loop { - match Operation::strict_decode(&mut stream) { - Ok(operation) => { - let opid = operation.opid(); - - // save operation - let out = - File::create(operations_dir.join(format!("{op_count:04}-op.{opid}.yaml")))?; - serde_yaml::to_writer(&out, &operation)?; - - // save seals - let out = File::create(operations_dir.join(format!("{op_count:04}-seals.yml")))?; - let defined_seals = SmallOrdMap::::strict_decode(&mut stream) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; - serde_yaml::to_writer(&out, &defined_seals)?; - seal_count += defined_seals.len(); - - // save witnesses - let len = u64::strict_decode(&mut stream) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; - for no in 0..len { - let out = File::create( - operations_dir.join(format!("{op_count:04}-witness-{:02}.yml", no + 1)), - )?; - let witness = SealWitness::::strict_decode(&mut stream) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?; - serde_yaml::to_writer(&out, &witness)?; - } - - witness_count += len as usize; - op_count += 1; - } - Err(DecodeError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => break, - Err(e) => return Err(ConsignmentParseError::Decoding(e)), - } - print!( - "\rParsing stream ... {op_count} operations, {seal_count} seals, {witness_count} \ - witnesses processed", - ); - } - println!(); - Ok(()) -} - -#[test] -#[ignore] -fn test_parse_and_rebuild_consignment() { - let src = Path::new("test-data/integration/00d99ed6/consignment-551.rgb"); - let dst = Path::new("test-data/integration/00d99ed6/output").to_owned(); - parse_consignment::(src, dst.as_path()).unwrap(); - - let rebuild = dst.join("rebuild.rgb").as_path().to_owned(); - rebuild_consignment::(dst.as_path(), rebuild.as_path()).unwrap(); - - let dst_rebuild = Path::new("test-data/integration/00d99ed6/rebuild_output"); - parse_consignment::(rebuild.as_path(), dst_rebuild).unwrap(); -} - -/// Modify file content -pub fn modify_file(path: &Path, pattern: &str, replacement: &str) -> io::Result<()> { - let content = fs::read_to_string(path)?; - let modified = content.replace(pattern, replacement); - fs::write(path, modified)?; - Ok(()) -} - -/// Rebuild consignment from parsed files -/// This function follows the logic of mound.rs(fn consign), stockpile.rs(fn consign) and stock.rs(fn export_aux) -pub fn rebuild_consignment( - src_dir: &Path, - dst_path: &Path, -) -> Result<(), ConsignmentParseError> -where - SealDef: RgbSealDef + Serialize + for<'de> Deserialize<'de>, - SealDef::Src: Serialize + for<'de> Deserialize<'de>, - ::CliWitness: - Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, - ::PubWitness: - Serialize + for<'de> Deserialize<'de> + StrictEncode + StrictDecode, - <::PubWitness as PublishedWitness>::PubId: - Ord + From<[u8; 32]> + Into<[u8; 32]> + Serialize, -{ - // Create output file - let file = File::create(dst_path)?; - let mut writer = StrictWriter::with(StreamWriter::new::<{ usize::MAX }>(file)); - - // Write magic bytes - writer = MAGIC_BYTES_CONSIGNMENT.strict_encode(writer)?; - writer = 0x00u16.strict_encode(writer)?; - - // Load contract ID - let contract_id_file = src_dir.join("contract_id.yaml"); - let contract_id: ContractId = if contract_id_file.exists() { - serde_yaml::from_reader(File::open(contract_id_file)?)? - } else { - // Try to extract from other files - let contract_file = src_dir.join("contract.yaml"); - if contract_file.exists() { - let contract: Contract = serde_yaml::from_reader(File::open(contract_file)?)?; - contract.contract_id() - } else { - return Err(ConsignmentParseError::InvalidData( - "Contract ID not found".to_string(), - )); - } - }; - - println!("rebuild_consignment: contract_id: {}", contract_id); - - // Write contract ID - writer = contract_id.strict_encode(writer)?; - - // Load and write articles - let schema_file = src_dir.join("schema.yaml"); - let contract_file = src_dir.join("contract.yaml"); - let contract_sigs_file = src_dir.join("contract_sigs.yaml"); - - if !schema_file.exists() || !contract_file.exists() || !contract_sigs_file.exists() { - return Err(ConsignmentParseError::InvalidData( - "Missing required article files".to_string(), - )); - } - - let schema: Schema = serde_yaml::from_reader(File::open(schema_file)?)?; - let contract: Contract = serde_yaml::from_reader(File::open(contract_file)?)?; - let contract_sigs: ContentSigs = serde_yaml::from_reader(File::open(contract_sigs_file)?)?; - - let articles = Articles { - schema, - contract, - contract_sigs, - }; - - // Write articles - writer = articles.strict_encode(writer)?; - - println!("Writing genesis seals"); - // Load and write genesis seals - let genesis_seals_file = src_dir.join("0000-seals.yml"); - if !genesis_seals_file.exists() { - return Err(ConsignmentParseError::InvalidData( - "Missing genesis seals file".to_string(), - )); - } - - let genesis_seals_file = File::open(genesis_seals_file)?; - - let genesis_seals: SmallOrdMap = - serde_yaml::from_reader(genesis_seals_file).map_err(|e| dbg!(e))?; - writer = genesis_seals.strict_encode(writer)?; - - // Write 0 witnesses for genesis - writer = (0u64).strict_encode(writer)?; - - println!("Writing operations"); - // Load and write operations - let operations_dir = src_dir.join("operations"); - if !operations_dir.exists() || !operations_dir.is_dir() { - return Err(ConsignmentParseError::InvalidData( - "Operations directory not found".to_string(), - )); - } - - // Get all operation files - let mut operation_files = Vec::new(); - for entry in fs::read_dir(&operations_dir)? { - let entry = entry?; - let path = entry.path(); - if path.is_file() && path.extension().map_or(false, |ext| ext == "yaml") { - operation_files.push(path); - } - } - - // Sort operation files by name to ensure correct order - operation_files.sort_by(|a, b| { - let a_name = a.file_name().unwrap().to_string_lossy(); - let b_name = b.file_name().unwrap().to_string_lossy(); - a_name.cmp(&b_name) - }); - - // Process each operation - for (op_index, op_file) in operation_files.iter().enumerate() { - println!("Processing operation: {}", op_file.display()); - let op_count = op_index + 1; // Operation count starts from 1 - - // Load and write operation - let operation: Operation = serde_yaml::from_reader(File::open(op_file)?)?; - writer = operation.strict_encode(writer)?; - - // Load and write operation seals - let seals_file = operations_dir.join(format!("{op_count:04}-seals.yml")); - if !seals_file.exists() { - return Err(ConsignmentParseError::InvalidData(format!( - "Missing seals file for operation {}", - op_count - ))); - } - - let seals_file = File::open(seals_file)?; - let seals: SmallOrdMap = - serde_yaml::from_reader(seals_file).map_err(|e| dbg!(e))?; - writer = seals.strict_encode(writer)?; - - // Count witness files for this operation - let mut witness_count = 0; - let mut witness_files = Vec::new(); - for i in 1..100 { - // Assuming maximum 99 witnesses per operation - let witness_file = operations_dir.join(format!("{op_count:04}-witness-{:02}.yml", i)); - if witness_file.exists() { - witness_count += 1; - witness_files.push(witness_file); - } else { - break; - } - } - - // Write witness count - writer = (witness_count as u64).strict_encode(writer)?; - - // Load and write witnesses - for witness_file in witness_files { - let witness = - serde_yaml::from_reader::<_, SealWitness>(File::open(witness_file)?)?; - writer = witness.strict_encode(writer)?; - } - } - - println!( - "Rebuilt consignment from {} to {}", - src_dir.display(), - dst_path.display() - ); - Ok(()) -} - -/// Create an attacked consignment -pub fn create_attack_consignment( - src: &Path, - attack_type: &str, -) -> Result { - // Create a temporary directory for parsing - let temp_dir_path = PathBuf::from("tests/fixtures/v0.12/temp").join(attack_type); - - // If the directory exists, clear it; otherwise, create a new directory - if temp_dir_path.exists() { - // Check if the directory is empty - if temp_dir_path.read_dir()?.next().is_some() { - // The directory is not empty, clear it - for entry in fs::read_dir(&temp_dir_path)? { - let entry = entry?; - let path = entry.path(); - if path.is_dir() { - fs::remove_dir_all(path)?; - } else { - fs::remove_file(path)?; - } - } - } - } else { - // The directory does not exist, create it - fs::create_dir_all(&temp_dir_path)?; - } - - // Parse the consignment - parse_consignment::(src, &temp_dir_path)?; - - // Create the attack path - let attack_path = PathBuf::from(format!("tests/fixtures/attack_{}.rgb", attack_type)); - - // Modify files based on attack type - match attack_type { - "chain" => { - // Attack type: chain - // Modify consensus from bitcoin to liquid in contract.yaml - let contract_path = temp_dir_path.join("contract.yaml"); - if contract_path.exists() { - modify_file(&contract_path, "consensus: bitcoin", "consensus: liquid")?; - println!("Modified contract.yaml: changed consensus from bitcoin to liquid"); - } else { - return Err(ConsignmentParseError::InvalidData( - "contract.yaml not found".to_string(), - )); - } - } - "genesis_schema_id" => { - // Attack type: genesis_schema_id - // Modify codexId in contract.yaml and schema.yaml - let contract_path = temp_dir_path.join("contract.yaml"); - let schema_path = temp_dir_path.join("schema.yaml"); - - if contract_path.exists() && schema_path.exists() { - // Read files to find the original codexId pattern - let contract_content = fs::read_to_string(&contract_path)?; - if let Some(line) = contract_content - .lines() - .find(|line| line.contains("codexId:")) - { - // let original_codex_id = line.trim(); - let original_codex_id = line.split("codexId:").nth(1).unwrap().trim(); - let mut modified_codex_id = original_codex_id.to_owned(); - modified_codex_id.push('1'); - - modify_file(&contract_path, original_codex_id, &modified_codex_id)?; - modify_file(&schema_path, original_codex_id, &modified_codex_id)?; - println!("Modified codexId in contract.yaml and schema.yaml"); - } else { - return Err(ConsignmentParseError::InvalidData( - "codexId not found in contract.yaml".to_string(), - )); - } - } else { - return Err(ConsignmentParseError::InvalidData( - "contract.yaml or schema.yaml not found".to_string(), - )); - } - } - "genesis_testnet" => { - // Attack type: genesis_testnet - // Modify testnet flag from true to false in contract.yaml - let contract_path = temp_dir_path.join("contract.yaml"); - if contract_path.exists() { - modify_file(&contract_path, "testnet: true", "testnet: false")?; - println!("Modified contract.yaml: changed testnet from true to false"); - } else { - return Err(ConsignmentParseError::InvalidData( - "contract.yaml not found".to_string(), - )); - } - } - "bundles_pubwitness_data_input_sequence" => { - // Attack type: bundles_pubwitness_data_input_sequence - // Modify sequence from 0 to 1 in operations/0001-witness-01.yml - let witness_path = temp_dir_path.join("operations").join("0001-witness-01.yml"); - if witness_path.exists() { - modify_file(&witness_path, "sequence: 0", "sequence: 1")?; - println!("Modified operations/0001-witness-01.yml: changed sequence from 0 to 1"); - } else { - return Err(ConsignmentParseError::InvalidData( - "operations/0001-witness-01.yml not found".to_string(), - )); - } - } - "resolver_error" => { - // Attack type: resolver_error - // This attack is handled by switching the esplora instance in the wallet - // No modification to the consignment is needed - println!("Resolver error attack: No modification to consignment needed."); - println!("This attack is handled by switching the esplora instance in the wallet."); - - // Just copy the original file to the attack path - fs::copy(src, &attack_path)?; - return Ok(attack_path); - } - _ => { - return Err(ConsignmentParseError::InvalidData(format!( - "Unknown attack type: {}", - attack_type - ))); - } - } - - // Rebuild consignment from modified files - rebuild_consignment::(&temp_dir_path, &attack_path)?; - - // Clean up temporary directory - // fs::remove_dir_all(&temp_dir_path)?; - - println!("Created attack consignment at {}", attack_path.display()); - Ok(attack_path) -} - -#[test] -#[ignore] -fn test_create_attack_consignment() { - let src = Path::new("test-data/integration/00d99ed6/consignment-551.rgb"); - let chain_attack_path = create_attack_consignment(src, "chain").unwrap(); - assert!(chain_attack_path.exists()); - - let genesis_schema_id_attack_path = - create_attack_consignment(src, "genesis_schema_id").unwrap(); - assert!(genesis_schema_id_attack_path.exists()); - - let genesis_testnet_attack_path = create_attack_consignment(src, "genesis_testnet").unwrap(); - assert!(genesis_testnet_attack_path.exists()); - - let bundles_pubwitness_data_input_sequence_attack_path = - create_attack_consignment(src, "bundles_pubwitness_data_input_sequence").unwrap(); - assert!(bundles_pubwitness_data_input_sequence_attack_path.exists()); - - let resolver_error_attack_path = create_attack_consignment(src, "resolver_error").unwrap(); - assert!(resolver_error_attack_path.exists()); -} diff --git a/tests/utils/helper/asset_types.rs b/tests/utils/helper/asset_types.rs index 6f199a9..38f7b69 100644 --- a/tests/utils/helper/asset_types.rs +++ b/tests/utils/helper/asset_types.rs @@ -65,7 +65,7 @@ pub struct ContractImmutableState { /// Contract's ownership state #[derive(Debug)] pub struct ContractOwnedState { - pub allocations: Vec<(Outpoint, u64)>, + pub allocations: Vec<(TxoSeal, u64)>, } /// Parameters for FUA (Fractional unique asset) issuance diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 143adb9..b2611ce 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -7,7 +7,7 @@ enum WalletAccount { /// Test wallet structure type pub struct TestWallet { /// RGB runtime for wallet operations - pub runtime: RgbDirRuntime, + pub runtime: RgbpRuntimeDir, /// RGB descriptor for wallet pub descriptor: RgbDescr, /// Signer for transaction signing @@ -230,15 +230,32 @@ fn _get_wallet( test_wallet } +pub fn contracts(network: Network, wallet_dir: PathBuf) -> Contracts> { + if !network.is_testnet() { + panic!("Non-testnet networks are not yet supported"); + } + let stockpile = StockpileDir::load(wallet_dir, Consensus::Bitcoin, true) + .expect("Invalid contracts directory"); + Contracts::load(stockpile) +} + /// Create a runtime for the wallet -fn make_runtime(descriptor: &RgbDescr, network: Network, wallet_dir: &PathBuf) -> RgbDirRuntime { +fn make_runtime(descriptor: &RgbDescr, network: Network, wallet_dir: &PathBuf) -> RgbpRuntimeDir { let name = "bp_wallet.wallet"; let provider = FsTextStore::new(wallet_dir.join(name)).unwrap(); - let wallet = RgbWallet::create(provider, descriptor.clone(), network, true) + + // Create wallet using Owner::create + let wallet = Owner::create(provider, descriptor.clone(), network, true) .expect("Unable to create wallet"); - let mound = BpDirMound::load_testnet(Consensus::Bitcoin, wallet_dir, false); - RgbDirRuntime::from(DirBarrow::with(wallet, mound)) + let contracts = contracts(network, wallet_dir.clone()); + // Create runtime with wallet and contracts + let mut runtime = RgbpRuntimeDir::from(RgbWallet::with(wallet, contracts)); + let indexer = get_indexer(&indexer_url(INSTANCE_1, network)); + runtime + .sync(&indexer) + .expect("Unable to synchronize wallet"); + runtime } /// Get an indexer instance @@ -392,21 +409,21 @@ impl TestWallet { pub fn sync(&mut self) { let indexer = self.get_indexer(); - self.runtime.wallet.update(&indexer).into_result().unwrap(); + self.runtime.sync(&indexer).expect("Failed to sync wallet"); } - pub fn runtime(&mut self) -> &mut RgbDirRuntime { + pub fn runtime(&mut self) -> &mut RgbpRuntimeDir { &mut self.runtime } pub fn contracts_info(&self) -> Vec { - self.runtime.mound.contracts_info().collect() + self.runtime.contracts.contracts_info().collect() } pub fn issue_with_params(&mut self, params: CreateParams) -> ContractId { let contract_id = self .runtime - .issue_to_file(params) + .issue(params) .expect("failed to issue contract"); println!("A new contract issued with ID {contract_id}"); contract_id @@ -561,14 +578,14 @@ impl TestWallet { } }; - let state = self.runtime.state_own(Some(contract_id)).next().unwrap().1; + let state = self.runtime.state_own(contract_id); let mut actual_fungible_allocations = state .owned .get(allocation_field) .unwrap() .iter() - .map(|(_, assignment)| assignment.data.unwrap_num().unwrap_uint::()) + .map(|(_, state)| state.assignment.data.unwrap_num().unwrap_uint::()) .collect::>(); actual_fungible_allocations.sort(); expected_fungible_allocations.sort(); @@ -679,8 +696,8 @@ impl TestWallet { .with_extension("rgb"); self.runtime - .mound - .consign_to_file(invoice.scope, [terminal], &consignment) + .contracts + .consign_to_file(&consignment, invoice.scope, [terminal]) .unwrap(); if let Some(report) = report { @@ -712,10 +729,12 @@ impl TestWallet { &mut self, consignment: &Path, report: Option<&mut Report>, - ) -> std::io::Result<()> { + ) -> Result<(), String> { self.sync(); let accept_start = Instant::now(); - self.runtime.consume_from_file(consignment)?; + self.runtime + .consume_from_file(consignment) + .map_err(|e| format!("consume_from_file error: {}", e.to_string()))?; let accept_duration = accept_start.elapsed(); if let Some(report) = report { let column_name = format!("{}_accept", self.wallet_id()); @@ -734,23 +753,23 @@ impl TestWallet { let name = immutable .get(&VariantName::from_str("name").unwrap()) .and_then(|m| m.values().next()) - .map(|v| v.verified.unwrap_string()) + .map(|v| v.data.verified.unwrap_string()) .unwrap_or_default(); let ticker = immutable .get(&VariantName::from_str("ticker").unwrap()) .and_then(|m| m.values().next()) - .map(|v| v.verified.unwrap_string()) + .map(|v| v.data.verified.unwrap_string()) .unwrap_or_default(); let precision = immutable .get(&VariantName::from_str("precision").unwrap()) .and_then(|m| m.values().next()) .inspect(|v| { - dbg!(&v.verified); + dbg!(&v.data.verified); }) .map(|v| { - let tag = v.verified.unwrap_enum_tag(); + let tag = v.data.verified.unwrap_enum_tag(); if let EnumTag::Name(name) = tag { name.to_string() } else { @@ -761,17 +780,17 @@ impl TestWallet { let circulating_supply = immutable .get(&VariantName::from_str("circulating").unwrap()) - .and_then(|m: &BTreeMap| m.values().next()) - .map(|v| v.verified.unwrap_num().unwrap_uint::()) + .and_then(|m: &BTreeMap| m.values().next()) + .map(|v| v.data.verified.unwrap_num().unwrap_uint::()) .unwrap_or_default(); // Parse ownership state let mut allocations = vec![]; if let Some(owned_map) = owned.get(&VariantName::from_str("amount").unwrap()) { - for assignment in owned_map.values() { + for state in owned_map.values() { allocations.push(( - assignment.seal, - assignment.data.unwrap_num().unwrap_uint::(), + state.assignment.seal, + state.assignment.data.unwrap_num().unwrap_uint::(), )); } } @@ -792,20 +811,17 @@ impl TestWallet { &mut self, contract_id: ContractId, ) -> Option<( - BTreeMap>, - BTreeMap>>, - BTreeMap, + BTreeMap>, + BTreeMap>>, + BTreeMap, )> { - self.runtime() - .state_all(Some(contract_id)) - .next() - .map(|(_, state)| { - ( - state.immutable.clone(), - state.owned.clone(), - state.computed.clone(), - ) - }) + let rgb_contract_state = self.runtime().state_all(contract_id); + + Some(( + rgb_contract_state.immutable, + rgb_contract_state.owned, + rgb_contract_state.computed, + )) } } @@ -863,7 +879,7 @@ pub struct ReserveData { /// Owned state part of RGB21 contract #[derive(Debug, Clone)] pub struct RGB21ContractOwnedState { - pub fractions: Vec<(Outpoint, u64)>, // (outpoint, amount) + pub fractions: Vec<(TxoSeal, u64)>, // (outpoint, amount) } /// Complete RGB21 contract state @@ -1213,13 +1229,13 @@ impl TestWallet { let name = immutable .get(&VariantName::from_str("name").unwrap()) .and_then(|m| m.values().next()) - .map(|v| v.verified.unwrap_string()) + .map(|v| v.data.verified.unwrap_string()) .unwrap_or_default(); let total_fractions = immutable .get(&VariantName::from_str("fractions").unwrap()) .and_then(|m| m.values().next()) - .map(|v| v.verified.unwrap_num().unwrap_uint::()) + .map(|v| v.data.verified.unwrap_num().unwrap_uint::()) .unwrap_or_default(); // Parse token/NFT metadata @@ -1231,7 +1247,7 @@ impl TestWallet { let mut amount = 0u64; // Parse verified token data - if let StrictVal::Struct(ref s) = v.verified { + if let StrictVal::Struct(ref s) = v.data.verified { if let Some(StrictVal::Number(n)) = s.get(&FieldName::from_str("index").unwrap()) { @@ -1253,7 +1269,7 @@ impl TestWallet { let mut attachments = BTreeMap::new(); let mut reserves = None; - if let Some(ref unverified) = v.unverified { + if let Some(ref unverified) = v.data.unverified { if let StrictVal::Struct(ref s) = unverified { if let Some(StrictVal::Union(_, t)) = s.get(&FieldName::from_str("ticker").unwrap()) @@ -1523,9 +1539,9 @@ impl TestWallet { // Parse ownership state (fractions) let mut fractions = vec![]; if let Some(owned_map) = owned.get(&VariantName::from_str("fractions").unwrap()) { - for assignment in owned_map.values() { - let amt_val = assignment.data.unwrap_num().unwrap_uint::(); - fractions.push((assignment.seal, amt_val)); + for state in owned_map.values() { + let amt_val = state.assignment.data.unwrap_num().unwrap_uint::(); + fractions.push((state.assignment.seal, amt_val)); } } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 6a9bcdf..31184a3 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -1,5 +1,4 @@ pub mod chain; -pub mod consignment_utils; pub mod helper; pub const TEST_DATA_DIR: &str = "test-data"; @@ -62,8 +61,8 @@ pub use bpstd::{ XpubDerivable, XpubFp, }; pub use bpwallet::{ - fs::FsTextStore, indexers::esplora::Client as EsploraClient, AnyIndexer, Indexer as BpIndexer, - Wallet, + fs::FsTextStore, indexers::esplora::Client as EsploraClient, seals::TxoSeal, AnyIndexer, + Indexer as BpIndexer, Wallet, }; pub use commit_verify::{Digest, DigestExt, Sha256}; pub use descriptors::Wpkh; @@ -82,14 +81,13 @@ pub use psbt::{ pub use rand::RngCore; pub use rgb::{ invoice::{RgbBeneficiary, RgbInvoice}, - popls::bp::{ - file::{BpDirMound, DirBarrow}, - Coinselect, OpRequestSet, WalletProvider, - }, - AuthToken, CellAddr, CodexId, Consensus, ContractId, ContractInfo, CreateParams, EitherSeal, - RgbSealDef, StateCalc, + popls::bp::{Coinselect, OpRequestSet, PaymentScript, PrefabBundle, RgbWallet, WalletProvider}, + AuthToken, CallScope, CellAddr, CodexId, Consensus, ContractId, ContractInfo, Contracts, + CreateParams, EitherSeal, RgbSealDef, Schema, StateCalc, StockpileDir, +}; +pub use rgbp::{ + descriptor::RgbDescr, CoinselectStrategy, Owner, PayError, RgbRuntime, RgbpRuntimeDir, }; -pub use rgbp::{descriptor::RgbDescr, CoinselectStrategy, PayError, RgbDirRuntime, RgbWallet}; pub use rgpsbt::ScriptResolver; pub use rstest::rstest; pub use serial_test::serial; @@ -121,4 +119,5 @@ pub use helper::wallet::{DescriptorType, InvoiceType, TestWallet, TransferType}; pub use chain::{fund_wallet, indexer_url, is_tx_confirmed, mine_custom, Indexer, INDEXER}; pub use helper::asset_types::{ContractImmutableState, ContractOwnedState, ContractState}; pub use rgb::{Assignment, NamedState, StateAtom}; +pub use rgb::{ConsumeError, ImmutableState, OwnedState, StateName}; pub use strict_types::value::EnumTag; diff --git a/ultrasonic b/ultrasonic index 4bd48cf..d9b53c5 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit 4bd48cf423fc344aa8a137cf42f9cc562fdde510 +Subproject commit d9b53c593a3539748574cc7c7c8069c5ef20342e diff --git a/vesper b/vesper index 6e1c889..0f0e7a2 160000 --- a/vesper +++ b/vesper @@ -1 +1 @@ -Subproject commit 6e1c889e9b951ac709d7db0e57d02dc427446527 +Subproject commit 0f0e7a2a6858b7eb13ec03199379772377d41856 diff --git a/zk-aluvm b/zk-aluvm index c3bb703..77d1fca 160000 --- a/zk-aluvm +++ b/zk-aluvm @@ -1 +1 @@ -Subproject commit c3bb7030c993b76640949b9ce3ef29d384abb8e4 +Subproject commit 77d1fca4d6408eec2d5925ab768a0d3766f1a688 From 51184a519bc9290341e98279b10b758867ef4a8d Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 29 Apr 2025 22:50:08 +0800 Subject: [PATCH 51/90] chore(WIP): Continuously adapt to the latest fixes Signed-off-by: will-bitlightlabs --- bp-electrum-client | 2 +- rgb | 2 +- rgb-std | 2 +- sonic | 2 +- tests/templates/issuance/FAC.yaml | 7 +- tests/templates/issuance/FUA.yaml | 6 +- tests/templates/issuance/NFA.yaml | 9 +- .../schemata/CollectibleFungibleAsset.issuer | Bin 2956 -> 0 bytes .../schemata/NonInflatableAsset.issuer | Bin 2945 -> 0 bytes tests/templates/schemata/RGB20-NFA.issuer | Bin 3387 -> 3397 bytes tests/templates/schemata/RGB21-FAC.issuer | Bin 8380 -> 8392 bytes tests/templates/schemata/RGB21-UAC.issuer | Bin 0 -> 8151 bytes tests/templates/schemata/RGB21-UDA.issuer | Bin 0 -> 8091 bytes tests/templates/schemata/RGB25-FUA.issuer | Bin 3382 -> 3392 bytes tests/utils/helper/wallet.rs | 100 ++++++++++++------ 15 files changed, 85 insertions(+), 45 deletions(-) delete mode 100644 tests/templates/schemata/CollectibleFungibleAsset.issuer delete mode 100644 tests/templates/schemata/NonInflatableAsset.issuer create mode 100644 tests/templates/schemata/RGB21-UAC.issuer create mode 100644 tests/templates/schemata/RGB21-UDA.issuer diff --git a/bp-electrum-client b/bp-electrum-client index 4d433e1..88abb6e 160000 --- a/bp-electrum-client +++ b/bp-electrum-client @@ -1 +1 @@ -Subproject commit 4d433e1acb52832098bcf70cfe1483e041b1cca5 +Subproject commit 88abb6e7ed03d567794f7dc595247dda27280fa3 diff --git a/rgb b/rgb index c347fa1..2fcba7d 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit c347fa1017d3452cdc6751acb20d7d9096f5a107 +Subproject commit 2fcba7d6e59a20ffb4079ce80a54af9a80bb9456 diff --git a/rgb-std b/rgb-std index f288ffe..85d3375 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit f288ffe080adc085d2c2b223ef222a76ed5d9b39 +Subproject commit 85d3375cb63f6b23659d69ffccf556c333604be4 diff --git a/sonic b/sonic index 0cedd84..40dfd3f 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 0cedd840862937d20234e7532f34992b76d6ab05 +Subproject commit 40dfd3ffaa6c88fa3bd6377623ccde342d5e1a17 diff --git a/tests/templates/issuance/FAC.yaml b/tests/templates/issuance/FAC.yaml index 9629bb3..371b353 100644 --- a/tests/templates/issuance/FAC.yaml +++ b/tests/templates/issuance/FAC.yaml @@ -1,14 +1,15 @@ consensus: bitcoin testnet: true -codexId: rlRZvs8I-GisCpaD-0L9GTZc-SHPBkK8-S0xp24p-eSZ3iNo#distant-recycle-paprika +codexId: cv343X_v-prQy_G7-utFnpPb-T2BpYVE-ibgujHd-zYzSLEw#horse-journal-voyage -# This is the correct codexId -# codexId: rlRZvs8I-GisCpaD-0L9GTZc-SHPBkK8-S0xp24p-eSZ3iNo#distant-recycle-paprika name: DemoFAC method: issue timestamp: "2025-03-17T10:32:00-02:00" global: + - name: details + verified: + unverified: first - name: name verified: FractionableAssetCollection - name: fractions diff --git a/tests/templates/issuance/FUA.yaml b/tests/templates/issuance/FUA.yaml index ac9e3fc..a6c6c33 100644 --- a/tests/templates/issuance/FUA.yaml +++ b/tests/templates/issuance/FUA.yaml @@ -1,11 +1,15 @@ consensus: bitcoin testnet: true -codexId: V7PSoqY~-Ki2PmBY-mNH~fq6-dQDDaDf-M0l09jz-8ThY4LI#diagram-fantasy-bazaar +codexId: WAHKjUOZ-gjaVJj0-IeQ8OHE-1lysvcD-E~Y~gnx-ZwsOezQ#rapid-forever-nice name: DemoFUA method: issue timestamp: "2025-03-17T10:32:00-02:00" global: +# TODO: why name is first, it can't issue contract? + - name: details + verified: + unverified: first - name: name verified: FUA - name: precision diff --git a/tests/templates/issuance/NFA.yaml b/tests/templates/issuance/NFA.yaml index 441489d..2925e08 100644 --- a/tests/templates/issuance/NFA.yaml +++ b/tests/templates/issuance/NFA.yaml @@ -1,15 +1,16 @@ consensus: bitcoin testnet: true -codexId: dLmJMaGC-A4CjS2t-cauJxL1-3f1_osG-0kuj~XB-n8KCQ1k#ranger-beast-puma +codexId: C11V4boH-t0lNXdS-U6MDKet-us0NCCo-1cWX7xU-7ahdfqw#regard-genius-belgium name: DemoToken method: issue -timestamp: "2025-03-17T10:32:00-02:00" +timestamp: "2025-04-27T10:32:00-02:00" global: - - name: name - verified: NFA - name: ticker verified: NFA +# TODO: why name is first, it can't issue contract? + - name: name + verified: NFA - name: precision verified: centiMilli - name: circulating diff --git a/tests/templates/schemata/CollectibleFungibleAsset.issuer b/tests/templates/schemata/CollectibleFungibleAsset.issuer deleted file mode 100644 index 1e6789e7c2608b230902ed4fa9784b54fbf62513..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2956 zcmdT`X;2hb5T5sT26iEW9FfF$EShM*6VWKhpRg1l4wdTk0KbaP*gA`#+XRd2!*?3s zuV42N#7nUP$6-ch%^Xfp_#D@Jq$FY4kFfAkxP#^`f=D|=){gr#wsnbdIfN?xo1M<5 z&c7Bw076F)_k1(g)QybjX1cVya$9rO!j7x!>O6g{lgz!FgTkq0WfO-om*4KtHKnUfA(hu|ZLS)zHgqEg)Eu=d?iMW5EGKCh zN{TQYt$RG=(VTM?s|vb0r#AmowsL($gS}?Y!mK6fCFOu@cN;YhFEv2$eT1h>7m<3i@VB13jvW7yNG-3?0)uL=9A zzOc>?k2`en?BkE^RZybtRAiIrz#vOAKImxgUP z+_}{I_>r&Id{Eoz-t9dPt%t6M?9Z-WXQ#k1+NWt#V|js>+s*220ZXIimt54Z-{SZE zm^~>!XDvTmFuJ;DK=6+X;>)kjA6(%UZFuYzGV}UdJtMBp+p<`>y6T_~QIdmZu#v=t z3>WB@rwB5ZdXP3+vh{ScsC|kSUv+n2k-@zDnt`^fP*VF-FAv%wNU|t6Y`C}HEYeIa zmJ?rZLuo;JT9UEIO1Z(LgHxnF6eHN}bYIHO@`}_?XA$K7l*FmK3?OG>uFpEA(}7&qKOkBnluTb z$&(?<$be|d6o@i2J*2#t*34uX%xa3#T>(#hzMN*F7+S>gG&fGLs1(w>v}Bga%?30L z%x1taz+wRy1FIF}E99pvT$jstc(;CUbjz~KOSc|a6_Bmr3liURWUK|uj1 zECfYGV8#ps)8@!b(!o0LtUnggiYb}pEO@q7JEMTs1)2KZm<&_X;9JZ0Ua1&(;P%;5 z2g<8=yf~m^_n}kv)dYHVC-hn!NayFt@)kBLKT diff --git a/tests/templates/schemata/NonInflatableAsset.issuer b/tests/templates/schemata/NonInflatableAsset.issuer deleted file mode 100644 index 58c9fe00a03ff0679abb6f3ba8598c75a1ec2abc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2945 zcmdT`c}x^%6rbTT*ukjZ`qOAncX=!yrb5G z7KPS|;ziZiYNXnr@d(9wm6&2}t+kaZ3YJ){x7b#p&{>4~Ps=oE)1)ui*FLA6FautX=V4 zMAh{X-5L+Fzk1d8`{lO>RCQsADX9F`y&aVkHwABFfs&&x1?MO`3jA_a0e<{WN}p3P z8AH2&ytjPD)?Uc-?sj`r%#wR6YpC%Nl>Ky{28Ij>RljgKv;hwdNBSIfX-Pp89 zGW7Ln3K(_1YR7@;Ya6<=D3p|g>-V=gnXe(@|_>5)w`nfd?<60~C*RMIYaojhxd7W2l>i}x)Lx9tv zi?$uDfcfItb*4-8`|u~9e;qmT)2d2$uOqr1*!qiV)gr)2%BOLALusz3_HNZ~zjfiu z3$E(6?CkzS?17}8GmDSqPOTc~H}uC9F{L+`hm>g}^v^tl7TkVoVA#!NJ6Fp$HyqKB zgy^7XWWZ4#&H8JdGA|)<0B)m1+d!>_XIV;k)y;tf8gbGfJ!My*sEnq;?v#TUC4qO? zP=L-XP)c)2aj$iv`@ zAF1Iv6r_=I`B8*q6A%iTb6(*Q{QHWrf8ra^N0bV$a zE!Rt(3n&Vh&48wX#R3olRx8NL0yZ097%*=h$j$~V3+#5lae(K6!vUO5AP7Jdfg}N0 z201w(Hy7mPf&6?hf4-jXyvPFF!8p*uKMs-?5fZ~%(Bk+o(}|jAqn|FhRJI|vZ`{`oKCm)#O-ey20n{GI?Du2SOpPJ;iYsoEjXZq+;<>}6ReN3@;oW~s`oU^{ z&;FQBZOUo7doY}Z$x%k4vJElZqD)6XxLS{aO6RaFqtUz0;$0ATZztL@p|G^TYdcs4 zx^=P&)+y7RMO9Nm!9x;=S5!PIf`>=Qi81 z4^BxE?@P`Z+<1lvdnG2?nE6>5nou^>t++YJ$L`$q>~hcgl$o0Ff70InRipm9&9-dd z(kA)A-Ghg&81swk#G>*Y-&e?iaax;kFQDOulbVqKXIyGKjR0ydKy6wRP%U>)ThS-G zTk8x^o4M41iYVqwOeW;S4w^Sx(ju0lQv4`X{i`U>Xz|*HE(lBnwY+-*K&F|kx5IwU+gQfP78>mD=jl9^fuWI+ zsezHHoymcTfx(Fb%us+a96$`X6Br#D9TqxlrR|n)Y|})A)E?|IynD9i zl8(>D@9!BWS1~CtGENp`QJk#7TrBC$z`zGI!9j?D!AX+IL9m@ylA)QAiC2H}Cg$n& zKQ?)-R~B09$9uAe{oaBFYd@WNw4H^ol{s?Xm$UKNntqIIp~3!sp3ap(Q-BU|n9Jli z(ZL94UOT%w&|FENXbOXqB9lXr0)tC28_=dMhVC{-E@pnmr4CL&4M`3lwf+oF8SGXJ zPLV(Yth5A30Ug9q!pOv?$-vM&`2veLn<5iiGD8B`<$SD;^@YOb@}HRN&x&E2^l_$nt)*;MiP$iKD~#YfMq-d|Ypje&uYfsmSL zhW|vUVSoZg28MMZk^9bbNNF=I6$}`hm8XlI9CnGhTVKRD z%kP$ZVt!LqcI@r2pYt}BF|vgQ`}=u1R|3rd+Uziw$#H^%6411Ec6Fes;y}?91}6a~ zhav?Amm)TxJzWglZH!#Z{Emw!Z)6cRwPd$q085qtDWC&N7@62Kf!Z0F91a1EX$32t z!^db0Gl?ykAz`v0v*KhaR>yiS`P{Fb^E3ro)E3Wwu)_1ulnNP-d#=aV@U_pmvFmtV z1F_DZ%D~Xb$kf2d)XoGB1`aSofx!vFZ~!qJ769F}0f-qL8XXooY~*KfU}Tznn^m1_ qf&(uTn=R1yLX&ye)VU@)$TG3zF(fcBPIhFop1gpOWpfRij}!o6^sE~I diff --git a/tests/templates/schemata/RGB21-UAC.issuer b/tests/templates/schemata/RGB21-UAC.issuer new file mode 100644 index 0000000000000000000000000000000000000000..59eedda6f66ce5d734a1227145e0a0fe2e924fd2 GIT binary patch literal 8151 zcmdT}2{csi-@o^oJ2Mm_OG%a#Arbm%k;b4%$W{?uW9BlG+04CTsVr&HPLxWUR4P&_ zZIV*t*jl7bQ7Tj_{z{w5dx`(=ec$uGJ-^QHciwZ}=bSn7%sk&``|h9b+A30 z1Hlk9(qAlyl;Z|GLAZeA2o1Orp%CYi0*QDy#1j+Kq#Q9%BI8J90ueru%ilHEIUJ(e z#BaU5KYIW722*P*K#;kt)p1GSnAxTA4OvBddlpSkjHrqi?TPwvJYBE4yT$;b$UroH zQ14%$={rLr*H7*#E99Px8_se_T z#PnLkG~nSkY)M0JX!p#D=}foj`E!kJ#kX$9JTT8vtxV~-)?)F=wHmwpueSlqS{%;6 zly3d9{U@P;_5z6jf)rq^7eWODA;%%;Prc~VwO_Xhgj{4G2{RCgrE-!m5D*4p32A^w z$|*x5B?bed5;@s7Of7{#Fx}tR%hSy%34&Cpd0YcZL2G{frvO-~q%}3Z(KY#R(I&)Yj5xOvS5UDlKQBzRfP;_= z1kvveADXD*xXZ?Pj>6$vy^fwPSrzHm?PMD9bJi$NaxX?Wvb%dkzhc+7#Ztsn)GDAZhayq9M1#~d$y-y|houwg^ z^-IJ!(7I`aM1*$^3*FRVEbTD07nA4wx;YaNUTSyx!Wg56OC#KP+Y1=S%x~|BIbfsJ zJMSqxrb(~DGC1|-?jzY9&8cY~&x%c%Jx3SHbY|H2(NFWQNdl8%6+>#CP5n`PqIq4> zj;VJWVg`BAJJ3-!bDgc6W$$$2a76K_I-jd6C4%HP-CpJ$&#K?No|)!FM-(|ysZfCP z{3JL$-|2%<MLBYdxSK0Fm{U~hbf%A7 z{ka>{>8&sx?XMq^=iWuHEpz=|z5QI7t70v+mz<1|yj;Sn4I205(z8{)f`k-S%EZvjx%^FvsjjGVb*1CGVy(8_KYgKn@lxN19Hs4s5brFSYuFBF< zVy7rP)DOo*UFD=8O4{uyL znqn)^E~<2rqwt}dJ=XH!jCe2o$`Dyvl5>{c{*A(h?i~$77EC_ISbTrX%Jio_nZ+fC z#)X6h^HVh(Bxu|x>FNECI&9r6PpHPC@ckLO>iak^4`@R~JK0fQqxNSO^e%m;WQFURHg*qYd%KnuD-)& zT`4J6Qa#VqfVS3KKImGiZK9s)u*4yw^K%d_vCvRQ``B%(fN$RQ2QM~F_&pzVQhF!l zW8KiemIn;Ys!4vM1AQ(wRp0U1Go`ihtjs`hyRC^+Ph+?!;912-GZ#_4uJH(i*Js`0 zXLJW-J}BFJS%$(OJFvf_$(NsVbzp`0+MOrPLeDDWiYMA}kZCb3eWJnSR|GFoDdl6)DC z+t9)!a+xhHOb~@nRv-j1f1m^&g^TS_ToBGDr_jU#F+LULa%4EUm@bs`t%t!J4jdW^ zbGa~&2jeLylh!+bt05Wq{8z!4F!PzZ}euviRBB(PKpM@GUj8B7o`Ny2hD92Ese zN5e5OaBM8RbSWrspzu|WTFbs?nb9irwwH!^o082-ZTo5~QiFB}Uq2FITx_wym_y zqR&+PsxoQW>kUTsZAk~#%G)x|D_|%g<#2I>pR%Dx$|WRDjQOuJVn}frmkI&n6e(fh zGJ--l#!4Kigdk-SDIYgshEn-{1WwK!KiKmzWpW4-mkEdnv!B96xe}3xGXWI|#B$=N zkWoTN3CQyA$yy?mh^HwMxJcmC*PTui;sjxj_NR<97~wLULmk6`Ng+0(52MXQI3x?f z932si%|qj&kw=;{Sj>bd<0vt0Kpb6M6iGW1PcsQA|lxXoLQt8O0med z@4`WU{_PX|-;|ZvM@0&_5h4Gq+A4Af53-CV6-e>r|Ng@#4kZOb9v%-u5OgLg5cBXD zP`*I#J3cOZZ1~FY%;F&qc}HanydSp|M+aUD+VRN5H$89P%<-+&zWv|{lx7X0#&qkZ zsa6YeO2mdfcjCKbmfUx%^M1UG>zZz2;xKL`yw2jgm3P&vxEE7IcGnvmjx9i7 zkBRHr&-iD~op}C~(eqU*YnLu~uAHu%YkKjC+Y9@{t=~4Rn7q3Pg+ZqTx+wB@~yLat49WVn(fJb z_xR-97woiijbB_I(h)?!i|)J?S9AKJ&%u>VsiiM{HfMR#hSIc?d>wU@^bGA%xcy!R zWH=z^1DUG=fzAQJF&}guZ@qF#Q^h0fX8TF;2!qfR#QJ45+|+n0BcplSZ4_>_)H$(g z$B>hUZgBW*GVy`&v(lamR#y9@eA9gy>te48Vi*d8U{R7$;s<%>+rl%Cy<@jD5vlpv zk50=c%%$_ab73x$aaF`; zHZ_M>&aeM0Q7J2nD!;-HnCni%=c6zv%L9Qbhz3gkQ5XdNK){`@(2wsy%Pq2HHN-v^Xlx;;EhgS zl31Em>2P_wEOOPl<;9f~H{|b*Ml}5j0)$Cb-cgHU;j7($H0PJ-ZZ^Dm@xv|@1_d=x z=A;DjnINDv$o4@q0@Wr^x&V3&$61P^>EQ89yT{L6kZt?p4yIw7Z4tlqWJ>P`JrNd$Qi6 zbM~QyMllVt%Ud<-E~eQzZ|~X}ug6Y*zf54+bifbw4iw)(o)wrL4Ei;bfer}N k{+?!m;w8vOD(L*P*a#HrfPiu^n_>*G3-nepNKcXf2ikHWfdBvi literal 0 HcmV?d00001 diff --git a/tests/templates/schemata/RGB21-UDA.issuer b/tests/templates/schemata/RGB21-UDA.issuer new file mode 100644 index 0000000000000000000000000000000000000000..dfdef4c909bbc0f91143f70e0f110fe7721b5cfb GIT binary patch literal 8091 zcmdT}c{EjD-#_QL=iW;p5+!4bC>i^a#C4^}l&K;*F86S6?&O|x4V599C!#2+q*9Se zX_82hWonQnMJYq2@F-0x?^Stz@B6OjY5!W!Z@p{1`>(yu*=O(loxh*YarAWY@$qx= zhF}O%@e^<(CAbco8_p$JJRKH6;N)0{Eg)<}ECE|6W{JdHK0YIqv&U_2I3yi2z6=e0 z8~XPHmToHpL6KvvwEJZeZmK5d>j}SVU`iTQ*Ht@n+aB-X7Qdcvm;p(bf!4S{Lw{k- z@TG=_RGM}(Vfrf51LG9}Y6ol;@7mPbZ|SaE8M2(yYi-fqUgbF=1N1K?gi-JLOmj1s zPKsFqA`BP9vSDIYD9IHHh#yBl5QWCZNfwt!Jg_f&Y9ilJ%=@U=ruE@#AFFz6W{_Fo z%bwg)#%_y!Ja^lmiu%tpKPBAD$%xh*3jET&ZAZ3k8^8M0x}_U^Hf6!m>;7{5dG>_v z&b?zr&Tam}imsOnPs*_?qA{@O?5 znp1$$*rNPG-@OxXg*W^8j!p?Z>zbbcPXQbPp`PBww!C>LWWc_9Hr-`*p_{&?;MVP!2h(yCYf^fzbr^qeuEWaz@y35;huv9N>RZ1Y z|IKKivp^<*AQ>1Nf>16&NN@=H(=Ud7?bl;EA>r!?!*sX;k%T04xP*>CNb2B`5^0Q) zLY<#)g%Wc3wR9^4f~kH!o*piat`MXkeZWwLAm#*wp|oCp0+b9R@+OcX#0b%Wm>h(W zia2C5a$tmU3Pu#6b&L?k_s1d9Pq+xPR{9)C8h)b~47@2woxc`S8g(B}FF2{ET<9TR zvxU~0lT+AV|Libk-6I$nh14{RBw}h ze6R^x_vZ()(hmfXEcKuJOFu|s7$Z~x1lABp1EA=FoFIsLZ|vwq1&2Kr`U_-^+!}K5 zaLTDpziuT~iC?fz-psWWg_*%)D05n^_m-${RlHVyf7gi`)&Aa717R0mnVk)8-ovNC ze(Jo5+N0a_2$#3|rdc5&c6oiXOZt1s#` zv=xx&eFs?65q9c8`jQyEhbtmn*qKGNGK#76I{$wKb>*8`r@dY{$3er2ELNkwE?A`y>^vwej)yvVWLdCS`mDwc5U{V6Y| z_Fr-R;!r=^;63WuY(;3&LWKen7my11C)8t)P>AEzdF#Bsnp6xyTK5}!7>N&+v$sS? zCJln#QxOUoE5eK9TfZgh6h6qQr5oxlEGV+|a*t~D;#AZ`qPg+mVZjtOi)8heOionY z7iZ)A6*4u}ev)|cxl#(8yEIQ?9CvedFWp+9QGND=wI2sC^`UBgO+W330@r?OL#6ZA zy3F&H&aw^Cvm|7U@WpaQL*SH8m!GW};vQBqKjJV=*YC2zBISzm=WBKbS5Z-sSSSnw z9j1D^_4Fa*%738U9b?(WUMl*zwSD?oO+|4tcg}Us-uHy2QBZ#Ef&P{9+b^T#HthRc zzd2mB5ME&SddxZhai)_}nVQgeRngvVXx6)mUCXJWB`9O7Wxw+v419uHY*F%$N zz%5iEP+3CZzymHzf;udFwx4;PV|u=~so{K9*|BjZW3;XOi>q}Nv_aQ|7#gP}+f=SX zTNI%!osCUe`zBbmH7M>@smh8sY`d{C=MoCnUlpgN#9GTd)D9}#>Q%oh!qMDXF>UgP z>I$hDw_QrreQxJil^@t|Xy9|ux+46|?9goYhc_-COR?mtmDD&&Q26l8L37DiTD+%r zO|UpEX>N|zfi1k|fnCj`7SB9RTXug^a{AN3tkSZ>Q-Z^SIH@XjLNxA!=*)pfy_PN} zClzB+`2HLX<^8M|2h|{=o9wMBkw00a&r$AkwOwnuih;)DP4!AR6SkoxZR^dt9+f6n zb9%feJ!bQwi(|SY)E*zL(*r779Wq*)e|+J_A=$0tMmbOa_Mr5Z`t~dLi-XK{1$Uzg zBD-6FTj)Tb0*}I#HgWqdoZO17Cb$6JID`ll}iWlfA(2gdP2mLG543tyt zmfL0YeGH@|7VE039lver|HZ56(52Stzn6nfiSDGlZyX)a@qjk2*34Hk!242b-5u|} z)}1Zq#5%H>mIjW4E#Z9sXVveGocK)|`r~z8opXtwGvJ@~pmJZi7==M`V0$}vZ++pO z?JM<7v5iL$4eE|JHS!>;j?2Z!cNRd)2pMAv9uvybrEpjTM~})D@^~!qWEmD;q)!p? zB*Zjn=o1`c8Mcs|L0N%|g{Csn3~MGsMhneRk|V}(3rd(!BDSQ2aij2=G6Xl~50t>8 zaDf$ybHh2LHATP`;Iq(BmKZ0OQF+4Q{V!&`_AohH)GY3xmVMVGal8a^dC6 z;fM&B$AkHNSRjCfLRch%BO_t47$yjqBw>jJj*5b#qv4nsI5rkuu>w>$Q1~iKsbl}M ztY`)5o3cE$6uab2E%fYzW7}O$EquRpdr7ooenQpz0k&sH?uljU$5NRM-RpNSpSy|e z2a*zsELu1H#XL!sVhEfdL7wVdrl)4~VvSQ)SF&Xe)n4|qg4xPfoAqqFk`8W=bY)zS z!B9fP3dMDP*oGP@5t2AD>3`aYCc?#`(h@L5R%$F+3j?BCb=`4c8#atr7=!bF9P$8esnvU|h0txZM$SA>+8pz~7v$c>X6xhfTIG^h{ zJe^J9;RIoee((L}(89$yOL`4Ex)gO0!_dMWVUY|3b8tW~CKJIN9T9BqTm*A+La=%B z5N!T@1ao#qFc%jDTd)AZTwM{&%?-ia-4V>g1Hn8!5p3Z?1oQGjFmG=J^YKA2Uta|C z^Fy#jix6z_Vgy^V1i}3M5iB4;j)-Lb)XY-Z5UGlMh6N7%^Rai(|8iFP@G6oU8WH^W zx~**J$VFCCL|hTR>Yoq1<4}^zW8?84C_ts7Tmc)80rd;i;p^k#$GR^a&Mq5eS8z`D~z+I0Fe9{Z{+fVJR^ZAZ~KyB6t{7W})on^W>uS}rpeJ8$OY!ceDw%}V& zT>oqX1G`1rE81xyF&@Rmqd#cj+m5)|&-BPHyQlL+bFPk`Mezr}n;Q*obd7t<_M@PD zoXurDU4PUv!(#pJla-s&lsGobxM_FnW*q6haP&grs|Cf~t4Fa&k`>C~OFf>bPwBdd z4LEN)5Ov4eMm1l?<^*vhW+t=j;hB9Jr0woEbTLlg;wYRDkoEgDN7wn@7&3l4xu(gl z;`l4ExlP0Qz#GW<%b5rLKnN9uL0zCnQRJ@X8-fChp#Ds{hf-sbQka_B-HQfB+k_IW zA|4-wbDQi2OKxjSYc&39>Q(zPuHBk%b-mf{_+kWhpRuv~tY4Pfj0>mrp082ZuwwCZ z`E>bw!%I(G+HH??e%ZWwW_Ae*gKi1xF(5j&OuwTFwVmiR*K6tZ9DGiW5pDaRnG!$p z(C3G$Z9aZ7cK=Dd|6fJ!-y40{-U|IyZ}W!88}Yeq^`76xRdgC0_;wn53Uz6o1Vb4 z{Y8Bz;=8AMC1Xm$8ePUIyo`^wD!0 zM80ao=ZVJd`I95_D!QCEm6kdcn&%AFO$hQZ+MD0=_|)BYX4?6dPfic12*PDY_uY!C zKXb|ZP;zT(#S8CkIUbbJ6tyHD2aO~xU8|JP?^y;EI3VQ%m8$@O?g7Cu@6;dfxN>@& zf_vD_?o)#CIw2{D`HMQZwdGbuM%&KYDBNPAesayOQKt^yU~#&{f`e1%r9I~+*LkOW z(RdN-WUB~L7z%@6QIcNbJ4xT0;-RmSrFXMBOm z!|ypJC`*E}EFIKyjnG*tKhgTZB<97!7gvNEdb3di5gm4Yuq zVNjO`0#y(N)c&I|2>gM7J5}a8z6WhXBP1ciJOBvY&_X#Zv6LMLtt(BSWZwJQ88CIm zt;>~(?L~!Wsq6?Uv|2M-6c$;pc zx2N*@1t92%A|M|eC{)v(Ti@6c^192jZ%~D;nZ7)+BB#c#JX0LGX5*^Tni-o5v!ju5 zzD54Lq*|}2rLpkUfj`;`%QUv>-n{f~4+?{d8mM!U1LaH*P#RJDNEm^*2^9IHMyIr# zpu~Q>dy*`e-H3F)au7c}cF~G9PW@3r<>&(-PXI9wC=4QcKztztJ=QYuUX&ol?wb~_ zS(hMxsHP;VZ?%QellERa+XbvC&L|Ah3$XM4E$$M;rGly!3WIu=mW{NY%}b^hZI-Pq z@t!&-CxM^3Ans+-<+QuS8|7!volv;dKy9Yhqw}^Q#dDWY~9yQJMnf1&LX`b9m!R+_&EWA+TZgmP`w1@NE!9N7aM^}9S~5CbW^mS N>H_^M8Cfq~{$FvN1Kt1t literal 0 HcmV?d00001 diff --git a/tests/templates/schemata/RGB25-FUA.issuer b/tests/templates/schemata/RGB25-FUA.issuer index 36a276047215e9621718b6885f2a62c13eeb7b8e..101a33fc5695c92013b0946fcf98e989b9ebe51d 100644 GIT binary patch delta 376 zcmdlcbwG;C+21obIMg+WfpJ1y{lT_79uku!l@Cte(d4t{`sM%O^=D2MEj&}cc)ysk zcVagK10w?=HTn$yiBQ7;1&j;~5sasLoo6EBaiYTlMka?1K&+&|;Bb(SA%($7k*S@LiJt*TfCP*g zpo07k49t@sve+gA-Tq^f*Lr24wSK%Od)V(SSg`ifnMd1M_*$7G_kB4VpRMV~$QByx z@8{_}m4Ts=k*R@^323Ph&{7F7LjlHc05RY$5OipCSm>~kpTR+BaxIHG*F*ww%z4!TTic?<~*j38HRmSL6R0074!d^-RD delta 372 zcmX>gwM}XwS6qGkx(ju0lQv4`X{i`U>Xz|*HE(lBnwY+-*K&F|VmTvzHF)=lh`unSw2k@9R*PK$}`hm8XlI9CnGhTVKRD%kP$ZVt!LqcI@r2pYt}BF|vgQ`}=u1Pi0_e zWMpb!WNK$}U}9i!;s7%gU4RtXLOI+S;W diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index b2611ce..5bac9bc 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -174,25 +174,6 @@ fn _get_wallet( std::fs::create_dir_all(&wallet_dir).unwrap(); println!("wallet dir: {wallet_dir:?}"); - // create consensus_dir for managing RGB smart contracts - let mut consensus_dir = wallet_dir.join(Consensus::Bitcoin.to_string()); - if network.is_testnet() { - consensus_dir.set_extension("testnet"); - } - std::fs::create_dir_all(&consensus_dir).unwrap(); - - // copy schema files from template directory to wallet_dir - let schemata_dir = PathBuf::from(SCHEMATA_DIR); - if schemata_dir.exists() { - for entry in std::fs::read_dir(schemata_dir).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - if path.is_file() { - std::fs::copy(&path, wallet_dir.join(path.file_name().unwrap())).unwrap(); - } - } - } - let xpub_account = match wallet_account { WalletAccount::Private(ref xpriv_account) => xpriv_account.to_xpub_account(), WalletAccount::Public(ref xpub_account) => xpub_account.clone(), @@ -222,11 +203,23 @@ fn _get_wallet( wallet_id: None, }; - // TODO: remove if once found solution for esplora 'Too many requests' error - if network.is_testnet() { - test_wallet.sync(); + // Import all issuer files from the schemata directory + let issuer_dir = PathBuf::from(SCHEMATA_DIR); + if issuer_dir.exists() { + for entry in std::fs::read_dir(issuer_dir).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + if path.is_file() && path.extension().map_or(false, |ext| ext == "issuer") { + println!("Auto-importing issuer file: {}", path.display()); + if let Err(err) = test_wallet.import(path) { + println!("Warning: Failed to import issuer: {}", err); + } + } + } } + test_wallet.sync(); + test_wallet } @@ -349,9 +342,6 @@ impl TestWallet { self.instance = instance; } - // TODO: Dr. Maxim mentioned in the meeting that - // He will support rollback state related APIs in the reorg and rbf scenarios - // Because it is not implemented at the moment, only sync is included for now pub fn sync_and_rollback_state(&mut self) { self.sync(); } @@ -449,14 +439,17 @@ impl TestWallet { } pub fn send_contract(&mut self, contract_name: &str, to_wallet: &mut TestWallet) { - let mut src_consensus_dir = self.wallet_dir.join(Consensus::Bitcoin.to_string()); - let mut dst_consensus_dir = to_wallet.wallet_dir.join(Consensus::Bitcoin.to_string()); - if self.network().is_testnet() { - src_consensus_dir.set_extension("testnet"); - dst_consensus_dir.set_extension("testnet"); - } - let src_contract_dir = src_consensus_dir.join(format!("{contract_name}.contract")); - let dst_contract_dir = dst_consensus_dir.join(format!("{contract_name}.contract")); + let src_consensus_dir = self.wallet_dir.clone(); + let dst_consensus_dir = to_wallet.wallet_dir.clone(); + + let contract_id = self + .runtime + .contracts + .find_contract_id(TypeName::from_str(contract_name).unwrap()) + .expect("Contract not found"); + let contract_file_name = format!("{}.{:-}.contract", contract_name, contract_id); + let src_contract_dir = src_consensus_dir.join(&contract_file_name); + let dst_contract_dir = dst_consensus_dir.join(&contract_file_name); std::fs::create_dir_all(&dst_contract_dir).unwrap(); let read_dir = std::fs::read_dir(&src_contract_dir).unwrap(); for entry in read_dir { @@ -742,6 +735,47 @@ impl TestWallet { } Ok(()) } + + /// Import an RGB schema(.issuer) file + /// + /// # Arguments + /// * `schema_path` - Path to the schema file to import + pub fn import(&mut self, schema_path: impl AsRef) -> Result<(), String> { + let schema_path = schema_path.as_ref(); + + // Check if file exists + if !schema_path.exists() { + return Err(format!( + "Schema file '{}' does not exist", + schema_path.display() + )); + } + + print!( + "Processing '{}' ... ", + schema_path.file_name().unwrap().to_string_lossy() + ); + + // Load schema and get codex ID + let schema = Schema::load(schema_path)?; + let codex_id = schema.codex.codex_id(); + + print!("codex id {} ... ", codex_id); + + // Import the schema into contracts + if self.runtime.contracts.has_issuer(codex_id) { + println!("already known, skipping"); + return Ok(()); + } + + self.runtime + .contracts + .import(schema) + .map_err(|e| format!("import error: {}", e.to_string()))?; + println!("success"); + + Ok(()) + } } impl TestWallet { From 64ad17b1e06c00a110d719eae385b23f8c6c3dce Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 4 May 2025 13:31:29 +0200 Subject: [PATCH 52/90] update repos to v0.12.0-beta.6 --- Cargo.lock | 179 ++++++++++++++++++++++++++++------------- bp-core | 2 +- bp-electrum-client | 2 +- bp-esplora-client | 2 +- bp-std | 2 +- bp-wallet | 2 +- client_side_validation | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-interfaces | 2 +- rgb-std | 2 +- rust-aluvm | 2 +- sonic | 2 +- ultrasonic | 2 +- zk-aluvm | 2 +- 15 files changed, 137 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e735ba..6a40ea5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,12 +28,12 @@ dependencies = [ [[package]] name = "aluvm" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "baid64", "commit_verify", - "getrandom", + "getrandom 0.2.14", "paste", "serde", "strict_encoding", @@ -97,13 +97,13 @@ dependencies = [ [[package]] name = "aora" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224dad22f0c757318ac61fbfbab2a77efabbe73696e6d95a13084db6c7367263" +checksum = "a0da0aa3a98a56f9002e0d30d642b62ba55b39821075951a764121bfe098ee98" dependencies = [ "amplify", "binfile", - "getrandom", + "getrandom 0.2.14", "indexmap 2.9.0", "strict_encoding", "wasm-bindgen", @@ -295,7 +295,7 @@ checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" [[package]] name = "bp-consensus" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "chrono", @@ -308,14 +308,14 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-consensus", "bp-dbc", "bp-seals", "commit_verify", - "getrandom", + "getrandom 0.2.14", "serde", "single_use_seals", "strict_encoding", @@ -324,7 +324,7 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "base85", @@ -337,7 +337,7 @@ dependencies = [ [[package]] name = "bp-derive" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-consensus", @@ -351,7 +351,7 @@ dependencies = [ [[package]] name = "bp-electrum" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-core", @@ -368,10 +368,11 @@ dependencies = [ [[package]] name = "bp-esplora" -version = "0.12.0-beta.5.1" +version = "0.12.0-beta.6" dependencies = [ "amplify", - "bp-std", + "bp-core", + "bp-invoice", "log", "minreq", "reqwest", @@ -383,7 +384,7 @@ dependencies = [ [[package]] name = "bp-invoice" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bech32", @@ -395,14 +396,14 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "baid64", "bp-consensus", "bp-dbc", "commit_verify", - "rand", + "rand 0.8.5", "serde", "single_use_seals", "strict_encoding", @@ -410,7 +411,7 @@ dependencies = [ [[package]] name = "bp-std" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-consensus", @@ -418,7 +419,7 @@ dependencies = [ "bp-derive", "bp-invoice", "descriptors", - "getrandom", + "getrandom 0.2.14", "psbt", "secp256k1", "serde", @@ -427,7 +428,7 @@ dependencies = [ [[package]] name = "bp-wallet" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-electrum", @@ -531,7 +532,7 @@ dependencies = [ [[package]] name = "commit_encoding_derive" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "amplify_syn", @@ -542,11 +543,11 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "commit_encoding_derive", - "rand", + "rand 0.9.1", "ripemd", "serde", "sha2", @@ -672,7 +673,7 @@ dependencies = [ [[package]] name = "descriptors" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-derive", @@ -891,10 +892,22 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + [[package]] name = "gimli" version = "0.28.1" @@ -1061,13 +1074,13 @@ dependencies = [ [[package]] name = "hypersonic" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "aluvm", "amplify", "aora", "commit_verify", - "getrandom", + "getrandom 0.2.14", "serde", "sonic-api", "sonic-callreq", @@ -1191,9 +1204,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" @@ -1273,7 +1286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -1531,7 +1544,7 @@ dependencies = [ [[package]] name = "psbt" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "base64 0.22.1", @@ -1553,6 +1566,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.8.5" @@ -1560,8 +1579,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -1571,7 +1600,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1580,7 +1619,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.14", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.2", ] [[package]] @@ -1689,12 +1737,12 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-core", "commit_verify", - "getrandom", + "getrandom 0.2.14", "serde", "single_use_seals", "strict_encoding", @@ -1704,12 +1752,12 @@ dependencies = [ [[package]] name = "rgb-interfaces" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-consensus", "commit_verify", - "getrandom", + "getrandom 0.2.14", "serde", "strict_encoding", "strict_types", @@ -1718,7 +1766,7 @@ dependencies = [ [[package]] name = "rgb-invoice" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "baid64", @@ -1734,7 +1782,7 @@ dependencies = [ [[package]] name = "rgb-psbt" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-core", @@ -1744,13 +1792,13 @@ dependencies = [ [[package]] name = "rgb-runtime" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "bp-std", "bp-wallet", "commit_verify", - "getrandom", + "getrandom 0.2.14", "indexmap 2.9.0", "nonasync", "rgb-psbt", @@ -1763,7 +1811,7 @@ dependencies = [ [[package]] name = "rgb-std" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "aora", @@ -1771,8 +1819,9 @@ dependencies = [ "bp-invoice", "chrono", "commit_verify", - "getrandom", + "getrandom 0.2.14", "hypersonic", + "indexmap 2.9.0", "rgb-core", "rgb-invoice", "serde", @@ -1803,7 +1852,7 @@ dependencies = [ "indexmap 2.9.0", "once_cell", "psbt", - "rand", + "rand 0.8.5", "rgb-interfaces", "rgb-psbt", "rgb-runtime", @@ -1831,7 +1880,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.14", "libc", "spin", "untrusted", @@ -1883,7 +1932,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88530b681abe67924d42cca181d070e3ac20e0740569441a9e35a7cedd2b34a4" dependencies = [ "quote", - "rand", + "rand 0.8.5", "rustc_version", "syn 2.0.95", ] @@ -2014,7 +2063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", - "rand", + "rand 0.8.5", "secp256k1-sys", "serde", ] @@ -2228,7 +2277,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "single_use_seals" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "serde", "strict_encoding", @@ -2261,14 +2310,14 @@ dependencies = [ [[package]] name = "sonic-api" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "aluvm", "amplify", "baid64", "chrono", "commit_verify", - "getrandom", + "getrandom 0.2.14", "serde", "sonic-callreq", "strict_encoding", @@ -2279,7 +2328,7 @@ dependencies = [ [[package]] name = "sonic-callreq" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "baid64", @@ -2644,12 +2693,12 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ultrasonic" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "amplify", "baid64", "commit_verify", - "getrandom", + "getrandom 0.2.14", "serde", "strict_encoding", "wasm-bindgen", @@ -2743,6 +2792,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -3049,6 +3107,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "zeroize" version = "1.8.0" @@ -3057,11 +3124,11 @@ checksum = "63381fa6624bf92130a6b87c0d07380116f80b565c42cf0d754136f0238359ef" [[package]] name = "zk-aluvm" -version = "0.12.0-beta.5" +version = "0.12.0-beta.6" dependencies = [ "aluvm", "amplify", - "getrandom", + "getrandom 0.2.14", "serde", "strict_encoding", "wasm-bindgen", diff --git a/bp-core b/bp-core index f1fbfbc..ea73ddd 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit f1fbfbc6e80360e636287d815839c040449c942c +Subproject commit ea73dddf3dd0f1d40074a8827468af83b48efe5e diff --git a/bp-electrum-client b/bp-electrum-client index 88abb6e..4a0def6 160000 --- a/bp-electrum-client +++ b/bp-electrum-client @@ -1 +1 @@ -Subproject commit 88abb6e7ed03d567794f7dc595247dda27280fa3 +Subproject commit 4a0def66a4d67b60feb80744d7f9314605b2d30c diff --git a/bp-esplora-client b/bp-esplora-client index 84016ca..01114f7 160000 --- a/bp-esplora-client +++ b/bp-esplora-client @@ -1 +1 @@ -Subproject commit 84016ca377364e6759101aa8e76e9a6da3f72c6e +Subproject commit 01114f76940fcd81bc6242b10717d42461f4d7d7 diff --git a/bp-std b/bp-std index f8d482e..a758653 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit f8d482ed765329970dafeb399a738d411b07ceea +Subproject commit a75865311f44a301032aa0db6a3cd0d0059d9d40 diff --git a/bp-wallet b/bp-wallet index 0d43906..54e23f4 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 0d439062ecb352d3601dee7df9d9eaebe2e27acf +Subproject commit 54e23f43e9c74712ffb497ff1d90fecb78a59ef1 diff --git a/client_side_validation b/client_side_validation index b502409..41a6f7a 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit b5024094fb3183b1cf4376efed7e2d3e38a0e7e2 +Subproject commit 41a6f7a8a8062ec3050afc96d6c4387177e0663a diff --git a/rgb b/rgb index 2fcba7d..6c1bc0a 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 2fcba7d6e59a20ffb4079ce80a54af9a80bb9456 +Subproject commit 6c1bc0a73504f1de15a0db4b952633ad00d5fb36 diff --git a/rgb-core b/rgb-core index 57a1800..b1d0e2b 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 57a1800032ce126e6fd05779f08d7792a4b42a19 +Subproject commit b1d0e2bdf2db5ffacd99d9a167b3f041c3cb7c78 diff --git a/rgb-interfaces b/rgb-interfaces index 4156451..5a24c50 160000 --- a/rgb-interfaces +++ b/rgb-interfaces @@ -1 +1 @@ -Subproject commit 4156451411a66e3db35bf03e02bb95de5a93c81c +Subproject commit 5a24c50701075d2bb7ab79fccdfeba9d65a9ed17 diff --git a/rgb-std b/rgb-std index 85d3375..ebd6f78 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 85d3375cb63f6b23659d69ffccf556c333604be4 +Subproject commit ebd6f78943d54b5dba7298562ca8c4ec21c0c71f diff --git a/rust-aluvm b/rust-aluvm index 7d3fba7..680c0b7 160000 --- a/rust-aluvm +++ b/rust-aluvm @@ -1 +1 @@ -Subproject commit 7d3fba7d269d799030071683479c541ea3449f90 +Subproject commit 680c0b73d98e2b90a79d771e80492161a5fbf013 diff --git a/sonic b/sonic index 40dfd3f..2398ad9 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 40dfd3ffaa6c88fa3bd6377623ccde342d5e1a17 +Subproject commit 2398ad9e1b4369a4c8fa87bb82630aeecc4ab90d diff --git a/ultrasonic b/ultrasonic index d9b53c5..91aa397 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit d9b53c593a3539748574cc7c7c8069c5ef20342e +Subproject commit 91aa397391696e787a11a60b45da264fa9a47e46 diff --git a/zk-aluvm b/zk-aluvm index 77d1fca..1b2d6e9 160000 --- a/zk-aluvm +++ b/zk-aluvm @@ -1 +1 @@ -Subproject commit 77d1fca4d6408eec2d5925ab768a0d3766f1a688 +Subproject commit 1b2d6e99a456e2b3c91349b4c0297038fdd6abd9 From e2df1846e9f8f814b878a6080c34e5454d3f5def Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 4 May 2025 17:13:03 +0200 Subject: [PATCH 53/90] use new RBF APIs --- rgb | 2 +- tests/transfer.rs | 62 +++++++++------------ tests/transfer_rgb21.rs | 4 +- tests/utils/helper/wallet.rs | 101 ++++++++++++++++++++--------------- tests/utils/mod.rs | 4 +- 5 files changed, 87 insertions(+), 86 deletions(-) diff --git a/rgb b/rgb index 6c1bc0a..dae58aa 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 6c1bc0a73504f1de15a0db4b952633ad00d5fb36 +Subproject commit dae58aa831317e68667de15213b9871553235559 diff --git a/tests/transfer.rs b/tests/transfer.rs index a42e4e3..ec287c5 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -76,7 +76,7 @@ fn simple_transfer(wout: bool) { // send asset to wlt2 // if `wout` is true (WitnessOut), // wlt2 will have a 3000 Sats UTXO, which will be spent to transfer assets to wlt1 in the next step - let (consignment_1, tx) = wlt_1.transfer(invoice, Some(3000), Some(500), true, None); + let (consignment_1, tx, _) = wlt_1.transfer(invoice, Some(3000), Some(500), true, None); // Receiver accepts the transfer wlt_2.accept_transfer(&consignment_1, None).unwrap(); @@ -99,7 +99,7 @@ fn simple_transfer(wout: bool) { wlt_2.runtime().wallet.coins().collect::>() ); // Sats cost: 500 fee + 2000 sats(default) = 2500 - let (consignment_2, tx) = wlt_2.transfer(invoice, None, Some(500), true, None); + let (consignment_2, tx, _) = wlt_2.transfer(invoice, None, Some(500), true, None); wlt_1.accept_transfer(&consignment_2, None).unwrap(); wlt_2.mine_tx(&tx.txid(), false); @@ -120,11 +120,6 @@ fn simple_transfer(wout: bool) { } #[test] -// FIXME: -// called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) -// -// RBF transfer fails in the second asset transfer, -// Likely due to the inability to spend the same asset balance twice. fn rbf_transfer() { initialize(); @@ -146,8 +141,9 @@ fn rbf_transfer() { stop_mining(); let initial_height = get_height(); - // First transfer attempt - with lower fee - let (consignment_1, _) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); + // First transfer attempt - with a lower fee + let (consignment_1, _tx, payment) = + wlt_1.transfer(invoice.clone(), None, Some(500), true, None); // Receiver accepts the transfer wlt_2.accept_transfer(&consignment_1, None).unwrap(); @@ -156,8 +152,8 @@ fn rbf_transfer() { let mid_height = get_height(); assert_eq!(initial_height, mid_height); - // Second transfer attempt - with higher fee for RBF - let (consignment_2, tx) = wlt_1.transfer(invoice, None, Some(1000), true, None); + // Second transfer attempt - with a higher fee for RBF + let (consignment_2, tx) = wlt_1.transfer_rbf(contract_id, payment, 1000, None); // Verify block height still hasn't changed let final_height = get_height(); @@ -614,7 +610,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) // .collect::>()); // TODO: called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) - let (consignment, _) = wlt_1.transfer(invoice, None, Some(1000), true, None); + let (consignment, _, _) = wlt_1.transfer(invoice, None, Some(1000), true, None); wlt_2.accept_transfer(&consignment, None).unwrap(); @@ -665,7 +661,7 @@ fn accept_0conf() { let amt = 200; let invoice = wlt_2.invoice(contract_id, amt, true, Some(0), None); - let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, None, true, None); + let (consignment, tx, _) = wlt_1.transfer(invoice.clone(), None, None, true, None); let txid = tx.txid(); wlt_2.accept_transfer(&consignment, None).unwrap(); @@ -740,7 +736,7 @@ fn check_fungible_history() { // transfer let amt = 200; - let (_, tx) = wlt_1.send(&mut wlt_2, true, contract_id, amt, 1000, None, None, None); + let (_, tx, _) = wlt_1.send(&mut wlt_2, true, contract_id, amt, 1000, None, None, None); let _txid = tx.txid(); // debug contract state @@ -767,7 +763,7 @@ fn send_to_oneself() { // Transfer 200 to yourself let amt = 200; let invoice = wlt.invoice(contract_id, amt, true, Some(0), None); - let (consignment, tx) = wlt.transfer(invoice.clone(), None, None, true, None); + let (consignment, tx, _) = wlt.transfer(invoice.clone(), None, None, true, None); wlt.mine_tx(&tx.txid(), false); wlt.accept_transfer(&consignment, None).unwrap(); wlt.sync(); @@ -931,7 +927,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let amt_0 = 590; // Create blinded invoice with specific UTXO let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); - let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + let (_, tx_0, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); // dbg!(wlt_1 // .runtime() // .state_own(Some(contract_id)) @@ -940,7 +936,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let amt_1 = 100; let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_1_1)); - let (_, tx_1) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); + let (_, tx_1, _) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); // dbg!(wlt_1 // .runtime() // .state_own(Some(contract_id)) @@ -949,37 +945,37 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let amt_2 = 80; let invoice = wlt_2.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_2_2)); - let (_, tx_2) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + let (_, tx_2, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); vec![tx_0, tx_1, tx_2] } HistoryType::Branching => { let amt_0 = 600; let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); - let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + let (_, tx_0, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); let amt_1 = 200; let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_1_1)); - let (_, tx_1) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); + let (_, tx_1, _) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); let amt_2 = amt_0 - amt_1 - 1; let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_1_2)); - let (_, tx_2) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); + let (_, tx_2, _) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); vec![tx_0, tx_1, tx_2] } HistoryType::Merging => { let amt_0 = 400; let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); - let (_, tx_0) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); + let (_, tx_0, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); let amt_1 = 200; let invoice = wlt_2.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_2_2)); - let (_, tx_1) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); + let (_, tx_1, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, None, None, None); let amt_2 = amt_0 + amt_1 - 1; let invoice = wlt_1.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_1_1)); - let (_, tx_2) = wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); + let (_, tx_2, _) = wlt_2.send_to_invoice(&mut wlt_1, invoice, None, None, None); vec![tx_0, tx_1, tx_2] } @@ -1286,7 +1282,7 @@ fn mainnet_wlt_receiving_test_asset() { .unwrap(); let invoice = wlt_2.invoice(contract_id, 150, false, None, Some(utxo)); - let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); + let (consignment, tx, _) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); wlt_1.mine_tx(&tx.txid(), false); match wlt_2.accept_transfer(&consignment, None) { Err(e) => { @@ -1325,21 +1321,11 @@ fn invoice_reuse(#[case] transfer_type: TransferType) { wlt_1.send_to_invoice(&mut wlt_2, invoice.clone(), Some(500), None, None); // Second use same invoice - let (_, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(600), None, None); - - // FIXME: There is a question here, - // should the two transfers of the same invoice be processed as one transfer by RBF, - // or should they correspond to two transfers? + let (_, _, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(600), None, None); // Check asset allocations wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![100, 200]); wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount, amount]); - - // FIXME: The following code needs to be redesigned in RGB v0.12 - // Note: In RGB v0.12, the type of consignment has been changed to PathBuf, no longer directly containing the bundles field - // This test needs to be redesigned in RGB v0.12 - - // The original test assertion: assert_eq!(consignment.bundles.len(), 1); } #[test] @@ -1401,7 +1387,7 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { let invoice = wlt_2.invoice(contract_id, 100, false, None, Some(utxo)); // Create transfer but do not broadcast its TX - let (consignment, _tx) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + let (consignment, _tx, _) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); wlt_2.accept_transfer(&consignment, None).unwrap(); // The following three lines are debug code, @@ -1414,7 +1400,7 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { dbg!(wlt_2.runtime().state_own(contract_id).owned); let invoice = wlt_3.invoice(contract_id, 50, true, None, None); - let (consignment, tx) = wlt_2.transfer(invoice, Some(2000), None, true, None); + let (consignment, tx, _) = wlt_2.transfer(invoice, Some(2000), None, true, None); wlt_2.mine_tx(&tx.txid(), false); wlt_2.sync(); wlt_1.sync(); diff --git a/tests/transfer_rgb21.rs b/tests/transfer_rgb21.rs index bffed6e..dbfb944 100644 --- a/tests/transfer_rgb21.rs +++ b/tests/transfer_rgb21.rs @@ -102,7 +102,7 @@ fn simple_fac_transfer(wout: bool) { // Transfer some fractions to wallet 2 let transfer_amount = 1001; let invoice = wlt_2.invoice(contract_id, transfer_amount, wout, Some(0), None); - let (consignment_1, tx) = wlt_1.transfer(invoice, Some(9000), Some(500), true, None); + let (consignment_1, tx, _) = wlt_1.transfer(invoice, Some(9000), Some(500), true, None); // Receiver accepts the transfer wlt_2.accept_transfer(&consignment_1, None).unwrap(); @@ -139,7 +139,7 @@ fn simple_fac_transfer(wout: bool) { // Test transferring some fractions back to wallet 1 let return_amount = 1000; let invoice = wlt_1.invoice(contract_id, return_amount, wout, Some(0), None); - let (consignment_2, tx) = wlt_2.transfer(invoice, Some(3000), Some(500), true, None); + let (consignment_2, tx, _) = wlt_2.transfer(invoice, Some(3000), Some(500), true, None); // Wallet 1 accepts the transfer wlt_1.accept_transfer(&consignment_2, None).unwrap(); diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 5bac9bc..cec510d 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -1,4 +1,5 @@ use super::*; +use rgbp::Payment; enum WalletAccount { Private(XprivAccount), @@ -342,10 +343,6 @@ impl TestWallet { self.instance = instance; } - pub fn sync_and_rollback_state(&mut self) { - self.sync(); - } - pub fn issue_nia_with_params(&mut self, params: NIAIssueParams) -> ContractId { let mut builder: AssetParamsBuilder = AssetParamsBuilder::default_nia() .name(params.name.as_str()) @@ -382,7 +379,7 @@ impl TestWallet { pub fn switch_to_instance(&mut self, instance: u8) { self.change_instance(instance); - self.sync_and_rollback_state(); + self.sync(); } pub fn indexer_url(&self) -> String { @@ -595,7 +592,7 @@ impl TestWallet { fee: Option, nonce: Option, report: Option<&mut Report>, - ) -> (PathBuf, Tx) { + ) -> (PathBuf, Tx, Payment) { let invoice = recv_wallet.invoice(contract_id, amount, wout, nonce, None); self.send_to_invoice(recv_wallet, invoice, Some(sats), fee, report) } @@ -607,43 +604,16 @@ impl TestWallet { sats: Option, fee: Option, mut report: Option<&mut Report>, - ) -> (PathBuf, Tx) { + ) -> (PathBuf, Tx, Payment) { // We need to handle the report parameter carefully to avoid moving it let transfer_report = report.as_deref_mut(); - let (consignment, tx) = self.transfer(invoice, sats, fee, true, transfer_report); + let (consignment, tx, payment) = self.transfer(invoice, sats, fee, true, transfer_report); self.mine_tx(&tx.txid(), false); // Now use the original report parameter recv_wallet.accept_transfer(&consignment, report).unwrap(); self.sync(); - (consignment, tx) - } - - /// Pay an invoice producing PSBT ready to be signed. - /// - /// This is a custom implementation of rgb-runtime's pay_invoice that supports - /// custom coinselection strategies. - /// - /// TODO: Keep this implementation in sync with the official rgb-runtime pay_invoice - /// method to ensure consistent behavior and avoid divergence. - pub fn pay_invoice( - &mut self, - invoice: &RgbInvoice, - strategy: impl Coinselect, - params: TxParams, - giveaway: Option, - ) -> Result<(Psbt, AuthToken), PayError> { - let request = self.runtime.fulfill(invoice, strategy, giveaway)?; - let script = OpRequestSet::with(request.clone()); - let psbt = self.runtime.transfer(script, params)?; - let terminal = match invoice.auth { - RgbBeneficiary::Token(auth) => auth, - RgbBeneficiary::WitnessOut(wout) => request - .resolve_seal(wout, psbt.script_resolver()) - .expect("witness out must be present in the PSBT") - .auth_token(), - }; - Ok((psbt, terminal)) + (consignment, tx, payment) } pub fn transfer( @@ -653,11 +623,7 @@ impl TestWallet { fee: Option, broadcast: bool, report: Option<&mut Report>, - ) -> (PathBuf, Tx) { - static COUNTER: OnceLock = OnceLock::new(); - let counter = COUNTER.get_or_init(|| AtomicU32::new(0)); - counter.fetch_add(1, Ordering::SeqCst); - let consignment_no = counter.load(Ordering::SeqCst); + ) -> (PathBuf, Tx, Payment) { self.sync(); let fee = Sats::from_sats(fee.unwrap_or(DEFAULT_FEE_ABS)); @@ -666,12 +632,61 @@ impl TestWallet { let strategy = self.coinselect_strategy; let pay_start = Instant::now(); let params = TxParams::with(fee); - let (mut psbt, terminal) = self + let (psbt, payment) = self + .runtime .pay_invoice(&invoice, strategy, params, Some(sats)) .unwrap(); let pay_duration = pay_start.elapsed(); + let (consignment, tx) = self.consign( + invoice.scope, + psbt.clone(), + &payment.terminals, + pay_duration, + broadcast, + report, + ); + (consignment, tx, payment) + } + + pub fn transfer_rbf( + &mut self, + contract_id: ContractId, + payment: Payment, + fee: u64, + report: Option<&mut Report>, + ) -> (PathBuf, Tx) { + let pay_start = Instant::now(); + let pay_duration = pay_start.elapsed(); + + let psbt = self.runtime.rbf(&payment, fee).unwrap(); + + let (consignment, tx) = self.consign( + contract_id, + psbt, + &payment.terminals, + pay_duration, + true, + report, + ); + (consignment, tx) + } + + fn consign<'a>( + &mut self, + contract_id: ContractId, + mut psbt: Psbt, + terminals: impl IntoIterator, + pay_duration: Duration, + broadcast: bool, + report: Option<&mut Report>, + ) -> (PathBuf, Tx) { + static COUNTER: OnceLock = OnceLock::new(); + let counter = COUNTER.get_or_init(|| AtomicU32::new(0)); + counter.fetch_add(1, Ordering::SeqCst); + let consignment_no = counter.load(Ordering::SeqCst); + let tx = self.sign_finalize_extract(&mut psbt); println!( @@ -690,7 +705,7 @@ impl TestWallet { self.runtime .contracts - .consign_to_file(&consignment, invoice.scope, [terminal]) + .consign_to_file(&consignment, contract_id, terminals) .unwrap(); if let Some(report) = report { diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 31184a3..9c25b13 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -75,8 +75,8 @@ pub use ifaces::{ pub use indexmap::IndexMap; pub use once_cell::sync::Lazy; pub use psbt::{ - Beneficiary as PsbtBeneficiary, Payment, Prevout, Psbt, PsbtConstructor, PsbtMeta, PsbtVer, - TxParams, + Beneficiary as PsbtBeneficiary, Payment as PaymentAmount, Prevout, Psbt, PsbtConstructor, + PsbtMeta, PsbtVer, TxParams, }; pub use rand::RngCore; pub use rgb::{ From dedc641d1ba5487e863d892b8dede1d1671db0c8 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 4 May 2025 18:03:12 +0200 Subject: [PATCH 54/90] fix same_transfer_twice_no_update_witnesses tests --- tests/transfer.rs | 45 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index ec287c5..577eda8 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -552,19 +552,13 @@ fn collaborative_transfer() { } #[rstest] +#[should_panic(expected = "unknown seal definition for cell address")] #[case(TransferType::Blinded)] +#[should_panic(expected = "Fulfill(StateInsufficient)")] #[case(TransferType::Witness)] fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) { println!("transfer_type {transfer_type:?}"); - // TODO: This test case aims to verify if asset transfers are handled correctly when using RBF (Replace-By-Fee) with the same invoice - // In RGB V0.11, there was an inflation attack vulnerability where using RBF with the same invoice would cause the receiver to record two receive states, - // while the sender only paid the assets once. This resulted in the total circulating assets exceeding the issued amount. - // - // In RGB V0.12, since it's not possible to use RBF with the same invoice, we cannot test for this inflation attack. - // NOTE: When paying the same invoice for the second time, the error `called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient)` occurs - // Need to consult with Dr. Maxim on how to construct RBF asset transfer examples using the current API. - initialize(); let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); @@ -585,36 +579,18 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) TransferType::Witness => true, }; let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), None); - let _ = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); - - // dbg!(wlt_1 - // .runtime() - // .state_all(None) - // .map(|(_, s)| { s.owned }) - // .collect::>()); - // dbg!(wlt_1 - // .runtime() - // .state_own(None) - // .map(|(_, s)| { s.owned }) - // .collect::>()); + let (_, _tx, payment) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); - // dbg!(wlt_2 - // .runtime() - // .state_all(None) - // .map(|(c, s)| { s.owned }) - // .collect::>()); - // dbg!(wlt_2 - // .runtime() - // .state_own(None) - // .map(|(c, s)| { s.owned }) - // .collect::>()); - - // TODO: called `Result::unwrap()` on an `Err` value: Fulfill(StateInsufficient) - let (consignment, _, _) = wlt_1.transfer(invoice, None, Some(1000), true, None); + let (consignment, _) = wlt_1.transfer_rbf(contract_id, payment, 1000, None); wlt_2.accept_transfer(&consignment, None).unwrap(); - wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount]); + if transfer_type == TransferType::Blinded { + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount]); + } else { + // Since the receiver state is not updated, it treats the witness transaction as not mined and thus has no state + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + } wlt_2.send( &mut wlt_1, @@ -631,6 +607,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) wlt_1.send_contract("TestAsset", &mut wlt_3); wlt_3.reload_runtime(); + // The receiver will fail to accept the consignment wlt_1.send( &mut wlt_3, wout, From 56c3235d9a43506067ef2dc3565b254d601449ed Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 5 May 2025 13:52:49 +0200 Subject: [PATCH 55/90] update dependencies with the latest fixes --- rgb | 2 +- rgb-core | 2 +- rgb-std | 2 +- sonic | 2 +- tests/utils/helper/wallet.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rgb b/rgb index dae58aa..69acc39 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit dae58aa831317e68667de15213b9871553235559 +Subproject commit 69acc39113918a8271fd65854fa3d372616526a0 diff --git a/rgb-core b/rgb-core index b1d0e2b..c8a07ff 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit b1d0e2bdf2db5ffacd99d9a167b3f041c3cb7c78 +Subproject commit c8a07ff2e8b2bb0c98f0cc963f9c1b061b6ea83a diff --git a/rgb-std b/rgb-std index ebd6f78..a45d927 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit ebd6f78943d54b5dba7298562ca8c4ec21c0c71f +Subproject commit a45d92705116d1e284ada9b9db6d9b566ffa6035 diff --git a/sonic b/sonic index 2398ad9..a8d418f 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 2398ad9e1b4369a4c8fa87bb82630aeecc4ab90d +Subproject commit a8d418f260b7ed36d8099d25dd48f58bbd75f546 diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index cec510d..306a4ba 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -785,7 +785,7 @@ impl TestWallet { self.runtime .contracts - .import(schema) + .import_issuer(schema) .map_err(|e| format!("import error: {}", e.to_string()))?; println!("success"); From d95ffc999cc3cf2fe9e87953d378d511bfc5ef7d Mon Sep 17 00:00:00 2001 From: astral-bitlight Date: Wed, 7 May 2025 15:02:08 +0800 Subject: [PATCH 56/90] chore: add test pay_one_invoice_twice --- tests/transfer.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index 577eda8..37da263 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1305,6 +1305,67 @@ fn invoice_reuse(#[case] transfer_type: TransferType) { wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount, amount]); } +#[rstest] +#[case(TransferType::Blinded)] +#[case(TransferType::Witness)] +fn pay_one_invoice_twice(#[case] transfer_type: TransferType) { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issue_supply = 2000; + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issue_supply); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, issue_supply); + + let contract_id = wlt_1.issue_nia_with_params(params); + + let amount = 100; + let wout = match transfer_type { + TransferType::Blinded => false, + TransferType::Witness => true, + }; + + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + let invoice = wlt_2.invoice(contract_id, amount, wout, None, None); + + wlt_1.sync(); + + let (consignment, tx, _payment) = wlt_1.transfer(invoice.clone(), None, Some(1000), true, None); + let (consignment2, tx2, _paytment2) = wlt_1.transfer(invoice, None, Some(1000), true, None); + + wlt_1.sync(); + + wlt_1.mine_tx(&tx.txid(), false); + let _ = wlt_2.accept_transfer(&consignment, None); + wlt_1.sync(); + + wlt_1.check_allocations( + contract_id, + AssetSchema::RGB20, + vec![issue_supply - amount - amount], + ); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount]); + + println!("first transfer complete. sending second one"); + + wlt_1.sync(); + + wlt_1.mine_tx(&tx2.txid(), false); + wlt_2.sync(); + let _ = wlt_2.accept_transfer(&consignment2, None); + wlt_1.sync(); + + wlt_1.check_allocations( + contract_id, + AssetSchema::RGB20, + vec![issue_supply - amount - amount], + ); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount, amount]); +} + #[test] #[ignore = "fix needed"] // https://github.com/BP-WG/bp-wallet/issues/70 #[serial] From 10ce58960829b9f1ab1e6792ce5aabe9496f6d7c Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 9 May 2025 00:43:19 +0800 Subject: [PATCH 57/90] fix: resolve reorg bug in rollback functions and enable reorg testing --- bp-wallet | 2 +- sonic | 2 +- tests/transfer.rs | 83 ++++++++++++++++++++++++-------------------- tests/utils/chain.rs | 37 ++++++++++++++++++++ 4 files changed, 84 insertions(+), 40 deletions(-) diff --git a/bp-wallet b/bp-wallet index 54e23f4..b639538 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 54e23f43e9c74712ffb497ff1d90fecb78a59ef1 +Subproject commit b639538c411091f249118bb49aeefec69c505eb8 diff --git a/sonic b/sonic index a8d418f..ca3261e 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit a8d418f260b7ed36d8099d25dd48f58bbd75f546 +Subproject commit ca3261e8e67effbedd3835e2876424f790c86efc diff --git a/tests/transfer.rs b/tests/transfer.rs index 37da263..249c42d 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -27,6 +27,7 @@ use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; +use utils::chain::{dbg_tx_status, get_tx_height}; use utils::helper::wallet::{ broadcast_tx_and_mine, get_mainnet_wallet, get_wallet, get_wallet_custom, AssetSchema, }; @@ -818,18 +819,14 @@ fn blank_tapret_opret( } #[rstest] -// Unable to accept a consignment: unknown seal definition for cell address qMWtQjXCWjJAXdrg7npyI2KZz3vXNVyZhoomqF7v8z4:0. -#[ignore = "fix needed"] #[case(HistoryType::Linear, ReorgType::ChangeOrder)] // TODO: This test case does not meet expectations, after (transferring 600 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 600 // thread 'reorg_history::case_2' panicked at tests/utils/helpers.rs:909:17: // assertion `left == right` failed // left: [10, 20] // right: [600] -#[ignore = "fix needed"] +// #[ignore = "fix needed"] #[case(HistoryType::Linear, ReorgType::Revert)] -// Unable to accept a consignment: unknown seal definition for cell address c6z0I0hYqaO6dV9qOjrP1lK4PJprjVAaAOdGCoqAdOY:0. -#[ignore = "fix needed"] #[case(HistoryType::Branching, ReorgType::ChangeOrder)] // #[ignore = "fix needed"] // TODO: This test case does not meet expectations, after (transferring 600 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 600 @@ -837,10 +834,8 @@ fn blank_tapret_opret( // assertion `left == right` failed // left: [200, 399] // right: [600] -#[ignore = "fix needed"] +// #[ignore = "fix needed"] #[case(HistoryType::Branching, ReorgType::Revert)] -// Unable to accept a consignment: unknown seal definition for cell address FrGmm~6ro7YOlE9bEuyCLcLt9AlX2uZOZRmjHEq6yyA:0. -#[ignore = "fix needed"] #[case(HistoryType::Merging, ReorgType::ChangeOrder)] // #[ignore = "fix needed"] // TODO: This test case does not meet expectations, after (transferring 400 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 400 @@ -848,7 +843,7 @@ fn blank_tapret_opret( // assertion `left == right` failed // left: [599] // right: [400] -#[ignore = "fix needed"] +// #[ignore = "fix needed"] #[case(HistoryType::Merging, ReorgType::Revert)] #[serial] fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgType) { @@ -859,6 +854,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let mut wlt_1 = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); let mut wlt_2 = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + let mut wlt_3 = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); let issued_supply = 600; @@ -882,6 +878,8 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_1.send_contract("TestAsset", &mut wlt_2); wlt_2.reload_runtime(); + wlt_1.send_contract("TestAsset", &mut wlt_3); + wlt_3.reload_runtime(); // Generate UTXOs before asset transfer to avoid mining blocks during transfer, affecting the test let utxo_wlt_1_1 = wlt_1.get_utxo(None); @@ -905,20 +903,10 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp // Create blinded invoice with specific UTXO let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); let (_, tx_0, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); - // dbg!(wlt_1 - // .runtime() - // .state_own(Some(contract_id)) - // .map(|s| { s.1.owned }) - // .collect::>()); let amt_1 = 100; let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_1_1)); let (_, tx_1, _) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); - // dbg!(wlt_1 - // .runtime() - // .state_own(Some(contract_id)) - // .map(|s| { s.1.owned }) - // .collect::>()); let amt_2 = 80; let invoice = wlt_2.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_2_2)); @@ -958,16 +946,18 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp } }; - // dbg!(wlt_1 - // .runtime() - // .state_own(Some(contract_id)) - // .map(|s| { s.1.owned }) - // .collect::>()); - // dbg!(wlt_2 - // .runtime() - // .state_own(Some(contract_id)) - // .map(|s| { s.1.owned }) - // .collect::>()); + dbg!( + "before switch", + wlt_1.runtime().state_own(contract_id).owned + ); + dbg!( + "before switch", + wlt_2.runtime().state_own(contract_id).owned + ); + + let tx_0_instance_2_height = get_tx_height(txs[0].txid(), INSTANCE_2); + let tx_1_instance_2_height = get_tx_height(txs[1].txid(), INSTANCE_2); + let tx_2_instance_2_height = get_tx_height(txs[2].txid(), INSTANCE_2); // Test different reorg scenarios match (history_type, reorg_type) { @@ -998,6 +988,9 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_1.switch_to_instance(INSTANCE_3); wlt_2.switch_to_instance(INSTANCE_3); let wlt_1_alloc_1 = 600; + dbg!(dbg_tx_status(txs[0].txid(), INSTANCE_3)); + dbg!(wlt_1.runtime().state_own(contract_id).owned); + dbg!(wlt_2.runtime().state_own(contract_id).owned); wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); } @@ -1040,12 +1033,34 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp } } + let tx_0_instance_3_height = get_tx_height(txs[0].txid(), INSTANCE_3); + let tx_1_instance_3_height = get_tx_height(txs[1].txid(), INSTANCE_3); + let tx_2_instance_3_height = get_tx_height(txs[2].txid(), INSTANCE_3); + + dbg!( + &txs[0].txid(), + tx_0_instance_2_height, + tx_0_instance_3_height + ); + dbg!( + &txs[1].txid(), + tx_1_instance_2_height, + tx_1_instance_3_height + ); + dbg!( + &txs[2].txid(), + tx_2_instance_2_height, + tx_2_instance_3_height + ); mine_custom(false, INSTANCE_3, 3); connect_reorg_nodes(); + dbg!("final"); wlt_1.switch_to_instance(INSTANCE_2); wlt_2.switch_to_instance(INSTANCE_2); - let mut wlt_3 = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + dbg!(wlt_1.runtime().state_own(contract_id).owned); + dbg!(wlt_2.runtime().state_own(contract_id).owned); + // Verify final state based on history type match history_type { @@ -1068,8 +1083,6 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp ); // Test spending the final allocations - wlt_1.send_contract("TestAsset", &mut wlt_3); - wlt_3.reload_runtime(); wlt_1.send( &mut wlt_3, false, @@ -1106,9 +1119,6 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp ); wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_2_alloc_1]); - // Test spending the final allocations - wlt_1.send_contract("TestAsset", &mut wlt_3); - wlt_3.reload_runtime(); wlt_1.send( &mut wlt_3, false, @@ -1143,9 +1153,6 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_2_alloc_1]); - // Test spending the final allocations - wlt_1.send_contract("TestAsset", &mut wlt_3); - wlt_3.reload_runtime(); wlt_1.send( &mut wlt_3, false, diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 723c547..0c75645 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -1,4 +1,5 @@ use super::*; +use bpwallet::TxStatus; static INIT: Once = Once::new(); @@ -285,6 +286,42 @@ pub fn get_height_custom(instance: u8) -> u32 { .expect("could not parse blockcount") } +pub fn get_tx_height(txid: Txid, instance: u8) -> Option { + let height = match INDEXER.get().unwrap() { + Indexer::Electrum => { + let status = ElectrumClient::new(&indexer_url(instance, Network::Regtest)) + .unwrap() + .status(txid) + .unwrap(); + match status { + TxStatus::Mined(block_height) => Some(block_height.height.into()), + _ => None, + } + } + Indexer::Esplora => { + EsploraClient::new_esplora(&indexer_url(instance, Network::Regtest)) + .unwrap() + .tx_status(&txid) + .unwrap() + .block_height + } + }; + height +} + +pub fn dbg_tx_status(txid: Txid, instance: u8){ + match INDEXER.get().unwrap() { + Indexer::Esplora => { + let status = EsploraClient::new_esplora(&indexer_url(instance, Network::Regtest)) + .unwrap() + .tx_status(&txid) + .unwrap(); + dbg!(txid, &status); + } + _ => unreachable!(), + } +} + pub fn indexer_url(instance: u8, network: Network) -> String { match (INDEXER.get().unwrap(), network, instance) { (Indexer::Electrum, Network::Mainnet, _) => ELECTRUM_MAINNET_URL, From aaf77fa6987dc58bcdf813b28ded9a925d2e6f32 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 9 May 2025 01:47:02 +0800 Subject: [PATCH 58/90] docs: add RGB reorg test report detailing test design, scenarios, implementation, and issues discovered --- reorg-test-en.md | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 reorg-test-en.md diff --git a/reorg-test-en.md b/reorg-test-en.md new file mode 100644 index 0000000..d15d249 --- /dev/null +++ b/reorg-test-en.md @@ -0,0 +1,105 @@ +# RGB Reorg Test Report + +## 1. Test Design Overview + +### 1.1 Test Purpose +Verify the state management capability of RGB v0.12 during blockchain reorganization (reorg), ensuring that asset states can be correctly rolled back and restored. + +### 1.2 Test Scenarios +The test was designed with two reorg modes (ReorgType) and three history types (HistoryType), resulting in 6 test case combinations: + +#### Reorg Modes (ReorgType) +- **ChangeOrder**: Change the transaction broadcasting order, simulating scenarios where transactions are confirmed in different orders in the blockchain +- **Revert**: Do not broadcast the initial transaction, simulating scenarios where certain transactions are completely excluded from the blockchain + +#### History Types (HistoryType) +- **Linear**: Linear transfer history, a simple scenario where assets are transferred from A to B, and then partially back to A +- **Branching**: Branching transfer history, where assets are first fully transferred to B, then B transfers part back to A, and B transfers the remaining part (minus 1) back to A +- **Merging**: Merging transfer history, where A holds two assets, transfers them to B in two transactions, and then B transfers almost all (minus 1) back to A + +### 1.3 Test Implementation Principles +The tests simulate blockchain reorganization through the following methods: + +1. **Dual-node Environment**: + - Using two independent Bitcoin node instances (INSTANCE_2 and INSTANCE_3) + - Initially connecting the two nodes to synchronize them + +2. **Reorg Simulation**: + - Disconnecting the nodes, executing transactions in normal order on INSTANCE_2 + - Based on the test scenario, broadcasting transactions in different orders or ignoring certain transactions on INSTANCE_3 + - Switching the wallet to INSTANCE_3 instance and checking state changes + +3. **Asset Reception Method**: + - Using the Auth Token method (pre-created UTXO) to receive assets + - This makes transactions relatively independent and allows flexible adjustment of broadcast order + +4. **State Verification**: + - Verifying asset allocation states after reorg using the `check_allocations` method + - Testing final state consistency after nodes reconnect + +## 2. Test Case Details + +### 2.1 Passed Test Cases + +| Case | History Type | Reorg Type | Status | +| ------ | ------------ | ----------- | -------- | +| case_1 | Linear | ChangeOrder | Passed ✅ | +| case_3 | Branching | ChangeOrder | Passed ✅ | +| case_5 | Merging | ChangeOrder | Passed ✅ | + +**ChangeOrder Test Implementation Details**: +- Execute transactions in the order [tx_0, tx_1, tx_2] on INSTANCE_2 +- Broadcast in different orders on INSTANCE_3 (such as [tx_2, tx_1, tx_0] in the Linear scenario) +- Results match expectations, indicating that RGB correctly handles changes in transaction order + +### 2.2 Failed Test Cases + +| Case | History Type | Reorg Type | Status | Failure Details | +| ------ | ------------ | ---------- | -------- | --------------- | +| case_2 | Linear | Revert | Failed ❌ | | +| case_4 | Branching | Revert | Failed ❌ | | +| case_6 | Merging | Revert | Failed ❌ | | + +**Revert Test Implementation Details**: +- Disconnect INSTANCE_3 from INSTANCE_2 +- Execute transactions in the complete order [tx_0, tx_1, tx_2] on INSTANCE_2 +- Only broadcast subsequent transactions [tx_1, tx_2] on INSTANCE_3, without broadcasting the initial transaction tx_0 +- Expect that without the initial transaction, the asset state should roll back to the initial allocation (passed) +- Reconnect INSTANCE_3 and INSTANCE_2, check state consistency (failed) + - tx_0 is mined in INSTANCE_2, reverted in INSTANCE_3 + - Additionally, INSTANCE_3's chain is 1 block longer than INSTANCE_2 + - But when the two nodes reconnect, tx_0 will be resubmitted to the mempool + - Expected asset state to be restored to its original state + +## 3. Issues Discovered and Fix Progress + +### 3.1 State Rollback Issues in Revert Scenarios +All Revert test cases failed. After multiple PR fixes, we are currently in the final stage, addressing the state forwarding after block reorg. + +#### 3.1.1 Issue One: Incorrect Transaction Status in Indexer (Resolved ✅) +- **Symptom**: Transaction status (TxStatus) in the transaction indexer was not correctly Responded +- **Root Cause**: The transaction indexer did not correctly reflect the confirmation status of transactions in the blockchain, causing the rollback logic based on these transactions to fail +- **Solution**: Fixed the transaction status tracking logic in the indexer +- **PR Link**: [BP-WG/bp-wallet#86](https://github.com/BP-WG/bp-wallet/pull/86) + +#### 3.1.2 Issue Two: Infinite Loop in Rollback Function (Resolved ✅) +- **Symptom**: During the rollback operation process, the same operation was repeatedly added to the rollback chain, causing performance issues and potential infinite loops +- **Root Cause**: The `rollback` function did not check for duplicate operations when building the dependency chain, and incorrectly increased the loop index +- **Solution**: + - Added duplicate check logic: `if chain.contains(&spent) { continue; }` + - Removed the incorrect index increment: `index += 1` (the loop itself already increases the index) +- **PR Link**: [AluVM/sonic#18](https://github.com/AluVM/sonic/pull/18) + +#### 3.1.3 Issue Three: Dependency Recovery Problem in Forward Function (Pending ⏳) +- **Symptom**: When attempting to restore operations after rollback, subsequent operations dependent on the restored operation are not automatically restored +- **Case Analysis**: + - In the first phase of Revert, after tx_0 is reverted in INSTANCE_3, although tx_1 and tx_2 are normally broadcast, the asset transfer chain depends on tx_0, so in the absence of tx_0, the asset correctly reverts to its issuance state + - In the second phase of Revert, after the two Bitcoin nodes reconnect and a reorg occurs (tx_0 is mined in INSTANCE_2, reverted in INSTANCE_3, and INSTANCE_3's chain is 1 block longer than INSTANCE_2; when the two nodes reconnect, tx_0 is resubmitted to the mempool), the expected behavior is that tx_0 (mempool), tx_1 (mined), tx_2 (mined) would sync and restore to the state after witness transaction tx_2, but currently it only restores to the state after witness transaction tx_0 +- **Analysis**: + - The `rollback` function can find the complete dependency chain through the `spent_by` method and roll back + - The `forward` function lacks a similar mechanism to restore the complete dependency chain + +## 4. Recommended Next Steps + +1. **Resolve Forward Function Issues**: + - Hope to receive solutions or suggestions from the doctor \ No newline at end of file From 58ee6200786c2772e8603e52d3cc613fb5101fdc Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 9 May 2025 16:56:13 +0800 Subject: [PATCH 59/90] feat: implement same_transfer_twice_update_witnesses test case with asset transfer logic --- tests/transfer.rs | 64 ++++++++++++++++++++++++++++++++++++-------- tests/utils/chain.rs | 2 +- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 249c42d..6718c64 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -522,14 +522,55 @@ fn transfer_loop( ); } -// Test case pending new rollback procedure API -// Will be updated once the high-level API for rollback handling is available #[rstest] -#[ignore = "Awaiting new rollback procedure API in RGB v0.12"] #[case(TransferType::Blinded)] -#[ignore = "Awaiting new rollback procedure API in RGB v0.12"] #[case(TransferType::Witness)] -fn same_transfer_twice_update_witnesses(#[case] _transfer_type: TransferType) {} +fn same_transfer_twice_update_witnesses(#[case] transfer_type: TransferType) { + println!("transfer_type {transfer_type:?}"); + + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issue_supply = 2000; + // Create and issue NIA asset + let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issue_supply); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, issue_supply); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("TestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + let amount = 100; + let wout = match transfer_type { + TransferType::Blinded => false, + TransferType::Witness => true, + }; + + let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), None); + let _ = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + + wlt_1.sync(); + + let (consignment, tx, _) = wlt_1.transfer(invoice, None, Some(1000), true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_2.accept_transfer(&consignment, None).unwrap(); + wlt_1.sync(); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![issue_supply - amount]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![amount]); + + wlt_2.send( + &mut wlt_1, + wout, + contract_id, + amount, + 1000, + None, + None, + None, + ); +} // Complex test cases - Implementation deferred to final phase // These test cases will be implemented last, after evaluating: @@ -825,25 +866,20 @@ fn blank_tapret_opret( // assertion `left == right` failed // left: [10, 20] // right: [600] -// #[ignore = "fix needed"] #[case(HistoryType::Linear, ReorgType::Revert)] #[case(HistoryType::Branching, ReorgType::ChangeOrder)] -// #[ignore = "fix needed"] // TODO: This test case does not meet expectations, after (transferring 600 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 600 // thread 'reorg_history::case_4' panicked at tests/utils/helpers.rs:909:17: // assertion `left == right` failed // left: [200, 399] // right: [600] -// #[ignore = "fix needed"] #[case(HistoryType::Branching, ReorgType::Revert)] #[case(HistoryType::Merging, ReorgType::ChangeOrder)] -// #[ignore = "fix needed"] // TODO: This test case does not meet expectations, after (transferring 400 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 400 // thread 'reorg_history::case_6' panicked at tests/utils/helpers.rs:909:17: // assertion `left == right` failed // left: [599] // right: [400] -// #[ignore = "fix needed"] #[case(HistoryType::Merging, ReorgType::Revert)] #[serial] fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgType) { @@ -1061,7 +1097,6 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp dbg!(wlt_1.runtime().state_own(contract_id).owned); dbg!(wlt_2.runtime().state_own(contract_id).owned); - // Verify final state based on history type match history_type { HistoryType::Linear => { @@ -1227,6 +1262,13 @@ fn revert_genesis(#[case] with_transfers: bool) { wlt.check_allocations(contract_id, AssetSchema::RGB20, vec![issued_supply - amt]); } + mine_custom(false, INSTANCE_2, 1); + wlt.sync(); + // TODO: + let state = wlt.runtime().state_own(contract_id).owned; + dbg!(state); + panic!(); + // TODO: The following code uses APIs that have been removed in RGB v0.12 // Need to implement new rollback procedure once the API is available // diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 0c75645..7b90394 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -309,7 +309,7 @@ pub fn get_tx_height(txid: Txid, instance: u8) -> Option { height } -pub fn dbg_tx_status(txid: Txid, instance: u8){ +pub fn dbg_tx_status(txid: Txid, instance: u8) { match INDEXER.get().unwrap() { Indexer::Esplora => { let status = EsploraClient::new_esplora(&indexer_url(instance, Network::Regtest)) From b0a43b6ec7f17cd9fc60632c4ce12277507c54aa Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 9 May 2025 18:38:35 +0800 Subject: [PATCH 60/90] refactor: implement revert_transfer_state function --- tests/transfer.rs | 102 +++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 60 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 6718c64..e6dc216 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -23,6 +23,7 @@ pub mod utils; +use rgb::WitnessStatus; use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -861,25 +862,13 @@ fn blank_tapret_opret( #[rstest] #[case(HistoryType::Linear, ReorgType::ChangeOrder)] -// TODO: This test case does not meet expectations, after (transferring 600 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 600 -// thread 'reorg_history::case_2' panicked at tests/utils/helpers.rs:909:17: -// assertion `left == right` failed -// left: [10, 20] -// right: [600] +// FIXME: Hope to receive solutions or suggestions from the doctor #[case(HistoryType::Linear, ReorgType::Revert)] #[case(HistoryType::Branching, ReorgType::ChangeOrder)] -// TODO: This test case does not meet expectations, after (transferring 600 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 600 -// thread 'reorg_history::case_4' panicked at tests/utils/helpers.rs:909:17: -// assertion `left == right` failed -// left: [200, 399] -// right: [600] +// FIXME: Hope to receive solutions or suggestions from the doctor #[case(HistoryType::Branching, ReorgType::Revert)] #[case(HistoryType::Merging, ReorgType::ChangeOrder)] -// TODO: This test case does not meet expectations, after (transferring 400 assets to wallet 2) transaction 0 is reverted, wlt_1's expected allocation is 400 -// thread 'reorg_history::case_6' panicked at tests/utils/helpers.rs:909:17: -// assertion `left == right` failed -// left: [599] -// right: [400] +// FIXME: Hope to receive solutions or suggestions from the doctor #[case(HistoryType::Merging, ReorgType::Revert)] #[serial] fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgType) { @@ -1219,20 +1208,15 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp } } -// TODO: Awaiting new rollback procedure API in RGB v0.12 -#[rstest] -#[case(false)] -#[case(true)] -#[serial] -fn revert_genesis(#[case] with_transfers: bool) { - println!("with_transfers {with_transfers}"); - +#[test] +fn revert_transfer_state() { initialize(); // connecting before disconnecting since disconnect is not idempotent connect_reorg_nodes(); disconnect_reorg_nodes(); let mut wlt = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); + let mut recv_wlt = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); let issued_supply = 600; let utxo = wlt.get_utxo(None); @@ -1241,49 +1225,47 @@ fn revert_genesis(#[case] with_transfers: bool) { let mut params = NIAIssueParams::new("TestAsset", "TEST", "centiMilli", issued_supply); params.add_allocation(utxo, issued_supply); let contract_id = wlt.issue_nia_with_params(params); + wlt.send_contract("TestAsset", &mut recv_wlt); + recv_wlt.reload_runtime(); wlt.check_allocations(contract_id, AssetSchema::RGB20, vec![issued_supply]); - if with_transfers { - let mut recv_wlt = get_wallet_custom(&DescriptorType::Wpkh, INSTANCE_2); - let amt = 200; - wlt.send_contract("TestAsset", &mut recv_wlt); - recv_wlt.reload_runtime(); - wlt.send( - &mut recv_wlt, - false, - contract_id, - amt, - 1000, - None, - None, - None, - ); - wlt.check_allocations(contract_id, AssetSchema::RGB20, vec![issued_supply - amt]); - } + let amt = 200; + + wlt.send( + &mut recv_wlt, + false, + contract_id, + amt, + 1000, + None, + None, + None, + ); + wlt.check_allocations(contract_id, AssetSchema::RGB20, vec![issued_supply - amt]); mine_custom(false, INSTANCE_2, 1); wlt.sync(); - // TODO: - let state = wlt.runtime().state_own(contract_id).owned; - dbg!(state); - panic!(); - - // TODO: The following code uses APIs that have been removed in RGB v0.12 - // Need to implement new rollback procedure once the API is available - // - // assert!(matches!( - // wlt.get_witness_ord(&utxo.txid), - // WitnessOrd::Mined(_) - // )); - // wlt.switch_to_instance(INSTANCE_3); - // assert_eq!(wlt.get_witness_ord(&utxo.txid), WitnessOrd::Archived); - // - // wlt.check_allocations( - // contract_id, - // AssetSchema::RGB20, - // vec![], - // ); + recv_wlt.sync(); + + let state = recv_wlt.runtime().state_own(contract_id).owned; + let witness_status = state + .values() + .next() + .unwrap() + .values() + .next() + .unwrap() + .status; + dbg!(state, witness_status); + assert!(matches!(witness_status, WitnessStatus::Mined(_))); + + recv_wlt.switch_to_instance(INSTANCE_3); + let state = recv_wlt.runtime().state_own(contract_id).owned; + let archived = state.values().next().unwrap().is_empty(); + dbg!(state, archived); + assert!(archived); + recv_wlt.check_allocations(contract_id, AssetSchema::RGB20, vec![]); } #[test] From d65d49e50b13a70b0c2a1a899927193781f46d7c Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 12 May 2025 22:14:46 +0800 Subject: [PATCH 61/90] chore: update submodule, add RBF and reorg test reports --- .gitmodules | 4 +- Cargo.lock | 2 +- bp-wallet | 2 +- reports/rbf-test.md | 115 ++++++++++++++++++++++ reorg-test-en.md => reports/reorg-test.md | 0 rgb-std | 2 +- sonic | 2 +- tests/transfer.rs | 10 +- tests/utils/chain.rs | 38 +++---- 9 files changed, 141 insertions(+), 34 deletions(-) create mode 100644 reports/rbf-test.md rename reorg-test-en.md => reports/reorg-test.md (100%) diff --git a/.gitmodules b/.gitmodules index ff87905..b9ef25b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -33,7 +33,7 @@ url = https://github.com/RGB-WG/rgb [submodule "bp-wallet"] path = bp-wallet - url = https://github.com/BP-WG/bp-wallet + url = https://github.com/BP-WG/bp-wallet.git [submodule "amplify-num"] path = amplify-num url = https://github.com/rust-amplify/amplify-num.git @@ -60,7 +60,7 @@ url = https://github.com/AluVM/ultrasonic [submodule "sonic"] path = sonic - url = https://github.com/AluVM/sonic + url = https://github.com/AluVM/sonic.git [submodule "rgb-interfaces"] path = rgb-interfaces url = https://github.com/RGB-WG/rgb-interfaces.git diff --git a/Cargo.lock b/Cargo.lock index 6a40ea5..e4f0aad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1215,7 +1215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] diff --git a/bp-wallet b/bp-wallet index b639538..d974b91 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit b639538c411091f249118bb49aeefec69c505eb8 +Subproject commit d974b91d1c28a81befbd12cf4ae13a9ca0a2c772 diff --git a/reports/rbf-test.md b/reports/rbf-test.md new file mode 100644 index 0000000..7b0c6d9 --- /dev/null +++ b/reports/rbf-test.md @@ -0,0 +1,115 @@ +# RGB RBF Transfer Test Report + +## 1. Test Design Overview + +### 1.1 Test Purpose +To verify the asset transfer process under the RGB20 protocol with RBF (Replace-By-Fee), ensuring that asset states, witness transactions, and consignment serialization behave as expected. + +### 1.2 Test Scenario +This test focuses on the following process: +- Initiate a normal transfer, with the witness transaction entering the mempool. +- Use RBF to broadcast a replacement transaction with a higher fee. +- (Debug step) Check whether the consignment serialization reflects the latest witness transaction. +- Mine and confirm the new transaction, then check asset allocation and witness status. +- Perform a subsequent transfer to verify the handling of historical witness information. + +### 1.3 Test Implementation +- Two wallet instances are used to simulate asset issuance, transfer, RBF replacement, and asset return. +- APIs such as `tx_status` and `check_allocations` are used to verify transaction status and asset allocation. +- (Debug step) Special attention is paid to whether the consignment serialization updates witness information in a timely manner. + +## 2. Test Case Details + +### 2.1 Test Case Flow + +1. **Asset Issuance and Initial Transfer** + - Wallet 1 issues an NIA asset and allocates it to itself. + - Wallet 1 initiates a transfer to Wallet 2, generating a witness transaction (mempool status). + - Wallet 2 receives and accepts the consignment. + +2. **RBF Replacement Process** + - Wallet 1 uses RBF to broadcast a replacement transaction with a higher fee. + - A new consignment is generated; + - The new transaction is mined and confirmed; both old and new transaction statuses are checked. + +3. **Asset Allocation and Return** + - Wallet 2 accepts the final consignment. + - Asset allocations in both wallets are verified. + - Wallet 2 returns assets to Wallet 1, verifying the handling of historical witness information. + +### 2.2 Key Debug Information and Observations + +- **Consignment Serialization Issue** + During debugging, it was found that after RBF and subsequent consignment generation, the serialized witness information still refers to the invalid (old) witness. + The likely cause is that during the initial transfer, the relationship between terminal (auth-token) and cell-addr (opid-pos) is established in `RgbRuntime::exec` when generating the Prefab, but RBF does not update this relationship, causing the terminal to always reference the old operation. + +- **Internal State Complexity** + The current internal state management is complex, so we are cautious about making changes to the RBF logic and expect a fix from the Doctor. + +### 2.3 Debug Log Excerpts + +- The initial transfer's witness transaction is in the mempool, and consignment serialization is correct. +- After RBF, the new consignment still serializes the old witness. +- After mining, the old witness transaction status becomes Unknown, and the new witness transaction is Mined. +- In subsequent transfers, the consignment still contains the opid corresponding to the invalid witness transaction. + +## 3. Identified Issues and Progress + +### 3.1 Consignment Serialization Not Updated After RBF +- **Symptom**: After RBF, the consignment still serializes the old (invalid) witness. +- **Root Cause**: The relationship between terminal (auth-token) and cell-addr (opid-pos) is not updated in time. +- **Solution**: Further analysis and a fix from the Doctor are needed. + + +**Debug Log for RBF Transfer Test Case** + +``` test-case debug info +// First, perform a normal transfer; the witness transaction is in the mempool +// At the same time, the consignment serializes the witness transaction correctly +transfer txid: 353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a, consignment: 1 +[rgb-std/src/contract.rs:521:21] opid = Opid( + Array<32>(5a7a6ca82d1b59a06cf42fb673c1f2257787e7d1408ef03c46e3550851e556d2), +) +[rgb-std/src/contract.rs:521:21] &wid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) +[rgb-std/src/contract.rs:521:21] status = Tentative + +[tests/transfer.rs:150:5] first_txid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) +[tests/transfer.rs:150:5] tx_status(first_txid, wlt_1.instance) = Mempool + +// Based on the previous transfer, perform RBF, generating consignment2 and a new witness transaction, but the serialized witness is still the old one +transfer txid: e2a057f50d037d48cd68bcdee4eadd29345db51caa16c1b763a6d6b07753be29, consignment: 2 +[rgb-std/src/contract.rs:521:21] opid = Opid( + Array<32>(5a7a6ca82d1b59a06cf42fb673c1f2257787e7d1408ef03c46e3550851e556d2), +) +[rgb-std/src/contract.rs:521:21] &wid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) +[rgb-std/src/contract.rs:521:21] status = Tentative + +// Mining and accept are performed here + +// Then check the status of the old and new transactions +// The old witness transaction is found to be invalid +[tests/transfer.rs:168:5] first_txid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) +[tests/transfer.rs:168:5] tx_status(first_txid, wlt_1.instance) = Unknown +// The new one is confirmed +[tests/transfer.rs:169:5] second_txid = Array<32>(e2a057f50d037d48cd68bcdee4eadd29345db51caa16c1b763a6d6b07753be29) +[tests/transfer.rs:169:5] tx_status(second_txid, wlt_1.instance) = Mined( + MiningInfo { + height: 1129, + time: 1747048278, + block_hash: Array<32>(5b8516b3a3554f67eb4d0103634ee409df04971fa803fb5c10643888ebed3fde), + }, +) + +// In the subsequent transfer, it can be seen that the opid corresponding to the invalid witness transaction is still included +transfer txid: 23cf85a01dbf024eeb8caf58170297097bb2ff01e5eaaeb7dd29c25116b819c4, consignment: 3 +[rgb-std/src/contract.rs:521:21] opid = Opid( + Array<32>(5a7a6ca82d1b59a06cf42fb673c1f2257787e7d1408ef03c46e3550851e556d2), +) +[rgb-std/src/contract.rs:521:21] &wid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) +[rgb-std/src/contract.rs:521:21] status = Archived +[rgb-std/src/contract.rs:521:21] opid = Opid( + Array<32>(bfbe0249576dac4dd64b6f3abff32efce0d899a24228172b905e0b73110c33cc), +) +[rgb-std/src/contract.rs:521:21] &wid = Array<32>(23cf85a01dbf024eeb8caf58170297097bb2ff01e5eaaeb7dd29c25116b819c4) +[rgb-std/src/contract.rs:521:21] status = Tentative +``` \ No newline at end of file diff --git a/reorg-test-en.md b/reports/reorg-test.md similarity index 100% rename from reorg-test-en.md rename to reports/reorg-test.md diff --git a/rgb-std b/rgb-std index a45d927..1b28f40 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit a45d92705116d1e284ada9b9db6d9b566ffa6035 +Subproject commit 1b28f403face9c462be5a1ccdee3cee8e816458e diff --git a/sonic b/sonic index ca3261e..50958b0 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit ca3261e8e67effbedd3835e2876424f790c86efc +Subproject commit 50958b02eba6e93e41b12b31b75d53ae675c154a diff --git a/tests/transfer.rs b/tests/transfer.rs index e6dc216..de29bff 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -28,7 +28,7 @@ use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; -use utils::chain::{dbg_tx_status, get_tx_height}; +use utils::chain::{tx_status, get_tx_height}; use utils::helper::wallet::{ broadcast_tx_and_mine, get_mainnet_wallet, get_wallet, get_wallet_custom, AssetSchema, }; @@ -146,6 +146,8 @@ fn rbf_transfer() { // First transfer attempt - with a lower fee let (consignment_1, _tx, payment) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None); + let first_txid = _tx.txid(); + dbg!(first_txid, tx_status(first_txid, wlt_1.instance)); // Receiver accepts the transfer wlt_2.accept_transfer(&consignment_1, None).unwrap(); @@ -156,13 +158,15 @@ fn rbf_transfer() { // Second transfer attempt - with a higher fee for RBF let (consignment_2, tx) = wlt_1.transfer_rbf(contract_id, payment, 1000, None); - + let second_txid = tx.txid(); // Verify block height still hasn't changed let final_height = get_height(); assert_eq!(initial_height, final_height); // Broadcast and confirm transaction wlt_1.mine_tx(&tx.txid(), true); + dbg!(first_txid, tx_status(first_txid, wlt_1.instance)); + dbg!(second_txid, tx_status(second_txid, wlt_1.instance)); // Receiver accepts final transfer wlt_2.accept_transfer(&consignment_2, None).unwrap(); @@ -1013,7 +1017,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_1.switch_to_instance(INSTANCE_3); wlt_2.switch_to_instance(INSTANCE_3); let wlt_1_alloc_1 = 600; - dbg!(dbg_tx_status(txs[0].txid(), INSTANCE_3)); + dbg!(tx_status(txs[0].txid(), INSTANCE_3)); dbg!(wlt_1.runtime().state_own(contract_id).owned); dbg!(wlt_2.runtime().state_own(contract_id).owned); wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 7b90394..6842387 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -287,38 +287,26 @@ pub fn get_height_custom(instance: u8) -> u32 { } pub fn get_tx_height(txid: Txid, instance: u8) -> Option { - let height = match INDEXER.get().unwrap() { - Indexer::Electrum => { - let status = ElectrumClient::new(&indexer_url(instance, Network::Regtest)) - .unwrap() - .status(txid) - .unwrap(); - match status { - TxStatus::Mined(block_height) => Some(block_height.height.into()), - _ => None, - } - } + match tx_status(txid, instance) { + TxStatus::Mined(info) => Some(info.height.into()), + _ => None, + } +} + +pub fn tx_status(txid: Txid, instance: u8) -> TxStatus { + match INDEXER.get().unwrap() { Indexer::Esplora => { EsploraClient::new_esplora(&indexer_url(instance, Network::Regtest)) .unwrap() - .tx_status(&txid) + .status(txid) .unwrap() - .block_height } - }; - height -} - -pub fn dbg_tx_status(txid: Txid, instance: u8) { - match INDEXER.get().unwrap() { - Indexer::Esplora => { - let status = EsploraClient::new_esplora(&indexer_url(instance, Network::Regtest)) + Indexer::Electrum => { + ElectrumClient::new(&indexer_url(instance, Network::Regtest)) + .unwrap() + .status(txid) .unwrap() - .tx_status(&txid) - .unwrap(); - dbg!(txid, &status); } - _ => unreachable!(), } } From 32b3b64d565fba8a16abde2eab389097be619a5a Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Mon, 12 May 2025 22:31:07 +0800 Subject: [PATCH 62/90] docs: clarify impact of bp-wallet fix on RBF test and explain previous bug in esplora --- reports/rbf-test.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/reports/rbf-test.md b/reports/rbf-test.md index 7b0c6d9..0b09375 100644 --- a/reports/rbf-test.md +++ b/reports/rbf-test.md @@ -46,6 +46,9 @@ This test focuses on the following process: - **Internal State Complexity** The current internal state management is complex, so we are cautious about making changes to the RBF logic and expect a fix from the Doctor. +- **Why the bp-wallet fix affects the RBF test:** + Previously, the rbf_transfer test could pass because of a bug in esplora: for non-existent transactions, it would still return `TxStatus::Mempool`, allowing the validation to succeed. After the bp-wallet fix, this behavior was corrected, which exposed the underlying issue in consignment serialization. + ### 2.3 Debug Log Excerpts - The initial transfer's witness transaction is in the mempool, and consignment serialization is correct. From 114072166bf48aac6c6c0fe2b6786b677f220e4f Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 13 May 2025 18:40:08 +0800 Subject: [PATCH 63/90] feat: add RGB Asset Issuance Test Report and update issuance tests --- reports/rgb_asset_issuance_test_report.md | 45 +++++++++++++++++++++++ tests/issuance.rs | 3 -- tests/templates/issuance/FAC.yaml | 7 +++- tests/utils/helper/asset_types.rs | 7 ++-- tests/utils/helper/wallet.rs | 31 ++++++++-------- tests/utils/mod.rs | 2 +- 6 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 reports/rgb_asset_issuance_test_report.md diff --git a/reports/rgb_asset_issuance_test_report.md b/reports/rgb_asset_issuance_test_report.md new file mode 100644 index 0000000..46dda37 --- /dev/null +++ b/reports/rgb_asset_issuance_test_report.md @@ -0,0 +1,45 @@ +# RGB Asset Issuance Test Report + +## Overview + +This test report covers the issuance functionality of different asset types in the RGB protocol, including RGB20 (NIA), RGB25 (FUA), and RGB21 (FAC) assets. + +## Test Environment +- Testing Framework: Rust Test +- Test File: `tests/issuance.rs` +- Test Cases: 10 test cases covering different asset types and wallet types + +## Test Results Summary + +### Successful Cases (8/10) + +1. **RGB20 - NIA Assets** + - Single UTXO issuance tests (`issue_nia::case_1`, `issue_nia::case_2`) + - Multiple UTXO issuance tests (`issue_nia_multiple_utxos::case_1`, `issue_nia_multiple_utxos::case_2`) + - Support for both Wpkh and Tr wallet types + +2. **RGB25 - FUA Assets** + - Single UTXO issuance tests (`issue_fua::case_1`, `issue_fua::case_2`) + - Multiple UTXO issuance tests (`issue_fua_multiple_utxos::case_1`, `issue_fua_multiple_utxos::case_2`) + - Support for both Wpkh and Tr wallet types + +### Failed Cases (2/10) + +**RGB21 - FAC Assets** +- Test cases: `issue_fac::case_1`, `issue_fac::case_2` +- Context: + Despite completing the adaptation for the latest RGB21 asset structure, we still encountered issuance failures during testing +- Error message: + ``` + failed to issue contract: Inner(Genesis(Named(TypeName("DigitalCollection")), ScriptUnspecified)) + ``` +- Failure analysis: + We suspect that the `FN_ASSET_SPEC` validation script implementation is incompatible with the RGB21 asset structure, causing validation failures. We respectfully request the Doctor's judgment on whether different validation logic needs to be created for RGB21 assets. + +## Next Steps + +1. Current focus is on stability and performance testing of RGB20 assets +2. RGB21-related issues are merely being collected for future solutions from the Doctor +3. Collect and synchronize feedback on RGB21 asset issuance problems + +*Note: RGB21 is not our main focus at this stage, as we are currently concentrating on improving the functionality of RGB20.* \ No newline at end of file diff --git a/tests/issuance.rs b/tests/issuance.rs index 742ed40..4cea310 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -52,7 +52,6 @@ fn issue_nia(wallet_desc: DescriptorType) { assert_eq!(state.immutable.circulating_supply, 1_000_000); // Verify ownership state - dbg!(&state.owned.allocations); assert_eq!(state.owned.allocations.len(), 2); assert!(state .owned @@ -64,7 +63,6 @@ fn issue_nia(wallet_desc: DescriptorType) { .allocations .iter() .any(|(outpoint, amount)| outpoint.primary == fake_outpoint_one && *amount == 500_000)); - dbg!(wallet.runtime().state_all(contract_id)); } #[apply(descriptor_and_close_method)] @@ -104,7 +102,6 @@ fn issue_fua(wallet_desc: DescriptorType) { .allocations .iter() .any(|(outpoint, amount)| outpoint.primary == fake_outpoint && *amount == 10_000)); - dbg!(wallet.runtime().state_all(contract_id)); } #[apply(descriptor_and_close_method)] diff --git a/tests/templates/issuance/FAC.yaml b/tests/templates/issuance/FAC.yaml index 371b353..bedb48a 100644 --- a/tests/templates/issuance/FAC.yaml +++ b/tests/templates/issuance/FAC.yaml @@ -68,5 +68,10 @@ global: owned: - name: fractions seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 - data: 10000 + data: + tokenIndex: 0 + fraction: 10000 + # TODO: `align` is a 26-sized U8 array, + # Need to rewrite to bytes in code + align: diff --git a/tests/utils/helper/asset_types.rs b/tests/utils/helper/asset_types.rs index 38f7b69..2dd595b 100644 --- a/tests/utils/helper/asset_types.rs +++ b/tests/utils/helper/asset_types.rs @@ -130,8 +130,8 @@ pub struct FACIssueParams { pub total_fractions: u64, /// Token index pub index: u32, - /// Initial token allocation (outpoint, amount) - pub initial_allocation: Option<(Outpoint, u64)>, + /// Initial token allocation (outpoint, Nft) + pub initial_allocation: Option<(Outpoint, Nft)>, /// NFT specification pub nft_spec: Option, } @@ -164,7 +164,8 @@ impl FACIssueParams { /// Set token allocation pub fn with_allocation(&mut self, outpoint: Outpoint, amount: u64) -> &mut Self { - self.initial_allocation = Some((outpoint, amount)); + let nft = Nft::new(self.index, amount); + self.initial_allocation = Some((outpoint, nft)); self } diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 306a4ba..2575275 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -211,7 +211,7 @@ fn _get_wallet( let entry = entry.unwrap(); let path = entry.path(); if path.is_file() && path.extension().map_or(false, |ext| ext == "issuer") { - println!("Auto-importing issuer file: {}", path.display()); + // println!("Auto-importing issuer file: {}", path.display()); if let Err(err) = test_wallet.import(path) { println!("Warning: Failed to import issuer: {}", err); } @@ -374,7 +374,7 @@ impl TestWallet { builder = builder.add_owned_state(outpoint, amount); } - self.issue_with_params(dbg!(builder.build())) + self.issue_with_params(builder.build()) } pub fn switch_to_instance(&mut self, instance: u8) { @@ -766,16 +766,16 @@ impl TestWallet { )); } - print!( - "Processing '{}' ... ", - schema_path.file_name().unwrap().to_string_lossy() - ); + // print!( + // "Processing '{}' ... ", + // schema_path.file_name().unwrap().to_string_lossy() + // ); // Load schema and get codex ID let schema = Schema::load(schema_path)?; let codex_id = schema.codex.codex_id(); - print!("codex id {} ... ", codex_id); + // print!("codex id {} ... ", codex_id); // Import the schema into contracts if self.runtime.contracts.has_issuer(codex_id) { @@ -787,7 +787,6 @@ impl TestWallet { .contracts .import_issuer(schema) .map_err(|e| format!("import error: {}", e.to_string()))?; - println!("success"); Ok(()) } @@ -814,9 +813,6 @@ impl TestWallet { let precision = immutable .get(&VariantName::from_str("precision").unwrap()) .and_then(|m| m.values().next()) - .inspect(|v| { - dbg!(&v.data.verified); - }) .map(|v| { let tag = v.data.verified.unwrap_enum_tag(); if let EnumTag::Name(name) = tag { @@ -1258,11 +1254,16 @@ impl TestWallet { let name = VariantName::from_str("fractions").unwrap(); if name_state.name == name { let fractions = &mut name_state.state; - fractions.seal = EitherSeal::Alt(params.initial_allocation.unwrap().0); + fractions.seal = EitherSeal::Alt(params.initial_allocation.as_ref().unwrap().0); let fractions_data = &mut fractions.data; - *fractions_data = StrictVal::Tuple(vec![StrictVal::Number(StrictNum::from( - params.initial_allocation.unwrap().1, - ))]); + + let nft = ¶ms.initial_allocation.as_ref().unwrap().1; + let nft_data = StrictVal::Struct(IndexMap::from([ + (FieldName::from_str("tokenIndex").unwrap(), StrictVal::Number(StrictNum::from(nft.token_index.into_inner()))), + (FieldName::from_str("fraction").unwrap(), StrictVal::Number(StrictNum::from(nft.fraction.into_inner()))), + (FieldName::from_str("align").unwrap(), StrictVal::Bytes(Blob(vec![0; 26]))), + ])); + *fractions_data = nft_data; } } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 9c25b13..125a06d 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -70,7 +70,7 @@ pub use electrum::{Client as ElectrumClient, ElectrumApi, Param}; pub use file_format::FileFormat; pub use ifaces::{ AssetName, Attachment, Details, EmbeddedMedia, MediaType, NftSpec, ProofOfReserves, Ticker, - TokenIndex, + TokenIndex,Nft }; pub use indexmap::IndexMap; pub use once_cell::sync::Lazy; From b66a335b74df5a39acacbc94ebd5f39ff4d536d0 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 13 May 2025 20:00:24 +0800 Subject: [PATCH 64/90] fix: error of same_transfer_twice_no_update_witnesses and fmt --- tests/transfer.rs | 4 ++-- tests/utils/chain.rs | 20 ++++++++------------ tests/utils/helper/wallet.rs | 15 ++++++++++++--- tests/utils/mod.rs | 4 ++-- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index de29bff..e0954e4 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -28,7 +28,7 @@ use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; -use utils::chain::{tx_status, get_tx_height}; +use utils::chain::{get_tx_height, tx_status}; use utils::helper::wallet::{ broadcast_tx_and_mine, get_mainnet_wallet, get_wallet, get_wallet_custom, AssetSchema, }; @@ -599,7 +599,7 @@ fn collaborative_transfer() { } #[rstest] -#[should_panic(expected = "unknown seal definition for cell address")] +#[should_panic(expected = "Fulfill(StateInsufficient)")] #[case(TransferType::Blinded)] #[should_panic(expected = "Fulfill(StateInsufficient)")] #[case(TransferType::Witness)] diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 6842387..9faaba6 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -295,18 +295,14 @@ pub fn get_tx_height(txid: Txid, instance: u8) -> Option { pub fn tx_status(txid: Txid, instance: u8) -> TxStatus { match INDEXER.get().unwrap() { - Indexer::Esplora => { - EsploraClient::new_esplora(&indexer_url(instance, Network::Regtest)) - .unwrap() - .status(txid) - .unwrap() - } - Indexer::Electrum => { - ElectrumClient::new(&indexer_url(instance, Network::Regtest)) - .unwrap() - .status(txid) - .unwrap() - } + Indexer::Esplora => EsploraClient::new_esplora(&indexer_url(instance, Network::Regtest)) + .unwrap() + .status(txid) + .unwrap(), + Indexer::Electrum => ElectrumClient::new(&indexer_url(instance, Network::Regtest)) + .unwrap() + .status(txid) + .unwrap(), } } diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 2575275..39f91f7 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -1259,9 +1259,18 @@ impl TestWallet { let nft = ¶ms.initial_allocation.as_ref().unwrap().1; let nft_data = StrictVal::Struct(IndexMap::from([ - (FieldName::from_str("tokenIndex").unwrap(), StrictVal::Number(StrictNum::from(nft.token_index.into_inner()))), - (FieldName::from_str("fraction").unwrap(), StrictVal::Number(StrictNum::from(nft.fraction.into_inner()))), - (FieldName::from_str("align").unwrap(), StrictVal::Bytes(Blob(vec![0; 26]))), + ( + FieldName::from_str("tokenIndex").unwrap(), + StrictVal::Number(StrictNum::from(nft.token_index.into_inner())), + ), + ( + FieldName::from_str("fraction").unwrap(), + StrictVal::Number(StrictNum::from(nft.fraction.into_inner())), + ), + ( + FieldName::from_str("align").unwrap(), + StrictVal::Bytes(Blob(vec![0; 26])), + ), ])); *fractions_data = nft_data; } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 125a06d..79bb66f 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -69,8 +69,8 @@ pub use descriptors::Wpkh; pub use electrum::{Client as ElectrumClient, ElectrumApi, Param}; pub use file_format::FileFormat; pub use ifaces::{ - AssetName, Attachment, Details, EmbeddedMedia, MediaType, NftSpec, ProofOfReserves, Ticker, - TokenIndex,Nft + AssetName, Attachment, Details, EmbeddedMedia, MediaType, Nft, NftSpec, ProofOfReserves, + Ticker, TokenIndex, }; pub use indexmap::IndexMap; pub use once_cell::sync::Lazy; From 67da5c26209f3101cabdbaa39f7da825abedca1d Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 13 May 2025 23:13:24 +0800 Subject: [PATCH 65/90] fix: failure of the rbf_transfer assertion --- rgb-core | 2 +- rgb-std | 2 +- sonic | 2 +- tests/utils/helper/wallet.rs | 12 ++++++++++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/rgb-core b/rgb-core index c8a07ff..6719b91 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit c8a07ff2e8b2bb0c98f0cc963f9c1b061b6ea83a +Subproject commit 6719b9147f55a4e3ce5dac05164da820aa6e9720 diff --git a/rgb-std b/rgb-std index 1b28f40..723671f 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 1b28f403face9c462be5a1ccdee3cee8e816458e +Subproject commit 723671fe32023dea9ab215ebc0a2a43bcdeb6988 diff --git a/sonic b/sonic index 50958b0..905b347 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 50958b02eba6e93e41b12b31b75d53ae675c154a +Subproject commit 905b34766625914354b841d8133585d9053e48b2 diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 39f91f7..a587c3c 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -660,14 +660,22 @@ impl TestWallet { let pay_start = Instant::now(); let pay_duration = pay_start.elapsed(); - let psbt = self.runtime.rbf(&payment, fee).unwrap(); + // broadcast the transaction immediately after rbf execution, + // Wait for the old transaction to be archived, and then actively sync the wallet + let mut psbt = self.runtime.rbf(&payment, fee).unwrap(); + + let tx = self.sign_finalize_extract(&mut psbt); + + self.broadcast_tx(&tx); + std::thread::sleep(Duration::from_secs(10)); + self.sync(); let (consignment, tx) = self.consign( contract_id, psbt, &payment.terminals, pay_duration, - true, + false, report, ); (consignment, tx) From cdd50ff68c1c69ddd18049bfed52837009001ae6 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 14 May 2025 14:24:08 +0800 Subject: [PATCH 66/90] test: add #[serial] attribute to revert_transfer_state for proper execution order Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index e0954e4..0d6965d 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1213,6 +1213,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp } #[test] +#[serial] fn revert_transfer_state() { initialize(); // connecting before disconnecting since disconnect is not idempotent From f4ac7563d9a6e5aa9a5fb12180aeffe40e3bfa3d Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 14 May 2025 17:36:43 +0800 Subject: [PATCH 67/90] fix: add force stop sync functionality to prevent invalid asset transfers Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 38 +++++++++++++----------------------- tests/utils/helper/wallet.rs | 14 +++++++++++++ 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 0d6965d..30b285e 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1403,7 +1403,7 @@ fn pay_one_invoice_twice(#[case] transfer_type: TransferType) { } #[test] -#[ignore = "fix needed"] // https://github.com/BP-WG/bp-wallet/issues/70 +#[ignore = "fix needed"] #[serial] fn sync_mainnet_wlt() { initialize(); @@ -1418,25 +1418,6 @@ fn sync_mainnet_wlt() { #[test] #[serial] -// TODO: This test case cannot pass currently -// -// The background is as follows: -// wallet 1 first transfers RGB assets to wallet 2, where wallet 2 receives the assets -// in a blinded manner (using an existing UTXO create rgb-invoice). -// The witness transaction generated between them has not been broadcasted to the network, -// wallet 2 accepts the consignment, use the received assets to transfer to wallet 3 -// finally, the transfer is completed, the asset results of wallet 2 and wallet 3 are correct, -// but the asset result of wallet 1 is incorrect -// -// However, I observed that in the original v0.11.0-beta.9 version, this test case expected wallet 3's accept_transfer to fail. -// The main distinction likely arises from the significant differences in the critical workflow between the two versions: -// In v0.11.0-beta.9, when wallet 1 transfers assets to wallet 2, if wallet 2 wants to accept the consignment, -// it must implement a custom Resolver; otherwise, the validation cannot pass (because the transaction hasn't been broadcast to the network). -// But in v0.12 version, the resolver concept has been removed, so wallet 2 can normally accept the consignment, -// and the phenomenon of wallet 2 successfully transferring to wallet 3 occurs. -// There is a significant distinction between the test cases in these two versions. I believe the expected behavior of this test case -// remains to be determined. -// We need to wait for the completion of the latest indexer/resolver implementation with the doctor before revisiting this issue. fn receive_from_unbroadcasted_transfer_to_blinded() { initialize(); @@ -1474,16 +1455,25 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { dbg!(wlt_2.runtime().state_own(contract_id).owned); let invoice = wlt_3.invoice(contract_id, 50, true, None, None); + // force stop sync, because the asset of wlt1 to wlt2 has not been on-chain, + // the transfer will execute sync, so it is impossible to transfer assets to wlt3 + wlt_2.set_force_stop_sync(true); let (consignment, tx, _) = wlt_2.transfer(invoice, Some(2000), None, true, None); wlt_2.mine_tx(&tx.txid(), false); - wlt_2.sync(); - wlt_1.sync(); wlt_3.accept_transfer(&consignment, None).unwrap(); let wlt_3_states = wlt_3.runtime().state_own(contract_id).owned; let wlt_2_states = wlt_2.runtime().state_own(contract_id).owned; dbg!(wlt_3_states, wlt_2_states); + dbg!(wlt_2.runtime().state_all(contract_id).owned); + dbg!(wlt_1.runtime().state_own(contract_id).owned); + dbg!(wlt_1.runtime().state_all(contract_id).owned); wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![50]); - wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![50]); - wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![500]); + // This is the key point: + // Since the asset transfer from wlt1 to wlt2 was not broadcasted on-chain, + // when wlt2 transfers part of this asset to wlt3 and broadcasts it on-chain, + // after sync the transaction is invalid because the original witness information + // cannot be traced back to its source. The asset becoming invalid is expected behavior. + wlt_3.sync(); + wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![]); } diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index a587c3c..ba3234c 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -21,6 +21,8 @@ pub struct TestWallet { pub coinselect_strategy: CustomCoinselectStrategy, /// Optional wallet identifier for reporting purposes pub wallet_id: Option, + /// Whether to force stop sync + pub force_stop_sync: bool, } pub enum AllocationFilter { @@ -202,6 +204,7 @@ fn _get_wallet( instance, coinselect_strategy: CustomCoinselectStrategy::default(), wallet_id: None, + force_stop_sync: false, }; // Import all issuer files from the schemata directory @@ -300,6 +303,14 @@ impl TestWallet { self.network().is_testnet() } + pub fn force_stop_sync(&self) -> bool { + self.force_stop_sync + } + + pub fn set_force_stop_sync(&mut self, force_stop_sync: bool) { + self.force_stop_sync = force_stop_sync; + } + pub fn get_derived_address(&self) -> DerivedAddr { self.runtime .wallet @@ -395,6 +406,9 @@ impl TestWallet { } pub fn sync(&mut self) { + if self.force_stop_sync { + return; + } let indexer = self.get_indexer(); self.runtime.sync(&indexer).expect("Failed to sync wallet"); } From ceb61c9b4aa5eb9d7576a8891d68461c26e08578 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 14 May 2025 19:04:35 +0800 Subject: [PATCH 68/90] test: enhance same_transfer_twice_no_update_witnesses with additional wallet interactions Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 30b285e..11d2d5c 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -610,6 +610,7 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_3 = get_wallet(&DescriptorType::Wpkh); let issue_supply = 2000; // Create and issue NIA asset @@ -619,13 +620,22 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) let contract_id = wlt_1.issue_nia_with_params(params); wlt_1.send_contract("TestAsset", &mut wlt_2); wlt_2.reload_runtime(); + wlt_1.send_contract("TestAsset", &mut wlt_3); + wlt_3.reload_runtime(); let amount = 100; let wout = match transfer_type { TransferType::Blinded => false, TransferType::Witness => true, }; - let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), None); + let wlt1_utxo = wlt_1.get_utxo(None); + let wlt2_utxo = wlt_2.get_utxo(None); + let wlt3_utxo = wlt_3.get_utxo(None); + wlt_1.set_force_stop_sync(true); + wlt_2.set_force_stop_sync(true); + wlt_3.set_force_stop_sync(true); + + let invoice = wlt_2.invoice(contract_id, amount, wout, Some(0), Some(wlt2_utxo)); let (_, _tx, payment) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None); let (consignment, _) = wlt_1.transfer_rbf(contract_id, payment, 1000, None); @@ -639,32 +649,16 @@ fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); } - wlt_2.send( - &mut wlt_1, - wout, - contract_id, - amount, - 1000, - None, - None, - None, - ); - - let mut wlt_3 = get_wallet(&DescriptorType::Wpkh); - wlt_1.send_contract("TestAsset", &mut wlt_3); - wlt_3.reload_runtime(); + let invoice = wlt_1.invoice(contract_id, amount, wout, Some(0), Some(wlt1_utxo)); + let (consignment, _tx, _payment) = + wlt_2.transfer(invoice.clone(), None, Some(500), false, None); + wlt_1.accept_transfer(&consignment, None).unwrap(); // The receiver will fail to accept the consignment - wlt_1.send( - &mut wlt_3, - wout, - contract_id, - issue_supply, - 1000, - None, - None, - None, - ); + let invoice = wlt_3.invoice(contract_id, issue_supply, wout, Some(0), Some(wlt3_utxo)); + let (consignment, _tx, _payment) = + wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + wlt_3.accept_transfer(&consignment, None).unwrap(); } #[test] From 5697e1e608cef973116dcb18f7e356de93fc322c Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 15 May 2025 14:42:34 +0800 Subject: [PATCH 69/90] chore: update dependencies and add RGB reorg test analysis report Signed-off-by: will-bitlightlabs --- Cargo.lock | 1 + reports/reorg-test-fix-v2.md | 162 +++++++++++++++++++++++++++++++++++ rgb-std | 2 +- sonic | 2 +- tests/transfer.rs | 22 ++++- tests/utils/helper/wallet.rs | 5 +- tests/utils/mod.rs | 4 +- 7 files changed, 186 insertions(+), 12 deletions(-) create mode 100644 reports/reorg-test-fix-v2.md diff --git a/Cargo.lock b/Cargo.lock index e4f0aad..eba4632 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1081,6 +1081,7 @@ dependencies = [ "aora", "commit_verify", "getrandom 0.2.14", + "indexmap 2.9.0", "serde", "sonic-api", "sonic-callreq", diff --git a/reports/reorg-test-fix-v2.md b/reports/reorg-test-fix-v2.md new file mode 100644 index 0000000..a6fe114 --- /dev/null +++ b/reports/reorg-test-fix-v2.md @@ -0,0 +1,162 @@ +# RGB Reorg Test Analysis Report + +## Introduction + +After updating to the latest dependencies (including Sonic develop and rgb-std fix/forward branch), the `Revert` type reorg scenarios in the `reorg_history` test case are still failing. + +## Dependency Versions and Additional Failures + +### Current Dependency Versions + +| Dependency | Version/Commit | Note | +| ----------- | ----------------------------------------------------------------- | ---- | +| **rgb-std** | `fix/forward` branch (`38af4585372df1326d0daac9b3b14c6d02b919a1`) | ⚠️ | +| **sonic** | `develop` branch (`323ac8078ff313c02d51c6d0d65218570aaeaafb`) | ⚠️ | + +### Additional Test Failures + +**Note to the doctor**: With the current versions of rgb-std and sonic, the `rbf_transfer` test case is also failing. This suggests that the issues with transaction dependency tracking affect not only reorg scenarios but also Replace-By-Fee (RBF) functionality, which relies on similar state management mechanisms. + +## Test Process and Failure Point + +The reorg test proceeds in three distinct stages: + +1. **Stage 1**: Execute RGB asset transactions on Bitcoin node INSTANCE_2. +2. **Stage 2**: On Bitcoin node INSTANCE_3, simulate a blockchain reorganization: + - For `ChangeOrder` scenarios: broadcast the same transactions but in a different order + - For `Revert` scenarios: broadcast only subsequent transactions (tx_1, tx_2) without the initial transaction (tx_0) + - **Check asset state validity after sync** ← Current Failure Point +3. **Stage 3**: Reconnect both Bitcoin nodes, allowing them to synchronize: + - For `Revert` scenarios: previously reverted transaction tx_0 is resubmitted to the mempool + - Check final asset state validity after complete synchronization + +**Note**: Unlike the previous implementation where failures occurred in Stage 3, the current implementation fails in Stage 2. + +## Test Scenario Overview + +The `reorg_history` test case verifies correct handling of RGB asset states across different history types and reorganization types. + +### Test Matrix + +| History Type | Reorg Type | Status | +| ------------ | ----------- | ------ | +| Linear | ChangeOrder | ✅ Pass | +| Linear | Revert | ❌ Fail | +| Branching | ChangeOrder | ✅ Pass | +| Branching | Revert | ❌ Fail | +| Merging | ChangeOrder | ✅ Pass | +| Merging | Revert | ❌ Fail | + +## Detailed Analysis: Linear-Revert Scenario + +Using the `HistoryType::Linear` and `ReorgType::Revert` case as an example: + +### 1. Initial Setup + +- Two Bitcoin node instances (INSTANCE_2 and INSTANCE_3) are created +- An RGB20 asset with total supply of 600 is issued on INSTANCE_2 +- Initial allocation: wlt_1 owns all 600 units + +### 2. Transaction Sequence (INSTANCE_2) + +| TX ID | Operation | Transfer Amount | Resulting State | +| ----- | ------------- | --------------- | ---------------------------------- | +| tx_0 | wlt_1 → wlt_2 | 590 | wlt_1: 10, wlt_2: 590 | +| tx_1 | wlt_2 → wlt_1 | 100 | wlt_1: 10+100=110, wlt_2: 490 | +| tx_2 | wlt_1 → wlt_2 | 80 | wlt_1: 10+20=30, wlt_2: 490+80=570 | + + +### 3. Reorg Scenario (INSTANCE_3) - Stage 2 Failure Point + +On INSTANCE_3, only tx_1 and tx_2 are broadcast, **tx_0 is not broadcast**, simulating a scenario where tx_0 has been reverted: + +```rust +broadcast_tx_and_mine(&txs[1], INSTANCE_3); +broadcast_tx_and_mine(&txs[2], INSTANCE_3); +``` + +After switching the wallet to INSTANCE_3 and syncing: + +```rust +wlt_1.switch_to_instance(INSTANCE_3); +wlt_2.switch_to_instance(INSTANCE_3); +``` + +### 4. Actual Results vs. Expected Results (Stage 2) + +**Expected Result**: +- When tx_0 is reverted, subsequent tx_1 and tx_2 that depend on the asset transfers in tx_0 should be invalid +- wlt_1 should maintain its original 600 assets, while wlt_2 should have no assets + +**Actual Result**: +- tx_0 related state is correctly marked as `Archived` +- However, tx_1 and tx_2 related states incorrectly remain valid +- wlt_1 assets: 10 (archived) + 20 = 20, not the expected 600 +- wlt_2 assets: 490 + 80 = 570, not the expected 0 + +### 5. State Details (After switching to INSTANCE_3) + +The debug output reveals the problematic state: + +``` +[tests/transfer.rs:1023:13] "after revert tx_0" = "after revert tx_0" +[tests/transfer.rs:1023:13] wlt_1.runtime().state_own(contract_id).owned = { + VariantName("amount"): { + CellAddr {opid: Opid(Array<32>(32130de9519410fb7887643d37aa4dbe63d7cd073c3edb537887c8a8049351e6))}: OwnedState { + assignment: Assignment { + seal: Outpoint { + txid: Array<32>(9b2654ce652961f071047fb2e4f68fa9966acfbd1d287f56f823afa9e540a9bd), + vout: Vout(1), + }, + data: Number(Uint(10)), + }, + status: Archived, // Correctly marked as archived + }, + CellAddr {opid: Opid(Array<32>(d30adf7c234714d23c78cd02b5ae6b1b6d19cc5eb23ddb7a9553922ed268640b))}: OwnedState { + assignment: Assignment { + seal: Outpoint { + txid: Array<32>(a1e19720651a890e5a217248442a7b5c6cc32db16da70348234b3eeac8b9cb69), + vout: Vout(1), + }, + data: Number(Uint(20)), + }, + status: Mined(2085), // Should be invalid but still considered valid + }, + }, +} + +[tests/transfer.rs:1027:13] "after revert tx_0" = "after revert tx_0" +[tests/transfer.rs:1027:13] wlt_2.runtime().state_own(contract_id).owned = { + VariantName("amount"): { + CellAddr {opid: Opid(Array<32>(d30adf7c234714d23c78cd02b5ae6b1b6d19cc5eb23ddb7a9553922ed268640b))}: OwnedState { + assignment: Assignment { + seal: Outpoint { + txid: Array<32>(c43bbaada4324315d6efe7e62c906698fdbc81dc59f13265727a506ee85ba6df), + vout: Vout(0), + }, + data: Number(Uint(80)), + }, + status: Mined(2085), + }, + CellAddr {opid: Opid(Array<32>(ef3258c075f938b49ab62dd8c7b13ab1d2211a87022f49e270d1fe73cb8d741e))}: OwnedState { + assignment: Assignment { + seal: Outpoint { + txid: Array<32>(bb501ff63075458275be50866ea568cad1db40f51b829bf17322f2f78f5188cb), + vout: Vout(1), + }, + data: Number(Uint(490)), + }, + status: Mined(2084), + }, + }, +} +``` + +The test fails at this point with the assertion: + +``` +thread 'reorg_history::case_2' panicked at tests/utils/helper/wallet.rs:593:9: +assertion `left == right` failed + left: [20] + right: [600] +``` \ No newline at end of file diff --git a/rgb-std b/rgb-std index 723671f..38af458 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 723671fe32023dea9ab215ebc0a2a43bcdeb6988 +Subproject commit 38af4585372df1326d0daac9b3b14c6d02b919a1 diff --git a/sonic b/sonic index 905b347..323ac80 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 905b34766625914354b841d8133585d9053e48b2 +Subproject commit 323ac8078ff313c02d51c6d0d65218570aaeaafb diff --git a/tests/transfer.rs b/tests/transfer.rs index 11d2d5c..75bd225 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -748,8 +748,6 @@ fn check_fungible_history() { wlt_1.send_contract("TestAsset", &mut wlt_2); wlt_2.reload_runtime(); - // debug contract info - dbg!(wlt_1.contracts_info()); dbg!(wlt_1.runtime().state_own(contract_id).owned); // transfer @@ -909,6 +907,7 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp let utxo_wlt_1_2 = wlt_1.get_utxo(None); let utxo_wlt_2_1 = wlt_2.get_utxo(None); let utxo_wlt_2_2 = wlt_2.get_utxo(None); + dbg!(utxo_wlt_1_1, utxo_wlt_1_2, utxo_wlt_2_1, utxo_wlt_2_2); mine_custom(false, INSTANCE_2, 6); dbg!(get_height_custom(INSTANCE_2)); @@ -926,14 +925,23 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp // Create blinded invoice with specific UTXO let invoice = wlt_2.invoice(contract_id, amt_0, false, Some(0), Some(utxo_wlt_2_1)); let (_, tx_0, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + let wlt_1_state = wlt_1.runtime().state_own(contract_id).owned; + let wlt_2_state = wlt_2.runtime().state_own(contract_id).owned; + dbg!(tx_0.txid(), wlt_1_state, wlt_2_state); let amt_1 = 100; let invoice = wlt_1.invoice(contract_id, amt_1, false, Some(0), Some(utxo_wlt_1_1)); let (_, tx_1, _) = wlt_2.send_to_invoice(&mut wlt_1, invoice, Some(1000), None, None); + let wlt_1_state = wlt_1.runtime().state_own(contract_id).owned; + let wlt_2_state = wlt_2.runtime().state_own(contract_id).owned; + dbg!(tx_1.txid(), wlt_1_state, wlt_2_state); let amt_2 = 80; let invoice = wlt_2.invoice(contract_id, amt_2, false, Some(0), Some(utxo_wlt_2_2)); let (_, tx_2, _) = wlt_1.send_to_invoice(&mut wlt_2, invoice, Some(1000), None, None); + let wlt_1_state = wlt_1.runtime().state_own(contract_id).owned; + let wlt_2_state = wlt_2.runtime().state_own(contract_id).owned; + dbg!(tx_2.txid(), wlt_1_state, wlt_2_state); vec![tx_0, tx_1, tx_2] } @@ -1012,8 +1020,14 @@ fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgTyp wlt_2.switch_to_instance(INSTANCE_3); let wlt_1_alloc_1 = 600; dbg!(tx_status(txs[0].txid(), INSTANCE_3)); - dbg!(wlt_1.runtime().state_own(contract_id).owned); - dbg!(wlt_2.runtime().state_own(contract_id).owned); + dbg!( + "after revert tx_0", + wlt_1.runtime().state_own(contract_id).owned + ); + dbg!( + "after revert tx_0", + wlt_2.runtime().state_own(contract_id).owned + ); wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt_1_alloc_1]); wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); } diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index ba3234c..6b2a373 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -417,10 +417,6 @@ impl TestWallet { &mut self.runtime } - pub fn contracts_info(&self) -> Vec { - self.runtime.contracts.contracts_info().collect() - } - pub fn issue_with_params(&mut self, params: CreateParams) -> ContractId { let contract_id = self .runtime @@ -589,6 +585,7 @@ impl TestWallet { .get(allocation_field) .unwrap() .iter() + .filter(|(_, state)| state.status.is_valid()) .map(|(_, state)| state.assignment.data.unwrap_num().unwrap_uint::()) .collect::>(); actual_fungible_allocations.sort(); diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 79bb66f..93fa2a3 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -82,8 +82,8 @@ pub use rand::RngCore; pub use rgb::{ invoice::{RgbBeneficiary, RgbInvoice}, popls::bp::{Coinselect, OpRequestSet, PaymentScript, PrefabBundle, RgbWallet, WalletProvider}, - AuthToken, CallScope, CellAddr, CodexId, Consensus, ContractId, ContractInfo, Contracts, - CreateParams, EitherSeal, RgbSealDef, Schema, StateCalc, StockpileDir, + AuthToken, CallScope, CellAddr, CodexId, Consensus, ContractId, Contracts, CreateParams, + EitherSeal, RgbSealDef, Schema, StateCalc, StockpileDir, }; pub use rgbp::{ descriptor::RgbDescr, CoinselectStrategy, Owner, PayError, RgbRuntime, RgbpRuntimeDir, From 311ca090034bf7808f8d4f6cb8270e3c45d04a7e Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Thu, 15 May 2025 17:28:56 +0800 Subject: [PATCH 70/90] feat: All reorg test cases have passed Signed-off-by: will-bitlightlabs --- rgb-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rgb-std b/rgb-std index 38af458..2c92313 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 38af4585372df1326d0daac9b3b14c6d02b919a1 +Subproject commit 2c923131eef3235179b38f531fdf00b4aa13244f From eb9b988e6fbfe42213f029397f2b5ecdbbf72564 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 16 May 2025 11:58:02 +0800 Subject: [PATCH 71/90] chore: update submodules rgb-std and sonic to latest commits Signed-off-by: will-bitlightlabs --- rgb-std | 2 +- sonic | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rgb-std b/rgb-std index 2c92313..29cd1dd 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 2c923131eef3235179b38f531fdf00b4aa13244f +Subproject commit 29cd1dd5263b675af2636051210165a252ba714a diff --git a/sonic b/sonic index 323ac80..b79bf58 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 323ac8078ff313c02d51c6d0d65218570aaeaafb +Subproject commit b79bf5896c8f9b5b18caa1cbe01147970d78be57 From aa39df95056ca9426591f1a8c5b6c899cd892c0e Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 16 May 2025 12:21:23 +0800 Subject: [PATCH 72/90] refactor: rename template functions for clarity and add ignore attribute for failing tests Signed-off-by: will-bitlightlabs --- tests/issuance.rs | 13 +++--- tests/transfer.rs | 99 +++++------------------------------------ tests/transfer_rgb21.rs | 1 + 3 files changed, 18 insertions(+), 95 deletions(-) diff --git a/tests/issuance.rs b/tests/issuance.rs index 4cea310..a4369e9 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -11,9 +11,9 @@ const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; #[rstest] #[case(DescriptorType::Wpkh)] #[case(DescriptorType::Tr)] -fn descriptor_and_close_method(#[case] wallet_desc: DescriptorType) {} +fn descriptor(#[case] wallet_desc: DescriptorType) {} -#[apply(descriptor_and_close_method)] +#[apply(descriptor)] fn issue_nia(wallet_desc: DescriptorType) { println!("wallet_desc {wallet_desc:?}"); @@ -65,7 +65,7 @@ fn issue_nia(wallet_desc: DescriptorType) { .any(|(outpoint, amount)| outpoint.primary == fake_outpoint_one && *amount == 500_000)); } -#[apply(descriptor_and_close_method)] +#[apply(descriptor)] fn issue_fua(wallet_desc: DescriptorType) { println!("wallet_desc {wallet_desc:?}"); @@ -104,7 +104,7 @@ fn issue_fua(wallet_desc: DescriptorType) { .any(|(outpoint, amount)| outpoint.primary == fake_outpoint && *amount == 10_000)); } -#[apply(descriptor_and_close_method)] +#[apply(descriptor)] fn issue_fua_multiple_utxos(wallet_desc: DescriptorType) { println!("wallet_desc {wallet_desc:?}"); @@ -146,7 +146,7 @@ fn issue_fua_multiple_utxos(wallet_desc: DescriptorType) { assert_eq!(total_allocated, 999); } -#[apply(descriptor_and_close_method)] +#[apply(descriptor)] fn issue_nia_multiple_utxos(wallet_desc: DescriptorType) { println!("wallet_desc {wallet_desc:?}"); @@ -189,7 +189,8 @@ fn issue_nia_multiple_utxos(wallet_desc: DescriptorType) { assert_eq!(total_allocated, 999); } -#[apply(descriptor_and_close_method)] +#[apply(descriptor)] +#[ignore = "failed to issue contract: Inner(Genesis(Named(TypeName('DigitalCollection')), ScriptUnspecified))"] fn issue_fac(wallet_desc: DescriptorType) { println!("wallet_desc {wallet_desc:?}"); diff --git a/tests/transfer.rs b/tests/transfer.rs index 75bd225..4986465 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -24,7 +24,6 @@ pub mod utils; use rgb::WitnessStatus; -use rstest_reuse::{self, *}; use serial_test::serial; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; @@ -46,81 +45,6 @@ type TT = TransferType; type DT = DescriptorType; type AS = AssetSchema; -#[template] -#[rstest] -#[case(true)] -#[case(false)] -fn wout(#[case] wout: bool) {} -#[apply(wout)] -fn simple_transfer(wout: bool) { - initialize(); - - // Create two wallet instances - let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); - let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); - let supply = 600; - let asset_name = "TestAsset"; - - // Create and issue NIA asset - let mut params = NIAIssueParams::new(asset_name, "RBF", "centiMilli", supply); - let outpoint = wlt_1.get_utxo(None); - params.add_allocation(outpoint, supply); - let contract_id = wlt_1.issue_nia_with_params(params); - wlt_1.send_contract(asset_name, &mut wlt_2); - // TODO: Because the RGB mound currently cannot dynamically load contracts, - // It needs to be reloaded at a special time, and consider submitting a PR to RGB - wlt_2.reload_runtime(); - - let assign = 400; - // recive asset by utxo - let invoice = wlt_2.invoice(contract_id, assign, wout, Some(0), None); - - // send asset to wlt2 - // if `wout` is true (WitnessOut), - // wlt2 will have a 3000 Sats UTXO, which will be spent to transfer assets to wlt1 in the next step - let (consignment_1, tx, _) = wlt_1.transfer(invoice, Some(3000), Some(500), true, None); - - // Receiver accepts the transfer - wlt_2.accept_transfer(&consignment_1, None).unwrap(); - - // Broadcast and confirm transaction - wlt_1.mine_tx(&tx.txid(), false); - - // Sync both wallets - wlt_1.sync(); - wlt_2.sync(); - - wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![supply - assign]); - wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![assign]); - - let assign_wlt1 = 200; - let invoice = wlt_1.invoice(contract_id, assign_wlt1, wout, Some(0), None); - dbg!( - "wlt2", - wlt_2.runtime().wallet.balance(), - wlt_2.runtime().wallet.coins().collect::>() - ); - // Sats cost: 500 fee + 2000 sats(default) = 2500 - let (consignment_2, tx, _) = wlt_2.transfer(invoice, None, Some(500), true, None); - wlt_1.accept_transfer(&consignment_2, None).unwrap(); - wlt_2.mine_tx(&tx.txid(), false); - - // // Sync both wallets - wlt_1.sync(); - wlt_2.sync(); - - // owned state - dbg!(wlt_1.runtime().state_own(contract_id).owned); - dbg!(wlt_2.runtime().state_own(contract_id).owned); - - wlt_1.check_allocations( - contract_id, - AssetSchema::RGB20, - vec![supply - assign, assign_wlt1], - ); - wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![assign - assign_wlt1]); -} - #[test] fn rbf_transfer() { initialize(); @@ -528,8 +452,8 @@ fn transfer_loop( } #[rstest] -#[case(TransferType::Blinded)] -#[case(TransferType::Witness)] +#[case(TT::Blinded)] +#[case(TT::Witness)] fn same_transfer_twice_update_witnesses(#[case] transfer_type: TransferType) { println!("transfer_type {transfer_type:?}"); @@ -600,9 +524,9 @@ fn collaborative_transfer() { #[rstest] #[should_panic(expected = "Fulfill(StateInsufficient)")] -#[case(TransferType::Blinded)] +#[case(TT::Blinded)] #[should_panic(expected = "Fulfill(StateInsufficient)")] -#[case(TransferType::Witness)] +#[case(TT::Witness)] fn same_transfer_twice_no_update_witnesses(#[case] transfer_type: TransferType) { println!("transfer_type {transfer_type:?}"); @@ -796,10 +720,10 @@ fn send_to_oneself() { } #[rstest] -#[case(DescriptorType::Tr, DescriptorType::Tr)] -#[case(DescriptorType::Tr, DescriptorType::Wpkh)] -#[case(DescriptorType::Wpkh, DescriptorType::Tr)] -#[case(DescriptorType::Wpkh, DescriptorType::Wpkh)] +#[case(DT::Tr, DT::Tr)] +#[case(DT::Tr, DT::Wpkh)] +#[case(DT::Wpkh, DT::Tr)] +#[case(DT::Wpkh, DT::Wpkh)] fn blank_tapret_opret( #[case] descriptor_type_0: DescriptorType, #[case] descriptor_type_1: DescriptorType, @@ -858,13 +782,10 @@ fn blank_tapret_opret( #[rstest] #[case(HistoryType::Linear, ReorgType::ChangeOrder)] -// FIXME: Hope to receive solutions or suggestions from the doctor #[case(HistoryType::Linear, ReorgType::Revert)] #[case(HistoryType::Branching, ReorgType::ChangeOrder)] -// FIXME: Hope to receive solutions or suggestions from the doctor #[case(HistoryType::Branching, ReorgType::Revert)] #[case(HistoryType::Merging, ReorgType::ChangeOrder)] -// FIXME: Hope to receive solutions or suggestions from the doctor #[case(HistoryType::Merging, ReorgType::Revert)] #[serial] fn reorg_history(#[case] history_type: HistoryType, #[case] reorg_type: ReorgType) { @@ -1350,8 +1271,8 @@ fn invoice_reuse(#[case] transfer_type: TransferType) { } #[rstest] -#[case(TransferType::Blinded)] -#[case(TransferType::Witness)] +#[case(TT::Blinded)] +#[case(TT::Witness)] fn pay_one_invoice_twice(#[case] transfer_type: TransferType) { initialize(); diff --git a/tests/transfer_rgb21.rs b/tests/transfer_rgb21.rs index dbfb944..e8c69bb 100644 --- a/tests/transfer_rgb21.rs +++ b/tests/transfer_rgb21.rs @@ -20,6 +20,7 @@ fn wout(#[case] wout: bool) {} const MEDIA_FPATH: &str = "tests/fixtures/rgb_logo.jpeg"; #[apply(wout)] +#[ignore = "failed to issue contract: Inner(Genesis(Named(TypeName('DigitalCollection')), ScriptUnspecified))"] fn simple_fac_transfer(wout: bool) { initialize(); From cc4d9ab8e1296462e0ddd5734f72bfbca388cb28 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 16 May 2025 12:25:36 +0800 Subject: [PATCH 73/90] chore: fix some lints Signed-off-by: will-bitlightlabs --- tests/utils/helper/wallet.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 6b2a373..f4ab954 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -213,7 +213,7 @@ fn _get_wallet( for entry in std::fs::read_dir(issuer_dir).unwrap() { let entry = entry.unwrap(); let path = entry.path(); - if path.is_file() && path.extension().map_or(false, |ext| ext == "issuer") { + if path.is_file() && path.extension().is_some_and(|ext| ext == "issuer") { // println!("Auto-importing issuer file: {}", path.display()); if let Err(err) = test_wallet.import(path) { println!("Warning: Failed to import issuer: {}", err); @@ -761,7 +761,7 @@ impl TestWallet { let accept_start = Instant::now(); self.runtime .consume_from_file(consignment) - .map_err(|e| format!("consume_from_file error: {}", e.to_string()))?; + .map_err(|e| format!("consume_from_file error: {}", e))?; let accept_duration = accept_start.elapsed(); if let Some(report) = report { let column_name = format!("{}_accept", self.wallet_id()); @@ -805,7 +805,7 @@ impl TestWallet { self.runtime .contracts .import_issuer(schema) - .map_err(|e| format!("import error: {}", e.to_string()))?; + .map_err(|e| format!("import error: {}", e))?; Ok(()) } @@ -969,7 +969,7 @@ fn extract_from_tuple(v: &StrictVal) -> Option { /// Extract the first element from a two-layer tuple fn extract_from_2_layer_tuple(v: &StrictVal) -> Option { if let StrictVal::Tuple(t) = v { - if let Some(inner) = t.get(0) { + if let Some(inner) = t.first() { extract_from_tuple(inner) } else { None @@ -1027,11 +1027,11 @@ impl TestWallet { let index_name = FieldName::from_str("tokenIndex").unwrap(); let index = s.get_mut(&index_name).unwrap(); - *index = StrictVal::Number(StrictNum::from(params.index as u32)); + *index = StrictVal::Number(StrictNum::from(params.index)); let amount_name = FieldName::from_str("fraction").unwrap(); let amount = s.get_mut(&amount_name).unwrap(); - *amount = StrictVal::Number(StrictNum::from(params.total_fractions as u64)); + *amount = StrictVal::Number(StrictNum::from(params.total_fractions)); } if let Some(ref nft_spec) = params.nft_spec { @@ -1041,7 +1041,7 @@ impl TestWallet { StrictVal::Struct(s) => { let index_name = FieldName::from_str("index").unwrap(); let index = s.get_mut(&index_name).unwrap(); - *index = StrictVal::Number(StrictNum::from(params.index as u32)); + *index = StrictVal::Number(StrictNum::from(params.index)); if let Some(ref ticker_params) = nft_spec.ticker { let ticker_name = FieldName::from_str("ticker").unwrap(); @@ -1213,7 +1213,7 @@ impl TestWallet { ); map_inner.push(( - StrictVal::Number(StrictNum::from(*id as u8)), + StrictVal::Number(StrictNum::from(*id)), StrictVal::Struct(attachmet_inner), )); } @@ -1295,8 +1295,7 @@ impl TestWallet { } } - let contract_id = self.issue_with_params(create_params); - contract_id + self.issue_with_params(create_params) } /// Get RGB21 contract state @@ -1372,7 +1371,7 @@ impl TestWallet { // Parse preview let preview_struct = s .get(&FieldName::from_str("preview").unwrap()) - .and_then(|v| extract_from_union_and_tuple(v)); + .and_then(extract_from_union_and_tuple); if let Some(StrictVal::Struct(ref p)) = preview_struct { let media_type = if let Some(StrictVal::Struct(ref t)) = @@ -1426,7 +1425,7 @@ impl TestWallet { // Parse media let media_struct = s .get(&FieldName::from_str("media").unwrap()) - .and_then(|v| extract_from_union_and_tuple(v)); + .and_then(extract_from_union_and_tuple); if let Some(StrictVal::Struct(ref m)) = media_struct { let media_type = if let Some(StrictVal::Struct(ref t)) = @@ -1543,7 +1542,7 @@ impl TestWallet { // Parse reserves let reserves_struct = s .get(&FieldName::from_str("reserves").unwrap()) - .and_then(|v| extract_from_union_and_tuple(v)); + .and_then(extract_from_union_and_tuple); if let Some(StrictVal::Struct(ref r)) = reserves_struct { if let Some(StrictVal::Struct(ref u)) = @@ -1551,7 +1550,7 @@ impl TestWallet { { let txid_bytes = u .get(&FieldName::from_str("txid").unwrap()) - .and_then(|v| extract_from_tuple(v)) + .and_then(extract_from_tuple) .and_then(|v| { if let StrictVal::Bytes(Blob(tx)) = v { Some(tx) @@ -1563,7 +1562,7 @@ impl TestWallet { let vout = u .get(&FieldName::from_str("vout").unwrap()) - .and_then(|v| extract_from_tuple(v)) + .and_then(extract_from_tuple) .and_then(|v| { if let StrictVal::Number(n) = v { Some(n.unwrap_uint::()) From 5f4e191c1d05d024478aea2878fe19736f81b837 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 16 May 2025 17:50:34 +0800 Subject: [PATCH 74/90] chore: update submodule rgb-std to latest commit and remove obsolete RBF and reorg test reports Signed-off-by: will-bitlightlabs --- reports/rbf-test.md | 118 ------------------------- reports/reorg-test-fix-v2.md | 162 ----------------------------------- reports/reorg-test.md | 105 ----------------------- rgb-std | 2 +- 4 files changed, 1 insertion(+), 386 deletions(-) delete mode 100644 reports/rbf-test.md delete mode 100644 reports/reorg-test-fix-v2.md delete mode 100644 reports/reorg-test.md diff --git a/reports/rbf-test.md b/reports/rbf-test.md deleted file mode 100644 index 0b09375..0000000 --- a/reports/rbf-test.md +++ /dev/null @@ -1,118 +0,0 @@ -# RGB RBF Transfer Test Report - -## 1. Test Design Overview - -### 1.1 Test Purpose -To verify the asset transfer process under the RGB20 protocol with RBF (Replace-By-Fee), ensuring that asset states, witness transactions, and consignment serialization behave as expected. - -### 1.2 Test Scenario -This test focuses on the following process: -- Initiate a normal transfer, with the witness transaction entering the mempool. -- Use RBF to broadcast a replacement transaction with a higher fee. -- (Debug step) Check whether the consignment serialization reflects the latest witness transaction. -- Mine and confirm the new transaction, then check asset allocation and witness status. -- Perform a subsequent transfer to verify the handling of historical witness information. - -### 1.3 Test Implementation -- Two wallet instances are used to simulate asset issuance, transfer, RBF replacement, and asset return. -- APIs such as `tx_status` and `check_allocations` are used to verify transaction status and asset allocation. -- (Debug step) Special attention is paid to whether the consignment serialization updates witness information in a timely manner. - -## 2. Test Case Details - -### 2.1 Test Case Flow - -1. **Asset Issuance and Initial Transfer** - - Wallet 1 issues an NIA asset and allocates it to itself. - - Wallet 1 initiates a transfer to Wallet 2, generating a witness transaction (mempool status). - - Wallet 2 receives and accepts the consignment. - -2. **RBF Replacement Process** - - Wallet 1 uses RBF to broadcast a replacement transaction with a higher fee. - - A new consignment is generated; - - The new transaction is mined and confirmed; both old and new transaction statuses are checked. - -3. **Asset Allocation and Return** - - Wallet 2 accepts the final consignment. - - Asset allocations in both wallets are verified. - - Wallet 2 returns assets to Wallet 1, verifying the handling of historical witness information. - -### 2.2 Key Debug Information and Observations - -- **Consignment Serialization Issue** - During debugging, it was found that after RBF and subsequent consignment generation, the serialized witness information still refers to the invalid (old) witness. - The likely cause is that during the initial transfer, the relationship between terminal (auth-token) and cell-addr (opid-pos) is established in `RgbRuntime::exec` when generating the Prefab, but RBF does not update this relationship, causing the terminal to always reference the old operation. - -- **Internal State Complexity** - The current internal state management is complex, so we are cautious about making changes to the RBF logic and expect a fix from the Doctor. - -- **Why the bp-wallet fix affects the RBF test:** - Previously, the rbf_transfer test could pass because of a bug in esplora: for non-existent transactions, it would still return `TxStatus::Mempool`, allowing the validation to succeed. After the bp-wallet fix, this behavior was corrected, which exposed the underlying issue in consignment serialization. - -### 2.3 Debug Log Excerpts - -- The initial transfer's witness transaction is in the mempool, and consignment serialization is correct. -- After RBF, the new consignment still serializes the old witness. -- After mining, the old witness transaction status becomes Unknown, and the new witness transaction is Mined. -- In subsequent transfers, the consignment still contains the opid corresponding to the invalid witness transaction. - -## 3. Identified Issues and Progress - -### 3.1 Consignment Serialization Not Updated After RBF -- **Symptom**: After RBF, the consignment still serializes the old (invalid) witness. -- **Root Cause**: The relationship between terminal (auth-token) and cell-addr (opid-pos) is not updated in time. -- **Solution**: Further analysis and a fix from the Doctor are needed. - - -**Debug Log for RBF Transfer Test Case** - -``` test-case debug info -// First, perform a normal transfer; the witness transaction is in the mempool -// At the same time, the consignment serializes the witness transaction correctly -transfer txid: 353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a, consignment: 1 -[rgb-std/src/contract.rs:521:21] opid = Opid( - Array<32>(5a7a6ca82d1b59a06cf42fb673c1f2257787e7d1408ef03c46e3550851e556d2), -) -[rgb-std/src/contract.rs:521:21] &wid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) -[rgb-std/src/contract.rs:521:21] status = Tentative - -[tests/transfer.rs:150:5] first_txid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) -[tests/transfer.rs:150:5] tx_status(first_txid, wlt_1.instance) = Mempool - -// Based on the previous transfer, perform RBF, generating consignment2 and a new witness transaction, but the serialized witness is still the old one -transfer txid: e2a057f50d037d48cd68bcdee4eadd29345db51caa16c1b763a6d6b07753be29, consignment: 2 -[rgb-std/src/contract.rs:521:21] opid = Opid( - Array<32>(5a7a6ca82d1b59a06cf42fb673c1f2257787e7d1408ef03c46e3550851e556d2), -) -[rgb-std/src/contract.rs:521:21] &wid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) -[rgb-std/src/contract.rs:521:21] status = Tentative - -// Mining and accept are performed here - -// Then check the status of the old and new transactions -// The old witness transaction is found to be invalid -[tests/transfer.rs:168:5] first_txid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) -[tests/transfer.rs:168:5] tx_status(first_txid, wlt_1.instance) = Unknown -// The new one is confirmed -[tests/transfer.rs:169:5] second_txid = Array<32>(e2a057f50d037d48cd68bcdee4eadd29345db51caa16c1b763a6d6b07753be29) -[tests/transfer.rs:169:5] tx_status(second_txid, wlt_1.instance) = Mined( - MiningInfo { - height: 1129, - time: 1747048278, - block_hash: Array<32>(5b8516b3a3554f67eb4d0103634ee409df04971fa803fb5c10643888ebed3fde), - }, -) - -// In the subsequent transfer, it can be seen that the opid corresponding to the invalid witness transaction is still included -transfer txid: 23cf85a01dbf024eeb8caf58170297097bb2ff01e5eaaeb7dd29c25116b819c4, consignment: 3 -[rgb-std/src/contract.rs:521:21] opid = Opid( - Array<32>(5a7a6ca82d1b59a06cf42fb673c1f2257787e7d1408ef03c46e3550851e556d2), -) -[rgb-std/src/contract.rs:521:21] &wid = Array<32>(353d9cfa6606c38985b8ecd2b79b74471515c98077e16d35f93bd11c07a6fe2a) -[rgb-std/src/contract.rs:521:21] status = Archived -[rgb-std/src/contract.rs:521:21] opid = Opid( - Array<32>(bfbe0249576dac4dd64b6f3abff32efce0d899a24228172b905e0b73110c33cc), -) -[rgb-std/src/contract.rs:521:21] &wid = Array<32>(23cf85a01dbf024eeb8caf58170297097bb2ff01e5eaaeb7dd29c25116b819c4) -[rgb-std/src/contract.rs:521:21] status = Tentative -``` \ No newline at end of file diff --git a/reports/reorg-test-fix-v2.md b/reports/reorg-test-fix-v2.md deleted file mode 100644 index a6fe114..0000000 --- a/reports/reorg-test-fix-v2.md +++ /dev/null @@ -1,162 +0,0 @@ -# RGB Reorg Test Analysis Report - -## Introduction - -After updating to the latest dependencies (including Sonic develop and rgb-std fix/forward branch), the `Revert` type reorg scenarios in the `reorg_history` test case are still failing. - -## Dependency Versions and Additional Failures - -### Current Dependency Versions - -| Dependency | Version/Commit | Note | -| ----------- | ----------------------------------------------------------------- | ---- | -| **rgb-std** | `fix/forward` branch (`38af4585372df1326d0daac9b3b14c6d02b919a1`) | ⚠️ | -| **sonic** | `develop` branch (`323ac8078ff313c02d51c6d0d65218570aaeaafb`) | ⚠️ | - -### Additional Test Failures - -**Note to the doctor**: With the current versions of rgb-std and sonic, the `rbf_transfer` test case is also failing. This suggests that the issues with transaction dependency tracking affect not only reorg scenarios but also Replace-By-Fee (RBF) functionality, which relies on similar state management mechanisms. - -## Test Process and Failure Point - -The reorg test proceeds in three distinct stages: - -1. **Stage 1**: Execute RGB asset transactions on Bitcoin node INSTANCE_2. -2. **Stage 2**: On Bitcoin node INSTANCE_3, simulate a blockchain reorganization: - - For `ChangeOrder` scenarios: broadcast the same transactions but in a different order - - For `Revert` scenarios: broadcast only subsequent transactions (tx_1, tx_2) without the initial transaction (tx_0) - - **Check asset state validity after sync** ← Current Failure Point -3. **Stage 3**: Reconnect both Bitcoin nodes, allowing them to synchronize: - - For `Revert` scenarios: previously reverted transaction tx_0 is resubmitted to the mempool - - Check final asset state validity after complete synchronization - -**Note**: Unlike the previous implementation where failures occurred in Stage 3, the current implementation fails in Stage 2. - -## Test Scenario Overview - -The `reorg_history` test case verifies correct handling of RGB asset states across different history types and reorganization types. - -### Test Matrix - -| History Type | Reorg Type | Status | -| ------------ | ----------- | ------ | -| Linear | ChangeOrder | ✅ Pass | -| Linear | Revert | ❌ Fail | -| Branching | ChangeOrder | ✅ Pass | -| Branching | Revert | ❌ Fail | -| Merging | ChangeOrder | ✅ Pass | -| Merging | Revert | ❌ Fail | - -## Detailed Analysis: Linear-Revert Scenario - -Using the `HistoryType::Linear` and `ReorgType::Revert` case as an example: - -### 1. Initial Setup - -- Two Bitcoin node instances (INSTANCE_2 and INSTANCE_3) are created -- An RGB20 asset with total supply of 600 is issued on INSTANCE_2 -- Initial allocation: wlt_1 owns all 600 units - -### 2. Transaction Sequence (INSTANCE_2) - -| TX ID | Operation | Transfer Amount | Resulting State | -| ----- | ------------- | --------------- | ---------------------------------- | -| tx_0 | wlt_1 → wlt_2 | 590 | wlt_1: 10, wlt_2: 590 | -| tx_1 | wlt_2 → wlt_1 | 100 | wlt_1: 10+100=110, wlt_2: 490 | -| tx_2 | wlt_1 → wlt_2 | 80 | wlt_1: 10+20=30, wlt_2: 490+80=570 | - - -### 3. Reorg Scenario (INSTANCE_3) - Stage 2 Failure Point - -On INSTANCE_3, only tx_1 and tx_2 are broadcast, **tx_0 is not broadcast**, simulating a scenario where tx_0 has been reverted: - -```rust -broadcast_tx_and_mine(&txs[1], INSTANCE_3); -broadcast_tx_and_mine(&txs[2], INSTANCE_3); -``` - -After switching the wallet to INSTANCE_3 and syncing: - -```rust -wlt_1.switch_to_instance(INSTANCE_3); -wlt_2.switch_to_instance(INSTANCE_3); -``` - -### 4. Actual Results vs. Expected Results (Stage 2) - -**Expected Result**: -- When tx_0 is reverted, subsequent tx_1 and tx_2 that depend on the asset transfers in tx_0 should be invalid -- wlt_1 should maintain its original 600 assets, while wlt_2 should have no assets - -**Actual Result**: -- tx_0 related state is correctly marked as `Archived` -- However, tx_1 and tx_2 related states incorrectly remain valid -- wlt_1 assets: 10 (archived) + 20 = 20, not the expected 600 -- wlt_2 assets: 490 + 80 = 570, not the expected 0 - -### 5. State Details (After switching to INSTANCE_3) - -The debug output reveals the problematic state: - -``` -[tests/transfer.rs:1023:13] "after revert tx_0" = "after revert tx_0" -[tests/transfer.rs:1023:13] wlt_1.runtime().state_own(contract_id).owned = { - VariantName("amount"): { - CellAddr {opid: Opid(Array<32>(32130de9519410fb7887643d37aa4dbe63d7cd073c3edb537887c8a8049351e6))}: OwnedState { - assignment: Assignment { - seal: Outpoint { - txid: Array<32>(9b2654ce652961f071047fb2e4f68fa9966acfbd1d287f56f823afa9e540a9bd), - vout: Vout(1), - }, - data: Number(Uint(10)), - }, - status: Archived, // Correctly marked as archived - }, - CellAddr {opid: Opid(Array<32>(d30adf7c234714d23c78cd02b5ae6b1b6d19cc5eb23ddb7a9553922ed268640b))}: OwnedState { - assignment: Assignment { - seal: Outpoint { - txid: Array<32>(a1e19720651a890e5a217248442a7b5c6cc32db16da70348234b3eeac8b9cb69), - vout: Vout(1), - }, - data: Number(Uint(20)), - }, - status: Mined(2085), // Should be invalid but still considered valid - }, - }, -} - -[tests/transfer.rs:1027:13] "after revert tx_0" = "after revert tx_0" -[tests/transfer.rs:1027:13] wlt_2.runtime().state_own(contract_id).owned = { - VariantName("amount"): { - CellAddr {opid: Opid(Array<32>(d30adf7c234714d23c78cd02b5ae6b1b6d19cc5eb23ddb7a9553922ed268640b))}: OwnedState { - assignment: Assignment { - seal: Outpoint { - txid: Array<32>(c43bbaada4324315d6efe7e62c906698fdbc81dc59f13265727a506ee85ba6df), - vout: Vout(0), - }, - data: Number(Uint(80)), - }, - status: Mined(2085), - }, - CellAddr {opid: Opid(Array<32>(ef3258c075f938b49ab62dd8c7b13ab1d2211a87022f49e270d1fe73cb8d741e))}: OwnedState { - assignment: Assignment { - seal: Outpoint { - txid: Array<32>(bb501ff63075458275be50866ea568cad1db40f51b829bf17322f2f78f5188cb), - vout: Vout(1), - }, - data: Number(Uint(490)), - }, - status: Mined(2084), - }, - }, -} -``` - -The test fails at this point with the assertion: - -``` -thread 'reorg_history::case_2' panicked at tests/utils/helper/wallet.rs:593:9: -assertion `left == right` failed - left: [20] - right: [600] -``` \ No newline at end of file diff --git a/reports/reorg-test.md b/reports/reorg-test.md deleted file mode 100644 index d15d249..0000000 --- a/reports/reorg-test.md +++ /dev/null @@ -1,105 +0,0 @@ -# RGB Reorg Test Report - -## 1. Test Design Overview - -### 1.1 Test Purpose -Verify the state management capability of RGB v0.12 during blockchain reorganization (reorg), ensuring that asset states can be correctly rolled back and restored. - -### 1.2 Test Scenarios -The test was designed with two reorg modes (ReorgType) and three history types (HistoryType), resulting in 6 test case combinations: - -#### Reorg Modes (ReorgType) -- **ChangeOrder**: Change the transaction broadcasting order, simulating scenarios where transactions are confirmed in different orders in the blockchain -- **Revert**: Do not broadcast the initial transaction, simulating scenarios where certain transactions are completely excluded from the blockchain - -#### History Types (HistoryType) -- **Linear**: Linear transfer history, a simple scenario where assets are transferred from A to B, and then partially back to A -- **Branching**: Branching transfer history, where assets are first fully transferred to B, then B transfers part back to A, and B transfers the remaining part (minus 1) back to A -- **Merging**: Merging transfer history, where A holds two assets, transfers them to B in two transactions, and then B transfers almost all (minus 1) back to A - -### 1.3 Test Implementation Principles -The tests simulate blockchain reorganization through the following methods: - -1. **Dual-node Environment**: - - Using two independent Bitcoin node instances (INSTANCE_2 and INSTANCE_3) - - Initially connecting the two nodes to synchronize them - -2. **Reorg Simulation**: - - Disconnecting the nodes, executing transactions in normal order on INSTANCE_2 - - Based on the test scenario, broadcasting transactions in different orders or ignoring certain transactions on INSTANCE_3 - - Switching the wallet to INSTANCE_3 instance and checking state changes - -3. **Asset Reception Method**: - - Using the Auth Token method (pre-created UTXO) to receive assets - - This makes transactions relatively independent and allows flexible adjustment of broadcast order - -4. **State Verification**: - - Verifying asset allocation states after reorg using the `check_allocations` method - - Testing final state consistency after nodes reconnect - -## 2. Test Case Details - -### 2.1 Passed Test Cases - -| Case | History Type | Reorg Type | Status | -| ------ | ------------ | ----------- | -------- | -| case_1 | Linear | ChangeOrder | Passed ✅ | -| case_3 | Branching | ChangeOrder | Passed ✅ | -| case_5 | Merging | ChangeOrder | Passed ✅ | - -**ChangeOrder Test Implementation Details**: -- Execute transactions in the order [tx_0, tx_1, tx_2] on INSTANCE_2 -- Broadcast in different orders on INSTANCE_3 (such as [tx_2, tx_1, tx_0] in the Linear scenario) -- Results match expectations, indicating that RGB correctly handles changes in transaction order - -### 2.2 Failed Test Cases - -| Case | History Type | Reorg Type | Status | Failure Details | -| ------ | ------------ | ---------- | -------- | --------------- | -| case_2 | Linear | Revert | Failed ❌ | | -| case_4 | Branching | Revert | Failed ❌ | | -| case_6 | Merging | Revert | Failed ❌ | | - -**Revert Test Implementation Details**: -- Disconnect INSTANCE_3 from INSTANCE_2 -- Execute transactions in the complete order [tx_0, tx_1, tx_2] on INSTANCE_2 -- Only broadcast subsequent transactions [tx_1, tx_2] on INSTANCE_3, without broadcasting the initial transaction tx_0 -- Expect that without the initial transaction, the asset state should roll back to the initial allocation (passed) -- Reconnect INSTANCE_3 and INSTANCE_2, check state consistency (failed) - - tx_0 is mined in INSTANCE_2, reverted in INSTANCE_3 - - Additionally, INSTANCE_3's chain is 1 block longer than INSTANCE_2 - - But when the two nodes reconnect, tx_0 will be resubmitted to the mempool - - Expected asset state to be restored to its original state - -## 3. Issues Discovered and Fix Progress - -### 3.1 State Rollback Issues in Revert Scenarios -All Revert test cases failed. After multiple PR fixes, we are currently in the final stage, addressing the state forwarding after block reorg. - -#### 3.1.1 Issue One: Incorrect Transaction Status in Indexer (Resolved ✅) -- **Symptom**: Transaction status (TxStatus) in the transaction indexer was not correctly Responded -- **Root Cause**: The transaction indexer did not correctly reflect the confirmation status of transactions in the blockchain, causing the rollback logic based on these transactions to fail -- **Solution**: Fixed the transaction status tracking logic in the indexer -- **PR Link**: [BP-WG/bp-wallet#86](https://github.com/BP-WG/bp-wallet/pull/86) - -#### 3.1.2 Issue Two: Infinite Loop in Rollback Function (Resolved ✅) -- **Symptom**: During the rollback operation process, the same operation was repeatedly added to the rollback chain, causing performance issues and potential infinite loops -- **Root Cause**: The `rollback` function did not check for duplicate operations when building the dependency chain, and incorrectly increased the loop index -- **Solution**: - - Added duplicate check logic: `if chain.contains(&spent) { continue; }` - - Removed the incorrect index increment: `index += 1` (the loop itself already increases the index) -- **PR Link**: [AluVM/sonic#18](https://github.com/AluVM/sonic/pull/18) - -#### 3.1.3 Issue Three: Dependency Recovery Problem in Forward Function (Pending ⏳) -- **Symptom**: When attempting to restore operations after rollback, subsequent operations dependent on the restored operation are not automatically restored -- **Case Analysis**: - - In the first phase of Revert, after tx_0 is reverted in INSTANCE_3, although tx_1 and tx_2 are normally broadcast, the asset transfer chain depends on tx_0, so in the absence of tx_0, the asset correctly reverts to its issuance state - - In the second phase of Revert, after the two Bitcoin nodes reconnect and a reorg occurs (tx_0 is mined in INSTANCE_2, reverted in INSTANCE_3, and INSTANCE_3's chain is 1 block longer than INSTANCE_2; when the two nodes reconnect, tx_0 is resubmitted to the mempool), the expected behavior is that tx_0 (mempool), tx_1 (mined), tx_2 (mined) would sync and restore to the state after witness transaction tx_2, but currently it only restores to the state after witness transaction tx_0 -- **Analysis**: - - The `rollback` function can find the complete dependency chain through the `spent_by` method and roll back - - The `forward` function lacks a similar mechanism to restore the complete dependency chain - -## 4. Recommended Next Steps - -1. **Resolve Forward Function Issues**: - - Hope to receive solutions or suggestions from the doctor \ No newline at end of file diff --git a/rgb-std b/rgb-std index 29cd1dd..1f7f09b 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 29cd1dd5263b675af2636051210165a252ba714a +Subproject commit 1f7f09b49a7bdda8c86bbaac7abd906bf9bfd2f7 From 8732b9f979e188f3048f4b1d5bab960595e372d3 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 16 May 2025 18:50:17 +0800 Subject: [PATCH 75/90] feat: update all submodules to align with official RGB v0.12 Signed-off-by: will-bitlightlabs --- Cargo.lock | 130 ++++++++++++----------------------------- client_side_validation | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-std | 2 +- sonic | 2 +- ultrasonic | 2 +- 7 files changed, 43 insertions(+), 99 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eba4632..34bd396 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ dependencies = [ "amplify", "baid64", "commit_verify", - "getrandom 0.2.14", + "getrandom", "paste", "serde", "strict_encoding", @@ -103,7 +103,7 @@ checksum = "a0da0aa3a98a56f9002e0d30d642b62ba55b39821075951a764121bfe098ee98" dependencies = [ "amplify", "binfile", - "getrandom 0.2.14", + "getrandom", "indexmap 2.9.0", "strict_encoding", "wasm-bindgen", @@ -315,7 +315,7 @@ dependencies = [ "bp-dbc", "bp-seals", "commit_verify", - "getrandom 0.2.14", + "getrandom", "serde", "single_use_seals", "strict_encoding", @@ -403,7 +403,7 @@ dependencies = [ "bp-consensus", "bp-dbc", "commit_verify", - "rand 0.8.5", + "rand", "serde", "single_use_seals", "strict_encoding", @@ -419,7 +419,7 @@ dependencies = [ "bp-derive", "bp-invoice", "descriptors", - "getrandom 0.2.14", + "getrandom", "psbt", "secp256k1", "serde", @@ -497,9 +497,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -507,7 +507,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -547,13 +547,15 @@ version = "0.12.0-beta.6" dependencies = [ "amplify", "commit_encoding_derive", - "rand 0.9.1", + "getrandom", + "rand", "ripemd", "serde", "sha2", "strict_encoding", "strict_types", "vesper-lang", + "wasm-bindgen", ] [[package]] @@ -892,22 +894,10 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] -[[package]] -name = "getrandom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - [[package]] name = "gimli" version = "0.28.1" @@ -1080,7 +1070,7 @@ dependencies = [ "amplify", "aora", "commit_verify", - "getrandom 0.2.14", + "getrandom", "indexmap 2.9.0", "serde", "sonic-api", @@ -1216,7 +1206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1287,7 +1277,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -1567,12 +1557,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - [[package]] name = "rand" version = "0.8.5" @@ -1580,18 +1564,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_chacha", + "rand_core", ] [[package]] @@ -1601,17 +1575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", + "rand_core", ] [[package]] @@ -1620,16 +1584,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.14", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.2", + "getrandom", ] [[package]] @@ -1743,7 +1698,7 @@ dependencies = [ "amplify", "bp-core", "commit_verify", - "getrandom 0.2.14", + "getrandom", "serde", "single_use_seals", "strict_encoding", @@ -1758,7 +1713,7 @@ dependencies = [ "amplify", "bp-consensus", "commit_verify", - "getrandom 0.2.14", + "getrandom", "serde", "strict_encoding", "strict_types", @@ -1798,8 +1753,9 @@ dependencies = [ "amplify", "bp-std", "bp-wallet", + "chrono", "commit_verify", - "getrandom 0.2.14", + "getrandom", "indexmap 2.9.0", "nonasync", "rgb-psbt", @@ -1820,7 +1776,7 @@ dependencies = [ "bp-invoice", "chrono", "commit_verify", - "getrandom 0.2.14", + "getrandom", "hypersonic", "indexmap 2.9.0", "rgb-core", @@ -1853,7 +1809,7 @@ dependencies = [ "indexmap 2.9.0", "once_cell", "psbt", - "rand 0.8.5", + "rand", "rgb-interfaces", "rgb-psbt", "rgb-runtime", @@ -1881,7 +1837,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.14", + "getrandom", "libc", "spin", "untrusted", @@ -1933,7 +1889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88530b681abe67924d42cca181d070e3ac20e0740569441a9e35a7cedd2b34a4" dependencies = [ "quote", - "rand 0.8.5", + "rand", "rustc_version", "syn 2.0.95", ] @@ -2064,7 +2020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand", "secp256k1-sys", "serde", ] @@ -2318,7 +2274,7 @@ dependencies = [ "baid64", "chrono", "commit_verify", - "getrandom 0.2.14", + "getrandom", "serde", "sonic-callreq", "strict_encoding", @@ -2699,7 +2655,7 @@ dependencies = [ "amplify", "baid64", "commit_verify", - "getrandom 0.2.14", + "getrandom", "serde", "strict_encoding", "wasm-bindgen", @@ -2793,15 +2749,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -2930,6 +2877,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + [[package]] name = "windows-registry" version = "0.2.0" @@ -3108,15 +3061,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.5.0", -] - [[package]] name = "zeroize" version = "1.8.0" @@ -3129,7 +3073,7 @@ version = "0.12.0-beta.6" dependencies = [ "aluvm", "amplify", - "getrandom 0.2.14", + "getrandom", "serde", "strict_encoding", "wasm-bindgen", diff --git a/client_side_validation b/client_side_validation index 41a6f7a..0fab906 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit 41a6f7a8a8062ec3050afc96d6c4387177e0663a +Subproject commit 0fab90652ff33e91be9c51ee90769c9a47b40cc2 diff --git a/rgb b/rgb index 69acc39..634c3a7 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 69acc39113918a8271fd65854fa3d372616526a0 +Subproject commit 634c3a7e8696483be6d333fc158ab014a72fc55d diff --git a/rgb-core b/rgb-core index 6719b91..9591089 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 6719b9147f55a4e3ce5dac05164da820aa6e9720 +Subproject commit 9591089d717dfbf01a24d33b11f8e3a44574c9c5 diff --git a/rgb-std b/rgb-std index 1f7f09b..dc2e0f4 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 1f7f09b49a7bdda8c86bbaac7abd906bf9bfd2f7 +Subproject commit dc2e0f4f3206f845321bf7ef511740de541ce5ef diff --git a/sonic b/sonic index b79bf58..fda0860 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit b79bf5896c8f9b5b18caa1cbe01147970d78be57 +Subproject commit fda08609334968967483b43d242c2620c11be67c diff --git a/ultrasonic b/ultrasonic index 91aa397..ab8fe90 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit 91aa397391696e787a11a60b45da264fa9a47e46 +Subproject commit ab8fe90e88c3be6dbcfe69655792a597531fcd30 From 8e195e2f23f74e23d8ab38e36d2bba066997c925 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 20 May 2025 13:46:39 +0800 Subject: [PATCH 76/90] fix: issue of failed restart of Node 2 Signed-off-by: will-bitlightlabs --- tests/docker/start_services.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docker/start_services.sh b/tests/docker/start_services.sh index 6f0fb3b..c87152f 100755 --- a/tests/docker/start_services.sh +++ b/tests/docker/start_services.sh @@ -167,7 +167,7 @@ _wait_for_bitcoin_ready() { } _start_services() { - _stop_services + _clean_environment # Check exposed ports EXPOSED_PORTS=( From f24fb09ebf99a7f75108a46839cced2b2d190922 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 19 May 2025 15:53:55 +0200 Subject: [PATCH 77/90] chore: update for revised pre-release v0.12 --- Cargo.lock | 1357 +++++++++++++-------- Cargo.toml | 7 +- bp-core | 2 +- client_side_validation | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-std | 2 +- rust-aluvm | 2 +- sonic | 2 +- strict-encoding | 2 +- strict-types | 2 +- tests/templates/issuance/FAC.yaml | 48 +- tests/templates/issuance/FUA.yaml | 3 +- tests/templates/issuance/NFA.yaml | 3 +- tests/templates/schemata/RGB20-NFA.issuer | Bin 3397 -> 3716 bytes tests/templates/schemata/RGB21-FAC.issuer | Bin 8392 -> 8739 bytes tests/templates/schemata/RGB21-UAC.issuer | Bin 8151 -> 8499 bytes tests/templates/schemata/RGB21-UDA.issuer | Bin 8091 -> 8444 bytes tests/templates/schemata/RGB25-FUA.issuer | Bin 3392 -> 3711 bytes tests/utils/helper/coinselect.rs | 2 +- tests/utils/helper/wallet.rs | 27 +- tests/utils/mod.rs | 5 +- ultrasonic | 2 +- zk-aluvm | 2 +- 24 files changed, 938 insertions(+), 536 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34bd396..b8a01f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -33,7 +33,8 @@ dependencies = [ "amplify", "baid64", "commit_verify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "paste", "serde", "strict_encoding", @@ -103,7 +104,7 @@ checksum = "a0da0aa3a98a56f9002e0d30d642b62ba55b39821075951a764121bfe098ee98" dependencies = [ "amplify", "binfile", - "getrandom", + "getrandom 0.2.16", "indexmap 2.9.0", "strict_encoding", "wasm-bindgen", @@ -111,9 +112,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii" @@ -139,15 +140,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" +checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" dependencies = [ "aws-lc-sys", "zeroize", @@ -155,9 +156,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.28.2" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa9b6986f250236c27e5a204062434a773a13243d2ffc2955f37bdba4c5c6a1" +checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" dependencies = [ "bindgen", "cc", @@ -168,17 +169,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -186,17 +187,11 @@ name = "baid64" version = "0.4.1" dependencies = [ "amplify", - "base64 0.22.1", + "base64", "mnemonic", "sha2", ] -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "base64" version = "0.22.1" @@ -224,7 +219,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.5.0", + "bitflags", "cexpr", "clang-sys", "itertools", @@ -237,7 +232,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.95", + "syn 2.0.101", "which", ] @@ -252,9 +247,9 @@ dependencies = [ [[package]] name = "bitcoin-io" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" [[package]] name = "bitcoin_hashes" @@ -268,15 +263,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.3.2" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" @@ -300,24 +289,26 @@ dependencies = [ "amplify", "chrono", "commit_verify", + "getrandom 0.2.16", + "getrandom 0.3.3", "secp256k1", "serde", "strict_encoding", "strict_types", + "wasm-bindgen", ] [[package]] name = "bp-core" version = "0.12.0-beta.6" dependencies = [ - "amplify", "bp-consensus", "bp-dbc", "bp-seals", "commit_verify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", - "single_use_seals", "strict_encoding", "wasm-bindgen", ] @@ -330,9 +321,12 @@ dependencies = [ "base85", "bp-consensus", "commit_verify", + "getrandom 0.2.16", + "getrandom 0.3.3", "secp256k1", "serde", "strict_encoding", + "wasm-bindgen", ] [[package]] @@ -362,7 +356,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "webpki-roots", + "webpki-roots 0.26.11", "winapi", ] @@ -377,7 +371,7 @@ dependencies = [ "minreq", "reqwest", "serde", - "serde_with 3.11.0", + "serde_with 3.12.0", "sha2", "tokio", ] @@ -399,14 +393,15 @@ name = "bp-seals" version = "0.12.0-beta.6" dependencies = [ "amplify", - "baid64", "bp-consensus", "bp-dbc", "commit_verify", - "rand", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "single_use_seals", "strict_encoding", + "wasm-bindgen", ] [[package]] @@ -419,7 +414,7 @@ dependencies = [ "bp-derive", "bp-invoice", "descriptors", - "getrandom", + "getrandom 0.2.16", "psbt", "secp256k1", "serde", @@ -447,9 +442,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytecount" @@ -465,15 +460,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.1.18" +version = "1.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" dependencies = [ "jobserver", "libc", @@ -523,9 +518,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.50" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] @@ -547,8 +542,9 @@ version = "0.12.0-beta.6" dependencies = [ "amplify", "commit_encoding_derive", - "getrandom", - "rand", + "getrandom 0.2.16", + "getrandom 0.3.3", + "rand 0.9.1", "ripemd", "serde", "sha2", @@ -570,15 +566,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -605,12 +601,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", + "darling_core 0.20.11", + "darling_macro 0.20.11", ] [[package]] @@ -623,22 +619,22 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim", - "syn 2.0.95", + "strsim 0.11.1", + "syn 2.0.101", ] [[package]] @@ -654,20 +650,20 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core 0.20.8", + "darling_core 0.20.11", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", "serde", @@ -694,39 +690,50 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.11.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.0.2" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "file-format" @@ -782,9 +789,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -797,9 +804,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -807,15 +814,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -824,32 +831,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -859,9 +866,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -887,28 +894,42 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" @@ -918,15 +939,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - -[[package]] -name = "heck" -version = "0.4.1" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" [[package]] name = "heck" @@ -960,18 +975,18 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "http" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -980,9 +995,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -990,12 +1005,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "pin-project-lite", @@ -1003,15 +1018,15 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.3.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -1044,9 +1059,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710" dependencies = [ "bytes", "futures-channel", @@ -1054,10 +1069,10 @@ dependencies = [ "http", "http-body", "hyper", + "libc", "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -1068,9 +1083,9 @@ version = "0.12.0-beta.6" dependencies = [ "aluvm", "amplify", - "aora", "commit_verify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "indexmap 2.9.0", "serde", "sonic-api", @@ -1083,14 +1098,15 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1104,6 +1120,92 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1112,12 +1214,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1138,15 +1251,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.3", "serde", ] [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "itertools" @@ -1159,33 +1272,35 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -1201,19 +1316,31 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.0", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" @@ -1227,15 +1354,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -1251,20 +1378,20 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ - "adler", + "adler2", ] [[package]] name = "minreq" -version = "2.13.2" +version = "2.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0c420feb01b9fb5061f8c8f452534361dd783756dcf38ec45191ce55e7a161" +checksum = "f0d2aaba477837b46ec1289588180fabfccf0c3b1d1a0c6b1866240cd6cd5ce9" dependencies = [ - "base64 0.12.3", + "base64", "log", "serde", "serde_json", @@ -1272,13 +1399,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", - "windows-sys 0.48.0", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] @@ -1289,11 +1416,10 @@ checksum = "f2b8f3a258db515d5e91a904ce4ae3f73e091149b90cadbdb93d210bee07f63b" [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -1330,35 +1456,35 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "object" -version = "0.32.2" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ - "bitflags 2.5.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -1375,20 +1501,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" dependencies = [ "cc", "libc", @@ -1432,9 +1558,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" @@ -1442,31 +1568,11 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.95", -] - [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1476,9 +1582,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -1488,18 +1603,21 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" dependencies = [ "proc-macro2", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] @@ -1521,14 +1639,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -1538,7 +1656,7 @@ name = "psbt" version = "0.12.0-beta.6" dependencies = [ "amplify", - "base64 0.22.1", + "base64", "bp-core", "bp-derive", "commit_verify", @@ -1550,13 +1668,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.8.5" @@ -1564,8 +1688,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -1575,7 +1709,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1584,43 +1728,52 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", ] [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ - "bitflags 2.5.0", + "bitflags", ] [[package]] name = "ref-cast" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "regex" -version = "1.10.4" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1630,9 +1783,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1641,9 +1794,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "relative-path" @@ -1653,11 +1806,11 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "futures-core", "futures-util", @@ -1683,6 +1836,7 @@ dependencies = [ "tokio", "tokio-native-tls", "tokio-socks", + "tower", "tower-service", "url", "wasm-bindgen", @@ -1698,7 +1852,8 @@ dependencies = [ "amplify", "bp-core", "commit_verify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "single_use_seals", "strict_encoding", @@ -1713,7 +1868,7 @@ dependencies = [ "amplify", "bp-consensus", "commit_verify", - "getrandom", + "getrandom 0.2.16", "serde", "strict_encoding", "strict_types", @@ -1755,7 +1910,7 @@ dependencies = [ "bp-wallet", "chrono", "commit_verify", - "getrandom", + "getrandom 0.2.16", "indexmap 2.9.0", "nonasync", "rgb-psbt", @@ -1776,7 +1931,8 @@ dependencies = [ "bp-invoice", "chrono", "commit_verify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "hypersonic", "indexmap 2.9.0", "rgb-core", @@ -1784,6 +1940,7 @@ dependencies = [ "serde", "serde_with 1.14.0", "single_use_seals", + "sonic-persist-fs", "strict_encoding", "strict_types", "wasm-bindgen", @@ -1809,7 +1966,7 @@ dependencies = [ "indexmap 2.9.0", "once_cell", "psbt", - "rand", + "rand 0.8.5", "rgb-interfaces", "rgb-psbt", "rgb-runtime", @@ -1821,6 +1978,7 @@ dependencies = [ "serde_yaml", "serial_test", "single_use_seals", + "sonic-persist-fs", "strict_encoding", "strict_types", "strum", @@ -1831,15 +1989,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.16", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -1878,7 +2035,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.95", + "syn 2.0.101", "unicode-ident", ] @@ -1889,16 +2046,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88530b681abe67924d42cca181d070e3ac20e0740569441a9e35a7cedd2b34a4" dependencies = [ "quote", - "rand", + "rand 0.8.5", "rustc_version", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -1908,31 +2065,44 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.5.0", + "bitflags", "errno", "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.26" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "aws-lc-rs", "log", @@ -1945,25 +2115,27 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ "aws-lc-rs", "ring", @@ -1973,32 +2145,32 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "scc" -version = "2.2.6" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b13f8ea6177672c49d12ed964cca44836f59621981b04a3e26b87e675181de" +checksum = "22b2d775fb28f245817589471dd49c5edf64237f4a19d10ce9a92ff4651a27f4" dependencies = [ "sdd", ] [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2009,9 +2181,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sdd" -version = "3.0.5" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478f121bb72bbf63c52c93011ea1791dca40140dfe13f8336c4c5ac952c33aa9" +checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21" [[package]] name = "secp256k1" @@ -2020,27 +2192,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", - "rand", + "rand 0.8.5", "secp256k1-sys", "serde", ] [[package]] name = "secp256k1-sys" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" dependencies = [ "cc", ] [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -2049,9 +2221,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -2059,46 +2231,47 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2137,11 +2310,11 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ - "base64 0.22.1", + "base64", "chrono", "hex", "indexmap 1.9.3", @@ -2149,7 +2322,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serde_with_macros 3.11.0", + "serde_with_macros 3.12.0", "time", ] @@ -2167,14 +2340,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ - "darling 0.20.8", + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] @@ -2212,14 +2385,14 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -2251,15 +2424,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2272,9 +2445,11 @@ dependencies = [ "aluvm", "amplify", "baid64", + "binfile", "chrono", "commit_verify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "sonic-callreq", "strict_encoding", @@ -2291,18 +2466,34 @@ dependencies = [ "baid64", "chrono", "fluent-uri", + "getrandom 0.2.16", + "getrandom 0.3.3", "indexmap 2.9.0", "serde", "strict_encoding", "strict_types", "ultrasonic", + "wasm-bindgen", +] + +[[package]] +name = "sonic-persist-fs" +version = "0.12.0-beta.6" +dependencies = [ + "amplify", + "aora", + "binfile", + "hypersonic", + "serde_yaml", + "strict_encoding", + "toml", ] [[package]] -name = "spin" -version = "0.9.8" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strict_encoding" @@ -2319,7 +2510,7 @@ name = "strict_encoding_derive" version = "2.8.2" dependencies = [ "amplify_syn", - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 1.0.109", @@ -2359,33 +2550,39 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -2400,9 +2597,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.95" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -2411,13 +2608,24 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "tabled" version = "0.18.0" @@ -2434,50 +2642,51 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d9946811baad81710ec921809e2af67ad77719418673b2a3794932d57b7538" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "tempfile" -version = "3.10.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", "fastrand", - "rustix", - "windows-sys 0.52.0", + "getrandom 0.3.3", + "once_cell", + "rustix 1.0.7", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", ] [[package]] name = "time" -version = "0.3.36" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -2490,40 +2699,35 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.37.0" +version = "1.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" dependencies = [ "backtrace", "bytes", @@ -2531,7 +2735,7 @@ dependencies = [ "mio", "pin-project-lite", "socket2", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2558,9 +2762,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", "serde_spanned", @@ -2570,36 +2774,43 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" + [[package]] name = "tower" -version = "0.4.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -2607,21 +2818,21 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", @@ -2629,9 +2840,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -2644,9 +2855,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ultrasonic" @@ -2655,33 +2866,19 @@ dependencies = [ "amplify", "baid64", "commit_verify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "strict_encoding", "wasm-bindgen", "zk-aluvm", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" @@ -2703,15 +2900,21 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2720,9 +2923,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vesper-lang" @@ -2749,48 +2952,59 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2798,28 +3012,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -2827,9 +3044,18 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" dependencies = [ "rustls-pki-types", ] @@ -2843,7 +3069,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.44", ] [[package]] @@ -2870,11 +3096,37 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", ] [[package]] @@ -2885,41 +3137,40 @@ checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] name = "windows-registry" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", - "windows-strings", - "windows-targets 0.52.6", + "windows-strings 0.3.1", + "windows-targets 0.53.0", ] [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ - "windows-result", - "windows-targets 0.52.6", + "windows-link", ] [[package]] -name = "windows-sys" -version = "0.48.0" +name = "windows-strings" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-targets 0.48.5", + "windows-link", ] [[package]] @@ -2932,18 +3183,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2955,7 +3200,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -2963,10 +3208,20 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" +name = "windows-targets" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] [[package]] name = "windows_aarch64_gnullvm" @@ -2975,10 +3230,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +name = "windows_aarch64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" @@ -2987,10 +3242,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" +name = "windows_aarch64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" @@ -2998,6 +3253,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -3005,10 +3266,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" @@ -3017,10 +3278,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "windows_i686_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" @@ -3029,10 +3290,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "windows_x86_64_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" @@ -3041,10 +3302,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "windows_x86_64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" @@ -3052,20 +3313,139 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.6.18" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "synstructure", +] + [[package]] name = "zeroize" -version = "1.8.0" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63381fa6624bf92130a6b87c0d07380116f80b565c42cf0d754136f0238359ef" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] [[package]] name = "zk-aluvm" @@ -3073,7 +3453,8 @@ version = "0.12.0-beta.6" dependencies = [ "aluvm", "amplify", - "getrandom", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "strict_encoding", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index aa555b2..a7ed7bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,7 @@ strict_types = { path = "./strict-types" } commit_verify = { path = "./client_side_validation/commit_verify" } ## sonic hypersonic = { path = "./sonic" } +sonic-persist-fs = { path = "./sonic/persistence/fs" } ## single_use_seals single_use_seals = { path = "./client_side_validation/single_use_seals", features = ["strict_encoding"] } tabled = "0.18.0" @@ -109,7 +110,7 @@ bp-wallet = { path = "./bp-wallet" } ## client_side_validation commit_verify = { path = "./client_side_validation/commit_verify" } commit_encoding_derive = { path = "./client_side_validation/commit_verify/derive" } -single_use_seals = { path = "./client_side_validation/single_use_seals"} +single_use_seals = { path = "./client_side_validation/single_use_seals" } ## rgb rgb-runtime = { path = "./rgb" } rgb-psbt = { path = "./rgb/psbt" } @@ -124,8 +125,10 @@ aluvm = { path = "./rust-aluvm" } zk-aluvm = { path = "./zk-aluvm" } ## SONIC ultrasonic = { path = "./ultrasonic" } -hypersonic = { path = "./sonic" } +sonic-api = { path = "./sonic/api" } sonic-callreq = { path = "./sonic/callreq" } +hypersonic = { path = "./sonic" } +sonic-persist-fs = { path = "./sonic/persistence/fs" } ## strict-encoding strict_encoding = { path = "./strict-encoding/rust" } strict_encoding_derive = { path = "./strict-encoding/rust/derive" } diff --git a/bp-core b/bp-core index ea73ddd..4937ff4 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit ea73dddf3dd0f1d40074a8827468af83b48efe5e +Subproject commit 4937ff4b48b9f43342ad7b36271322aa2e807330 diff --git a/client_side_validation b/client_side_validation index 0fab906..568d006 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit 0fab90652ff33e91be9c51ee90769c9a47b40cc2 +Subproject commit 568d00688175c24c0cd1747534135cd09476079c diff --git a/rgb b/rgb index 634c3a7..3b1f6ed 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 634c3a7e8696483be6d333fc158ab014a72fc55d +Subproject commit 3b1f6edabf0c7db938d4a235aa454150526878ff diff --git a/rgb-core b/rgb-core index 9591089..46f9616 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 9591089d717dfbf01a24d33b11f8e3a44574c9c5 +Subproject commit 46f9616c4aa58dc2de6e5ebe88c19316adbe1ba8 diff --git a/rgb-std b/rgb-std index dc2e0f4..ec27b4c 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit dc2e0f4f3206f845321bf7ef511740de541ce5ef +Subproject commit ec27b4ce071057207076f07079922c2448d153e9 diff --git a/rust-aluvm b/rust-aluvm index 680c0b7..2996dfe 160000 --- a/rust-aluvm +++ b/rust-aluvm @@ -1 +1 @@ -Subproject commit 680c0b73d98e2b90a79d771e80492161a5fbf013 +Subproject commit 2996dfeb8e38fd3d396b1d04e4c894c90db02bdf diff --git a/sonic b/sonic index fda0860..70c2916 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit fda08609334968967483b43d242c2620c11be67c +Subproject commit 70c29166c6974453eea2ba5a8704a08c789fec2b diff --git a/strict-encoding b/strict-encoding index 6981414..ab618ce 160000 --- a/strict-encoding +++ b/strict-encoding @@ -1 +1 @@ -Subproject commit 698141467e12886509e2c6d0e93c96d7f6ce0cf4 +Subproject commit ab618ce5666860c202b5eb0af6b7727cd0501d4b diff --git a/strict-types b/strict-types index e445a98..4ff6323 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit e445a989f5152548e3db632d654b5ac4729ca710 +Subproject commit 4ff6323667dee5abfa75ffde999abc51a3918f18 diff --git a/tests/templates/issuance/FAC.yaml b/tests/templates/issuance/FAC.yaml index bedb48a..1dbab5b 100644 --- a/tests/templates/issuance/FAC.yaml +++ b/tests/templates/issuance/FAC.yaml @@ -1,6 +1,6 @@ consensus: bitcoin testnet: true -codexId: cv343X_v-prQy_G7-utFnpPb-T2BpYVE-ibgujHd-zYzSLEw#horse-journal-voyage +codexId: 3DrJ~lGh-IgvMl3X-lLFKWQo-4v~~MiV-0eIvR1L-2nOuvBQ#angel-tokyo-mystery name: DemoFAC method: issue @@ -32,9 +32,9 @@ global: subtype: jpeg charset: null data: - - 1 - - 3 - - 9 + - 1 + - 3 + - 9 media: type: type: image @@ -42,33 +42,33 @@ global: charset: null digest: 02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a attachments: - # TODO: the following fields cannot be recognized by strict-types directly, - # need to be converted in code - # 0: - # type: - # type: text - # subtype: plain - # charset: - # digest: 4bdf15cfc812b9c6d7a7b335daeb73dea8bef0e69c88b69e15db37c016c0737a - # 1: - # type: - # type: text - # subtype: plain - # charset: - # digest: dd0d0ed1a817858d4597336e4faa1061b81dc95b3ca77d4ecd352b6e940555d7 + # TODO: the following fields cannot be recognized by strict-types directly, + # need to be converted in code + # 0: + # type: + # type: text + # subtype: plain + # charset: + # digest: 4bdf15cfc812b9c6d7a7b335daeb73dea8bef0e69c88b69e15db37c016c0737a + # 1: + # type: + # type: text + # subtype: plain + # charset: + # digest: dd0d0ed1a817858d4597336e4faa1061b81dc95b3ca77d4ecd352b6e940555d7 reserves: - utxo: + utxo: txid: e5a3e577309df31bd606f48049049d2e1e02b048206ba232944fcc053a176ccb vout: 0 proof: - - 2 - - 4 - - 6 - - 10 + - 2 + - 4 + - 6 + - 10 owned: - name: fractions seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 - data: + data: tokenIndex: 0 fraction: 10000 # TODO: `align` is a 26-sized U8 array, diff --git a/tests/templates/issuance/FUA.yaml b/tests/templates/issuance/FUA.yaml index a6c6c33..e93246b 100644 --- a/tests/templates/issuance/FUA.yaml +++ b/tests/templates/issuance/FUA.yaml @@ -1,12 +1,11 @@ consensus: bitcoin testnet: true -codexId: WAHKjUOZ-gjaVJj0-IeQ8OHE-1lysvcD-E~Y~gnx-ZwsOezQ#rapid-forever-nice +codexId: ti~gONQJ-XsxUn8I-lxaZSsv-jf0T7CK-2a3Fm_8-NBFdtas#grace-grand-gibson name: DemoFUA method: issue timestamp: "2025-03-17T10:32:00-02:00" global: -# TODO: why name is first, it can't issue contract? - name: details verified: unverified: first diff --git a/tests/templates/issuance/NFA.yaml b/tests/templates/issuance/NFA.yaml index 2925e08..1000758 100644 --- a/tests/templates/issuance/NFA.yaml +++ b/tests/templates/issuance/NFA.yaml @@ -1,6 +1,6 @@ consensus: bitcoin testnet: true -codexId: C11V4boH-t0lNXdS-U6MDKet-us0NCCo-1cWX7xU-7ahdfqw#regard-genius-belgium +codexId: BOoO7uU4-jEJQVTW-5InKqHv-AFQd01q-3bToMSP-KedmASY#tonight-hunter-crater name: DemoToken method: issue timestamp: "2025-04-27T10:32:00-02:00" @@ -8,7 +8,6 @@ timestamp: "2025-04-27T10:32:00-02:00" global: - name: ticker verified: NFA -# TODO: why name is first, it can't issue contract? - name: name verified: NFA - name: precision diff --git a/tests/templates/schemata/RGB20-NFA.issuer b/tests/templates/schemata/RGB20-NFA.issuer index 3f11c10140a70bad7fc5d65fea8901adc74c4b97..c0d8fa795c3f05e1afca2cab60457a9302b1bad9 100644 GIT binary patch delta 537 zcmX>q)gmk6?C%*I9O@dxzyN14PUKFmzqi=EXX&m;Cu{a?>e^e9l25WMelO`d^YOKN z|DLW0^_a%Mz{o&IjV{A~BGfRjyyAQJ)S|~JAk=iHQqd~853G)Nc}!QAU0!gcU-Nky zquOL1Mm=5@?&Qp(L3Y0W<@ZD8KXG)6_fhpk1RHm7cjDejs3{1G})NhlGUUn zBUNE?F0-5}h*4actB{|jkY8F-P+C&V00m48jBKI7{(hd$_LG-0D<~;D9OPq2VsKJq zYG-8PX8;l)0b>TJAin~`m0yz{%ot3TVRyAfC(QGSNYn riOrgU!9jWQeil*5ECxS8NI(K}N>Ojf@JD zdziE!N|-=OCR;PBL%57!?sH}hpgKV&#mQ4xEUk5lOLGDr6nL~pd*+V7}-LD{rx0f^9h@DK6c~Uiy&0S`*v%N6B7p>0VF`mnu~P{n z6Pr4N0z)$+lfxkg28LF!t~q>+#xO(KVi^)Z0jMw;=;g@9|@+21obIMg+WfstXNNMe1Y=UIEczbexlFRn*VNOLGCB_;EPSoZk^8=!jnCHfV`K{r z_V@F2u4G`~1A59~E|cR#2P2?M+u79__!uOCqA3hcicAhg3JfmAY(cLS=yRlf{@+ zfvN*pttKyE~7 z4DC!@%=~-|k_=rA!n_6y4oN`yOeQu_pi~=3${|T%@&jgZbpr;V3ZQ0)ibSS1kesmN zoNk78_6P>2Q|y@xE{SZJlNDJ!JsFOD7WVr!$?{;5@|oHGzcdzm={R0ysjX!bIrz^j zZtWA%%YV)r%bUn|oqCvRpkix+k%Vr1xG zXki4}=v2YvaDa;)Xq`0!CyUc5Mka?1Ks=YpWuk*D6Pq>AdCDN=T?}mq<(xp}Sqz+P b4hs;D()lq_a@%uxVTG0JVeg# z*))IU**-4mVC56_MJEe0%5cCmPu6GDoa`s0z{ogxBa_19yNp_sH^?e7GEF|nBtN-_ zNfpGKya^~{#;i8^AhRMPGg#&!vo=t@(&ULOmW(=+&$GzY7nkNLt~YT@oEOFtHgifOG+^0qaR*l4=7f7h+^^oYT$F z&K||!bc#Kf!6lI`mtk@jtEXq7u(|vv=KAwu&8w92|H{M*${al=_H5C^JF_#lym8l@ z_G6RRdS#)te!M4p*zYY^u=dlLN84HWTA3sFeK{MSt?38z%hbs-Y-Wi-dmM@w89EqR z7=hM0RWLam;9>{bXv@IK;&h6U$zcN!&t-C%=pf6)W(#zr5=286LmNT^Cs0Ek11Foq h0)&Q14!TTic?=1YC$c(E)?t$0EXb}T#R-cn1^}0Zyl?;j diff --git a/tests/templates/schemata/RGB21-UDA.issuer b/tests/templates/schemata/RGB21-UDA.issuer index dfdef4c909bbc0f91143f70e0f110fe7721b5cfb..b3442302470d5c3cbd6cb4b86f8d174bdd4c5da9 100644 GIT binary patch delta 488 zcmbPj|Ho0p+21obIMg+WfdS59oX8zj&v5Lsu-~sqmIsrR&&>A!rLovc$MG^tZ7rL~ z!GB(HYo9PMFftHQV=43}^Wk$xyf-DM?6S))^878k4P?)@oQHu%4{K%*<*^gBTDgl(9 zEXbq^Qp{>Mc>yCULY$4YBtJVfZ}LGI1!hJDX0U0zEQ*uoGJ#B-%cMB@K9d%*HlPZn z$=b}8RwgAGsS3rVxeEDd3YmEYr6t7*nZ*iu`6UXeg{6r(3MKgpNGkG6OF&8(Kw$Dj z=DnJtm;anMmN${_Jb#|uEOm?0&kYA+uL#e{oHlhI@AP_0V@9^nV1GYP=ZTZcSZGiU_ZG%a zo*ea`?cq{24AyXmSsN^_IJt+#l2K>!DHb`t;?i7&{4|C9(vpJGlH$q# zS@vrF*yOcdS!k^v@5vtadkYq<{dDHhb{4)?=E!|t&c^jeh>@X#p@or)nct~`$>9JOyVEIlTLw-Rr&Ekf4jX`YE|bed2U#XITLuOPC5VPD ihBkx-PN0Uo$%$+tta%Ix3?T2>Z{Eq~EX4`)I|Bgf5|60> diff --git a/tests/templates/schemata/RGB25-FUA.issuer b/tests/templates/schemata/RGB25-FUA.issuer index 101a33fc5695c92013b0946fcf98e989b9ebe51d..473c4ce628276068bb9ae7440750b2130ab2c526 100644 GIT binary patch delta 577 zcmX>g^M@Ohfsuib8eN9}M5tldrvJd=3TNDzkokvHk1h+^^yB_TJDx+@Y1_r}_m~LA zZe2Z@jZts14WlkIBLnl~kIV{;U~+OMqXHuXh@8BNQ3EK)2$lnrP&sc71y+{4#N5=$ zb6FJ_fif)SlNFeGkaSiuX#sUIfpkvRU{!?6D6+F9=H{2?l}yg%RzTJVRH-yskJ*yd zq$DF%VR8nuTn30yT$-zppQeysT2fG2Qp^AaObm={p~3!sp3e3R417RAhZ#)mOb$g1 z3{DkH4ilIhCps)(WOCR5#L5l_`52NIoD`Yb8JYMQfCNau7^n*@$gcqQy1W*n=;c4> zjpa?`JI|kIH%r~3^mD_3*ek+wGN(=5$2+~=(impr#K{3HW^Td`MT`s`3@waY%={ob z4{)(Nonp6U;AC++1+{rDlgmU0Std4Xp!1YL%DWia5Xw1$%Cjb4U=d->Vn_f5F)#=h MFmi0xVCClk07HkgnE(I) delta 505 zcmew_b3lsQ+21obIMg+WfstXNNNoMVwmTjYlO>f8PT$ewv*!Bc|Kas#P8BUYQ@(h= zn6h_bHv>=|AvO98|A|n;00oQ;3=xc{dYxxBnN3xbx8CPwDT8=2%M-(l34oXG^_GJ?6COsXJRFi&B! zF|!s#EfZMs5wiwZLUD3GizTDZ1PE@>;JfwAPRJ zWDonj1q;@GI`e2d3tua9G!Tqc)^4zf&awhRmoN)QcQ3~dMvoInkE44iBZ3lJJ6Ip{L6 P, ) -> Option> { diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index f4ab954..5ea4404 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -1,5 +1,4 @@ use super::*; -use rgbp::Payment; enum WalletAccount { Private(XprivAccount), @@ -524,7 +523,13 @@ impl TestWallet { RgbBeneficiary::Token(auth.unwrap()) }; let value = StrictVal::num(amount); - RgbInvoice::new(contract_id, beneficiary, Some(value)) + RgbInvoice::new( + contract_id, + Consensus::Bitcoin, + true, + beneficiary, + Some(value), + ) } /// Set the coin selection strategy @@ -757,10 +762,22 @@ impl TestWallet { consignment: &Path, report: Option<&mut Report>, ) -> Result<(), String> { + pub struct DumbValidator; + impl SigValidator for DumbValidator { + fn validate_sig( + &self, + _: impl Into<[u8; 32]>, + _: &Identity, + _: &SigBlob, + ) -> Result { + Result::<_, Infallible>::Ok(0) + } + } + self.sync(); let accept_start = Instant::now(); self.runtime - .consume_from_file(consignment) + .consume_from_file(consignment, DumbValidator) .map_err(|e| format!("consume_from_file error: {}", e))?; let accept_duration = accept_start.elapsed(); if let Some(report) = report { @@ -791,7 +808,7 @@ impl TestWallet { // ); // Load schema and get codex ID - let schema = Schema::load(schema_path)?; + let schema = Issuer::load(schema_path)?; let codex_id = schema.codex.codex_id(); // print!("codex id {} ... ", codex_id); @@ -884,7 +901,7 @@ impl TestWallet { Some(( rgb_contract_state.immutable, rgb_contract_state.owned, - rgb_contract_state.computed, + rgb_contract_state.aggregated, )) } } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 93fa2a3..ea2c085 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -83,14 +83,17 @@ pub use rgb::{ invoice::{RgbBeneficiary, RgbInvoice}, popls::bp::{Coinselect, OpRequestSet, PaymentScript, PrefabBundle, RgbWallet, WalletProvider}, AuthToken, CallScope, CellAddr, CodexId, Consensus, ContractId, Contracts, CreateParams, - EitherSeal, RgbSealDef, Schema, StateCalc, StockpileDir, + EitherSeal, Issuer, RgbSealDef, StateCalc, StockpileDir, }; +use rgb::{Identity, SigBlob, SigValidator}; +use rgbp::Payment; pub use rgbp::{ descriptor::RgbDescr, CoinselectStrategy, Owner, PayError, RgbRuntime, RgbpRuntimeDir, }; pub use rgpsbt::ScriptResolver; pub use rstest::rstest; pub use serial_test::serial; +use std::convert::Infallible; pub use strict_encoding::{fname, tn, StrictSerialize}; pub use strict_types::{ value::{Blob, StrictNum, StrictVal}, diff --git a/ultrasonic b/ultrasonic index ab8fe90..b006b44 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit ab8fe90e88c3be6dbcfe69655792a597531fcd30 +Subproject commit b006b44c189809204505d112f10e2dd1b04b6707 diff --git a/zk-aluvm b/zk-aluvm index 1b2d6e9..36bd020 160000 --- a/zk-aluvm +++ b/zk-aluvm @@ -1 +1 @@ -Subproject commit 1b2d6e99a456e2b3c91349b4c0297038fdd6abd9 +Subproject commit 36bd0202f6100c7ba4251fa02a404b91f40c8cea From 0871e8ce5dd42f6ba06357b2203334363120dcf3 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Tue, 20 May 2025 19:42:32 +0200 Subject: [PATCH 78/90] chore: update to v0.12 RC1 --- Cargo.lock | 76 +++++++++++++++++++++--------------- Cargo.toml | 2 - amplify-num | 2 +- bp-core | 2 +- bp-electrum-client | 2 +- bp-esplora-client | 2 +- bp-std | 2 +- bp-wallet | 2 +- client_side_validation | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-interfaces | 2 +- rgb-std | 2 +- rust-aluvm | 2 +- rust-amplify | 2 +- sonic | 2 +- strict-encoding | 2 +- strict-types | 2 +- tests/utils/helper/wallet.rs | 12 ++++-- ultrasonic | 2 +- zk-aluvm | 2 +- 21 files changed, 70 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8a01f0..5c6b5e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,7 +28,7 @@ dependencies = [ [[package]] name = "aluvm" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "baid64", @@ -43,12 +43,14 @@ dependencies = [ [[package]] name = "amplify" -version = "4.8.1" +version = "4.9.0" dependencies = [ "amplify_derive", "amplify_num", "amplify_syn", "ascii", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "stringly_conversions", "wasm-bindgen", @@ -284,7 +286,7 @@ checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" [[package]] name = "bp-consensus" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "chrono", @@ -300,7 +302,7 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "bp-consensus", "bp-dbc", @@ -315,7 +317,7 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "base85", @@ -331,7 +333,7 @@ dependencies = [ [[package]] name = "bp-derive" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-consensus", @@ -345,7 +347,7 @@ dependencies = [ [[package]] name = "bp-electrum" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-core", @@ -362,7 +364,7 @@ dependencies = [ [[package]] name = "bp-esplora" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-core", @@ -378,7 +380,7 @@ dependencies = [ [[package]] name = "bp-invoice" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bech32", @@ -390,7 +392,7 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-consensus", @@ -406,7 +408,7 @@ dependencies = [ [[package]] name = "bp-std" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-consensus", @@ -415,6 +417,7 @@ dependencies = [ "bp-invoice", "descriptors", "getrandom 0.2.16", + "getrandom 0.3.3", "psbt", "secp256k1", "serde", @@ -423,13 +426,15 @@ dependencies = [ [[package]] name = "bp-wallet" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-electrum", "bp-esplora", "bp-std", "descriptors", + "getrandom 0.2.16", + "getrandom 0.3.3", "nonasync", "psbt", "serde", @@ -438,6 +443,7 @@ dependencies = [ "sha2", "strict_encoding", "toml", + "wasm-bindgen", ] [[package]] @@ -527,7 +533,7 @@ dependencies = [ [[package]] name = "commit_encoding_derive" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "amplify_syn", @@ -538,7 +544,7 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "commit_encoding_derive", @@ -671,7 +677,7 @@ dependencies = [ [[package]] name = "descriptors" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-derive", @@ -1079,7 +1085,7 @@ dependencies = [ [[package]] name = "hypersonic" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "aluvm", "amplify", @@ -1653,7 +1659,7 @@ dependencies = [ [[package]] name = "psbt" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "base64", @@ -1847,7 +1853,7 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-core", @@ -1863,12 +1869,13 @@ dependencies = [ [[package]] name = "rgb-interfaces" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "bp-consensus", "commit_verify", "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "strict_encoding", "strict_types", @@ -1877,7 +1884,7 @@ dependencies = [ [[package]] name = "rgb-invoice" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "baid64", @@ -1893,7 +1900,7 @@ dependencies = [ [[package]] name = "rgb-psbt" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1.1" dependencies = [ "amplify", "bp-core", @@ -1903,7 +1910,7 @@ dependencies = [ [[package]] name = "rgb-runtime" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1.1" dependencies = [ "amplify", "bp-std", @@ -1911,6 +1918,7 @@ dependencies = [ "chrono", "commit_verify", "getrandom 0.2.16", + "getrandom 0.3.3", "indexmap 2.9.0", "nonasync", "rgb-psbt", @@ -1923,7 +1931,7 @@ dependencies = [ [[package]] name = "rgb-std" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "aora", @@ -2407,7 +2415,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "single_use_seals" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "serde", "strict_encoding", @@ -2440,7 +2448,7 @@ dependencies = [ [[package]] name = "sonic-api" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "aluvm", "amplify", @@ -2460,7 +2468,7 @@ dependencies = [ [[package]] name = "sonic-callreq" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "baid64", @@ -2478,7 +2486,7 @@ dependencies = [ [[package]] name = "sonic-persist-fs" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "aora", @@ -2497,9 +2505,11 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strict_encoding" -version = "2.8.2" +version = "2.9.1" dependencies = [ "amplify", + "getrandom 0.2.16", + "getrandom 0.3.3", "serde", "strict_encoding_derive", "wasm-bindgen", @@ -2507,7 +2517,7 @@ dependencies = [ [[package]] name = "strict_encoding_derive" -version = "2.8.2" +version = "2.9.1" dependencies = [ "amplify_syn", "heck", @@ -2518,11 +2528,13 @@ dependencies = [ [[package]] name = "strict_types" -version = "2.8.3" +version = "2.9.0" dependencies = [ "amplify", "ascii-armor", "baid64", + "getrandom 0.2.16", + "getrandom 0.3.3", "indexmap 2.9.0", "serde", "serde_json", @@ -2861,7 +2873,7 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ultrasonic" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "amplify", "baid64", @@ -3449,7 +3461,7 @@ dependencies = [ [[package]] name = "zk-aluvm" -version = "0.12.0-beta.6" +version = "0.12.0-rc.1" dependencies = [ "aluvm", "amplify", diff --git a/Cargo.toml b/Cargo.toml index a7ed7bf..5f97310 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,6 +133,4 @@ sonic-persist-fs = { path = "./sonic/persistence/fs" } strict_encoding = { path = "./strict-encoding/rust" } strict_encoding_derive = { path = "./strict-encoding/rust/derive" } ## strict-types -# Temporarily use the `fix/value-type-order-mismatch` branch of `will-bitlightlabs/strict-types` -# After the upstream PR is merged, switch back to `strict-types/strict-types` strict_types = { path = "./strict-types" } diff --git a/amplify-num b/amplify-num index be035c1..98cda24 160000 --- a/amplify-num +++ b/amplify-num @@ -1 +1 @@ -Subproject commit be035c1ed260313217bd799bd47cbc9bdfdf27ec +Subproject commit 98cda24f2ed2d19ffaba743f59f9ad34464bb492 diff --git a/bp-core b/bp-core index 4937ff4..c6acce4 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit 4937ff4b48b9f43342ad7b36271322aa2e807330 +Subproject commit c6acce4b1cd227a196a1fcf2dbb4f4c8d4de87d2 diff --git a/bp-electrum-client b/bp-electrum-client index 4a0def6..150fa03 160000 --- a/bp-electrum-client +++ b/bp-electrum-client @@ -1 +1 @@ -Subproject commit 4a0def66a4d67b60feb80744d7f9314605b2d30c +Subproject commit 150fa0343b116e39b44530743afdb7a64a0aa3d9 diff --git a/bp-esplora-client b/bp-esplora-client index 01114f7..8313e0e 160000 --- a/bp-esplora-client +++ b/bp-esplora-client @@ -1 +1 @@ -Subproject commit 01114f76940fcd81bc6242b10717d42461f4d7d7 +Subproject commit 8313e0eda770d67e1552d72afb2ae30ca766431b diff --git a/bp-std b/bp-std index a758653..cc74fd2 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit a75865311f44a301032aa0db6a3cd0d0059d9d40 +Subproject commit cc74fd2789d4146b3ca8e2226601639b714e8570 diff --git a/bp-wallet b/bp-wallet index d974b91..9a0ef49 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit d974b91d1c28a81befbd12cf4ae13a9ca0a2c772 +Subproject commit 9a0ef49d7fce8b3d9e66559de6e81976dc20e315 diff --git a/client_side_validation b/client_side_validation index 568d006..8d34606 160000 --- a/client_side_validation +++ b/client_side_validation @@ -1 +1 @@ -Subproject commit 568d00688175c24c0cd1747534135cd09476079c +Subproject commit 8d3460691469b0c7e9fbbf863ff54e1047618dc9 diff --git a/rgb b/rgb index 3b1f6ed..4efe351 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 3b1f6edabf0c7db938d4a235aa454150526878ff +Subproject commit 4efe3518434e4b65d8c8a00cd319857acf4fb7f2 diff --git a/rgb-core b/rgb-core index 46f9616..ecd56a5 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit 46f9616c4aa58dc2de6e5ebe88c19316adbe1ba8 +Subproject commit ecd56a50d22b9cca4eb4184449cc6d23a92a06ef diff --git a/rgb-interfaces b/rgb-interfaces index 5a24c50..8632140 160000 --- a/rgb-interfaces +++ b/rgb-interfaces @@ -1 +1 @@ -Subproject commit 5a24c50701075d2bb7ab79fccdfeba9d65a9ed17 +Subproject commit 8632140cf62161cc4ffabbb176f2fe31cc303cb8 diff --git a/rgb-std b/rgb-std index ec27b4c..d754fef 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit ec27b4ce071057207076f07079922c2448d153e9 +Subproject commit d754fef231fa999292a534972e705c6f9dcaf263 diff --git a/rust-aluvm b/rust-aluvm index 2996dfe..b72e543 160000 --- a/rust-aluvm +++ b/rust-aluvm @@ -1 +1 @@ -Subproject commit 2996dfeb8e38fd3d396b1d04e4c894c90db02bdf +Subproject commit b72e543d4373036965323775b6113e05a0b43bef diff --git a/rust-amplify b/rust-amplify index f60a5a8..97e49a3 160000 --- a/rust-amplify +++ b/rust-amplify @@ -1 +1 @@ -Subproject commit f60a5a87002353f5e40ace0c3e332a609a17c1b3 +Subproject commit 97e49a3e8716ab2990a55d65475cf6d409395432 diff --git a/sonic b/sonic index 70c2916..706089f 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 70c29166c6974453eea2ba5a8704a08c789fec2b +Subproject commit 706089f2747a676362abcf644db7b867d67d2bd8 diff --git a/strict-encoding b/strict-encoding index ab618ce..c32aa6c 160000 --- a/strict-encoding +++ b/strict-encoding @@ -1 +1 @@ -Subproject commit ab618ce5666860c202b5eb0af6b7727cd0501d4b +Subproject commit c32aa6c3d850663941ad9782ab50445593d3e4ea diff --git a/strict-types b/strict-types index 4ff6323..3b101ec 160000 --- a/strict-types +++ b/strict-types @@ -1 +1 @@ -Subproject commit 4ff6323667dee5abfa75ffde999abc51a3918f18 +Subproject commit 3b101ec7c91cfac45c8b9feff01540dd5f593f64 diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 5ea4404..b63ac7a 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -7,7 +7,7 @@ enum WalletAccount { /// Test wallet structure type pub struct TestWallet { /// RGB runtime for wallet operations - pub runtime: RgbpRuntimeDir, + pub runtime: RgbpRuntimeDir, /// RGB descriptor for wallet pub descriptor: RgbDescr, /// Signer for transaction signing @@ -236,7 +236,11 @@ pub fn contracts(network: Network, wallet_dir: PathBuf) -> Contracts RgbpRuntimeDir { +fn make_runtime( + descriptor: &RgbDescr, + network: Network, + wallet_dir: &PathBuf, +) -> RgbpRuntimeDir { let name = "bp_wallet.wallet"; let provider = FsTextStore::new(wallet_dir.join(name)).unwrap(); @@ -412,7 +416,7 @@ impl TestWallet { self.runtime.sync(&indexer).expect("Failed to sync wallet"); } - pub fn runtime(&mut self) -> &mut RgbpRuntimeDir { + pub fn runtime(&mut self) -> &mut RgbpRuntimeDir { &mut self.runtime } @@ -420,7 +424,7 @@ impl TestWallet { let contract_id = self .runtime .issue(params) - .expect("failed to issue contract"); + .expect("failed to issue a contract"); println!("A new contract issued with ID {contract_id}"); contract_id } diff --git a/ultrasonic b/ultrasonic index b006b44..122bce7 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit b006b44c189809204505d112f10e2dd1b04b6707 +Subproject commit 122bce74d6cf0ee5cd3607620dcdbb96c4b596c3 diff --git a/zk-aluvm b/zk-aluvm index 36bd020..02b5cc8 160000 --- a/zk-aluvm +++ b/zk-aluvm @@ -1 +1 @@ -Subproject commit 36bd0202f6100c7ba4251fa02a404b91f40c8cea +Subproject commit 02b5cc85f937f60fbf69f6d5460769bbfc498a99 From cde94bebbbe9e7ad9607ce59f519cc8ab09ea0f6 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 1 Jun 2025 15:17:29 +0200 Subject: [PATCH 79/90] chore: update to v0.12 RC2 pre-publication --- Cargo.lock | 150 +++++++----- Cargo.toml | 5 +- rgb | 2 +- rgb-interfaces | 2 +- rgb-std | 2 +- sonic | 2 +- tests/issuance.rs | 7 +- tests/templates/issuance/FAC.yaml | 57 ++--- tests/templates/issuance/FUA.yaml | 11 +- tests/templates/issuance/NFA.yaml | 9 +- tests/templates/schemata/RGB20-NFA.issuer | Bin 3716 -> 0 bytes .../schemata/RGB20-Simplest-v0-rLosfg.issuer | Bin 0 -> 6152 bytes tests/templates/schemata/RGB21-FAC.issuer | Bin 8739 -> 0 bytes tests/templates/schemata/RGB21-UAC.issuer | Bin 8499 -> 0 bytes tests/templates/schemata/RGB21-UDA.issuer | Bin 8444 -> 0 bytes .../schemata/RGB21-UniqueNFT-v0-TFKAmg.issuer | Bin 0 -> 8371 bytes tests/templates/schemata/RGB25-FUA.issuer | Bin 3711 -> 0 bytes .../RGB25-UniquelyFungible-v0-r~mUOw.issuer | Bin 0 -> 6056 bytes tests/transfer.rs | 9 +- tests/transfer_rgb21.rs | 6 +- tests/utils/helper/asset_params.rs | 7 +- tests/utils/helper/asset_types.rs | 21 +- tests/utils/helper/coinselect.rs | 31 ++- tests/utils/helper/wallet.rs | 228 ++++++------------ tests/utils/mod.rs | 6 +- ultrasonic | 2 +- zk-aluvm | 2 +- 27 files changed, 240 insertions(+), 319 deletions(-) delete mode 100644 tests/templates/schemata/RGB20-NFA.issuer create mode 100644 tests/templates/schemata/RGB20-Simplest-v0-rLosfg.issuer delete mode 100644 tests/templates/schemata/RGB21-FAC.issuer delete mode 100644 tests/templates/schemata/RGB21-UAC.issuer delete mode 100644 tests/templates/schemata/RGB21-UDA.issuer create mode 100644 tests/templates/schemata/RGB21-UniqueNFT-v0-TFKAmg.issuer delete mode 100644 tests/templates/schemata/RGB25-FUA.issuer create mode 100644 tests/templates/schemata/RGB25-UniquelyFungible-v0-r~mUOw.issuer diff --git a/Cargo.lock b/Cargo.lock index 5c6b5e5..98ec6a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,9 +100,9 @@ dependencies = [ [[package]] name = "aora" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0da0aa3a98a56f9002e0d30d642b62ba55b39821075951a764121bfe098ee98" +checksum = "fa0b56f69d2c47f8ee387f40849742d552e8b94596d997c19095809ac5c6b377" dependencies = [ "amplify", "binfile", @@ -472,9 +472,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.23" +version = "1.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" dependencies = [ "jobserver", "libc", @@ -1065,17 +1065,21 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ + "base64", "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2", "tokio", @@ -1089,6 +1093,7 @@ version = "0.12.0-rc.1" dependencies = [ "aluvm", "amplify", + "binfile", "commit_verify", "getrandom 0.2.16", "getrandom 0.3.3", @@ -1267,6 +1272,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "itertools" version = "0.12.1" @@ -1322,9 +1337,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", "windows-targets 0.53.0", @@ -1350,9 +1365,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -1405,13 +1420,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1486,9 +1501,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ "bitflags", "cfg-if", @@ -1518,9 +1533,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.108" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -1541,9 +1556,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -1551,9 +1566,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", @@ -1618,9 +1633,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", "syn 2.0.101", @@ -1812,14 +1827,13 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "e98ff6b0dbbe4d5a37318f433d4fc82babd21631f194d370409ceb2e40b2f0b5" dependencies = [ "base64", "bytes", "futures-core", - "futures-util", "http", "http-body", "http-body-util", @@ -1834,7 +1848,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", @@ -1843,12 +1857,12 @@ dependencies = [ "tokio-native-tls", "tokio-socks", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows-registry", ] [[package]] @@ -1877,6 +1891,7 @@ dependencies = [ "getrandom 0.2.16", "getrandom 0.3.3", "serde", + "serde_with 1.14.0", "strict_encoding", "strict_types", "wasm-bindgen", @@ -1898,6 +1913,17 @@ dependencies = [ "strict_encoding", ] +[[package]] +name = "rgb-persist-fs" +version = "0.12.0-rc.1" +dependencies = [ + "amplify", + "aora", + "rgb-std", + "sonic-persist-fs", + "strict_encoding", +] + [[package]] name = "rgb-psbt" version = "0.12.0-rc.1.1" @@ -1921,6 +1947,7 @@ dependencies = [ "getrandom 0.3.3", "indexmap 2.9.0", "nonasync", + "rgb-persist-fs", "rgb-psbt", "rgb-std", "serde", @@ -1935,6 +1962,7 @@ version = "0.12.0-rc.1" dependencies = [ "amplify", "aora", + "binfile", "bp-core", "bp-invoice", "chrono", @@ -1948,7 +1976,6 @@ dependencies = [ "serde", "serde_with 1.14.0", "single_use_seals", - "sonic-persist-fs", "strict_encoding", "strict_types", "wasm-bindgen", @@ -1976,6 +2003,7 @@ dependencies = [ "psbt", "rand 0.8.5", "rgb-interfaces", + "rgb-persist-fs", "rgb-psbt", "rgb-runtime", "rgb-std", @@ -2121,15 +2149,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.12.0" @@ -2153,9 +2172,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -2438,9 +2457,9 @@ checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2458,7 +2477,9 @@ dependencies = [ "commit_verify", "getrandom 0.2.16", "getrandom 0.3.3", + "indexmap 2.9.0", "serde", + "serde_yaml", "sonic-callreq", "strict_encoding", "strict_types", @@ -2491,6 +2512,7 @@ dependencies = [ "amplify", "aora", "binfile", + "commit_verify", "hypersonic", "serde_yaml", "strict_encoding", @@ -2737,9 +2759,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.45.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -2828,6 +2850,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -3116,7 +3156,7 @@ dependencies = [ "windows-interface", "windows-link", "windows-result", - "windows-strings 0.4.2", + "windows-strings", ] [[package]] @@ -3147,17 +3187,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result", - "windows-strings 0.3.1", - "windows-targets 0.53.0", -] - [[package]] name = "windows-result" version = "0.3.4" @@ -3167,15 +3196,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-strings" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index 5f97310..0a64e46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,8 @@ rgb-runtime = { path = "./rgb", features = [ ] } rgb-psbt = { path = "./rgb/psbt", features = ["bp"] } ## rgb-std -rgb-std = { path = "./rgb-std", features = ["fs"] } +rgb-std = { path = "./rgb-std", features = ["binfile"] } +rgb-persist-fs = { path = "./rgb-std/persistence/fs" } ## rgb-interfaces rgb-interfaces = { path = "./rgb-interfaces", features = ["serde"] } ## rust-amplify @@ -117,7 +118,9 @@ rgb-psbt = { path = "./rgb/psbt" } ## rgb-core rgb-core = { path = "./rgb-core" } ## rgb-std +rgb-invoice = { path = "./rgb-std/invoice" } rgb-std = { path = "./rgb-std" } +rgb-persist-fs = { path = "./rgb-std/persistence/fs" } ## rgb-interfaces rgb-interfaces = { path = "./rgb-interfaces" } ## rust-aluvm diff --git a/rgb b/rgb index 4efe351..9277811 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 4efe3518434e4b65d8c8a00cd319857acf4fb7f2 +Subproject commit 9277811dbf4085bd041453acd65f918e80808b5f diff --git a/rgb-interfaces b/rgb-interfaces index 8632140..4dea227 160000 --- a/rgb-interfaces +++ b/rgb-interfaces @@ -1 +1 @@ -Subproject commit 8632140cf62161cc4ffabbb176f2fe31cc303cb8 +Subproject commit 4dea2271f36130c2a477481fdc75f8def302f82d diff --git a/rgb-std b/rgb-std index d754fef..9d1c9ee 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit d754fef231fa999292a534972e705c6f9dcaf263 +Subproject commit 9d1c9ee7250eb1a216e04543958b91607a482d6f diff --git a/sonic b/sonic index 706089f..3e9636e 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 706089f2747a676362abcf644db7b867d67d2bd8 +Subproject commit 3e9636eb9472bd3a79ca7207352afdc79eb2b0a5 diff --git a/tests/issuance.rs b/tests/issuance.rs index a4369e9..0f344ac 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -211,7 +211,7 @@ fn issue_fac(wallet_desc: DescriptorType) { let data = vec![1u8, 3u8, 9u8]; let preview_ty = "image/jpeg"; let token_data_preview = EmbeddedMedia { - ty: MediaType::with(preview_ty), + mime: MediaType::with(preview_ty), data: Confined::try_from(data.clone()).unwrap(), }; let proof = vec![2u8, 4u8, 6u8, 10u8]; @@ -226,12 +226,9 @@ fn issue_fac(wallet_desc: DescriptorType) { } let nft_spec = nft_spec( - ticker, name, - details, token_data_preview.clone(), token_data_attachment.clone(), - token_data_attachments.clone(), token_data_reserves.clone(), ); @@ -252,7 +249,7 @@ fn issue_fac(wallet_desc: DescriptorType) { assert_eq!(token.details.unwrap().to_string(), details); assert_eq!( token.preview.as_ref().unwrap().media_type.r#type.as_str(), - token_data_preview.ty.ty.as_str() + token_data_preview.mime.ty.as_str() ); assert_eq!( diff --git a/tests/templates/issuance/FAC.yaml b/tests/templates/issuance/FAC.yaml index 1dbab5b..2bd8ed1 100644 --- a/tests/templates/issuance/FAC.yaml +++ b/tests/templates/issuance/FAC.yaml @@ -1,32 +1,30 @@ consensus: bitcoin testnet: true -codexId: 3DrJ~lGh-IgvMl3X-lLFKWQo-4v~~MiV-0eIvR1L-2nOuvBQ#angel-tokyo-mystery +issuer: + codexId: aq_P8~q_-6FL9taO-OwXLij6-gfC3d0u-oH0rARg-KiFs7dM + version: 0 + api: TFKAmg name: DemoFAC method: issue timestamp: "2025-03-17T10:32:00-02:00" global: - - name: details - verified: - unverified: first + - name: ticker + verified: NFT - name: name verified: FractionableAssetCollection - - name: fractions + - name: maxFractions verified: 10000 - name: token verified: - tokenIndex: 0 - fraction: 10000 - # TODO: `align` is a 26-sized U8 array, - # Need to rewrite to bytes in code - align: + tokenNo: 0 + fractions: 10000 unverified: - index: 0 ticker: TCKR name: asset name details: some details - preview: + embedded: type: type: image subtype: jpeg @@ -35,43 +33,16 @@ global: - 1 - 3 - 9 - media: + external: type: type: image subtype: jpeg charset: null digest: 02d2cc5d7883885bb7472e4fe96a07344b1d7cf794cb06943e1cdb5c57754d8a - attachments: - # TODO: the following fields cannot be recognized by strict-types directly, - # need to be converted in code - # 0: - # type: - # type: text - # subtype: plain - # charset: - # digest: 4bdf15cfc812b9c6d7a7b335daeb73dea8bef0e69c88b69e15db37c016c0737a - # 1: - # type: - # type: text - # subtype: plain - # charset: - # digest: dd0d0ed1a817858d4597336e4faa1061b81dc95b3ca77d4ecd352b6e940555d7 reserves: - utxo: - txid: e5a3e577309df31bd606f48049049d2e1e02b048206ba232944fcc053a176ccb - vout: 0 - proof: - - 2 - - 4 - - 6 - - 10 owned: - - name: fractions + - name: balance seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 data: - tokenIndex: 0 - fraction: 10000 - # TODO: `align` is a 26-sized U8 array, - # Need to rewrite to bytes in code - align: - + tokenNo: 0 + fractions: 10000 diff --git a/tests/templates/issuance/FUA.yaml b/tests/templates/issuance/FUA.yaml index e93246b..fb619c1 100644 --- a/tests/templates/issuance/FUA.yaml +++ b/tests/templates/issuance/FUA.yaml @@ -1,22 +1,25 @@ consensus: bitcoin testnet: true -codexId: ti~gONQJ-XsxUn8I-lxaZSsv-jf0T7CK-2a3Fm_8-NBFdtas#grace-grand-gibson +issuer: + codexId: qg8TdlRF-~RGz7bI-pceS960-evWjLKg-NcWTNWy-D9pIYBA + version: 0 + api: r~mUOw name: DemoFUA method: issue timestamp: "2025-03-17T10:32:00-02:00" global: - name: details - verified: + verified: { } unverified: first - name: name verified: FUA - name: precision verified: centiMilli - - name: circulating + - name: issued verified: 10000 owned: - - name: amount + - name: balance seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 data: 10000 diff --git a/tests/templates/issuance/NFA.yaml b/tests/templates/issuance/NFA.yaml index 1000758..65e5732 100644 --- a/tests/templates/issuance/NFA.yaml +++ b/tests/templates/issuance/NFA.yaml @@ -1,6 +1,9 @@ consensus: bitcoin testnet: true -codexId: BOoO7uU4-jEJQVTW-5InKqHv-AFQd01q-3bToMSP-KedmASY#tonight-hunter-crater +issuer: + codexId: y6L7YTlM-5_v4LWy-oQsj5hV-I2imvxD-zRu0JBo-yaguhrY + version: 0 + api: rLosfg name: DemoToken method: issue timestamp: "2025-04-27T10:32:00-02:00" @@ -12,10 +15,10 @@ global: verified: NFA - name: precision verified: centiMilli - - name: circulating + - name: issued verified: 10000 owned: - - name: amount + - name: balance seal: b7116550736fbe5d3e234d0141c6bc8d1825f94da78514a3cede5674e9a5eae9:1 data: 10000 diff --git a/tests/templates/schemata/RGB20-NFA.issuer b/tests/templates/schemata/RGB20-NFA.issuer deleted file mode 100644 index c0d8fa795c3f05e1afca2cab60457a9302b1bad9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3716 zcmdT`d2kd}8h`Ii_Z(r#5Q3m+V3O>D+=K)r2T3zYfI#jcm;kZU>3Ngs(9=EXBL|8c zQXE;XxEc;YBXM0p*^Nb9j>-lQG=+Nt=d;L zGrxM@@4fzg-+V`>=47~B1?l+!qy`ZL5!s?JffGDDqcEjBc6d~wjMD)l%UB5qZb44) zGlE-`7{A2%@I==8VrE(y(ALCTeSN)sKfNG;zyv^N7zg{rA9%wWp&IHhR4;(;T2))!jZM`$MVCumrY0ro&5v*aD3C4 z9uFM#qwYX5f0lE~WN1|+Mvy&Nf@a1is)9lcU^$6Zwa9Qn+1mAmm`(UH@rC^#4Bt@u zRmag!h78yu<$Zj*<7!*pBO6x*T-BrU(@TrR-Phk!T0fmMu)CT6uf1!;f4;rKv~Ac@ z9JBYcOS@XAZLu%$z=%Kyj1Q0h%bHr^@E5K}j-@Xc8~)awz4LZHghMaB>`P5wc4>9T zKjGa)+>_Nvh@n!OU&1UWbD~geIzDW}?v2l+BwS5Bzip}FhzR?7^py72T}^X0rhG|9 zL4b@T84~VWu36#O#aMEd3?im?PTP5C_y+s2!++cQ`x8UIy4-ZlbMQjU+a(<@`t*!9 zScZiA)*4J-ql`5WdM{=}t%jGFAl(N@PL@>+z?}*-j$@qS#SU5ZIYf_x6a18POs0{B=M8^*pqN?bWpd19Cxxkf^ospUXK&ZA$ZAEJkB>~{9M$~3BqmF8Th-%V4 z(bUmUPzs!pXbnVmpnd5ZvD&G?rrn{pxVtX+z^Pm9u_NO~u4`|%JcgU2t~VViJ{`V; ztAC+&;Fe|au|X|$0IYy$In<>L)}%Zb0FEG_bZ}c&7`1|Wg?h^lsBlVxU@ce$LrivE z{*e%i^LW{((0%PWKPsPjn?V4VD%lkO{13soB8(L8vQwH0y39_65~JO zuD%1~;qgYfFgzfOQCX{#bXISugc>{R`mIp@uZIvRC$8QEh-a9nb)2&iCBUqak5DiaEwW*5~q-gSHd`! z@QA7uM|ikOJk=y~)sK-fuEfIQB<9Mz$}~dY1RSs3%8NpRO~yVhRfmZLk7YTD43yt= zOPPcjO-8b{LdCM8_4yRUC={Y+%s{l$iRjc+M5m=8Iz1iHGiM@t)+|KNo{i{?3`EbF zgXp<)5uKTd=&US6XJ;ciCkN5FxroloLv(&VqFpXT&zpznf&xU(pO5G#odb zj|Y~OL9Z8b94s$~ix)$lhdv(^1SpEo?}rr?P?Df5Lq&nA3M(sNRTZqRhBY;C$r2kI z6!H||=luBT+Z*{yNrmIx_?fJv;-e>TOufGBOhbKDMBk!YpKpAAM^cxst!eebb*|d& zBs40JMXzKO7I(*8s@r$IVe<5klLn1^yr{V?GIS)c8ckVK_yA6DbCudi z)?WSq;nt=zB=ywekd`?-&zWrcUX~7tkboh8NzKYiqPgFyK}*o8VXO8=B8WDtel%M{ zA-2Ft9S+dK!HT~Km~u5V@OzUELrD+zDWW}a=S&?A`u@%U4kH*v5eL&xj_Q7wOnNvy zEpOp_4S0IPSWDf_m@r?(t2aI#+T|)RCErha|F07D=S{Yi(aXP9uUu??`;)wyx=wlX z-d+FLr;g7wd-L`{7S+FFiu?cc%ji{xghmx$)U8Qm6uaxa_)o9hs%H53bH5W_y*mE@ zom|vA<^b-B{3t(X@R~VB6NN-Z6XDw4VUcMkKRR3bMNiI^n?u|YzbRjSwBbbZ;Vn|d js&!Ad7}>2x4+xIQ(fz>4C96@5!TyUZ{l7+Y8iMZtFU{qt diff --git a/tests/templates/schemata/RGB20-Simplest-v0-rLosfg.issuer b/tests/templates/schemata/RGB20-Simplest-v0-rLosfg.issuer new file mode 100644 index 0000000000000000000000000000000000000000..408e7ff66f00a2c6e24b2c555854e344457d4158 GIT binary patch literal 6152 zcmdT|3s4kC8lIlrS#}`;ijj)ZIEc|;L_tYneBiKvK}8f0l%Nj7ZZA7BJG0EpE~vpn z#l)bfm`lvlpys8~D{~rO=QC<{djrATgZGD74_wwb!`&voCygHBorQ{?{KC<=tCX{%ur>cw&XS>6O6` zZv)*4U{z&KR9sL7VWphFi4JJC@QUJt&c#coLC1)1M?Sv&c+dK}mgWN=c8^#k=bk>< z+dgBt=Jz_7`QX5q*EVdL^4x7O^3wC3^vpke{c!UqAUc$X#ynPl_+ZT5 zPlt3lzg4&zb>@!muYbcGsb4iCdD9nPuiec&HEgwj6|i|_=-?Gz5@(nW#n!K1HgC*` z*7S2vRjYLGuHOw9`qtjHnl{4)9VlICYTAR7Fprv!l&z`BAJXooHivII8ISOF{!D4U0? z%J+G_!fcYfB~VI%p^jA&=${TWkf4LMC;`3XUe9SF3daw?>q&>?U#ry}&y zcWK<98O1I61Sef;NFa3=FDq&S4#7&hL!5SU(pnk+Zl`o3H*raU4oP$-;EpSQyHD+< z`nz4~uyhl@R5vd>6U>+b>c@+IPT-wCPoPS77)DGVq%cN$OI{evpU0=Dw43uo8ts=C zy*^d3V6+Ex(iSC^_9>9&#M!^VNf^e?-8ZolfYz^V8Rv@e?QA+hgJDM$BtMj0f>f#K z;6)|Kdwd>RkBx!FP?iSiad1hpCjfA+RPw31nLzc@fvTikl23FRAPQw{l;&1&PpFpk zo76Dil%RrwuF_~Bhg)9(t%MRl8&_{|lc9{q`b1deg$@3i2oAj7win5Ru3vgMh>gCmE6^mXM6h5cVpPSwW^X zFpYp@Hlx4zF4ah?gs{gUsTyJlngUTscM8!Zm(Y2QIuA`UF-*&TVkxm0gqxxm@>9Zo z73mPb{x_tg*?Nx5XkdDimLjxhJkzqCSVq(ZWNDzwGN653B)gJHBrS`G5&$rp$5n#? z@SvGreGI;_PGV( z94IbY_J>#|C#Lnqsqfj28mMuh#Gzo<&j&hWmey!rMuScZf{vE$5`9n;7&PjGlE7d; zp#kf$_5=fFKGVRgVO~SPX}9?)v3wyQqYz9x$EefT2zjUJ_F!u#je-S|xoxi#b01&L8%it!?99>^k)2w7cU9_CywTJFxFu z?c*hfEtFT5Bv;F>el+TxddiPdk-zib`e>(zY+Kj^=I z-`ihQhA&?IysTZTS72TTDcZHo`;?AX}AKoy%C1F7Ry5R@PE{$|NJMr}2 z_pD!@!pH7vO7~IV#kZ~v^~HqEo7AVNL|(Zdqw$V4ONHhuPc}zPy=PXqG!YYQ(I>YjT7JVzgqFtM`1W8Xae^#qQIdM)vI@IA!jR1%V)fQ zW~2Ga(Rc04{=K`yqjp%k6MsC3djL@24X*3?=g&S}8ELt+_odk7sSE2qvOc>m=Cg5| zC;zj!VOM3=-uT#opVwwSePLlrqh*Zk$H?TlUoMFsbz#A}#l8zq>@cyE;zgY&ZH842 zA*9dB_;0_r^bg`xJv0Y&vr8|Oi!g5KEu!#S^{sIugB!vWS(nM3at zHTy1u%1f|viV9_3DIaL|3O?m-${~3?+#t%si#{dM&2hM4C-SxPcVB1|@^ zmC{g3b;}SAGou?{PBFW9KfK4J@KyIx3iLzqJ__<>Zgsd>ue7Z)C zGz(BsMp63JIy$UOhNy#_&~sAvuJ7?M*Nl1)n^S-YKN)6+>dBZFi!Gf8&rSdx9< z0g}ziBH3}{NOt^qlASPtWV5qLcH%^m&B-CzNs~x+@??_D%_Z5qJd(}NC)p`eNVcGW zWD5&PcIs4;oi>eRi;770!3V>Y3VSdz#kNuuqI_+`(>tc~W>5}JhU!dwQ5pY zdtU-L4wRMxhXXjB07Bq$fwD5-b_1RVvu1(vav%u6;{l=wBnf!EprQiEGEfwts=((1 zem|(J1XWdF_G~a`j?G~>GS}?oz3`#-iM(n`JngSWF+N+ z9#x9cZI0E*=zvX~?rP>#RqDph?0^0+HR|@vjNIZk8{z22fng2TlDm2;Uik5Jk2CoN zrqtg9&i@t6{<~0F5MT41@0&|oU;i+7cEiWYicM?(vBfti+v3jM0375KZSVp`Hh z|9xldb^c9hC(;rIuS@#u#=MERe}GT`S7YlI*jtaDdi%thZq4;)N`@4kyedT=I^;jR z-(8eF!3+y2fV-A(*BW8Q-53;!L%MY)aj?O0KAV^r7AF?TMH>clR;N zS6k^>3&P4@nDdtp=XjU3E{M#@i(Oe+SWW?4wsE<%;=o|ELpOp1uCqZ6kXpq%aTzxI p(Mt%|z2N#IE3P*&oNsFjP`G&i+tC;hw2Xs@6?gI)U2%K&`7h}_FTDT& literal 0 HcmV?d00001 diff --git a/tests/templates/schemata/RGB21-FAC.issuer b/tests/templates/schemata/RGB21-FAC.issuer deleted file mode 100644 index 00137eddecc5abc7cc99ed01677b8d982b6f8f9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8739 zcmdT}dpJ~E|KDqyJu?(eh>~lHC=p6U8iS5Y$So0#VKy_Fo7sC@I=Q5a?!-BCq>@S} zQYoEEQo0yMfBto_|YD}j4PE1MELXw z{*HytQ3y4re;6Db82s}A5P&EkNP%*F?k(RFGj*Q?d_3m6i!p0bZ(c4MnJ=Dck@c&& zW(Pu%!Ds@I!7rde9?Y#7@YyqQR9%j|ZJKX3d#lA@@5I1w*Pqq(Xd(_*X#Ahz0L=GW zw$%*4BxPJN5sAxyV&rFy5Hto4C%FP4ad&>@BMarWGT~d*R=qbLySdd{azba6JbztK z!TQm9mvBf{$bb^SzJYk!hgQ|SpZPBNc7Ar8?qJA=&aL0)*|&hWE{{wqp)^`(Lv|g~MMDH@lLB#x~;XH{$P3%~!2S@4DD# z{>HVIbM7Cng1&2WIDx6D={Qfm3U-T5JS?DebfHR0-0)mj^2=Ye=!o$giTv4E}{eA}5DPM%Yn606oCZ+sn<#13^@%RhAlp zu*ajUF=@)kD}pz64v6cCkLT4?!1kqi_+~V?Hdh|Z$ySQ{E1wV zB43Uu(tqEZBF|)*qx9uppuInFir<%^N!HpYur_vAIBHP=k9DjT%+03b+j+?^otoM!kTu77$87fI6;4O zs}bSWYiyYt9_~=sZC4)D#ccFBmhAsC4Mk{Ti5Q0^2S6hvBE0*X@GV`&(k@ebF?rIz zk2?+JW%Ok&i8s2pBHE3YQ_46r^~TQlz1Et8iyncAEqc`!p&9jgKNWPfW@LIkt}tcx zA6z2So@eb(KhD1>2~JH=46A!QXQ1Lp>xS~}b8a=ok7#G`^F-Oq^;_k9d#57@qAMme z_+D5o5v0BB^PbxExc23X`I+8yRFNx{3I#aNUxI_hPETDo_rB4v0SR{|Kbz8X-s6K~ zot?>Vn0J#cq05Mnh)G;bsuUg8PB=g#4pkSf^Z95|HHhflX?V>_xu=%5IW8u(ANHJ% z(#QlUUaH(OkYZ4BH~$LL)NoO8slAV9Y>N-SswM_2NQ#OKqw%;Tx2Jqkisr7wxvn1( zOLP5)DW{)|Ne2Z>3+3jC^{cv=vsD_j?Z&Tt+sDx!tTxsS(2p+m=%HV|cv^kjd}PK3+2@*gwYVfa6rdfU_!#)vC@tS@T2KWjZF6NhFc5k7*uj zIkwOI(m$}yHg#T^kA`u5*&Zc~(I z32=9K`OVKkV=X6Uuyv7fnwtBtRn>v|*RwoICyrCDzpL55+{$#kiKmXL$G(XS=oXp? ztlYss$R4*Pp=~y=w;g|yZ+Wt-@#@Lk%7bGqzR|Z0DyueB(TA~#uyl^fw`yEKHmf3= z+Z!77c8#}fy{h`7#^u~3)7ER><)6Vo-33`@dctgld-|azTYT!aM>|=~R?VFBrn-tU zX}vFy&o)me}Fb1N$MPY#O=EmbuQIj5eyY&#Qul6RJb-uDfN%a&{1Npwu;%?6hEfcj2hvg30 z-ETu^DP@M*T8C~}27T~p+;^sB+Slcvqtct{zcq{wZoA7Edu4{dZm{o}mfD-XJ7>2y z|12|5%&{?X>Tiw`1wF3*&CEsAsAD|N;Kk2wN%Q)Ga_?T+bxwu>SRB~jDA-w7vSZtK z#+IB7Kke%`9A|0fMO;3l6tCP~j4UG*%xQRhgwT-2=MsD)I*;nWxUxwKT#?k6CKbww zsZ{6_d~*e!gq%)Wfy*S83RH%jp+Lq-tT2)B#_HNY%GY21M%@7Apxvd0XsM_aDh9fZTI8cI2HP< z%0jJlht(UKnR$EFpSm4g^xM*H<#A3$$(MiY<9W9g9A2h$*X{2TLY>i89$7-8=`h3OrDl@)&vB}83BX#e3c}Mms1rA0? zxe>U*C)?0tmKm zev5KkT~Usk8_IEaM>!rIC}-h9l;i1%a=g4yj<+|;S+oe{`1qh4Utg5t=ZA9q{ZURp z0Lods807>8qMRj5P)<+~$_WluB4XH|HM3MPoKlhBkia2-Ec=H3FK1;AQIUd(=&--n zZ51O%82OGS6-e=wzc2VEVx&OG!;@fL7oCX-#5_D6Rxi+p*vDlL44*rmST@R`_@FG% z=RsRVT=2z^?e|UmvWj=lpVD6IH{2P+%B&G+BFm~}j%8qBrP$E-W>SyLBI5Ph;(^zR zJ$5E04vV){J!ME`c&q@Ad!vVMJ+N^8Os~Ak+XfGHoecu4%iaXkZ!o#mF}9Z%K*K~h zPr!YY_LEJvb=r?dE^W*l!=KAeoO;t?`hm_;a=9cY800wxe=5z^Xv6(wOZ{*Tluvp*=ZFuQ3g&VXFPXy#HoPO$<(UUbQ>sJIm zQO;5>GClLq?Wz5N_79s@&CDyu0E|mmje#&Z%Z%GDWA+nVoPC!5l8?{JH)Cw;pD{)h zv+w;q%~rnv1&4np-v3jP`}am4XJ?i1%HG03@>)_sYn}JN*s6AuJp;$^Us4vld}uK1 z2?j{(8INp@O1)PoZ@oFK>;jv;JM>nfhuROxWlCh|lFjWAy3gO-x73?s^~U2gXYT8e z6FsHfhm$&|t}W(ICAvs|XhEWbz~UBOn!#NB>k5)Y+$-l*w&qHEdpGq!wvWlr=ewB& zSEc@1#QO>6o<);l3adI?H&#@*lvw2t){YPLGTT}7`oYm#PuZC#o8P(Iqob&R7uS6~ zvF`X8-+ilFGOC{WZq4_ijiza(`Z?;P>KWRmM+|2fSm3~v4^^%T0^;|#*nQLAUQpr!eGc6RFzH!#p_p?ze{_EAUoU*qySWa7P37GypVtgiJ< z|Df|M!Npz`rZ5b^+M-mWlwalDugXq5@JZO#LS&Q_+&?a#wvf*EDFP8__5}r-|IYY= z9S>jUn6NAf%d$*Z%|&5W!$afq|K3z~Z|$8M*Y~J3ZD|d&SlswlqH^g{?B(?PIFccPu?*{O*g&*R%!a0u*i1+m_KE-he8ZbSD zw;DG1daI?m!&*lSh52A#iI$;rT|;yD%MS1Eehr>(*7B69{2GUIIkK2F8&+1-Oy5+J z7l)4ZFAWl=Uh#=tngA~J&1x;F)Y)oSf9BU67=RsWu*yjZmNQ|E(umqe!U%>M(=@n0t|V;01W7X;e`nDK+nQ=ak7ka z$FgM2x@6^jHRZY8tE|U7eA?w;@6Mg#+;Y_Bjb575X zNouTHwyVvWOX+O~&*(QWpXs|re9#WI7jN>KrlY*FIQfot+mgCV7=WQ0urFW$hAP3D zimy9^U|s-2HitljcmWS~ve06wOCuO&2fJgVD<}=$9lCu!{K1)FB1xze$GRKpTT!nW`&jqBYBOwi5ecTruOSR3wB<@a-@Rx-`g9(jyh;V QIZ{nAKC26MR|1fK0=!h3y8r+H diff --git a/tests/templates/schemata/RGB21-UAC.issuer b/tests/templates/schemata/RGB21-UAC.issuer deleted file mode 100644 index 7f7dd221d14987e3783d9df860e05d3b2c805242..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8499 zcmdT}3p7+~-`{(iJu?)_wd9&2Btof3W6*I4xkog{%w{HYGkcFq<&ru{H&RhjNu?r1 z=_V;fmXMN4ic+Cc@#^TN@(uBx_j}iS&U0GtS>IaUv(~J6W#p3K; z;urx*$E>eIL*Iw~c)$=0$v}{7{yF6Yt<3cmczAWS(Y>4(i4O50t!+=V@5ogtx>RXF zQZf*YH#GDYXdrsIe6qieeO};BD|xEi{d4WyuAx+we2si`Rk7x)iEq$ zrV?VN01wB+uxz-PIU+tzqOdW7$>rfKiz=R)$#<6WJ}Gu+fBe?Rtl63sGP~&2yS#GR z9?Si_VOaqKNC0{VJ!C!l}?aZ<5;MWvySf1*$Df@T6C--#i zQx-XQ1PUv=UoAZ)$F7WK7`;%MR%mMSTX$%13=AOvZovdVc0mLr0h5o-yq&U%bmfhY z=5?naW95>9BHw+JF@?7W_zq5q?>4kP0cs5-hjbmp2#^3Jgpruwbv|lPGA2who02EUK}gj(Gc@vm*_MKOZhOMN15<1h?3&dFa|1!@+!iww*df>17wOE3ufJp{qwWJPc=U0lM~ z6^83_1tJN7>vC~jfsoL}q9oEJMhJEPg+eGHhDpZQK_Hmy=i}+&;t&r(3Q`}VDM1i@ zGD4duuL{X~LyAxeA}6D$08NHA(Uj%QAzGMpor{oFrAr%zmuO+S5S@e2Z~pi(vg*jB z6(eMGNctb?c0c~ZL^cdlE8FL6hEgcYAo@)T7jk5hxe&AtMigmaLC1LhgKq@7@m|^E zOUC@lF#YfNu6mO55Csf~@4xmfAc&&5|mnw4|7 znY$|Fvl8c9j%i{$1g(XUBp69SMzk?$WFnRF$AmUKq22Ikpe zVRrd_Hf4dm)Ml^KiN5DZ2t*PH1sEt?U=l9mV|^3Cw)Pr`dW~!a#ChKV=1hd0KCok1 ztp3AQkuL1463PjaJNse}S*i^!eF{%)*RC-ONpH+Kme<>np5gwi+=x1Oe3@8dp`|bR z4ClHqC^=3xwEo%r@8zdDQp7x`RUhf_x*%cnGXUt1^Sro0*O zH0ga-_vZDY3{Ns5%M^)tT#W52#9)7i7tUMWe^jx8;~q?ZIivro+gJN~8^aH%XR9@? zMPUgA1STL93QlUo9VOu>YVtRDeKV^Zg0vqry`v>PRLa>B6O}v&S|=kUB2I*r$hUt_ z(k*Jqy-79FTUuCR>*XHZ?!~FBjY9JhBEmySY$n0%FPoO6wm*J>^Eb%cROd<3#pe^# z;JoGe64Us`wY}7N3QZa|lYjj*z|a_~G0^hUi7a&MCpT0%f2+$nU*#;@AbppFh!wtE zNoxq6{`vB=^+Vhv6D^L~o9OvnR`6GkPoo+vU*tF^&Xiujy zyVOg?An#_ML3VRV{G45m?m7FPP&5m#TyHVBdgacm7`cu6ztnGzP%DC6?cPi{7pQ7J zHJz>nO;S@kjION-(7Cwf9f9?r2cl zqf(unVAOGIb?zk;uD>SENQ;{%^H3+GXscKK?nnoVd5Rg+KGsx9&A9DSy54g;hw6gh zej`JlL-Q&l-rBHo+#lY$d_2vHt6o;?AVJ|Hje`~vWlDmlPHm_-BiS)m``{K{>%i{T zaRGBqP*yycx^BnQ!R+#iBhy2}LpbRwc0x4%qv*`RN4-`qW~UV6Q24<@O{D|Omxt6L zyoczmE|Wi1V!%=AbF=-`Y7GsI&7a|wcqV*fTgKMLx_2tgZWh!8(T>>7{ud|oM5;eN zR;LeCwgzOpyx_#r)FIies^gqzes3wit+D;;gVGQSJ;A-`!l<4$;1;?Ns0>2kss-`; zFP=f-@Y=MH`yD4p19f-lw5t{6a*7wID$vemvzGo<>V`_`b}Q{N`#uGel1lY7)KA^%o+iWOiwsC2o&-0MhCa?Qm0=5sS)^5% zSZFRI&9Jj&h!~*-N^ry&W=RScO2k&AaBeg-M!8#m%K>!i^A;HuQ%)4b|)X&DCy3;Aj3d$5tD`K{;&->N+KjM zeCq$U5k-WFS<)k5x~$Y#m>8F$M*}&gNQe_+p@@SSQp2S1DiR}>%ov+_8&R1!fr+_z zr11~qqAVew&zyv| zj45Tqjw(gN_%QxmgfIyj!mzhT7<4+qaBx5vj*bY!$q8XBUW_n)`2}G(J0lDi7lh&J ziZI;V5XO=v2*ceSVR(2T3{Ovlv2-cI@bW?!-rfkq#|L5f`XUTJKZN1$k1zrP5XQ1) z2qQ2MVFU%q;ZgKa%`BG=qfAyZMVfQ`k1>IL#J`*lp{a>`H`#3iW4fT)ZW2A$QY?Gz_RujMy#v4y$Dl@29aFNsHe+(VhDog$c{qPp$P!JXgtY zyF0V=8l8S1R#bOfhvYm=={^ z+3mckyxghCB6p~6a)^iVzJhm;i|@UlXPj^Q?DUX~AY67#-|hJNGnc#%uWL`QeCfR{ z*Ml^kq@L_!ubHf^XPw3x$ugk80VyA-Tm=Zk2L#9drtx^^)zhj9?%|C+#ezw?VQGlP z%R0Ed?RI8n$F4gl+-9b6YW?nU#Yb*2Io)Exp&5%ao^#jLd8d8Vd>Q9ts|ZpU3WH!# zvVPKUlD@a4XCHgTZEwfZi}D_wk<45|=6DsrEF|-qjMe|o_yQddKj)aBED6f8R8Y+& z?M{shmC^4*$@KSi5ANJPsMNZ(Bh<{l`IAtgsw%qrDkpG>8wvAAVNjI^0#y(RRQ{td z2>gM7J6UD~--EWH;F7T6J^%>aP*@zM7{>?@U3nrY>;AW{pc%7ncO6`Zf2#GGf&`Zi ze#?w#sXbuvC`cL=fX2m@w7OT-^8;q*mo_j5p(ou(?i-flowd0rCk9dVEeYf$-}H)J9tU3= znA=fQp}9@3@zQU5Q5bZnfhs3CP|gGar7^XSg%PMXfg+#Psid}(q_|J_P7#GRO-R>k zd-22L7p*C(8jljI#vcTE0;uzV!k|VEs9y*{kG0Lb{S(EE2j)fVHzdj*t}V;%TWdM- z$%|e)TUX|EXA}nM1z36iRPPehO9h=;C=9Ay+EOX+HZPk|vRU?KnfHu^xrzLA*Z5b- zmox5_rpnKvI-zj8q52%{N9S$BO7&w~#aDK!G+oNDcFgMElb}SqXT8q2t%Tfp{E|)+ z^`(vr>#IhPtzfgqOilSUg^3R|I+xW~p)jbs0eS-pgStu}Q1NqT5XcKaoz3AULM)dJ zI$223(rXk@&kl6!M3#{oxlMEVE9ekq^0*NKkjbfI_qCv|C#bWI!k|7JsQXI=woOO# z(9me}9h6yt<-u59GaQ|OK<&?Y7U;YL^&}(OX?)uh@zwtr6NV? zLL!wcQA)ZgN`*?{r=y$7J1Xb=-gmv{Jg4s{;J|ID+V{heoj@89p|``CLr`}p`d zdP9)?_zH%U{rH?{F{aJpL~;lwSDT6B7@-8Q`1nF0lg|=}m_iYUhs_CR?{Ra8ge1?L z&!eMXNB{hRAsCX9&|Q72Rk=sLi&aYfzU2;?(xa2VLD2|EoAK>irAdY%WYCL`*&& zfr()02oW=!;0X9QiNeANCWnjPUtIIVM7Fzv`$4`-^Zl1WX2aH;kh!HV`wOaRyUq7; z$7BUOKmyP=Aa|RPy5>*wJ|^AG&yLj?4gTD>ZAYF>7q6jg!}2trO}T&YJ+-fAuaeNI zD^O6^`*P_C8CG2k!{E8%j1ps`-+DuXV_^sZa0?~?vI`<0@tHhq_RZ8yq}ta$>X#jZ z43)}@OMUlF#pK@X=h-_Z^>1i@4AdG(4#|5EBR~R_5JX}8S4F5^`GnMjYkm7ZzEw}o zx{eqGKKRU7**+RJytu)d`rX_AlAp0~_{+!Hy3|e2f`9W?+uj`lBdTZw2Lwn`ZbC*Bu%1U z`>p`mUc_NLO#>lYOSGmtM!pH!@CUiHgnT6=P5%9C33(>X7$L8Oz}oo}p?}{7CM`z@ zBHvY-m@H?v$6U`v>hR4`I}gYFhODcWBIQJv4YG4xt5KL9I*GKXbHUy!wXO1(Ywztk z-l#G(P&OP<`D*Uz(Dpq%3hbxGou)OhOBZ*3t7n=U7G_&CXk8UJKyC9nndEzhgg_*| zfRBNkA12`f9yT~BZ0mrYaKONZPn`7~X3j=f8N*r2;&dOZigISwoNWnl?MyC7IY6I%X(PbjFMdrTbQ|!xvppZ)1Pra8&iQR_{ye1f0~@!=6S1Pn%x9TAb-gMx>cSA(w-( zd<7WnZ~xqB%iH(L7I6H%nJ;DyU3C3y*KDo-4)tue#5E}40zQH93Ay6qYVn6j__2nf z4PIYN>P8{Wd#(Mn<@8@5m8t5!7DYx-*kLmPc z*EL3?1&NUnp(GZQU=CHyNLJaGu+ZrXWNNJSIJxqfLONWqyhv=E(6V-bxRQZY5TQm$F{LwL!hyw(^8|J00Bf z_C2Pkm(*UquXnNb*2`F#jr%?|Z;n(cgrjaT?3k;qH+*j+Yq32Gt0Gn z`V`rg`zj+V%?zgMyQ|B)9-K}A9-#t($~g)LA8=k4(rwYd{nWF3)3XC@*U#qG9Gz@3 zNy{>@qCrPa3&bWwQ!f*5Q@#Xkk%zYQw6;>g zr`cccSKn0Ie(_#Kh?x%mPE1L3UkC6AZ3xuVpzxK23HvHfA@O))ddS_bW2E7x+jQE+ znra#Ob5vz$N1Mt0p;fB-iW#;mZLpH&82&`uhuhVq#ZdpqBF(R&;zeOCKD&yQv$8PrHn~fTsT*U z#Af1bT{26+SW4hw_B z!(kQ+#xOV{0*;J?*=(4@fmg1CqoQCg7v}L`J|7kcV4)C>j)p}d7{_6PfW=}sCI*g; zh2!Gj_;`5LDp27-;Y&<~?)^`5W97(iYKm0TZP#t;pym}SJ$Ei!`fmC5s#yEtr22Qm zEYI$O<15sTX3($qrS70Va}zBdPDv^^@7(k^^CVdU(lDF=d8$*5uBzdS^^Uo{>n!rg zi={uw&0YO!v#w2VO5sLvZ}vGU28s)r;h6S!+mNHh0s_OQ|92ZvgqSE?QUYd5ON@ny za0wRFlVJ)4I3W@U*_b{xOahjoFv4xt_{!UW%ESpw#KEHszZ(|~7w~w@*(i_07vtZJ zjN)90flU50TMM`X{z7RS<8kcAmewRLhT}Hqw+3(#B~pYjC2ZJIC9oDBgL8`!CP70O zc6JDZPDdE__6Wnl0bw{gB8(+V5XLXRAPgrbgyHOrFkD;^hN~;WaC1W#?(PV~!vkS> zdLoRaOA&^b7sBxNMi@Rm2*cMGVfgtW41a%w5fFedmMudVfq@7kC`bm6rvK2)a_KOM zihRZd4*p}?JLG>jD|L*D;Dkqo{1fdEt73J_* zSRANdAdj(+i5}^^v^%|Gf^ErBQGnN@?&{c}%fY)I>icAs>|Z>qr^)9V@&mP569 ze&tfpw{`-PAeiB7p2Xwv=Jei5#<0_-12MN3EL16$T6i2k95;_%^WfAzb;4%%8>$Gy zF;NVL^NHsD8WWp*Z;Tqhozd9lS9k1{$ZX;Dv%xozvlns-{XoDSg+X1QM|t$F_8a^X z^N^t&s)s^rib8~{>YYk`!)*ewW;vIK!Ub)%BUQK5jarSrn0j4%neco8&+=-!?Xds^ zcAt~hciJ!4ZO*xqy3f|jZCn-bOg2ll*x>wQ=jS$udp>VoJ1?&ag+W|`dJKrlSfSTl zkJ?Ogbnse!H6L4)Z%ElbGFO2Yeelx*l`bDYDck=f-v6&6_n(bE#@;%;HE)YXi5rOp zUCo|fC)f4pANYC_yPCY@^<(Y%&rp~!pZmm8x7>4;?6%vpD=yLL`$O&|xGL^Us*oW< zmTl0KyeFh%|I^xa}7xX z=8^LzTV;)njk8h!-An(>#X)Mpb)l~+{%M-Ad-06uqPkwEP1V(orDpk~O;bZW4EGlI zKPtQPoSu2MS=?R)O=Vs4=b@+!yuW3kd#mJZJ$oq}^%^n6xq5?3us7-Hr zS#K3Ex2WPea|C+ad+4sgd>^a&pjS^)3oB)cmry~#=7$-f#XlAx1b`x-K>YX>yHNBw zj>)xpdYFIkt^YZOZQxgfb6A&7tGB0OstX7@q6o+bhf7s;9GY7@!d~}!4vr|ZG_qDE z*X1|b*5-(!*Qc$iZk)5ZG%psJ>{}klO}XY3vpgQYG(5knv_^fKPRse<_MkARsDU~s z8Bopy0i|)ZkB1RxHi04^RjH(o9?-lHf*xs_c>5=b823y|*KbIYJ=j>4JGj^z%|J3Xf zG)o0lEffazE*)u<{>{r~m2Z~5R^>fwQGOCH!zJNm%7x536=||_sE#PysjoUu^Wj;W zunOI{c2VsP<<|3=mJT^XyAu^@cP!T#c9fI5kDk|RrM}Q|4*#qcWW(R=FIs^xqcCU=2b%s;fn(Djd1&;<@Ew#{f$hO~Ueo`v0D;<{ h^DI!k1m#F6wSN{Hfl3_^P>y#~lppE>-Ic)5e*x!!VH^Me diff --git a/tests/templates/schemata/RGB21-UniqueNFT-v0-TFKAmg.issuer b/tests/templates/schemata/RGB21-UniqueNFT-v0-TFKAmg.issuer new file mode 100644 index 0000000000000000000000000000000000000000..73c25375925c2845e5e95f64876972ba59ea79bf GIT binary patch literal 8371 zcmdT}3s_Xu_CNc~oS6XxL&h?=?-hdj^grSK9T}|Nnje^L>1?_g-tS zz4ltawf9<^h`6|fuvn!M!?2-IEaNrJ$Yj##I!c+q&^bm*8N~CHV2^1TezJjNv@Ay& zI9gA=pvih`W@sjyW&U3Hxx2foyZ;Yh0K+kCM^*hezj)C0g~U}-SCrA^ysvh~4qtCo z!j%2>X(iu(j6pUOPb^$;{)gqA4;sIXee`i{Srhkl`3J+T@`Syw+^v(QdAjOup8*aS zPzW5!@EH^bY6KbzaOzn>LouZv_P1QYp zbA|V7i)MT(0|TMLzxg2mw2JJ}Gv^x4yM5-o5PZ zN3-5vmO9j-V%_;%%nqR}ngNMcDWPGFjDWlL7|;w(9GHK4-H(IbhRkeY9(U_ul>jxs z2%6`O6o&m0nV2mK4GhC7qo&0xd(fq%c_loK#wb}%NeiZ)p5_fYQbTE#G@}%8}?n1wt= z6`sdH}{r-$GY``>DL;Hfap)`AJ9!bce`TZUZS)*XW`>$2RU_J$8331U;5h0r}%myx_f@`Qclvr>luKLkhgIO=eY~i2^ z4yIwj_i+_of~i*FK@}>z8dFsRT(u40kfY;}nQEp~<3Y7O!!}qvW^KTNMnW;c!H{o- z^-w77D{Qf8(n=Lvei?4P77i&viD{?|E(MnN45fiZrXg#8NXA5^Y)b$tIz&3$%~LJ`;$)dtme6BSx za{B9wkm!#ty1YNS=(7IkaNG<2aci%4WY<~!&(b1S^_=dYTXi9ZgephlgbR-}j+>&x z2;jdjrEX(o%AS4cfsIvM_k!@m1{cZbw8+;#__XNof?PKcR**g9P{h{Oy?$+R@1Jsi zcYFI%+ z+Wq$?-BGm0eDresPAQH_;SENiGD{%kSv}Q0FunASyWx&U03+;*zekS2wX5!}nUn8! zzA!sNTe;olw6p)vrT6ctox6{@4@(%Hy>&*1tmR1fqZ5_8j)YsZ$Z)Aq$Y;NuuWCto z?xzD^FX^V=v-5pF=y}(K12(e$B^J`n9##zB%~lx?+#E&x)$|5uo`nS5aOtQF4BGYJF);b5(YT z??l^*k^er{6cd?Swr`c|)xeOWTT(haM#a@mY|6atuX#K2{AUL?myf5N_8t#065zeh zANm^Y<;Bs%kEd}Ji$bfP-LO)3;a=4RtHcR)@_Ao+CU2>m^;)+@se@Jcn67jCPdcwY z^kqY;uPbvlcWch~m*l8zC^1xZNq{4h7p~v4125o@m#2QwRwuo8;!LpWP~(0}+ue%6 z*z2uh&vg_!jT*EnaDL$0_WLQ)k_K02r@B+#Nk7N5Zrpcy%pXI+Hp7|nf1MsM_u4tR z!>2y+!{)~ByL{qI>^l>$U)sqjEh(5nxs_<}~wRL*{H2LM2 ztfu2RL``vKMw(1ZXHvX?GGM@|ns=J(-&$Sd?yY|9gN+Yehj@EN@ki?{^R2IM#pdx6 zFDaF;(YZ>qNIuI=re$@o;20?(^#*sTL1*NjmuexwOQL0k7o>$0$9hX(Jore2Jl2;G zvN(zwC(U4u+<0jQol8xS@O1u*1W)Bsj2}VKnOVX_DMK^VBtk=SlrT@GV@>kZfFwbB zI?!liXRPM+T`30rq#@%U=lREq~TK1DZIxCPu;RJ+W0W9@Eq_5?$LeWr+@SFv7I>qtuk<8taG_btDv4$*alp-D0XW5i6bF|os^-z$!Kyfsm z?b!noSXb-yFE$t(_gBics_uja*U*Iiae8} zV3EuPD&RXGZ>o`};-sL$)j>hH8fJXzkPuuQ8j7pK!f^GpX}Eg&bX*-Cj;kXgaP>WtS4TzR>gZ@(J!=-Oj)}q5v9Y*1E)G}6$K&dR1YA9PHm*)g#MN`= z;Oe9#Ts?QLC7%=AYnfz=bZDYD(}q)i8IDcu1A2vt%T&Rq{k8D7(1?l@Ne#4tTJU%v zb|E3qIxSU3tTH!U~iIgb8{y z4w0kN(Gm;OSfr^bwKNmVZ30p?94qUk!lqoL!nOjw-!QC&!ZbAswk$2oGfhn^XbufK zz)YG2Th=`!Q`3gXp!5Q3YnD09)Ew9&)7-X`l7hevQqOb0c9aNsCM+~2`5)EPlxk1; z>W4md`kajq&O5fnB}fAQ47~rZfcn>hjS-sP9X8-Z{Ab->og`M6z z-*up}HsOz5mJ6w<%G+xl7X$=E*e3?ZjM{mqT~X6wh4&A`>g<;n`k!gmFIa5&C`vYE zkIVR-s`8G~e>gT<#XD6JIO=w|vSg3DJTw&hVux3dcU`VuTk!JS`k<3R9xv2-f74YQ zxoqVeN;COK|2KBEIF~N(xX^TQuvH}&bH4RL=dl=>L=OQyLiBu>sP$)5S-k5IULuHe4 zO%}<)M_?4+!SWN|9i5cuv#Ftle287S@!l66FUCzeI``&Ruh#Cd+%ippO6|mgZE9}= zm5&fODpr2#q7H2OIiJ)``ucrlW9RJM>cFHfkKI(8>*?6&L9f1qO0?0KyjSn!8rppN zQu?hM(d`chYlp3wU(!^4Jnm$T%x1^ZDI34#CQq>x_vyR_i`*$;)S{-^QlH-otI zoA>z19i0F9@{s`>P-Z=Qz^bTdf3xiS2Ic%k^6ZU;`z{t5$~qU>M8!H)L3s;wdhd;!)QIYQ^7K6~SsnAW@|;s=$V83Hh`Zb$Us2;j<>H1V$O?k6o9jR~FO@ y1OZUhGRk%eR6#C6v%9;eg^K9kjrCEzl2HLJasF!)9@L?yKxK*I1K;C^wEqBni~Sz} literal 0 HcmV?d00001 diff --git a/tests/templates/schemata/RGB25-FUA.issuer b/tests/templates/schemata/RGB25-FUA.issuer deleted file mode 100644 index 473c4ce628276068bb9ae7440750b2130ab2c526..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3711 zcmdT`dvp}l8Nc`L%sxWN5`v^skqxO*o-rgSd5|od1PCM~*-bD3mdRxHZg!H{na#{> z9w>sy;gJdwtKlI?B$kR5jS>VoF}$=nSUjnk(wb@{&>UJT4@FveH0jKm1^=jA&uLH3 z={;w6e&>F_`_1pW^L_WbnfW;`S8=uzfXpz0AZCutaw;#0tY8a@e031pSVh5VH1LQ@ zN`MtTlFSBV-jAnozUOkYDu6bo-5eYo82tVL0R#pBdRyi``OCwlj#Sf|6DGHnb0?{m zOLu2)J9oNwp#P=fc}+m0kvLPq;1A${H{;LD?6xdBRkZ8)eedpZzVXdxAEY0j>^(SI zYEO!CANcjZ4F}TBxsK^Gpjnk!QSo9K8d<*-6jf>%$IDz$U{zkMSpQ@R=2E^)efHq{ zV>UK?)pP8VQNy;#g&%kKT%ZA@TGtLl{H?=^Y?1&3)|D^%>Vzo^Ecc9Xq)6 z=HE6wvm>p~-`To$$p%-$c1mRZc*^hAHBd*saNTnvd-0^`*I(XOwDWEpd1047GkfL5 zwLPB^We~#9%|xXnf+Zkhj#squa2wu<*|>MpV;Lz|GS6*Wq1whqeLZ1%SI6$w1)DOy zWX3~)NP>t2k{V(>;ru0~EJ^7PuoJZseHb7!2xwkWf*63?B}h)tB-Mv)O3-hUyf$78 z1XabxD>hM5ZMZt99b>9w`wl}2syZbs2LWg-cI7Y3$;<#CQk%7JMeC4V2Eb8=?3>Z- zMtd_v_Ezl|XFnDR%7G&mt%Jx4v_E|!QCk(7wA%DD?v4ZA_0i3)#BoXEHgt8F9>i_q zueBa^cSrBwo1X0$zGY={VpvNf0FOho3hGiuYEph20=6))>)@8IDEs5~7woTFfj!zT zL$DsKfe{9)F8^qR$?={k6<8?8dqY9&L|KjYvB;RJMH;8m8^GGzbc;r>1Qz2h-x~dC z`&4AC1ZCt8amUyJxge|nm|mIu!Opst#L%-0wRfEnZ!3DLZvGd7%BZz72=BCjY*tF05g22#}5y8oraV;`z7sqk84! zQ|{A!uTWQi`;o(bw4*)3ddNHqJk#wc8$r$Low@Vyn2pvGNB*$&)sv&Yy3~5r`_|_P z2g-V$^V9G+8`Zz-?DpD7y)j>(c%6Q7hD!w?QM-l{9 z{;4T|We$t#eHPZQK}GAt_eZb+Nl|4f;KLKloTX|y6}Z;7XtV_AB@Ac;7^pw>#$Y1JoVoJe`4pqxZ``5HXK zpzw7M(h9D@;zKm%D}3rqO5{bHta%kAF~y=_KcA_?R7${#l17KhZ1cDA|^i{F$D#PDJ(>c(}@_D3o%7Sh$${c%%VkzdH7+(l$0Q*v=lLm7e^@7j-j1d zVky_Q$fXCo^!BvVO>?Y_)n!IO@@OW;tg}>}t15#m3(LzP$3c$=Vhp`rSWy9eKFIU1 zvJzHRK|z3iKNLkMNiYzA)zwgzp`t)lg~1@Kse!e%u&xf)*Tdz@EnHa0BUFG7;74yw zI9JdrFL>}{q)tggQh_XeA*aOMpLDTt|GDM|4qobh|KRqHy?4cr823PgUk5K= zXglypVSQt-vU%U`KkW}r$u;^4UxplNI&Mh%|BQ=tm7yW20!XJdjYxZUZ2-T$=Vl!% zB%l42_~MmChnV!zfr*E3U+jm@{E_SClR65GNFCwozL?moQy+d>{>AzH%Qr@O#{Qym r)v@N2=|{H6)oV69+D@{YNiPVu$q7S%6q1=#V{pikY3NDn(-8a%PNU~C diff --git a/tests/templates/schemata/RGB25-UniquelyFungible-v0-r~mUOw.issuer b/tests/templates/schemata/RGB25-UniquelyFungible-v0-r~mUOw.issuer new file mode 100644 index 0000000000000000000000000000000000000000..75014b349a01f128ea38f1f08af4dc82a020ab6a GIT binary patch literal 6056 zcmdT|33L=i8t&?up3EeYgD80-NQWR85dexj9nZm^pbsyZK zmd$-LYR=))1Tw?f3`Y~LjfxEvWL}Bcc;WTL$}e_&Gy1PnlHaL4(Ixx%>rqWvrP1Ja z0@ziV6BQ4XL0B0laH0!Z!`x8ictQDSR#Z-fv>UnvPUcjUHu`Q|8-!83k|wz6GSdPL_wcf!CgM`3 zv^&JAcK?@c>pfZV_(1-c~Borv3~fp(wTIeODBT|>HoU#gdv-HFye7?b z@b2pqsM6Pfky3*c2Bf>>hr#^$G)1MoTmaH&y}anxRK8{N-@am3S$8irwEF5`23H8YI^OZj=d!pcA)S$tiX1Vs16fb!&j>(B_d1=yd$03t7 z9+Wr~?E1ODpv>Z0{mJOmX-3r1vt4R5YTFu(Mx(T?v769|^>}-N0W+6rU{*4(A>y=S zeoic%56CD)(~dFf&^ANfp}V~qDwL*yNg1>KpFT~>gc@g3CY0VxX(&DFk3(DZ{jS4q zf9UchwrlHw-rWm(RJ=N_*>+@K)|ErcH}A`G9I=sBO|6!`oWUHKde=`oPS>^aFU2Ik zl6Fsg;f~0n&U<#9se7Vyzm4+ClH_UL)~mM5ikhKWSBRwkJwB`5dM0KmSXJ_}*1zW6 zxfkt2y1lwp8kP2uCV9Zc6K@Y1`#Bx|u@b0+jSSSl}@m(h6V%Edy{rKg%A zCf&O(Z2F15C2QABe6-b3e_KRWzpEc@Kiain_lZr@lHRyo?2(Ubm#*ovwP?E@Te{JTZum(bCyP1M|?Wu`E6b6qxSAP@zh@q zc4@x2;gVew&FY?%1Zl7?+n zSvwQr`hHoL`OLZbDUG&~j-Mk3&Hj2(!titRRxi-bJ-NlgQi>l{p0pKKyM%aKr6#FR z>1p+HiZ{XLmIPFJ_6kGgiwlbCT@KENLBoPj>s8v!jrFvxu z2V2pJFQ-^Nd;s2SQTXaVQ3?z|@jeRjKI~mCj&fN*rY|fdHtg0@c-E z=1eeamcwN_GTZ9s{qTYIj=UO5jKi^q;^erD&I+XhDW zxUYEAf%wQCgdKNhw8Td6qMHw(3nuz@LRe8D#sf+x4o{-I3j%L(=zZgL(Hd?j44Fb& zmn_+WS|o;eQyv#YoBneX0~?V2;wo z=r&A4j`;X2F3U)U;O!Gms9zLmeiXe=l_ak z|6QugOQ`)p`|iS~H$Kjt+3>0I*!orf*r@f(ws~{c0vGw@Tb7jn&viXCcwOwmS;Ia! z?0aCo|MeW(h^^gH-ei_G*T3E6a701ea*D*gD?h8-+B+;GgZOY`|Fooaf%{H57Y5d+ z9ZgFdusZ3Bt8>QVzEV&Cx5rk`bG95h@!rvuotx@Ul@2UAc3Fztw=b}Nx3@TZoD~*P z0Cz0mjy1xHJ25B{$AF)%!W}RFTFnXfpMFJrv88AWn_7G|aSJ>Z|9;+t&X0`6ooe_< zUs@j*pKhoW0 CD-ksS literal 0 HcmV?d00001 diff --git a/tests/transfer.rs b/tests/transfer.rs index 4986465..88576bb 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1183,14 +1183,7 @@ fn revert_transfer_state() { recv_wlt.sync(); let state = recv_wlt.runtime().state_own(contract_id).owned; - let witness_status = state - .values() - .next() - .unwrap() - .values() - .next() - .unwrap() - .status; + let witness_status = state.values().next().unwrap().iter().next().unwrap().status; dbg!(state, witness_status); assert!(matches!(witness_status, WitnessStatus::Mined(_))); diff --git a/tests/transfer_rgb21.rs b/tests/transfer_rgb21.rs index e8c69bb..99254f6 100644 --- a/tests/transfer_rgb21.rs +++ b/tests/transfer_rgb21.rs @@ -40,13 +40,12 @@ fn simple_fac_transfer(wout: bool) { // Prepare NFT data let ticker = "DCOLL"; let name = "Digital Collection #1"; - let details = "First item in the digital collection"; // Create preview data let data = vec![1u8, 3u8, 9u8]; let preview_ty = "image/jpeg"; let token_data_preview = EmbeddedMedia { - ty: MediaType::with(preview_ty), + mime: MediaType::with(preview_ty), data: Confined::try_from(data.clone()).unwrap(), }; @@ -68,12 +67,9 @@ fn simple_fac_transfer(wout: bool) { // Create NFT spec let nft_spec = nft_spec( - ticker, name, - details, token_data_preview.clone(), token_data_attachment.clone(), - token_data_attachments, token_data_reserves.clone(), ); diff --git a/tests/utils/helper/asset_params.rs b/tests/utils/helper/asset_params.rs index ded35ab..af313ff 100644 --- a/tests/utils/helper/asset_params.rs +++ b/tests/utils/helper/asset_params.rs @@ -1,4 +1,5 @@ use super::*; +use hypersonic::IssuerSpec; /// RGB Asset creation parameters builder #[derive(Clone)] @@ -38,7 +39,7 @@ impl AssetParamsBuilder { /// Set the contract template ID pub fn codex_id(mut self, codex_id: CodexId) -> Self { - self.params.codex_id = codex_id; + self.params.issuer = IssuerSpec::Latest(codex_id); self } @@ -126,7 +127,7 @@ impl AssetParamsBuilder { .params .global .iter_mut() - .find(|s| s.name == "circulating".into()) + .find(|s| s.name == "issued".into()) { state.state.verified = value.into(); } @@ -166,7 +167,7 @@ impl AssetParamsBuilder { /// Add owned state pub fn add_owned_state(mut self, seal: Outpoint, val: u64) -> Self { self.params.owned.push(NamedState { - name: "amount".into(), + name: "balance".into(), state: Assignment { seal: EitherSeal::Alt(seal), data: val.into(), diff --git a/tests/utils/helper/asset_types.rs b/tests/utils/helper/asset_types.rs index 2dd595b..35314f1 100644 --- a/tests/utils/helper/asset_types.rs +++ b/tests/utils/helper/asset_types.rs @@ -179,29 +179,28 @@ impl FACIssueParams { /// Create a minimal NFT spec with just index pub fn nft_spec_minimal() -> NftSpec { NftSpec { - index: TokenIndex::from(UDA_FIXED_INDEX), - ..Default::default() + name: None, + embedded: EmbeddedMedia { + mime: MediaType::with("text/plain"), + data: Default::default(), + }, + external: None, + reserves: None, } } /// Create a complete NFT spec with all details pub fn nft_spec( - ticker: &str, name: &str, - details: &str, preview: EmbeddedMedia, media: Attachment, - attachments: BTreeMap, reserves: ProofOfReserves, ) -> NftSpec { let mut nft_spec = nft_spec_minimal(); - nft_spec.preview = Some(preview); - nft_spec.media = Some(media); - nft_spec.attachments = Confined::try_from(attachments.clone()).unwrap(); + nft_spec.embedded = preview; + nft_spec.external = Some(media); nft_spec.reserves = Some(reserves); - nft_spec.ticker = Some(Ticker::try_from(ticker.to_string()).unwrap()); nft_spec.name = Some(AssetName::try_from(name.to_string()).unwrap()); - nft_spec.details = Some(Details::from_str(details).unwrap()); nft_spec } @@ -217,7 +216,7 @@ pub fn attachment_from_fpath(fpath: &str) -> Attachment { let media_ty: &'static str = Box::leak(mime.clone().into_boxed_str()); let media_type = MediaType::with(media_ty); Attachment { - ty: media_type, + mime: media_type, digest, } } diff --git a/tests/utils/helper/coinselect.rs b/tests/utils/helper/coinselect.rs index ee616aa..8944382 100644 --- a/tests/utils/helper/coinselect.rs +++ b/tests/utils/helper/coinselect.rs @@ -42,13 +42,16 @@ impl Default for CustomCoinselectStrategy { /// Implementation of the Coinselect trait for our custom strategy impl Coinselect for CustomCoinselectStrategy { - fn coinselect( + fn coinselect<'a>( &mut self, invoiced_state: &StrictVal, calc: &mut StateCalc, // Sorted vector by values - owned_state: Vec<(CellAddr, &StrictVal)>, - ) -> Option> { + owned_state: impl IntoIterator< + Item = &'a OwnedState, + IntoIter: DoubleEndedIterator>, + >, + ) -> Option> { match self { // For standard strategies, delegate to the original implementation CustomCoinselectStrategy::Standard(strategy) => { @@ -58,14 +61,16 @@ impl Coinselect for CustomCoinselectStrategy { // True small size implementation - sort by value before selection CustomCoinselectStrategy::TrueSmallSize => { // Clone the state to allow sorting (we need to own the data) - let mut value_sorted_state: Vec<(CellAddr, &StrictVal, u64)> = owned_state - .iter() - .filter_map(|(addr, val)| { - // Extract numeric value (assuming we're dealing with u64 values) - let amount: u64 = val.unwrap_num().unwrap_uint(); - Some((*addr, *val, amount)) - }) - .collect(); + let mut value_sorted_state: Vec<(CellAddr, &StrictVal, u64, Outpoint)> = + owned_state + .into_iter() + .filter_map(|state| { + // Extract numeric value (assuming we're dealing with u64 values) + let val = &state.assignment.data; + let amount: u64 = val.unwrap_num().unwrap_uint(); + Some((state.addr, val, amount, state.assignment.seal)) + }) + .collect(); // Sort by value in descending order (largest first) value_sorted_state.sort_by(|a, b| b.2.cmp(&a.2)); @@ -73,13 +78,13 @@ impl Coinselect for CustomCoinselectStrategy { // Now use the sorted state for iteration let res = value_sorted_state .into_iter() - .take_while(|(_, val, _)| { + .take_while(|(_, val, _, _)| { if calc.is_satisfied(invoiced_state) { return false; } calc.accumulate(val).is_ok() }) - .map(|(addr, _, _)| addr) + .map(|(addr, _, _, outpoint)| (addr, outpoint)) .collect(); if !calc.is_satisfied(invoiced_state) { diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index b63ac7a..70e3804 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -579,11 +579,11 @@ impl TestWallet { let allocation_field = match asset_schema { AssetSchema::RGB20 | AssetSchema::RGB25 => { // For fungible assets, we need to check the "amount" allocation - "amount" + "balance" } AssetSchema::RGB21 => { // for RGB21, we need to check the "fractions" allocation - "fractions" + "balance" } }; @@ -594,8 +594,8 @@ impl TestWallet { .get(allocation_field) .unwrap() .iter() - .filter(|(_, state)| state.status.is_valid()) - .map(|(_, state)| state.assignment.data.unwrap_num().unwrap_uint::()) + .filter(|state| state.status.is_valid()) + .map(|state| state.assignment.data.unwrap_num().unwrap_uint::()) .collect::>(); actual_fungible_allocations.sort(); expected_fungible_allocations.sort(); @@ -766,22 +766,14 @@ impl TestWallet { consignment: &Path, report: Option<&mut Report>, ) -> Result<(), String> { - pub struct DumbValidator; - impl SigValidator for DumbValidator { - fn validate_sig( - &self, - _: impl Into<[u8; 32]>, - _: &Identity, - _: &SigBlob, - ) -> Result { - Result::<_, Infallible>::Ok(0) - } - } - self.sync(); let accept_start = Instant::now(); self.runtime - .consume_from_file(consignment, DumbValidator) + .consume_from_file( + false, + consignment, + |_, _, _| Result::<_, Infallible>::Ok(()), + ) .map_err(|e| format!("consume_from_file error: {}", e))?; let accept_duration = accept_start.elapsed(); if let Some(report) = report { @@ -812,8 +804,8 @@ impl TestWallet { // ); // Load schema and get codex ID - let schema = Issuer::load(schema_path)?; - let codex_id = schema.codex.codex_id(); + let issuer = Issuer::load(schema_path, |_, _, _| Result::<_, Infallible>::Ok(()))?; + let codex_id = issuer.codex_id(); // print!("codex id {} ... ", codex_id); @@ -825,7 +817,7 @@ impl TestWallet { self.runtime .contracts - .import_issuer(schema) + .import_issuer(issuer) .map_err(|e| format!("import error: {}", e))?; Ok(()) @@ -840,19 +832,19 @@ impl TestWallet { // Parse immutable state let name = immutable .get(&VariantName::from_str("name").unwrap()) - .and_then(|m| m.values().next()) + .and_then(|m| m.iter().next()) .map(|v| v.data.verified.unwrap_string()) .unwrap_or_default(); let ticker = immutable .get(&VariantName::from_str("ticker").unwrap()) - .and_then(|m| m.values().next()) + .and_then(|m| m.iter().next()) .map(|v| v.data.verified.unwrap_string()) .unwrap_or_default(); let precision = immutable .get(&VariantName::from_str("precision").unwrap()) - .and_then(|m| m.values().next()) + .and_then(|m| m.iter().next()) .map(|v| { let tag = v.data.verified.unwrap_enum_tag(); if let EnumTag::Name(name) = tag { @@ -864,15 +856,15 @@ impl TestWallet { .unwrap_or_default(); let circulating_supply = immutable - .get(&VariantName::from_str("circulating").unwrap()) - .and_then(|m: &BTreeMap| m.values().next()) + .get(&VariantName::from_str("issued").unwrap()) + .and_then(|m: &Vec| m.iter().next()) .map(|v| v.data.verified.unwrap_num().unwrap_uint::()) .unwrap_or_default(); // Parse ownership state let mut allocations = vec![]; - if let Some(owned_map) = owned.get(&VariantName::from_str("amount").unwrap()) { - for state in owned_map.values() { + if let Some(owned_map) = owned.get(&VariantName::from_str("balance").unwrap()) { + for state in owned_map { allocations.push(( state.assignment.seal, state.assignment.data.unwrap_num().unwrap_uint::(), @@ -896,8 +888,8 @@ impl TestWallet { &mut self, contract_id: ContractId, ) -> Option<( - BTreeMap>, - BTreeMap>>, + BTreeMap>, + BTreeMap>>, BTreeMap, )> { let rgb_contract_state = self.runtime().state_all(contract_id); @@ -1064,84 +1056,67 @@ impl TestWallet { let index = s.get_mut(&index_name).unwrap(); *index = StrictVal::Number(StrictNum::from(params.index)); - if let Some(ref ticker_params) = nft_spec.ticker { - let ticker_name = FieldName::from_str("ticker").unwrap(); - let ticker = s.get_mut(&ticker_name).unwrap(); - *ticker = StrictVal::String(ticker_params.to_string()); - } - if let Some(ref name_params) = nft_spec.name { let name_name = FieldName::from_str("name").unwrap(); let name = s.get_mut(&name_name).unwrap(); *name = StrictVal::String(name_params.to_string()); } - if let Some(ref details_params) = nft_spec.details { - let details_name = FieldName::from_str("details").unwrap(); - let details = s.get_mut(&details_name).unwrap(); - *details = StrictVal::String(details_params.to_string()); - } - - if let Some(ref preview_params) = nft_spec.preview { - let preview_name = FieldName::from_str("preview").unwrap(); - let preview = s.get_mut(&preview_name).unwrap(); - match preview { - StrictVal::Struct(s) => { - let preview_type_name = - FieldName::from_str("type").unwrap(); - let preview_type = s.get_mut(&preview_type_name).unwrap(); - match preview_type { - StrictVal::Struct(ty) => { - let ty_name = FieldName::from_str("type").unwrap(); - let ty_type = ty.get_mut(&ty_name).unwrap(); - *ty_type = StrictVal::String( - preview_params.ty.ty.to_string(), - ); - - let subtype_name = - FieldName::from_str("subtype").unwrap(); - let subtype = ty.get_mut(&subtype_name).unwrap(); - - if let Some(ref subtype_params) = - preview_params.ty.subtype - { - *subtype = StrictVal::String( - subtype_params.to_string(), - ); - } else { - *subtype = StrictVal::Unit; - } - - let charset_name = - FieldName::from_str("charset").unwrap(); - let charset = ty.get_mut(&charset_name).unwrap(); - if let Some(ref charset_params) = - preview_params.ty.charset - { - *charset = StrictVal::String( - charset_params.to_string(), - ); - } else { - *charset = StrictVal::Unit; - } + let preview_params = &nft_spec.embedded; + let preview_name = FieldName::from_str("preview").unwrap(); + let preview = s.get_mut(&preview_name).unwrap(); + match preview { + StrictVal::Struct(s) => { + let preview_type_name = FieldName::from_str("type").unwrap(); + let preview_type = s.get_mut(&preview_type_name).unwrap(); + match preview_type { + StrictVal::Struct(ty) => { + let ty_name = FieldName::from_str("type").unwrap(); + let ty_type = ty.get_mut(&ty_name).unwrap(); + *ty_type = StrictVal::String( + preview_params.mime.ty.to_string(), + ); + + let subtype_name = + FieldName::from_str("subtype").unwrap(); + let subtype = ty.get_mut(&subtype_name).unwrap(); + + if let Some(ref subtype_params) = + preview_params.mime.subtype + { + *subtype = + StrictVal::String(subtype_params.to_string()); + } else { + *subtype = StrictVal::Unit; } - _ => { - panic!("Invalid preview type"); + + let charset_name = + FieldName::from_str("charset").unwrap(); + let charset = ty.get_mut(&charset_name).unwrap(); + if let Some(ref charset_params) = + preview_params.mime.charset + { + *charset = + StrictVal::String(charset_params.to_string()); + } else { + *charset = StrictVal::Unit; } } - - let data_name = FieldName::from_str("data").unwrap(); - let data = s.get_mut(&data_name).unwrap(); - *data = - StrictVal::Bytes(Blob(preview_params.data.to_vec())); - } - _ => { - panic!("Invalid preview"); + _ => { + panic!("Invalid preview type"); + } } + + let data_name = FieldName::from_str("data").unwrap(); + let data = s.get_mut(&data_name).unwrap(); + *data = StrictVal::Bytes(Blob(preview_params.data.to_vec())); + } + _ => { + panic!("Invalid preview"); } } - if let Some(ref media_params) = nft_spec.media { + if let Some(ref media_params) = nft_spec.external { let media_name = FieldName::from_str("media").unwrap(); let media = s.get_mut(&media_name).unwrap(); match media { @@ -1153,14 +1128,14 @@ impl TestWallet { let ty_name = FieldName::from_str("type").unwrap(); let ty_type = ty.get_mut(&ty_name).unwrap(); *ty_type = StrictVal::String( - media_params.ty.ty.to_string(), + media_params.mime.ty.to_string(), ); let subtype_name = FieldName::from_str("subtype").unwrap(); let subtype = ty.get_mut(&subtype_name).unwrap(); if let Some(ref subtype_params) = - media_params.ty.subtype + media_params.mime.subtype { *subtype = StrictVal::String( subtype_params.to_string(), @@ -1173,7 +1148,7 @@ impl TestWallet { FieldName::from_str("charset").unwrap(); let charset = ty.get_mut(&charset_name).unwrap(); if let Some(ref charset_params) = - media_params.ty.charset + media_params.mime.charset { *charset = StrictVal::String( charset_params.to_string(), @@ -1198,51 +1173,6 @@ impl TestWallet { } } - let mut map_inner = vec![]; - let attachments = nft_spec.attachments.deref(); - for (id, attachment) in attachments { - // let mut attachment = StrictVal::Struct(IndexMap::new()); - let mut attachmet_inner: IndexMap = - IndexMap::new(); - let mut ty_inner: IndexMap = IndexMap::new(); - ty_inner.insert( - FieldName::from("type"), - StrictVal::String(attachment.ty.ty.to_string()), - ); - ty_inner.insert( - FieldName::from("subtype"), - if let Some(ref subtype_params) = attachment.ty.subtype { - StrictVal::String(subtype_params.to_string()) - } else { - StrictVal::Unit - }, - ); - ty_inner.insert( - FieldName::from("charset"), - if let Some(ref charset_params) = attachment.ty.charset { - StrictVal::String(charset_params.to_string()) - } else { - StrictVal::Unit - }, - ); - - attachmet_inner - .insert(FieldName::from("type"), StrictVal::Struct(ty_inner)); - attachmet_inner.insert( - FieldName::from("digest"), - StrictVal::Bytes(Blob(attachment.digest.to_vec())), - ); - - map_inner.push(( - StrictVal::Number(StrictNum::from(*id)), - StrictVal::Struct(attachmet_inner), - )); - } - - let attachments_name = FieldName::from_str("attachments").unwrap(); - let attachments_val = s.get_mut(&attachments_name).unwrap(); - *attachments_val = StrictVal::Map(map_inner); - if let Some(ref reserves_params) = nft_spec.reserves { let reserves_name = FieldName::from_str("reserves").unwrap(); let reserves = s.get_mut(&reserves_name).unwrap(); @@ -1301,11 +1231,11 @@ impl TestWallet { let nft_data = StrictVal::Struct(IndexMap::from([ ( FieldName::from_str("tokenIndex").unwrap(), - StrictVal::Number(StrictNum::from(nft.token_index.into_inner())), + StrictVal::Number(StrictNum::from(nft.token_no.into_inner())), ), ( FieldName::from_str("fraction").unwrap(), - StrictVal::Number(StrictNum::from(nft.fraction.into_inner())), + StrictVal::Number(StrictNum::from(nft.fractions.into_inner())), ), ( FieldName::from_str("align").unwrap(), @@ -1326,20 +1256,20 @@ impl TestWallet { // Parse immutable state let name = immutable .get(&VariantName::from_str("name").unwrap()) - .and_then(|m| m.values().next()) + .and_then(|m| m.iter().next()) .map(|v| v.data.verified.unwrap_string()) .unwrap_or_default(); let total_fractions = immutable .get(&VariantName::from_str("fractions").unwrap()) - .and_then(|m| m.values().next()) + .and_then(|m| m.iter().next()) .map(|v| v.data.verified.unwrap_num().unwrap_uint::()) .unwrap_or_default(); // Parse token/NFT metadata let token = immutable .get(&VariantName::from_str("token").unwrap()) - .and_then(|m| m.values().next()) + .and_then(|m| m.iter().next()) .map(|v| { let mut index = 0u32; let mut amount = 0u64; @@ -1352,7 +1282,7 @@ impl TestWallet { index = n.unwrap_uint::(); } if let Some(StrictVal::Number(n)) = - s.get(&FieldName::from_str("amount").unwrap()) + s.get(&FieldName::from_str("balance").unwrap()) { amount = n.unwrap_uint::(); } @@ -1637,7 +1567,7 @@ impl TestWallet { // Parse ownership state (fractions) let mut fractions = vec![]; if let Some(owned_map) = owned.get(&VariantName::from_str("fractions").unwrap()) { - for state in owned_map.values() { + for state in owned_map { let amt_val = state.assignment.data.unwrap_num().unwrap_uint::(); fractions.push((state.assignment.seal, amt_val)); } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index ea2c085..505f6ef 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -70,7 +70,7 @@ pub use electrum::{Client as ElectrumClient, ElectrumApi, Param}; pub use file_format::FileFormat; pub use ifaces::{ AssetName, Attachment, Details, EmbeddedMedia, MediaType, Nft, NftSpec, ProofOfReserves, - Ticker, TokenIndex, + Ticker, TokenNo, }; pub use indexmap::IndexMap; pub use once_cell::sync::Lazy; @@ -83,9 +83,9 @@ pub use rgb::{ invoice::{RgbBeneficiary, RgbInvoice}, popls::bp::{Coinselect, OpRequestSet, PaymentScript, PrefabBundle, RgbWallet, WalletProvider}, AuthToken, CallScope, CellAddr, CodexId, Consensus, ContractId, Contracts, CreateParams, - EitherSeal, Issuer, RgbSealDef, StateCalc, StockpileDir, + EitherSeal, Issuer, RgbSealDef, StateCalc, }; -use rgb::{Identity, SigBlob, SigValidator}; +pub use rgb_persist_fs::StockpileDir; use rgbp::Payment; pub use rgbp::{ descriptor::RgbDescr, CoinselectStrategy, Owner, PayError, RgbRuntime, RgbpRuntimeDir, diff --git a/ultrasonic b/ultrasonic index 122bce7..342c674 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit 122bce74d6cf0ee5cd3607620dcdbb96c4b596c3 +Subproject commit 342c6746635af97bdd4843283faa729264a88811 diff --git a/zk-aluvm b/zk-aluvm index 02b5cc8..04a005f 160000 --- a/zk-aluvm +++ b/zk-aluvm @@ -1 +1 @@ -Subproject commit 02b5cc85f937f60fbf69f6d5460769bbfc498a99 +Subproject commit 04a005f0f96053d32a9cf3af17bb19ea3227e091 From 98fafd0962dc4f3074cb6f6abeaf632696309ca7 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 3 Jun 2025 13:17:53 +0800 Subject: [PATCH 80/90] refactor: simplify allocation checks in transfer tests Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 21 +-------------------- tests/utils/helper/wallet.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index 88576bb..2bceacc 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -25,7 +25,6 @@ pub mod utils; use rgb::WitnessStatus; use serial_test::serial; -use std::panic::{catch_unwind, AssertUnwindSafe}; use std::str::FromStr; use utils::chain::{get_tx_height, tx_status}; use utils::helper::wallet::{ @@ -393,25 +392,7 @@ fn transfer_loop( ); wlt_1.check_allocations(contract_id_1, asset_schema_1, vec![]); - // Theoretically, there should be two outputs, one for the change UTXO and one for the income UTXO. - // But because the change UTXO is associated with two assets (asset 1 and asset 2), asset 1 has been fully transferred to the UTXO of wlt2. - // So there will only be one UTXO, which combines the change and income of asset 2. - // - // In most cases, it will be merged into one UTXO, - // And in a few cases, there will be two UTXOs. - if let Err(_) = catch_unwind(AssertUnwindSafe(|| { - wlt_1.check_allocations( - contract_id_2, - asset_schema_2, - vec![issued_supply_2 - amount_3 + amount_5], - ); - })) { - wlt_1.check_allocations( - contract_id_2, - asset_schema_2, - vec![issued_supply_2 - amount_3, amount_5], - ); - } + wlt_1.check_allocation_sum(contract_id_2, issued_supply_2 - amount_3 + amount_5); wlt_2.check_allocations( contract_id_1, diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 70e3804..7069c3d 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -602,6 +602,20 @@ impl TestWallet { assert_eq!(actual_fungible_allocations, expected_fungible_allocations); } + pub fn check_allocation_sum(&mut self, contract_id: ContractId, expected_sum: u64) { + let allocation_field = "balance"; + let state = self.runtime.state_own(contract_id); + let actual_allocation_sum = state + .owned + .get(allocation_field) + .unwrap() + .iter() + .filter(|state| state.status.is_valid()) + .map(|state| state.assignment.data.unwrap_num().unwrap_uint::()) + .sum::(); + assert_eq!(actual_allocation_sum, expected_sum); + } + pub fn send( &mut self, recv_wallet: &mut TestWallet, From 4225dcd7527a4dd2323562774a2f494c541182f0 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 10 Jun 2025 18:32:15 +0800 Subject: [PATCH 81/90] test: add RBF failure scenario to transfer tests Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index 2bceacc..6a17a0a 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -115,6 +115,70 @@ fn rbf_transfer() { ); } +#[test] +fn rbf_fail() { + initialize(); + + // Create two wallet instances + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + // Create and issue NIA asset + let mut params = NIAIssueParams::new("RBFTestAsset", "RBF", "centiMilli", 600); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, 600); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("RBFTestAsset", &mut wlt_2); + wlt_2.reload_runtime(); + + let invoice = wlt_2.invoice(contract_id, 400, false, Some(0), None); + + // Stop mining to test RBF + stop_mining(); + let initial_height = get_height(); + + // First transfer attempt - with a lower fee + let (consignment_1, first_tx, payment) = + wlt_1.transfer(invoice.clone(), None, Some(500), false, None); + let first_txid = first_tx.txid(); + dbg!(first_txid, tx_status(first_txid, wlt_1.instance)); + + // Receiver accepts the transfer + wlt_2.accept_transfer(&consignment_1, None).unwrap(); + + // Verify block height hasn't changed (transaction not confirmed) + let mid_height = get_height(); + assert_eq!(initial_height, mid_height); + + // Second transfer -- just make it + let unbroadcast_psbt = wlt_1.runtime.rbf(&payment, 1000_u64).unwrap(); + + // Verify block height still hasn't changed + let final_height = get_height(); + assert_eq!(initial_height, final_height); + + // Only broadcast and confirm first transaction + wlt_1.broadcast_tx(&first_tx); + wlt_1.mine_tx(&first_tx.txid(), true); + dbg!(first_txid, tx_status(first_txid, wlt_1.instance)); + + // Sync both wallets + wlt_1.sync(); + wlt_2.sync(); + + println!("broadcasted tx: {}", first_tx.txid()); + println!("unbroadcasted tx: {}", unbroadcast_psbt.txid()); + dbg!(wlt_1.runtime.state_own(contract_id).owned); + dbg!(wlt_2.runtime.state_own(contract_id).owned); + + dbg!("all", wlt_1.runtime.state_all(contract_id).owned); + dbg!("all", wlt_2.runtime.state_all(contract_id).owned); + + // Verify asset allocations in both wallets + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![200]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![400]); +} + #[rstest] // blinded: nia - nia #[case(TT::Blinded, DT::Wpkh, DT::Wpkh, AS::RGB20, AS::RGB20)] From dfbdf72e68238ed84bb22fdc9d54d4371573cac7 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 10 Jun 2025 19:22:24 +0800 Subject: [PATCH 82/90] chore: update submodules and dependencies to v0.12 RC2 Signed-off-by: will-bitlightlabs --- Cargo.lock | 54 ++++++++++++++++++++++++++--------------------- bp-core | 2 +- bp-std | 2 +- bp-wallet | 2 +- rgb | 2 +- rgb-core | 2 +- rgb-interfaces | 2 +- rgb-std | 2 +- sonic | 2 +- tests/transfer.rs | 17 +++++++++++++-- ultrasonic | 2 +- zk-aluvm | 2 +- 12 files changed, 55 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 98ec6a9..c41db09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,7 +186,9 @@ dependencies = [ [[package]] name = "baid64" -version = "0.4.1" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61eced31ae690ea39ffe808ed970bd11ebbb3ccc6861d2ab787d848b03a0d049" dependencies = [ "amplify", "base64", @@ -286,7 +288,7 @@ checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" [[package]] name = "bp-consensus" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "chrono", @@ -302,7 +304,7 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "bp-consensus", "bp-dbc", @@ -317,7 +319,7 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "base85", @@ -333,7 +335,7 @@ dependencies = [ [[package]] name = "bp-derive" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-consensus", @@ -380,7 +382,7 @@ dependencies = [ [[package]] name = "bp-invoice" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bech32", @@ -392,7 +394,7 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-consensus", @@ -408,7 +410,7 @@ dependencies = [ [[package]] name = "bp-std" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-consensus", @@ -426,7 +428,7 @@ dependencies = [ [[package]] name = "bp-wallet" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-electrum", @@ -677,7 +679,7 @@ dependencies = [ [[package]] name = "descriptors" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-derive", @@ -1089,7 +1091,7 @@ dependencies = [ [[package]] name = "hypersonic" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "aluvm", "amplify", @@ -1674,7 +1676,7 @@ dependencies = [ [[package]] name = "psbt" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "base64", @@ -1867,7 +1869,7 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-core", @@ -1883,7 +1885,7 @@ dependencies = [ [[package]] name = "rgb-interfaces" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-consensus", @@ -1899,7 +1901,7 @@ dependencies = [ [[package]] name = "rgb-invoice" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "baid64", @@ -1915,7 +1917,7 @@ dependencies = [ [[package]] name = "rgb-persist-fs" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "aora", @@ -1926,7 +1928,7 @@ dependencies = [ [[package]] name = "rgb-psbt" -version = "0.12.0-rc.1.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-core", @@ -1936,7 +1938,7 @@ dependencies = [ [[package]] name = "rgb-runtime" -version = "0.12.0-rc.1.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "bp-std", @@ -1958,7 +1960,7 @@ dependencies = [ [[package]] name = "rgb-std" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "aora", @@ -2467,7 +2469,7 @@ dependencies = [ [[package]] name = "sonic-api" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "aluvm", "amplify", @@ -2489,7 +2491,7 @@ dependencies = [ [[package]] name = "sonic-callreq" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "baid64", @@ -2507,7 +2509,7 @@ dependencies = [ [[package]] name = "sonic-persist-fs" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "aora", @@ -2913,7 +2915,7 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ultrasonic" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "amplify", "baid64", @@ -3481,7 +3483,7 @@ dependencies = [ [[package]] name = "zk-aluvm" -version = "0.12.0-rc.1" +version = "0.12.0-rc.2" dependencies = [ "aluvm", "amplify", @@ -3491,3 +3493,7 @@ dependencies = [ "strict_encoding", "wasm-bindgen", ] + +[[patch.unused]] +name = "baid64" +version = "0.4.1" diff --git a/bp-core b/bp-core index c6acce4..0967b34 160000 --- a/bp-core +++ b/bp-core @@ -1 +1 @@ -Subproject commit c6acce4b1cd227a196a1fcf2dbb4f4c8d4de87d2 +Subproject commit 0967b34cbfe43bf8a79ac963e3a96589a1cc49b1 diff --git a/bp-std b/bp-std index cc74fd2..d987b3a 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit cc74fd2789d4146b3ca8e2226601639b714e8570 +Subproject commit d987b3ad4aab6800e01f6b3b6cb7299bf58f38fa diff --git a/bp-wallet b/bp-wallet index 9a0ef49..106d5a8 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 9a0ef49d7fce8b3d9e66559de6e81976dc20e315 +Subproject commit 106d5a828fde76346457fcae92d00e45aea10844 diff --git a/rgb b/rgb index 9277811..3d23d04 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit 9277811dbf4085bd041453acd65f918e80808b5f +Subproject commit 3d23d04e30adc8f4ad8ff055e787e12197e0ec0e diff --git a/rgb-core b/rgb-core index ecd56a5..e7ca10d 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit ecd56a50d22b9cca4eb4184449cc6d23a92a06ef +Subproject commit e7ca10d858271309d32f06527ba9e0aaf9595689 diff --git a/rgb-interfaces b/rgb-interfaces index 4dea227..5070fd3 160000 --- a/rgb-interfaces +++ b/rgb-interfaces @@ -1 +1 @@ -Subproject commit 4dea2271f36130c2a477481fdc75f8def302f82d +Subproject commit 5070fd31574975564d00a73107e011c927319fc2 diff --git a/rgb-std b/rgb-std index 9d1c9ee..884edb2 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 9d1c9ee7250eb1a216e04543958b91607a482d6f +Subproject commit 884edb2e2cc909241b5a95f0f97c0d7a255aaeaf diff --git a/sonic b/sonic index 3e9636e..8ff532b 160000 --- a/sonic +++ b/sonic @@ -1 +1 @@ -Subproject commit 3e9636eb9472bd3a79ca7207352afdc79eb2b0a5 +Subproject commit 8ff532b84f38fa85ca7c6da859eabcbd42e807a0 diff --git a/tests/transfer.rs b/tests/transfer.rs index 6a17a0a..ad05b2d 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -116,7 +116,7 @@ fn rbf_transfer() { } #[test] -fn rbf_fail() { +fn rbf_unbroadcasted_state_all() { initialize(); // Create two wallet instances @@ -172,7 +172,20 @@ fn rbf_fail() { dbg!(wlt_2.runtime.state_own(contract_id).owned); dbg!("all", wlt_1.runtime.state_all(contract_id).owned); - dbg!("all", wlt_2.runtime.state_all(contract_id).owned); + let wlt_1_state_all = wlt_1.runtime.state_all(contract_id).owned; + let unbroadcast_txid = unbroadcast_psbt.txid(); + // get the status of the unbroadcast_txid + let wlt_1_state_all_unbroadcast = wlt_1_state_all + .iter() + .find_map(|(_, states)| { + states + .iter() + .find(|s| s.assignment.seal.primary.txid == unbroadcast_txid) + .map(|s| s.status) + }) + .unwrap(); + assert_eq!(wlt_1_state_all_unbroadcast, WitnessStatus::Archived); + dbg!("unbroadcast", unbroadcast_txid, wlt_1_state_all_unbroadcast); // Verify asset allocations in both wallets wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![200]); diff --git a/ultrasonic b/ultrasonic index 342c674..36ee081 160000 --- a/ultrasonic +++ b/ultrasonic @@ -1 +1 @@ -Subproject commit 342c6746635af97bdd4843283faa729264a88811 +Subproject commit 36ee081936420f189b160321e56cdc1175848f35 diff --git a/zk-aluvm b/zk-aluvm index 04a005f..5120662 160000 --- a/zk-aluvm +++ b/zk-aluvm @@ -1 +1 @@ -Subproject commit 04a005f0f96053d32a9cf3af17bb19ea3227e091 +Subproject commit 5120662cfaaf271e36885a768d404b7fcbcd17f2 From ada9f2ba7c4cea92de064147d43358f3def9a0c7 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 11 Jun 2025 23:24:49 +0800 Subject: [PATCH 83/90] chore: update dependencies and submodule for rgb-std Signed-off-by: will-bitlightlabs --- Cargo.lock | 168 +++++++++++++++++++++++------------------------------ rgb-std | 2 +- 2 files changed, 74 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c41db09..1f8330f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" @@ -236,7 +236,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.101", + "syn 2.0.102", "which", ] @@ -450,15 +450,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "bytecount" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] name = "byteorder" @@ -474,9 +474,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.25" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "jobserver", "libc", @@ -494,9 +494,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "chrono" @@ -642,7 +642,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -664,7 +664,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -706,7 +706,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -851,7 +851,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -909,7 +909,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -947,9 +947,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "heck" @@ -1067,9 +1067,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" dependencies = [ "base64", "bytes", @@ -1264,7 +1264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "serde", ] @@ -1387,12 +1387,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 = "minimal-lexical" version = "0.2.1" @@ -1401,9 +1395,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] @@ -1427,7 +1421,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.59.0", ] @@ -1524,7 +1518,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1640,7 +1634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1662,7 +1656,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1789,7 +1783,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1829,9 +1823,9 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.12.18" +version = "0.12.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e98ff6b0dbbe4d5a37318f433d4fc82babd21631f194d370409ceb2e40b2f0b5" +checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" dependencies = [ "base64", "bytes", @@ -1842,12 +1836,9 @@ dependencies = [ "hyper", "hyper-tls", "hyper-util", - "ipnet", "js-sys", "log", - "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", "rustls-pki-types", @@ -1857,7 +1848,6 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", - "tokio-socks", "tower", "tower-http", "tower-service", @@ -2073,7 +2063,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.101", + "syn 2.0.102", "unicode-ident", ] @@ -2086,14 +2076,14 @@ dependencies = [ "quote", "rand 0.8.5", "rustc_version", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] name = "rustc-hash" @@ -2281,7 +2271,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2298,9 +2288,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -2376,7 +2366,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2414,7 +2404,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2453,9 +2443,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" @@ -2611,7 +2601,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2633,9 +2623,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" dependencies = [ "proc-macro2", "quote", @@ -2659,7 +2649,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2682,7 +2672,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2715,7 +2705,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2784,23 +2774,11 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-socks" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" -dependencies = [ - "either", - "futures-util", - "thiserror", - "tokio", -] - [[package]] name = "toml" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -2810,18 +2788,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.26" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap 2.9.0", "serde", @@ -2833,9 +2811,9 @@ dependencies = [ [[package]] name = "toml_write" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tower" @@ -2854,9 +2832,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.4" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ "bitflags", "bytes", @@ -2894,9 +2872,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] @@ -2936,9 +2914,9 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "unsafe-libyaml" @@ -3002,9 +2980,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -3037,7 +3015,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-shared", ] @@ -3072,7 +3050,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3169,7 +3147,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3180,7 +3158,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3355,9 +3333,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -3397,7 +3375,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "synstructure", ] @@ -3418,7 +3396,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3438,7 +3416,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "synstructure", ] @@ -3478,7 +3456,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] diff --git a/rgb-std b/rgb-std index 884edb2..c8d79ef 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 884edb2e2cc909241b5a95f0f97c0d7a255aaeaf +Subproject commit c8d79ef4607e95c1d9ccadd91695d79e6f528430 From 93a190441dcf4cac4a8f4e9b133bc01bd8810d30 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Fri, 13 Jun 2025 22:27:00 +0800 Subject: [PATCH 84/90] chore: update submodule commit for bp-std Signed-off-by: will-bitlightlabs --- bp-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bp-std b/bp-std index d987b3a..e6ee238 160000 --- a/bp-std +++ b/bp-std @@ -1 +1 @@ -Subproject commit d987b3ad4aab6800e01f6b3b6cb7299bf58f38fa +Subproject commit e6ee238ad1be3982bb41e3193ccf10acb42e7fbc From 72ecd2aab1cb432202e05838f91f0f495020ed32 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Sun, 15 Jun 2025 00:31:26 +0800 Subject: [PATCH 85/90] test: add multi-wallet blind transfer scenario to transfer tests Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 87 ++++++++++++++++++++++++++++++++++++ tests/utils/helper/wallet.rs | 10 +++-- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/tests/transfer.rs b/tests/transfer.rs index ad05b2d..ec1fe36 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1457,3 +1457,90 @@ fn receive_from_unbroadcasted_transfer_to_blinded() { wlt_3.sync(); wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![]); } + +#[test] +#[serial] +fn tr_multi_wallet_blind_transfers() { + initialize(); + + // Create three wallets using TR descriptor + let mut wlt_1 = get_wallet(&DescriptorType::Tr); + let mut wlt_2 = get_wallet(&DescriptorType::Tr); + let mut wlt_3 = get_wallet(&DescriptorType::Tr); + + // Issue NIA asset with 21 million supply + let circulating_supply = 21_000_000; + let mut params = NIAIssueParams::new( + "TestAssetMultiTransfer", + "TEST", + "centiMilli", + circulating_supply, + ); + let utxo = wlt_1.get_utxo(None); + params.add_allocation(utxo, circulating_supply); + let contract_id = wlt_1.issue_nia_with_params(params); + + // Send contract to other wallets + wlt_1.send_contract("TestAssetMultiTransfer", &mut wlt_2); + wlt_2.reload_runtime(); + wlt_1.send_contract("TestAssetMultiTransfer", &mut wlt_3); + wlt_3.reload_runtime(); + + // Transfer 120k from wallet 1 to wallet 2 using blind invoice + let wlt1_to_wlt2_amount = 120_000; + let invoice = wlt_2.invoice(contract_id, wlt1_to_wlt2_amount, false, None, None); + let (consignment, wlt1_to_wlt2_tx, _) = wlt_1.transfer(invoice, None, Some(1000), true, None); + wlt_2.accept_transfer(&consignment, None).unwrap(); + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt1_to_wlt2_amount]); + + // Check wallet states after first transfer (unconfirmed transaction state) + // wlt1 shows 0 available assets, wlt2 shows 120k available assets + println!("After Wallet 1 makes a payment to Wallet 2, the unconfirmed status of the witnessed transaction is not in the sync state"); + println!("wlt1_state: {:?}", wlt_1.get_allocation_sum(contract_id)); + println!("wlt2_state: {:?}", wlt_2.get_allocation_sum(contract_id)); + + // Transfer 100k from wallet 2 to wallet 3 using blind invoice + let wlt2_to_wlt3_amount = 100_000; + let invoice = wlt_3.invoice(contract_id, wlt2_to_wlt3_amount, false, None, None); + let (consignment, wlt2_to_wlt3_tx, _) = wlt_2.transfer(invoice, None, Some(1000), true, None); + wlt_3.accept_transfer(&consignment, None).unwrap(); + + wlt_1.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt2_to_wlt3_amount]); + + // Check wallet states after second transfer (unconfirmed transaction state) + // wlt2 shows 0 available assets, wlt3 shows 100k available assets + println!("After Wallet 2 makes a payment to Wallet 3, the unconfirmed status of the witnessed transaction is not in the sync state"); + println!("wlt2_state: {:?}", wlt_2.get_allocation_sum(contract_id)); + println!("wlt3_state: {:?}", wlt_3.get_allocation_sum(contract_id)); + + // Mine both transactions + wlt_1.mine_tx(&wlt1_to_wlt2_tx.txid(), false); + wlt_2.mine_tx(&wlt2_to_wlt3_tx.txid(), false); + + // Sync all wallets + wlt_1.sync(); + wlt_2.sync(); + wlt_3.sync(); + + // Verify final allocations after sync + wlt_1.check_allocations( + contract_id, + AssetSchema::RGB20, + vec![circulating_supply - wlt1_to_wlt2_amount], + ); + wlt_2.check_allocations( + contract_id, + AssetSchema::RGB20, + vec![wlt1_to_wlt2_amount - wlt2_to_wlt3_amount], + ); + wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![wlt2_to_wlt3_amount]); + + // Print final wallet states after sync - all states should be correct + println!("After sync"); + println!("wlt1_state: {:?}", wlt_1.get_allocation_sum(contract_id)); + println!("wlt2_state: {:?}", wlt_2.get_allocation_sum(contract_id)); + println!("wlt3_state: {:?}", wlt_3.get_allocation_sum(contract_id)); +} diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 7069c3d..2416558 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -602,17 +602,21 @@ impl TestWallet { assert_eq!(actual_fungible_allocations, expected_fungible_allocations); } - pub fn check_allocation_sum(&mut self, contract_id: ContractId, expected_sum: u64) { + pub fn get_allocation_sum(&mut self, contract_id: ContractId) -> u64 { let allocation_field = "balance"; let state = self.runtime.state_own(contract_id); - let actual_allocation_sum = state + state .owned .get(allocation_field) .unwrap() .iter() .filter(|state| state.status.is_valid()) .map(|state| state.assignment.data.unwrap_num().unwrap_uint::()) - .sum::(); + .sum::() + } + + pub fn check_allocation_sum(&mut self, contract_id: ContractId, expected_sum: u64) { + let actual_allocation_sum = self.get_allocation_sum(contract_id); assert_eq!(actual_allocation_sum, expected_sum); } From 245a03cbaefd6b7d7da8bfd594c50a09bb3681f0 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 17 Jun 2025 14:46:52 +0800 Subject: [PATCH 86/90] test: add cross transfer unconfirmed scenario to transfer tests Signed-off-by: will-bitlightlabs --- tests/transfer.rs | 179 +++++++++++++++++++++++++++++++++++ tests/utils/helper/wallet.rs | 18 ++++ 2 files changed, 197 insertions(+) diff --git a/tests/transfer.rs b/tests/transfer.rs index ec1fe36..f42408c 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1544,3 +1544,182 @@ fn tr_multi_wallet_blind_transfers() { println!("wlt2_state: {:?}", wlt_2.get_allocation_sum(contract_id)); println!("wlt3_state: {:?}", wlt_3.get_allocation_sum(contract_id)); } + +#[test] +#[serial] +fn cross_transfer_unconfirmed_test() { + initialize(); + + // Create three wallets using TR descriptor + let mut wlt_a = get_wallet(&DescriptorType::Tr); + let mut wlt_b = get_wallet(&DescriptorType::Tr); + let mut wlt_c = get_wallet(&DescriptorType::Tr); + wlt_b.set_coinselect_strategy(CustomCoinselectStrategy::TrueSmallSize); + + // Issue NIA asset with 600 total supply, distributed across 2 UTXOs + let total_supply = 600; + let mut params = + NIAIssueParams::new("CrossTransferTestUSDT", "USDT", "centiMilli", total_supply); + + // A UTXO gets 300, B UTXO gets 300 + let utxo_a = wlt_a.get_utxo(None); + let utxo_b = wlt_b.get_utxo(None); + params.add_allocation(utxo_a, 300); + params.add_allocation(utxo_b, 300); + + let contract_id = wlt_a.issue_nia_with_params(params); + + // Send contract to other wallets + wlt_a.send_contract("CrossTransferTestUSDT", &mut wlt_b); + wlt_b.reload_runtime(); + wlt_a.send_contract("CrossTransferTestUSDT", &mut wlt_c); + wlt_c.reload_runtime(); + + // Initial state check: A has 300, B has 300, C has 0 + println!("=== Initial State ==="); + wlt_a.check_allocations(contract_id, AssetSchema::RGB20, vec![300]); + wlt_b.check_allocations(contract_id, AssetSchema::RGB20, vec![300]); + wlt_c.check_allocations(contract_id, AssetSchema::RGB20, vec![]); + + println!( + "A balance: {:?}, {:?}", + wlt_a.get_allocation_sum(contract_id), + wlt_a.get_allocation_tuple(contract_id) + ); + println!( + "B balance: {:?}, {:?}", + wlt_b.get_allocation_sum(contract_id), + wlt_b.get_allocation_tuple(contract_id) + ); + println!( + "C balance: {:?}, {:?}", + wlt_c.get_allocation_sum(contract_id), + wlt_c.get_allocation_tuple(contract_id) + ); + + // Step 1: A transfers 50 USDT to B (unconfirmed) + println!("\n=== Step 1: A -> B (50 USDT) ==="); + let a_to_b_amount = 50; + let invoice_b = wlt_b.invoice(contract_id, a_to_b_amount, false, None, None); + let (consignment_a_to_b, tx_a_to_b, _) = + wlt_a.transfer(invoice_b, None, Some(1000), true, None); + wlt_b.accept_transfer(&consignment_a_to_b, None).unwrap(); + + // Check state after A->B transfer (before confirmation) + println!("After A->B transfer (unconfirmed):"); + println!( + "A balance: {:?}, {:?}", + wlt_a.get_allocation_sum(contract_id), + wlt_a.get_allocation_tuple(contract_id) + ); + println!( + "B balance: {:?}, {:?}", + wlt_b.get_allocation_sum(contract_id), + wlt_b.get_allocation_tuple(contract_id) + ); + println!( + "C balance: {:?}, {:?}", + wlt_c.get_allocation_sum(contract_id), + wlt_c.get_allocation_tuple(contract_id) + ); + + // Expected: A should show 250 (300-50), B should show 350 (300+50), C should show 0 + // Note: In unconfirmed state, wallets might show different behavior + wlt_a.check_allocations(contract_id, AssetSchema::RGB20, vec![]); // A shows 0 in unconfirmed state + wlt_b.check_allocations(contract_id, AssetSchema::RGB20, vec![300, 50]); // B shows original 300 + received 50 + + // Step 2: B transfers 51 USDT to C (while A->B is still unconfirmed) + println!("\n=== Step 2: B -> C (51 USDT) while A->B unconfirmed ==="); + let b_to_c_amount = 51; + let invoice_c = wlt_c.invoice(contract_id, b_to_c_amount, false, None, None); + let (consignment_b_to_c, tx_b_to_c, _) = + wlt_b.transfer(invoice_c, None, Some(1000), true, None); + wlt_c.accept_transfer(&consignment_b_to_c, None).unwrap(); + + // Check state after B->C transfer (both transactions unconfirmed) + println!("After B->C transfer (tx_b_to_c unconfirmed):"); + println!( + "A balance: {:?}, {:?}", + wlt_a.get_allocation_sum(contract_id), + wlt_a.get_allocation_tuple(contract_id) + ); + println!( + "B balance: {:?}, {:?}", + wlt_b.get_allocation_sum(contract_id), + wlt_b.get_allocation_tuple(contract_id) + ); + println!( + "C balance: {:?}, {:?}", + wlt_c.get_allocation_sum(contract_id), + wlt_c.get_allocation_tuple(contract_id) + ); + + // Check the potential BUG: B's original 300 USDT might disappear + wlt_a.check_allocations(contract_id, AssetSchema::RGB20, vec![]); // A shows 0 + wlt_b.check_allocations(contract_id, AssetSchema::RGB20, vec![50]); // B shows 50 + wlt_c.check_allocations(contract_id, AssetSchema::RGB20, vec![51]); // C shows 51 + + // Step 3: Mine both transactions to confirm them + println!("\n=== Step 3: Mining transactions ==="); + wlt_a.mine_tx(&tx_a_to_b.txid(), false); + wlt_b.mine_tx(&tx_b_to_c.txid(), false); + + // Step 4: Sync all wallets + println!("\n=== Step 4: Syncing wallets ==="); + wlt_a.sync(); + wlt_b.sync(); + wlt_c.sync(); + + // Final state check after confirmation and sync + println!("\n=== Final State (after confirmation and sync) ==="); + println!( + "A balance: {:?}, {:?}", + wlt_a.get_allocation_sum(contract_id), + wlt_a.get_allocation_tuple(contract_id) + ); + println!( + "B balance: {:?}, {:?}", + wlt_b.get_allocation_sum(contract_id), + wlt_b.get_allocation_tuple(contract_id) + ); + println!( + "C balance: {:?}, {:?}", + wlt_c.get_allocation_sum(contract_id), + wlt_c.get_allocation_tuple(contract_id) + ); + + // Expected final state: + // A: 300 - 50 = 250 + // B: 300 + 50 - 51 = 299 + // C: 0 + 51 = 51 + // Total should still be 600 + + // BUG reproduction: If the bug exists, B might only show 50 (from A) instead of 299 + println!("\n=== Verifying final allocations ==="); + wlt_a.check_allocations(contract_id, AssetSchema::RGB20, vec![250]); + + wlt_b.check_allocations(contract_id, AssetSchema::RGB20, vec![50, 249]); + + wlt_c.check_allocations(contract_id, AssetSchema::RGB20, vec![51]); + + // Verify total supply is conserved + let total_final = wlt_a.get_allocation_sum(contract_id) + + wlt_b.get_allocation_sum(contract_id) + + wlt_c.get_allocation_sum(contract_id); + assert_eq!( + total_final, total_supply, + "Total supply should be conserved" + ); + + println!( + "Total supply verification: {} == {}", + total_final, total_supply + ); + + if wlt_b.get_allocation_sum(contract_id) == 50 { + println!(" BUG DETECTED: Wallet B only shows 50 USDT instead of expected 320!"); + println!(" This indicates B's original 300 USDT disappeared during cross-transfer"); + } else { + println!(" No bug detected: Wallet B correctly shows expected balance"); + } +} diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index 2416558..ad2ba39 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -1,3 +1,5 @@ +use rgb::WitnessStatus; + use super::*; enum WalletAccount { @@ -602,6 +604,22 @@ impl TestWallet { assert_eq!(actual_fungible_allocations, expected_fungible_allocations); } + pub fn get_allocation_tuple(&mut self, contract_id: ContractId) -> Vec<(u64, WitnessStatus)> { + let allocation_field = "balance"; + let state = self.runtime.state_own(contract_id); + state + .owned + .get(allocation_field) + .unwrap() + .iter() + .map(|state| { + ( + state.assignment.data.unwrap_num().unwrap_uint::(), + state.status, + ) + }) + .collect::>() + } pub fn get_allocation_sum(&mut self, contract_id: ContractId) -> u64 { let allocation_field = "balance"; let state = self.runtime.state_own(contract_id); From c691f9d8c77f55a63c610e894a1ba8f27d300da7 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 18 Jun 2025 17:55:04 +0800 Subject: [PATCH 87/90] test: add spend from UTXO with multiple allocations scenario to transfer tests Signed-off-by: will-bitlightlabs --- bp-wallet | 2 +- tests/transfer.rs | 207 +++++++++++++++++++++++++++++++++++ tests/utils/helper/wallet.rs | 7 +- 3 files changed, 214 insertions(+), 2 deletions(-) diff --git a/bp-wallet b/bp-wallet index 106d5a8..a98b19b 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit 106d5a828fde76346457fcae92d00e45aea10844 +Subproject commit a98b19b24d40b89494730df2866f24e689e9ddd1 diff --git a/tests/transfer.rs b/tests/transfer.rs index f42408c..3b4e8c2 100644 --- a/tests/transfer.rs +++ b/tests/transfer.rs @@ -1723,3 +1723,210 @@ fn cross_transfer_unconfirmed_test() { println!(" No bug detected: Wallet B correctly shows expected balance"); } } + +#[rstest] +#[serial] +#[case(DT::Tr, CustomCoinselectStrategy::TrueSmallSize)] +#[case(DT::Wpkh, CustomCoinselectStrategy::TrueSmallSize)] +#[case( + DT::Tr, + CustomCoinselectStrategy::Standard(CoinselectStrategy::Aggregate) +)] +#[case( + DT::Wpkh, + CustomCoinselectStrategy::Standard(CoinselectStrategy::Aggregate) +)] +fn spend_from_utxo_with_multiple_allocations( + #[case] descriptor_type: DescriptorType, + #[case] coinselect_strategy: CustomCoinselectStrategy, +) { + initialize(); + + let mut wlt_1 = get_wallet(&descriptor_type); + let mut wlt_2 = get_wallet(&descriptor_type); + wlt_2.set_coinselect_strategy(coinselect_strategy); + let mut wlt_3 = get_wallet(&descriptor_type); + + println!("\n=== Test: spend_from_utxo_with_multiple_allocations ==="); + println!("Testing scenario: spending from UTXO with multiple confirmed allocations"); + + // 1. Preparation phase: Construct a state of "one UTXO, multiple allocations" + + // 1.1. wlt_1 issues the asset + let issue_supply = 1200; + let mut params = NIAIssueParams::new("ConsolidationTest", "CON", "centiMilli", issue_supply); + let outpoint = wlt_1.get_utxo(None); + params.add_allocation(outpoint, issue_supply); + let contract_id = wlt_1.issue_nia_with_params(params); + wlt_1.send_contract("ConsolidationTest", &mut wlt_2); + wlt_2.reload_runtime(); + wlt_1.send_contract("ConsolidationTest", &mut wlt_3); + wlt_3.reload_runtime(); + + println!("\n--- Phase 1.1: Asset issuance completed ---"); + println!("Issued {} tokens to wlt_1", issue_supply); + println!("Contract shared with wlt_2 and wlt_3"); + println!( + "wlt_1 initial balance: {}", + wlt_1.get_allocation_sum(contract_id) + ); + + // 1.2. wlt_2 obtains a specific UTXO to receive two payments + let receiving_utxo = wlt_2.get_utxo(None); + + println!("\n--- Phase 1.2: Receiving UTXO prepared ---"); + println!("wlt_2 receiving UTXO: {}", receiving_utxo); + + // 1.3. wlt_1 sends assets twice to the same UTXO of wlt_2 + // First send 800 + let invoice1 = wlt_2.invoice(contract_id, 800, false, None, Some(receiving_utxo)); + wlt_1.send_to_invoice(&mut wlt_2, invoice1, None, None, None); + + println!("\n--- Phase 1.3a: First transfer completed ---"); + println!("wlt_1 -> wlt_2: 800 tokens (confirmed)"); + println!("wlt_1 balance: {}", wlt_1.get_allocation_sum(contract_id)); + println!("wlt_2 balance: {}", wlt_2.get_allocation_sum(contract_id)); + for (addr, outpoint, amount, status) in wlt_2.get_allocation_tuple(contract_id) { + println!( + "wlt_2 addr: {}, outpoint: {}, amount: {}, status: {:?}", + addr, outpoint, amount, status + ); + } + + // Second send 200 to the exact same UTXO + let invoice2 = wlt_2.invoice(contract_id, 200, false, None, Some(receiving_utxo)); + wlt_1.send_to_invoice(&mut wlt_2, invoice2, None, None, None); + wlt_2.sync(); + + println!("\n--- Phase 1.3b: Second transfer completed ---"); + println!("wlt_1 -> wlt_2: 200 tokens (confirmed)"); + println!("wlt_1 balance: {}", wlt_1.get_allocation_sum(contract_id)); + println!("wlt_2 balance: {}", wlt_2.get_allocation_sum(contract_id)); + for (addr, outpoint, amount, status) in wlt_2.get_allocation_tuple(contract_id) { + println!( + "wlt_2 addr: {}, outpoint: {}, amount: {}, status: {:?}", + addr, outpoint, amount, status + ); + } + + // 1.4. Verify the initial state + // wlt_2 should now have two allocations on one UTXO, totaling 1000 + println!("\n--- Phase 1.4: Verifying initial state ---"); + wlt_2.check_allocations(contract_id, AssetSchema::RGB20, vec![800, 200]); + wlt_1.check_allocations( + contract_id, + AssetSchema::RGB20, + vec![issue_supply - 800 - 200], + ); // Change 200 + + println!("✓ wlt_2 has correct allocations: [800, 200]"); + println!( + "✓ wlt_1 has correct remaining balance: {}", + issue_supply - 800 - 200 + ); + + // 2. Action phase: wlt_2 spends part of the assets from this UTXO + + println!("\n--- Phase 2: Action phase - wlt_2 spending from multi-allocation UTXO ---"); + // wlt_2 sends 400 to wlt_3 + let amount_to_spend = 400; + println!("wlt_2 will send {} tokens to wlt_3", amount_to_spend); + println!( + "wlt_2 balance before spending: {}", + wlt_2.get_allocation_sum(contract_id) + ); + println!( + "wlt_3 balance before receiving: {}", + wlt_3.get_allocation_sum(contract_id) + ); + + wlt_2.send( + &mut wlt_3, + false, + contract_id, + amount_to_spend, + 1000, + None, + None, + None, + ); + + println!("\n--- Phase 2 completed: Transfer executed ---"); + println!( + "wlt_2 balance after spending: {}", + wlt_2.get_allocation_sum(contract_id) + ); + println!( + "wlt_3 balance after receiving: {}", + wlt_3.get_allocation_sum(contract_id) + ); + for (addr, outpoint, amount, status) in wlt_2.get_allocation_tuple(contract_id) { + println!( + "wlt_2 addr: {}, outpoint: {}, amount: {}, status: {:?}", + addr, outpoint, amount, status + ); + } + for (addr, outpoint, amount, status) in wlt_3.get_allocation_tuple(contract_id) { + println!( + "wlt_3 addr: {}, outpoint: {}, amount: {}, status: {:?}", + addr, outpoint, amount, status + ); + } + + // 3. Verification phase: Check if the results are correct + + println!("\n--- Phase 3: Verification phase ---"); + + // 3.1. wlt_3 should have received 400 + println!("Verifying wlt_3 received correct amount..."); + wlt_3.check_allocations(contract_id, AssetSchema::RGB20, vec![amount_to_spend]); + println!("✓ wlt_3 correctly received {} tokens", amount_to_spend); + + // 3.2. This is the most critical check: + // The change of wlt_2 should be 1000 - 400 = 600, and it should be a single merged allocation + let expected_change = 800 + 200 - amount_to_spend; + println!("\nCritical verification: wlt_2 change calculation"); + println!( + "Expected change: {} + {} - {} = {}", + 800, 200, amount_to_spend, expected_change + ); + + println!("\n--- Debug: wlt_2 owned state after spending ---"); + dbg!(wlt_2.runtime.state_own(contract_id).owned); + + println!("Verifying wlt_2 has correct remaining balance..."); + wlt_2.check_allocation_sum(contract_id, expected_change); + println!("✓ wlt_2 correctly has {} tokens remaining", expected_change); + + // Final verification: Total supply conservation + let total_final = wlt_1.get_allocation_sum(contract_id) + + wlt_2.get_allocation_sum(contract_id) + + wlt_3.get_allocation_sum(contract_id); + + println!("\n--- Final verification: Total supply conservation ---"); + println!( + "wlt_1 final balance: {}", + wlt_1.get_allocation_sum(contract_id) + ); + println!( + "wlt_2 final balance: {}", + wlt_2.get_allocation_sum(contract_id) + ); + println!( + "wlt_3 final balance: {}", + wlt_3.get_allocation_sum(contract_id) + ); + println!("Total final: {}", total_final); + println!("Original supply: {}", issue_supply); + + assert_eq!( + total_final, issue_supply, + "Total supply should be conserved" + ); + println!( + "✓ Total supply conservation verified: {} == {}", + total_final, issue_supply + ); + + println!("\n=== Test completed successfully ==="); +} diff --git a/tests/utils/helper/wallet.rs b/tests/utils/helper/wallet.rs index ad2ba39..c21a17d 100644 --- a/tests/utils/helper/wallet.rs +++ b/tests/utils/helper/wallet.rs @@ -604,7 +604,10 @@ impl TestWallet { assert_eq!(actual_fungible_allocations, expected_fungible_allocations); } - pub fn get_allocation_tuple(&mut self, contract_id: ContractId) -> Vec<(u64, WitnessStatus)> { + pub fn get_allocation_tuple( + &mut self, + contract_id: ContractId, + ) -> Vec<(String, String, u64, WitnessStatus)> { let allocation_field = "balance"; let state = self.runtime.state_own(contract_id); state @@ -614,6 +617,8 @@ impl TestWallet { .iter() .map(|state| { ( + state.addr.to_string(), + state.assignment.seal.to_string(), state.assignment.data.unwrap_num().unwrap_uint::(), state.status, ) From 2f1d00ba530d6b8b7297a909741651c596d5b6d3 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 18 Jun 2025 18:23:16 +0800 Subject: [PATCH 88/90] chore: update submodule commit for rgb-std Signed-off-by: will-bitlightlabs --- rgb-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rgb-std b/rgb-std index c8d79ef..3d91b60 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit c8d79ef4607e95c1d9ccadd91695d79e6f528430 +Subproject commit 3d91b60ed17d4de7eb656b72a4428c09d127c199 From 12f09df665172a7146709940b3ad74719971d740 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Tue, 24 Jun 2025 23:54:37 +0800 Subject: [PATCH 89/90] chore: update submodule commit for rgb-std Signed-off-by: will-bitlightlabs --- rgb-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rgb-std b/rgb-std index 3d91b60..78393b5 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit 3d91b60ed17d4de7eb656b72a4428c09d127c199 +Subproject commit 78393b5821a0bf5e80e02cae7090dae53c39d685 From 6520d153c36f06d382c1d8180c2103e6f27268a8 Mon Sep 17 00:00:00 2001 From: will-bitlightlabs Date: Wed, 25 Jun 2025 00:00:46 +0800 Subject: [PATCH 90/90] chore: update submodule commit for bp-wallet Signed-off-by: will-bitlightlabs --- bp-wallet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bp-wallet b/bp-wallet index a98b19b..346eadd 160000 --- a/bp-wallet +++ b/bp-wallet @@ -1 +1 @@ -Subproject commit a98b19b24d40b89494730df2866f24e689e9ddd1 +Subproject commit 346eadd1c3c5f41813f05387903082d9a457803f