From e32fa4234e767b1dea40a2b06f1250b23999bf73 Mon Sep 17 00:00:00 2001 From: Siddharth Suresh Date: Fri, 26 Jun 2026 21:58:01 -0700 Subject: [PATCH 1/2] =?UTF-8?q?SPIKE:=20Protocol=2028=20(CAP-0084)=20?= =?UTF-8?q?=E2=80=94=20muxed=20contract=20address=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add protocol 28 / CAP-0084 (muxed contract addresses) to the vnext build. Soroban host: - Add the src/rust/soroban/p28 rs-soroban-env submodule (CAP-0084 host) with its .gitmodules entry, and wire it into the multi-soroban rlib build (src/Makefile.am, src/rust/Cargo.toml, Cargo.lock, soroban_proto_all.rs). - soroban_module_cache.rs: add a separate p28 protocol-specific module cache (the next protocol is a real WIP host, not an alias of p27). XDR / address handling (gated on CAP_0084_MUXED_CONTRACT): - Bump the src/protocol-curr/xdr submodule to the CAP-0084 .x. - Hash and JSON-serialize the new SC_ADDRESS_TYPE_MUXED_CONTRACT arm (LedgerHashUtils.h, XDRCereal.cpp). - Wire the CAP_0084_MUXED_CONTRACT feature flag (configure.ac, common.mk, src/Makefile.am); enabled with --enable-next-protocol-version-unsafe-for-production. Tests: - SorobanTxTestUtils: makeMuxedContractAddress helper + de-muxing of MUXED_CONTRACT to the underlying contract in transfer invocations. - InvokeHostFunctionTests: new muxed-contract transfer/mint sections in the "Stellar asset contract transfer with CAP-67 address types" test; update "Module cache across protocol versions" to account for p28's separate module cache (next protocol now adds to the module-cache entry count). - Re-record test-tx-meta-baseline-next/InvokeHostFunctionTests.json and add the p28 cargo dep-tree expectation. SPIKE: depends on unmerged upstream rs-soroban-env / rs-stellar-xdr / stellar-xdr. --- .gitmodules | 8 +- Cargo.lock | 137 +++++++- common.mk | 4 + configure.ac | 3 + src/Makefile.am | 8 +- src/ledger/LedgerHashUtils.h | 6 + src/protocol-curr/xdr | 2 +- src/rust/Cargo.toml | 11 +- src/rust/soroban/p28 | 1 + src/rust/src/dep-trees/p28-expect.txt | 311 ++++++++++++++++++ src/rust/src/soroban_module_cache.rs | 18 +- src/rust/src/soroban_proto_all.rs | 177 +++++++++- .../test/InvokeHostFunctionTests.cpp | 54 ++- src/transactions/test/SorobanTxTestUtils.cpp | 35 ++ src/transactions/test/SorobanTxTestUtils.h | 3 + src/util/XDRCereal.cpp | 13 + .../InvokeHostFunctionTests.json | 20 +- 17 files changed, 772 insertions(+), 39 deletions(-) create mode 160000 src/rust/soroban/p28 create mode 100644 src/rust/src/dep-trees/p28-expect.txt diff --git a/.gitmodules b/.gitmodules index 140d3658f9..00fc12cfcf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,8 +25,8 @@ ignore = dirty [submodule "src/protocol-curr/xdr"] path = src/protocol-curr/xdr - url = https://github.com/stellar/stellar-xdr - branch = main + url = https://github.com/sisuresh/stellar-xdr-next.git + branch = p28-cap-0084 [submodule "src/rust/soroban/p21"] path = src/rust/soroban/p21 url = https://github.com/stellar/rs-soroban-env @@ -52,3 +52,7 @@ [submodule "lib/gperftools"] path = lib/gperftools url = https://github.com/gperftools/gperftools.git +[submodule "src/rust/soroban/p28"] + path = src/rust/soroban/p28 + url = https://github.com/sisuresh/rs-soroban-env.git + branch = p28-cap-0084 diff --git a/Cargo.lock b/Cargo.lock index 45ecdbd1ae..9159a78bc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -464,6 +464,17 @@ dependencies = [ "serde_json", ] +[[package]] +name = "crate-git-revision" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54851b5b3f24621804b1cded2820975623c205e3055d2d44031cdb1237339ac8" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -1449,12 +1460,23 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "soroban-builtin-sdk-macros" +version = "27.0.0" +source = "git+https://github.com/sisuresh/rs-soroban-env?rev=8cf4f5e1580b86d65529e6ed4f78b734908c62fa#8cf4f5e1580b86d65529e6ed4f78b734908c62fa" +dependencies = [ + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "soroban-env-common" version = "21.2.2" source = "git+https://github.com/stellar/rs-soroban-env?rev=7eeddd897cfb0f700f938b0c8d6f0541150d1fcb#7eeddd897cfb0f700f938b0c8d6f0541150d1fcb" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", @@ -1470,7 +1492,7 @@ name = "soroban-env-common" version = "22.0.0" source = "git+https://github.com/stellar/rs-soroban-env?rev=1cd8b8dca9aeeca9ce45b129cd923992b32dc258#1cd8b8dca9aeeca9ce45b129cd923992b32dc258" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", @@ -1486,7 +1508,7 @@ name = "soroban-env-common" version = "23.0.0" source = "git+https://github.com/stellar/rs-soroban-env?rev=688bc34e6cd15c71742139e625268c7f30f55a92#688bc34e6cd15c71742139e625268c7f30f55a92" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", @@ -1502,7 +1524,7 @@ name = "soroban-env-common" version = "24.0.0" source = "git+https://github.com/stellar/rs-soroban-env?rev=a37eeda815e626f416eff13f2eacb32a8b0c3729#a37eeda815e626f416eff13f2eacb32a8b0c3729" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", @@ -1518,7 +1540,7 @@ name = "soroban-env-common" version = "25.0.0" source = "git+https://github.com/stellar/rs-soroban-env?rev=0a0c2df704edeb3cdafabfcc759eddccd6775337#0a0c2df704edeb3cdafabfcc759eddccd6775337" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", @@ -1535,7 +1557,7 @@ version = "26.0.0" source = "git+https://github.com/stellar/rs-soroban-env?rev=b351f88a468d3b9e1d6de53d5b0ca585f6b7dadb#b351f88a468d3b9e1d6de53d5b0ca585f6b7dadb" dependencies = [ "arbitrary", - "crate-git-revision", + "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", @@ -1551,7 +1573,7 @@ name = "soroban-env-common" version = "26.1.2" source = "git+https://github.com/stellar/rs-soroban-env?rev=c0e58f94ff2983a09440cef6a54253349fd3c4db#c0e58f94ff2983a09440cef6a54253349fd3c4db" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", @@ -1562,6 +1584,22 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "soroban-env-common" +version = "27.0.0" +source = "git+https://github.com/sisuresh/rs-soroban-env?rev=8cf4f5e1580b86d65529e6ed4f78b734908c62fa#8cf4f5e1580b86d65529e6ed4f78b734908c62fa" +dependencies = [ + "crate-git-revision 0.0.9", + "ethnum", + "num-derive", + "num-traits", + "soroban-env-macros 27.0.0", + "soroban-wasmi", + "static_assertions", + "stellar-xdr 28.0.0", + "wasmparser", +] + [[package]] name = "soroban-env-host" version = "21.2.2" @@ -1806,6 +1844,42 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "soroban-env-host" +version = "27.0.0" +source = "git+https://github.com/sisuresh/rs-soroban-env?rev=8cf4f5e1580b86d65529e6ed4f78b734908c62fa#8cf4f5e1580b86d65529e6ed4f78b734908c62fa" +dependencies = [ + "ark-bls12-381 0.5.0", + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "curve25519-dalek", + "ecdsa", + "ed25519-dalek", + "elliptic-curve", + "generic-array", + "getrandom", + "hex-literal", + "hmac", + "k256", + "num-derive", + "num-integer", + "num-traits", + "p256", + "rand", + "rand_chacha", + "sec1", + "sha2", + "sha3", + "soroban-builtin-sdk-macros 27.0.0", + "soroban-env-common 27.0.0", + "soroban-wasmi", + "static_assertions", + "stellar-strkey 0.0.13", + "wasmparser", +] + [[package]] name = "soroban-env-macros" version = "21.2.2" @@ -1904,6 +1978,20 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "soroban-env-macros" +version = "27.0.0" +source = "git+https://github.com/sisuresh/rs-soroban-env?rev=8cf4f5e1580b86d65529e6ed4f78b734908c62fa#8cf4f5e1580b86d65529e6ed4f78b734908c62fa" +dependencies = [ + "itertools 0.13.0", + "proc-macro2", + "quote", + "serde", + "serde_json", + "stellar-xdr 28.0.0", + "syn 2.0.39", +] + [[package]] name = "soroban-fuzz-targets" version = "26.0.0" @@ -1988,6 +2076,7 @@ dependencies = [ "soroban-env-host 25.0.0", "soroban-env-host 26.0.0", "soroban-env-host 26.1.2", + "soroban-env-host 27.0.0", "soroban-fuzz-targets", "soroban-synth-wasm", "soroban-test-wasms", @@ -2015,7 +2104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12d2bf45e114117ea91d820a846fd1afbe3ba7d717988fee094ce8227a3bf8bd" dependencies = [ "base32", - "crate-git-revision", + "crate-git-revision 0.0.6", "thiserror", ] @@ -2025,7 +2114,7 @@ version = "0.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e3aa3ed00e70082cb43febc1c2afa5056b9bb3e348bbb43d0cd0aa88a611144" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "data-encoding", "thiserror", ] @@ -2036,7 +2125,7 @@ version = "0.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee1832fb50c651ad10f734aaf5d31ca5acdfb197a6ecda64d93fcdb8885af913" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", "data-encoding", ] @@ -2047,7 +2136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2675a71212ed39a806e415b0dbf4702879ff288ec7f5ee996dda42a135512b50" dependencies = [ "base64 0.13.1", - "crate-git-revision", + "crate-git-revision 0.0.6", "escape-bytes", "hex", "stellar-strkey 0.0.8", @@ -2060,7 +2149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20c2130275cc730d042b3082f51145f0486f5a543d6d72fced02ed9048b82b57" dependencies = [ "base64 0.13.1", - "crate-git-revision", + "crate-git-revision 0.0.6", "escape-bytes", "hex", "stellar-strkey 0.0.9", @@ -2074,7 +2163,7 @@ checksum = "89d2848e1694b0c8db81fd812bfab5ea71ee28073e09ccc45620ef3cf7a75a9b" dependencies = [ "base64 0.22.1", "cfg_eval", - "crate-git-revision", + "crate-git-revision 0.0.6", "escape-bytes", "ethnum", "hex", @@ -2090,7 +2179,7 @@ checksum = "4ceec163a64a9ed03359dab3b73ca556251020edc0103bae7073a38eb1708ab5" dependencies = [ "base64 0.22.1", "cfg_eval", - "crate-git-revision", + "crate-git-revision 0.0.6", "escape-bytes", "ethnum", "hex", @@ -2105,7 +2194,7 @@ source = "git+https://github.com/stellar/rs-stellar-xdr?rev=89cc1cbadf1b9a168438 dependencies = [ "base64 0.22.1", "cfg_eval", - "crate-git-revision", + "crate-git-revision 0.0.6", "escape-bytes", "ethnum", "hex", @@ -2122,7 +2211,7 @@ dependencies = [ "arbitrary", "base64 0.22.1", "cfg_eval", - "crate-git-revision", + "crate-git-revision 0.0.6", "escape-bytes", "ethnum", "hex", @@ -2136,7 +2225,21 @@ version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05ff843326969bdf1ef673dcdba94c08f4a3c8f1e58d6e6ef39b1bd4f749179a" dependencies = [ - "crate-git-revision", + "crate-git-revision 0.0.6", + "escape-bytes", + "ethnum", + "hex", + "sha2", + "stellar-strkey 0.0.13", +] + +[[package]] +name = "stellar-xdr" +version = "28.0.0" +source = "git+https://github.com/sisuresh/rs-stellar-xdr?rev=7b46a60d914c1e5befd6a2d2c50d2fdf7e5eb1f0#7b46a60d914c1e5befd6a2d2c50d2fdf7e5eb1f0" +dependencies = [ + "base64 0.22.1", + "crate-git-revision 0.0.9", "escape-bytes", "ethnum", "hex", diff --git a/common.mk b/common.mk index 0f9c96b3e2..eb1e0b8ac1 100644 --- a/common.mk +++ b/common.mk @@ -45,4 +45,8 @@ endif # ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION if CAP_0083 AM_CPPFLAGS += -DCAP_0083 +endif + +if CAP_0084_MUXED_CONTRACT +AM_CPPFLAGS += -DCAP_0084_MUXED_CONTRACT endif \ No newline at end of file diff --git a/configure.ac b/configure.ac index 76cc595238..d71ea7d03b 100644 --- a/configure.ac +++ b/configure.ac @@ -564,6 +564,9 @@ AM_CONDITIONAL(ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION, AM_CONDITIONAL(CAP_0083, [test x$enable_next_protocol_version_unsafe_for_production = xyes]) +AM_CONDITIONAL(CAP_0084_MUXED_CONTRACT, + [test x$enable_next_protocol_version_unsafe_for_production = xyes]) + AC_PATH_PROG(CARGO, cargo) if test x"$CARGO" = x; then AC_MSG_ERROR([cannot find cargo, needed for rust code]) diff --git a/src/Makefile.am b/src/Makefile.am index e33128a57b..8a6ee5defd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -100,6 +100,9 @@ XDR_FEATURE_FLAGS = if CAP_0083 XDR_FEATURE_FLAGS += -DCAP_0083 endif +if CAP_0084_MUXED_CONTRACT +XDR_FEATURE_FLAGS += -DCAP_0084_MUXED_CONTRACT +endif SUFFIXES = .x .h .rs .x.h: @@ -202,9 +205,12 @@ SOROBAN_BUILD_DIR=$(abspath $(RUST_BUILD_DIR))/soroban # ALL_SOROBAN_PROTOCOLS as you see fit). ALL_SOROBAN_PROTOCOLS=p21 p22 p23 p24 p25 p26 p27 -WIP_SOROBAN_PROTOCOL= +WIP_SOROBAN_PROTOCOL=p28 CARGO_XDR_FEATURE_FLAGS = +if CAP_0084_MUXED_CONTRACT +CARGO_XDR_FEATURE_FLAGS += --features cap_0084_muxed_contract +endif if ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION ALL_SOROBAN_PROTOCOLS+=$(WIP_SOROBAN_PROTOCOL) diff --git a/src/ledger/LedgerHashUtils.h b/src/ledger/LedgerHashUtils.h index b9748d5935..4c394b7e05 100644 --- a/src/ledger/LedgerHashUtils.h +++ b/src/ledger/LedgerHashUtils.h @@ -128,6 +128,12 @@ template <> class hash stellar::hashMix( res, std::hash()(addr.liquidityPoolId())); break; +#ifdef CAP_0084_MUXED_CONTRACT + case stellar::SC_ADDRESS_TYPE_MUXED_CONTRACT: + stellar::hashMix( + res, stellar::shortHash::xdrComputeHash(addr.muxedContract())); + break; +#endif } return res; } diff --git a/src/protocol-curr/xdr b/src/protocol-curr/xdr index 68fa1ac556..7b56181465 160000 --- a/src/protocol-curr/xdr +++ b/src/protocol-curr/xdr @@ -1 +1 @@ -Subproject commit 68fa1ac55692f68ad2a2ca549d0a283273554439 +Subproject commit 7b5618146590e15d2e250538dccbc7c89ac55c58 diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index b679667976..00cfe57c4c 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -114,6 +114,13 @@ tracy-client = { version = "=0.17.0", features = [ # Cargo.lock! The unified build will re-resolve transitive dependencies and # unify them, perturbing the contents of the lockfile. +[dependencies.soroban-env-host-p28] +version = "=27.0.0" +git = "https://github.com/sisuresh/rs-soroban-env" +package = "soroban-env-host" +rev = "8cf4f5e1580b86d65529e6ed4f78b734908c62fa" +optional = true + [dependencies.soroban-env-host-p27] version = "=26.1.2" git = "https://github.com/stellar/rs-soroban-env" @@ -202,7 +209,9 @@ unified = ["dep:soroban-env-host-p21", "dep:soroban-env-host-p24", "dep:soroban-env-host-p25", "dep:soroban-env-host-p26", - "dep:soroban-env-host-p27"] + "dep:soroban-env-host-p27", + "dep:soroban-env-host-p28", + "soroban-env-host-p28/cap_0084_muxed_contract"] tracy = ["dep:tracy-client"] diff --git a/src/rust/soroban/p28 b/src/rust/soroban/p28 new file mode 160000 index 0000000000..8cf4f5e158 --- /dev/null +++ b/src/rust/soroban/p28 @@ -0,0 +1 @@ +Subproject commit 8cf4f5e1580b86d65529e6ed4f78b734908c62fa diff --git a/src/rust/src/dep-trees/p28-expect.txt b/src/rust/src/dep-trees/p28-expect.txt new file mode 100644 index 0000000000..bad8e84817 --- /dev/null +++ b/src/rust/src/dep-trees/p28-expect.txt @@ -0,0 +1,311 @@ +soroban-env-host v27.0.0 (src/rust/soroban/p28/soroban-env-host) +├── ark-bls12-381 v0.5.0 +│ ├── ark-ec v0.5.0 +│ │ ├── ahash v0.8.11 +│ │ │ ├── cfg-if v1.0.0 +│ │ │ ├── once_cell v1.19.0 +│ │ │ └── zerocopy v0.7.35 +│ │ │ └── zerocopy-derive v0.7.35 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.69 +│ │ │ │ └── unicode-ident v1.0.9 +│ │ │ ├── quote v1.0.33 +│ │ │ │ └── proc-macro2 v1.0.69 (*) +│ │ │ └── syn v2.0.39 +│ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ ├── quote v1.0.33 (*) +│ │ │ └── unicode-ident v1.0.9 +│ │ │ [build-dependencies] +│ │ │ └── version_check v0.9.4 +│ │ ├── ark-ff v0.5.0 +│ │ │ ├── ark-ff-asm v0.5.0 (proc-macro) +│ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ └── syn v2.0.39 (*) +│ │ │ ├── ark-ff-macros v0.5.0 (proc-macro) +│ │ │ │ ├── num-bigint v0.4.4 +│ │ │ │ │ ├── num-integer v0.1.45 +│ │ │ │ │ │ └── num-traits v0.2.17 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── autocfg v1.1.0 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── autocfg v1.1.0 +│ │ │ │ │ └── num-traits v0.2.17 (*) +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── autocfg v1.1.0 +│ │ │ │ ├── num-traits v0.2.17 (*) +│ │ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ └── syn v2.0.39 (*) +│ │ │ ├── ark-serialize v0.5.0 +│ │ │ │ ├── ark-serialize-derive v0.5.0 (proc-macro) +│ │ │ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ │ └── syn v2.0.39 (*) +│ │ │ │ ├── ark-std v0.5.0 +│ │ │ │ │ ├── num-traits v0.2.17 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── autocfg v1.1.0 +│ │ │ │ │ └── rand v0.8.5 +│ │ │ │ │ ├── libc v0.2.176 +│ │ │ │ │ ├── rand_chacha v0.3.1 +│ │ │ │ │ │ ├── ppv-lite86 v0.2.17 +│ │ │ │ │ │ └── rand_core v0.6.4 +│ │ │ │ │ │ └── getrandom v0.2.11 +│ │ │ │ │ │ ├── cfg-if v1.0.0 +│ │ │ │ │ │ ├── js-sys v0.3.64 +│ │ │ │ │ │ │ └── wasm-bindgen v0.2.100 +│ │ │ │ │ │ │ ├── cfg-if v1.0.0 +│ │ │ │ │ │ │ ├── once_cell v1.19.0 +│ │ │ │ │ │ │ ├── rustversion v1.0.14 (proc-macro) +│ │ │ │ │ │ │ └── wasm-bindgen-macro v0.2.100 (proc-macro) +│ │ │ │ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ │ │ │ └── wasm-bindgen-macro-support v0.2.100 +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ │ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ │ │ │ ├── syn v2.0.39 (*) +│ │ │ │ │ │ │ ├── wasm-bindgen-backend v0.2.100 +│ │ │ │ │ │ │ │ ├── bumpalo v3.13.0 +│ │ │ │ │ │ │ │ ├── log v0.4.19 +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ │ │ │ │ ├── syn v2.0.39 (*) +│ │ │ │ │ │ │ │ └── wasm-bindgen-shared v0.2.100 +│ │ │ │ │ │ │ │ └── unicode-ident v1.0.9 +│ │ │ │ │ │ │ └── wasm-bindgen-shared v0.2.100 (*) +│ │ │ │ │ │ ├── libc v0.2.176 +│ │ │ │ │ │ ├── wasi v0.11.0+wasi-snapshot-preview1 +│ │ │ │ │ │ └── wasm-bindgen v0.2.100 (*) +│ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ ├── arrayvec v0.7.6 +│ │ │ │ ├── digest v0.10.7 +│ │ │ │ │ ├── block-buffer v0.10.4 +│ │ │ │ │ │ └── generic-array v0.14.7 +│ │ │ │ │ │ ├── typenum v1.16.0 +│ │ │ │ │ │ └── zeroize v1.8.1 +│ │ │ │ │ │ └── zeroize_derive v1.4.2 (proc-macro) +│ │ │ │ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ │ │ └── syn v2.0.39 (*) +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── version_check v0.9.4 +│ │ │ │ │ ├── const-oid v0.9.2 +│ │ │ │ │ ├── crypto-common v0.1.6 +│ │ │ │ │ │ ├── generic-array v0.14.7 (*) +│ │ │ │ │ │ └── typenum v1.16.0 +│ │ │ │ │ └── subtle v2.5.0 +│ │ │ │ └── num-bigint v0.4.4 (*) +│ │ │ ├── ark-std v0.5.0 (*) +│ │ │ ├── arrayvec v0.7.6 +│ │ │ ├── digest v0.10.7 (*) +│ │ │ ├── educe v0.6.0 (proc-macro) +│ │ │ │ ├── enum-ordinalize v4.3.2 +│ │ │ │ │ └── enum-ordinalize-derive v4.3.2 (proc-macro) +│ │ │ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ │ └── syn v2.0.39 (*) +│ │ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ │ ├── quote v1.0.33 (*) +│ │ │ │ └── syn v2.0.39 (*) +│ │ │ ├── itertools v0.13.0 +│ │ │ │ └── either v1.8.1 +│ │ │ ├── num-bigint v0.4.4 (*) +│ │ │ ├── num-traits v0.2.17 (*) +│ │ │ ├── paste v1.0.12 (proc-macro) +│ │ │ └── zeroize v1.8.1 (*) +│ │ ├── ark-poly v0.5.0 +│ │ │ ├── ahash v0.8.11 (*) +│ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ ├── ark-std v0.5.0 (*) +│ │ │ ├── educe v0.6.0 (proc-macro) (*) +│ │ │ ├── fnv v1.0.7 +│ │ │ └── hashbrown v0.15.5 +│ │ │ └── allocator-api2 v0.2.21 +│ │ ├── ark-serialize v0.5.0 (*) +│ │ ├── ark-std v0.5.0 (*) +│ │ ├── educe v0.6.0 (proc-macro) (*) +│ │ ├── fnv v1.0.7 +│ │ ├── hashbrown v0.15.5 (*) +│ │ ├── itertools v0.13.0 (*) +│ │ ├── num-bigint v0.4.4 (*) +│ │ ├── num-integer v0.1.45 +│ │ │ └── num-traits v0.2.17 (*) +│ │ │ [build-dependencies] +│ │ │ └── autocfg v1.1.0 +│ │ ├── num-traits v0.2.17 (*) +│ │ └── zeroize v1.8.1 (*) +│ ├── ark-ff v0.5.0 (*) +│ ├── ark-serialize v0.5.0 (*) +│ └── ark-std v0.5.0 (*) +├── ark-bn254 v0.5.0 +│ ├── ark-ec v0.5.0 (*) +│ ├── ark-ff v0.5.0 (*) +│ └── ark-std v0.5.0 (*) +├── ark-ec v0.5.0 (*) +├── ark-ff v0.5.0 (*) +├── ark-serialize v0.5.0 (*) +├── curve25519-dalek v4.1.3 +│ ├── cfg-if v1.0.0 +│ ├── cpufeatures v0.2.8 +│ │ └── libc v0.2.176 +│ ├── curve25519-dalek-derive v0.1.0 (proc-macro) +│ │ ├── proc-macro2 v1.0.69 (*) +│ │ ├── quote v1.0.33 (*) +│ │ └── syn v2.0.39 (*) +│ ├── digest v0.10.7 (*) +│ ├── fiat-crypto v0.2.5 +│ ├── subtle v2.5.0 +│ └── zeroize v1.8.1 (*) +│ [build-dependencies] +│ └── rustc_version v0.4.0 +│ └── semver v1.0.17 +├── ecdsa v0.16.9 +│ ├── der v0.7.6 +│ │ ├── const-oid v0.9.2 +│ │ └── zeroize v1.8.1 (*) +│ ├── digest v0.10.7 (*) +│ ├── elliptic-curve v0.13.8 +│ │ ├── base16ct v0.2.0 +│ │ ├── crypto-bigint v0.5.2 +│ │ │ ├── generic-array v0.14.7 (*) +│ │ │ ├── rand_core v0.6.4 (*) +│ │ │ ├── subtle v2.5.0 +│ │ │ └── zeroize v1.8.1 (*) +│ │ ├── digest v0.10.7 (*) +│ │ ├── ff v0.13.0 +│ │ │ ├── rand_core v0.6.4 (*) +│ │ │ └── subtle v2.5.0 +│ │ ├── generic-array v0.14.7 (*) +│ │ ├── group v0.13.0 +│ │ │ ├── ff v0.13.0 (*) +│ │ │ ├── rand_core v0.6.4 (*) +│ │ │ └── subtle v2.5.0 +│ │ ├── rand_core v0.6.4 (*) +│ │ ├── sec1 v0.7.2 +│ │ │ ├── base16ct v0.2.0 +│ │ │ ├── der v0.7.6 (*) +│ │ │ ├── generic-array v0.14.7 (*) +│ │ │ ├── subtle v2.5.0 +│ │ │ └── zeroize v1.8.1 (*) +│ │ ├── subtle v2.5.0 +│ │ └── zeroize v1.8.1 (*) +│ ├── rfc6979 v0.4.0 +│ │ ├── hmac v0.12.1 +│ │ │ └── digest v0.10.7 (*) +│ │ └── subtle v2.5.0 +│ └── signature v2.1.0 +│ ├── digest v0.10.7 (*) +│ └── rand_core v0.6.4 (*) +├── ed25519-dalek v2.1.1 +│ ├── curve25519-dalek v4.1.3 (*) +│ ├── ed25519 v2.2.2 +│ │ └── signature v2.1.0 (*) +│ ├── rand_core v0.6.4 (*) +│ ├── sha2 v0.10.9 +│ │ ├── cfg-if v1.0.0 +│ │ ├── cpufeatures v0.2.8 (*) +│ │ └── digest v0.10.7 (*) +│ ├── subtle v2.5.0 +│ └── zeroize v1.8.1 (*) +├── elliptic-curve v0.13.8 (*) +├── generic-array v0.14.7 (*) +├── getrandom v0.2.11 (*) +├── hex-literal v0.4.1 +├── hmac v0.12.1 (*) +├── k256 v0.13.4 +│ ├── cfg-if v1.0.0 +│ ├── ecdsa v0.16.9 (*) +│ ├── elliptic-curve v0.13.8 (*) +│ └── sha2 v0.10.9 (*) +├── num-derive v0.4.1 (proc-macro) +│ ├── proc-macro2 v1.0.69 (*) +│ ├── quote v1.0.33 (*) +│ └── syn v2.0.39 (*) +├── num-integer v0.1.45 (*) +├── num-traits v0.2.17 (*) +├── p256 v0.13.2 +│ ├── ecdsa v0.16.9 (*) +│ ├── elliptic-curve v0.13.8 (*) +│ ├── primeorder v0.13.3 +│ │ └── elliptic-curve v0.13.8 (*) +│ └── sha2 v0.10.9 (*) +├── rand v0.8.5 (*) +├── rand_chacha v0.3.1 (*) +├── sec1 v0.7.2 (*) +├── sha2 v0.10.9 (*) +├── sha3 v0.10.8 +│ ├── digest v0.10.7 (*) +│ └── keccak v0.1.4 +│ └── cpufeatures v0.2.8 (*) +├── soroban-builtin-sdk-macros v27.0.0 (proc-macro) (src/rust/soroban/p28/soroban-builtin-sdk-macros) +│ ├── itertools v0.13.0 +│ │ └── either v1.8.1 +│ ├── proc-macro2 v1.0.69 (*) +│ ├── quote v1.0.33 (*) +│ └── syn v2.0.39 (*) +├── soroban-env-common v27.0.0 (src/rust/soroban/p28/soroban-env-common) +│ ├── ethnum v1.5.3 +│ ├── num-derive v0.4.1 (proc-macro) (*) +│ ├── num-traits v0.2.17 (*) +│ ├── soroban-env-macros v27.0.0 (proc-macro) (src/rust/soroban/p28/soroban-env-macros) +│ │ ├── itertools v0.13.0 (*) +│ │ ├── proc-macro2 v1.0.69 (*) +│ │ ├── quote v1.0.33 (*) +│ │ ├── serde v1.0.192 +│ │ │ └── serde_derive v1.0.192 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.69 (*) +│ │ │ ├── quote v1.0.33 (*) +│ │ │ └── syn v2.0.39 (*) +│ │ ├── serde_json v1.0.108 +│ │ │ ├── itoa v1.0.6 +│ │ │ ├── ryu v1.0.13 +│ │ │ └── serde v1.0.192 (*) +│ │ ├── stellar-xdr v28.0.0 (https://github.com/sisuresh/rs-stellar-xdr?rev=7b46a60d914c1e5befd6a2d2c50d2fdf7e5eb1f0#7b46a60d) +│ │ │ ├── escape-bytes v0.1.1 +│ │ │ ├── ethnum v1.5.3 +│ │ │ ├── hex v0.4.3 +│ │ │ ├── sha2 v0.10.9 (*) +│ │ │ └── stellar-strkey v0.0.13 +│ │ │ └── data-encoding v2.6.0 +│ │ │ [build-dependencies] +│ │ │ └── crate-git-revision v0.0.6 +│ │ │ ├── serde v1.0.192 (*) +│ │ │ ├── serde_derive v1.0.192 (proc-macro) (*) +│ │ │ └── serde_json v1.0.108 (*) +│ │ │ [build-dependencies] +│ │ │ └── crate-git-revision v0.0.9 +│ │ │ ├── serde v1.0.192 (*) +│ │ │ ├── serde_derive v1.0.192 (proc-macro) (*) +│ │ │ └── serde_json v1.0.108 (*) +│ │ └── syn v2.0.39 (*) +│ ├── soroban-wasmi v0.31.1-soroban.20.0.1 (https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3de) +│ │ ├── smallvec v1.13.2 +│ │ ├── spin v0.9.8 +│ │ ├── wasmi_arena v0.4.0 (https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3de) +│ │ ├── wasmi_core v0.13.0 (https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3de) +│ │ │ ├── downcast-rs v1.2.0 +│ │ │ ├── libm v0.2.8 +│ │ │ ├── num-traits v0.2.17 (*) +│ │ │ └── paste v1.0.12 (proc-macro) +│ │ └── wasmparser-nostd v0.100.2 +│ │ └── indexmap-nostd v0.4.0 +│ ├── static_assertions v1.1.0 +│ ├── stellar-xdr v28.0.0 (https://github.com/sisuresh/rs-stellar-xdr?rev=7b46a60d914c1e5befd6a2d2c50d2fdf7e5eb1f0#7b46a60d) +│ │ ├── base64 v0.22.1 +│ │ ├── escape-bytes v0.1.1 +│ │ ├── ethnum v1.5.3 +│ │ ├── hex v0.4.3 +│ │ ├── sha2 v0.10.9 (*) +│ │ └── stellar-strkey v0.0.13 (*) +│ │ [build-dependencies] +│ │ └── crate-git-revision v0.0.9 (*) +│ └── wasmparser v0.116.1 +│ ├── indexmap v2.0.2 +│ │ ├── equivalent v1.0.1 +│ │ └── hashbrown v0.14.1 +│ └── semver v1.0.17 +│ [build-dependencies] +│ └── crate-git-revision v0.0.9 (*) +├── soroban-wasmi v0.31.1-soroban.20.0.1 (https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3de) (*) +├── static_assertions v1.1.0 +├── stellar-strkey v0.0.13 (*) +└── wasmparser v0.116.1 (*) diff --git a/src/rust/src/soroban_module_cache.rs b/src/rust/src/soroban_module_cache.rs index 9270b46c79..75c08ba4c1 100644 --- a/src/rust/src/soroban_module_cache.rs +++ b/src/rust/src/soroban_module_cache.rs @@ -18,6 +18,8 @@ use crate::{ rust_bridge::CxxBuf, soroban_proto_all::{get_host_module_for_protocol, p23, p24, p25, p26, p27, protocol_agnostic}, }; +#[cfg(feature = "next")] +use crate::soroban_proto_all::p28; pub(crate) struct SorobanModuleCache { pub(crate) p23_cache: p23::soroban_proto_any::ProtocolSpecificModuleCache, @@ -25,6 +27,8 @@ pub(crate) struct SorobanModuleCache { pub(crate) p25_cache: p25::soroban_proto_any::ProtocolSpecificModuleCache, pub(crate) p26_cache: p26::soroban_proto_any::ProtocolSpecificModuleCache, pub(crate) p27_cache: p27::soroban_proto_any::ProtocolSpecificModuleCache, + #[cfg(feature = "next")] + pub(crate) p28_cache: p28::soroban_proto_any::ProtocolSpecificModuleCache, } impl SorobanModuleCache { @@ -35,6 +39,8 @@ impl SorobanModuleCache { p25_cache: p25::soroban_proto_any::ProtocolSpecificModuleCache::new()?, p26_cache: p26::soroban_proto_any::ProtocolSpecificModuleCache::new()?, p27_cache: p27::soroban_proto_any::ProtocolSpecificModuleCache::new()?, + #[cfg(feature = "next")] + p28_cache: p28::soroban_proto_any::ProtocolSpecificModuleCache::new()?, }) } pub fn compile( @@ -49,7 +55,7 @@ impl SorobanModuleCache { 26 => self.p26_cache.compile(_wasm), 27 => self.p27_cache.compile(_wasm), #[cfg(feature = "next")] - 28 => self.p27_cache.compile(_wasm), + 28 => self.p28_cache.compile(_wasm), // Add other protocols here as needed. _ => Err(protocol_agnostic::make_error("unsupported protocol")), } @@ -61,6 +67,8 @@ impl SorobanModuleCache { p25_cache: self.p25_cache.shallow_clone()?, p26_cache: self.p26_cache.shallow_clone()?, p27_cache: self.p27_cache.shallow_clone()?, + #[cfg(feature = "next")] + p28_cache: self.p28_cache.shallow_clone()?, })) } @@ -74,6 +82,8 @@ impl SorobanModuleCache { self.p25_cache.evict(&_hash)?; self.p26_cache.evict(&_hash)?; self.p27_cache.evict(&_hash)?; + #[cfg(feature = "next")] + self.p28_cache.evict(&_hash)?; Ok(()) } pub fn clear(&self) -> Result<(), Box> { @@ -82,6 +92,8 @@ impl SorobanModuleCache { self.p25_cache.clear()?; self.p26_cache.clear()?; self.p27_cache.clear()?; + #[cfg(feature = "next")] + self.p28_cache.clear()?; Ok(()) } @@ -101,7 +113,7 @@ impl SorobanModuleCache { 26 => self.p26_cache.contains_module(&_hash), 27 => self.p27_cache.contains_module(&_hash), #[cfg(feature = "next")] - 28 => self.p27_cache.contains_module(&_hash), + 28 => self.p28_cache.contains_module(&_hash), _ => Err(protocol_agnostic::make_error("unsupported protocol")), } } @@ -118,7 +130,7 @@ impl SorobanModuleCache { 26 => bytes = bytes.max(self.p26_cache.get_wasm_bytes_input()?), 27 => bytes = bytes.max(self.p27_cache.get_wasm_bytes_input()?), #[cfg(feature = "next")] - 28 => bytes = bytes.max(self.p27_cache.get_wasm_bytes_input()?), + 28 => bytes = bytes.max(self.p28_cache.get_wasm_bytes_input()?), _ => return Err(protocol_agnostic::make_error("unsupported protocol")), } Ok(bytes) diff --git a/src/rust/src/soroban_proto_all.rs b/src/rust/src/soroban_proto_all.rs index ccdc467866..fc6cd29a6b 100644 --- a/src/rust/src/soroban_proto_all.rs +++ b/src/rust/src/soroban_proto_all.rs @@ -32,10 +32,10 @@ use crate::RustBuf; // We also alias the latest soroban as soroban_curr to help reduce churn in code // that's just "always supposed to use the latest". -//#[cfg(not(feature = "next"))] +#[cfg(not(feature = "next"))] pub(crate) use p27 as soroban_curr; -//#[cfg(feature = "next")] -//pub(crate) use p28 as soroban_curr; +#[cfg(feature = "next")] +pub(crate) use p28 as soroban_curr; // We also pin some protocol _agnostic_ definitions that are technically // implemented by a specific version of soroban, but which is protocol-stable @@ -52,6 +52,175 @@ pub(crate) mod protocol_agnostic { pub(crate) use super::p24::soroban_env_host::xdr::int128_helpers; } +#[cfg(feature = "next")] +#[path = "."] +pub(crate) mod p28 { + pub(crate) extern crate soroban_env_host_p28; + use crate::{ + bridge::rust_bridge::CxxLedgerEntryRentChange, + rust_bridge::{ + CxxFeeConfiguration, CxxRentFeeConfiguration, CxxRentWriteFeeConfiguration, + CxxTransactionResources, + }, + SorobanModuleCache, + }; + use soroban_env_host::{ + budget::Budget, + e2e_invoke::{self, InvokeHostFunctionResult}, + fees::{ + compute_rent_write_fee_per_1kb, FeeConfiguration, LedgerEntryRentChange, + RentFeeConfiguration, RentWriteFeeConfiguration, TransactionResources, + }, + vm::wasm_module_memory_cost, + xdr::{ContractCodeEntry, DiagnosticEvent}, + HostError, LedgerInfo, TraceHook, + }; + pub(crate) use soroban_env_host_p28 as soroban_env_host; + + pub(crate) mod soroban_proto_any; + + pub(crate) use soroban_env_host::{CompilationContext, ErrorHandler, ModuleCache}; + + pub(crate) const fn get_version_pre_release(v: &soroban_env_host::Version) -> u32 { + v.interface.pre_release + } + + pub(crate) const fn get_version_protocol(v: &soroban_env_host::Version) -> u32 { + v.interface.protocol + } + + pub(crate) fn get_xdr_base_git_rev() -> String { + soroban_env_host::xdr::VERSION.xdr.to_string() + } + pub(crate) fn get_xdr_pkg_ver() -> String { + soroban_env_host::xdr::VERSION.pkg.to_string() + } + pub(crate) fn get_xdr_git_rev() -> String { + soroban_env_host::xdr::VERSION.rev.to_string() + } + pub(crate) fn get_xdr_features() -> Vec { + soroban_env_host::xdr::VERSION + .features + .iter() + .map(|s| s.to_string()) + .collect() + } + + pub fn invoke_host_function_with_trace_hook_and_module_cache< + T: AsRef<[u8]>, + I: ExactSizeIterator, + >( + budget: &Budget, + enable_diagnostics: bool, + encoded_host_fn: T, + encoded_resources: T, + restored_rw_entry_indices: &[u32], + encoded_source_account: T, + encoded_auth_entries: I, + ledger_info: LedgerInfo, + encoded_ledger_entries: I, + encoded_ttl_entries: I, + base_prng_seed: T, + diagnostic_events: &mut Vec, + trace_hook: Option, + module_cache: &SorobanModuleCache, + ) -> Result { + e2e_invoke::invoke_host_function( + budget, + enable_diagnostics, + encoded_host_fn, + encoded_resources, + restored_rw_entry_indices, + encoded_source_account, + encoded_auth_entries, + ledger_info, + encoded_ledger_entries, + encoded_ttl_entries, + base_prng_seed, + diagnostic_events, + trace_hook, + Some(module_cache.p28_cache.module_cache.clone()), + ) + } + + pub(crate) fn wasm_module_memory_cost_wrapper( + budget: &Budget, + contract_code_entry: &ContractCodeEntry, + ) -> Result { + wasm_module_memory_cost(budget, contract_code_entry) + } + + pub(crate) fn compute_rent_write_fee_per_1kb_wrapper( + bucket_list_size: i64, + fee_config: CxxRentWriteFeeConfiguration, + ) -> i64 { + compute_rent_write_fee_per_1kb(bucket_list_size, &fee_config.into()) + } + + pub(crate) fn convert_transaction_resources( + value: &CxxTransactionResources, + ) -> TransactionResources { + TransactionResources { + instructions: value.instructions, + disk_read_entries: value.disk_read_entries, + write_entries: value.write_entries, + disk_read_bytes: value.disk_read_bytes, + write_bytes: value.write_bytes, + contract_events_size_bytes: value.contract_events_size_bytes, + transaction_size_bytes: value.transaction_size_bytes, + } + } + + impl From for RentWriteFeeConfiguration { + fn from(value: CxxRentWriteFeeConfiguration) -> Self { + Self { + state_target_size_bytes: value.state_target_size_bytes, + rent_fee_1kb_state_size_low: value.rent_fee_1kb_state_size_low, + rent_fee_1kb_state_size_high: value.rent_fee_1kb_state_size_high, + state_size_rent_fee_growth_factor: value.state_size_rent_fee_growth_factor, + } + } + } + + pub(crate) fn convert_rent_fee_configuration( + value: &CxxRentFeeConfiguration, + ) -> RentFeeConfiguration { + RentFeeConfiguration { + fee_per_rent_1kb: value.fee_per_rent_1kb, + fee_per_write_1kb: value.fee_per_write_1kb, + fee_per_write_entry: value.fee_per_write_entry, + persistent_rent_rate_denominator: value.persistent_rent_rate_denominator, + temporary_rent_rate_denominator: value.temporary_rent_rate_denominator, + } + } + + pub(crate) fn convert_fee_configuration(value: CxxFeeConfiguration) -> FeeConfiguration { + FeeConfiguration { + fee_per_instruction_increment: value.fee_per_instruction_increment, + fee_per_disk_read_entry: value.fee_per_disk_read_entry, + fee_per_write_entry: value.fee_per_write_entry, + fee_per_disk_read_1kb: value.fee_per_disk_read_1kb, + fee_per_write_1kb: value.fee_per_write_1kb, + fee_per_historical_1kb: value.fee_per_historical_1kb, + fee_per_contract_event_1kb: value.fee_per_contract_event_1kb, + fee_per_transaction_size_1kb: value.fee_per_transaction_size_1kb, + } + } + + pub(crate) fn convert_ledger_entry_rent_change( + value: &CxxLedgerEntryRentChange, + ) -> LedgerEntryRentChange { + LedgerEntryRentChange { + is_persistent: value.is_persistent, + is_code_entry: value.is_code_entry, + old_size_bytes: value.old_size_bytes, + new_size_bytes: value.new_size_bytes, + old_live_until_ledger: value.old_live_until_ledger, + new_live_until_ledger: value.new_live_until_ledger, + } + } +} + #[path = "."] pub(crate) mod p27 { pub(crate) extern crate soroban_env_host_p27; @@ -1469,6 +1638,8 @@ const HOST_MODULES: &'static [HostModule] = &[ proto_versioned_functions_for_module!(p25), proto_versioned_functions_for_module!(p26), proto_versioned_functions_for_module!(p27), + #[cfg(feature = "next")] + proto_versioned_functions_for_module!(p28), ]; pub(crate) fn get_host_module_for_protocol( diff --git a/src/transactions/test/InvokeHostFunctionTests.cpp b/src/transactions/test/InvokeHostFunctionTests.cpp index 13166c0c8a..23dbcea05b 100644 --- a/src/transactions/test/InvokeHostFunctionTests.cpp +++ b/src/transactions/test/InvokeHostFunctionTests.cpp @@ -600,7 +600,14 @@ TEST_CASE("Stellar asset contract transfer with CAP-67 address types", SorobanTest test(cfg); auto& root = test.getRoot(); +#ifdef CAP_0084_MUXED_CONTRACT + // a1 makes several native transfers within a single run (100M + 300M + + // 400M for the muxed-contract case), so it needs enough balance to stay + // above its account reserve after all of them. + auto a1 = root.create("a1", 2'000'000'000); +#else auto a1 = root.create("a1", 1'000'000'000); +#endif auto a2 = root.create("a2", 1'000'000'000); Asset asset = makeAsset(root.getSecretKey(), "USDC"); a1.changeTrust(asset, 2'000'000'000); @@ -685,6 +692,46 @@ TEST_CASE("Stellar asset contract transfer with CAP-67 address types", a1, makeClaimableBalanceAddress(ClaimableBalanceID()), 1)); REQUIRE(client.lastEvent() == std::nullopt); } +#ifdef CAP_0084_MUXED_CONTRACT + { + INFO("transfer to muxed contract (CAP-0084)"); + // The destination is the SAC-transfer contract wrapped in a muxed + // contract address; the SAC de-muxes to the underlying contract for + // the balance and surfaces the id via the `to_muxed_id` event. + REQUIRE(client.transfer( + a1, + makeMuxedContractAddress( + transferContract.getAddress().contractId(), + 987'654'321'987'654'321ULL), + 400'000'000)); + REQUIRE(*client.lastEvent() == + client.makeTransferEvent(a1Address, + transferContract.getAddress(), + 400'000'000, + 987'654'321'987'654'321ULL)); + } + if (!useNativeAsset) + { + INFO("mint to muxed contract (CAP-0084)"); + // Mint to a muxed-contract destination: the SAC de-muxes to the + // underlying contract for the balance (asserted inside mint() via + // the de-muxed getBalance) and surfaces the id via `to_muxed_id`. + // Native has no admin, so mint only applies to the issued asset. + uint64_t const toMuxId = 111'222'333'444'555'666ULL; + REQUIRE(client.mint( + root, + makeMuxedContractAddress( + transferContract.getAddress().contractId(), toMuxId), + 500'000'000)); + REQUIRE(*client.lastEvent() == + makeMintOrBurnEvent( + /*isMint=*/true, + client.getContract().getAddress().contractId(), + tokenAsset, transferContract.getAddress(), 500'000'000, + SCMapEntry(makeSymbolSCVal("to_muxed_id"), + makeU64(toMuxId)))); + } +#endif }; SECTION("native asset") @@ -7681,7 +7728,12 @@ TEST_CASE("Module cache across protocol versions", "[tx][soroban][modulecache]") // work-in-progress next host, in which case there _is_ a separate module // cache and the following line of code should be commented-out. // - moduleCacheProtocolCount -= 1; + // p28 (CAP-0084) ships its own work-in-progress next host with a separate + // module cache (see p28_cache in soroban_module_cache.rs), so the next + // protocol version _does_ add to the module cache count and the following + // line stays commented-out. + // + // moduleCacheProtocolCount -= 1; #endif REQUIRE(app->getLedgerManager() .getSorobanMetrics() diff --git a/src/transactions/test/SorobanTxTestUtils.cpp b/src/transactions/test/SorobanTxTestUtils.cpp index 4615593862..616cfff8b1 100644 --- a/src/transactions/test/SorobanTxTestUtils.cpp +++ b/src/transactions/test/SorobanTxTestUtils.cpp @@ -66,6 +66,33 @@ makeMuxedAccountAddress(AccountID const& accountID, uint64_t id) return addr; } +#ifdef CAP_0084_MUXED_CONTRACT +SCAddress +makeMuxedContractAddress(Hash const& contractId, uint64_t id) +{ + SCAddress addr(SC_ADDRESS_TYPE_MUXED_CONTRACT); + addr.muxedContract().contractId = contractId; + addr.muxedContract().id = id; + return addr; +} + +// CAP-0084: resolve a muxed contract address to its underlying contract id. +// The SAC keys balances on the underlying contract, so every balance +// key/value built from an SCAddress must de-mux first. Non-muxed-contract +// addresses are returned unchanged. +static SCAddress +demuxContractAddress(SCAddress const& addr) +{ + if (addr.type() == SC_ADDRESS_TYPE_MUXED_CONTRACT) + { + SCAddress c(SC_ADDRESS_TYPE_CONTRACT); + c.contractId() = addr.muxedContract().contractId; + return c; + } + return addr; +} +#endif + SCVal makeI32(int32_t i32) { @@ -1576,7 +1603,11 @@ LedgerKey AssetContractTestClient::makeContractDataBalanceKey(SCAddress const& addr) { SCVal val(SCV_ADDRESS); +#ifdef CAP_0084_MUXED_CONTRACT + val.address() = demuxContractAddress(addr); +#else val.address() = addr; +#endif LedgerKey balanceKey(CONTRACT_DATA); balanceKey.contractData().contract = mContract.getAddress(); @@ -1628,7 +1659,11 @@ int64_t AssetContractTestClient::getBalance(SCAddress const& addr) { SCVal val(SCV_ADDRESS); +#ifdef CAP_0084_MUXED_CONTRACT + val.address() = demuxContractAddress(addr); +#else val.address() = addr; +#endif return addr.type() == SC_ADDRESS_TYPE_ACCOUNT ? txtest::getBalance(mApp, addr.accountId(), mAsset) diff --git a/src/transactions/test/SorobanTxTestUtils.h b/src/transactions/test/SorobanTxTestUtils.h index b61d2d4043..2de6daf02e 100644 --- a/src/transactions/test/SorobanTxTestUtils.h +++ b/src/transactions/test/SorobanTxTestUtils.h @@ -19,6 +19,9 @@ namespace txtest SCAddress makeContractAddress(Hash const& hash); SCAddress makeMuxedAccountAddress(AccountID const& accountID, uint64_t id); +#ifdef CAP_0084_MUXED_CONTRACT +SCAddress makeMuxedContractAddress(Hash const& contractId, uint64_t id); +#endif SCVal makeI32(int32_t i32); SCVal makeI128(uint64_t u64); SCSymbol makeSymbol(std::string const& str); diff --git a/src/util/XDRCereal.cpp b/src/util/XDRCereal.cpp index 596831f71a..fb499feb5f 100644 --- a/src/util/XDRCereal.cpp +++ b/src/util/XDRCereal.cpp @@ -59,6 +59,19 @@ cereal_override(cereal::JSONOutputArchive& ar, stellar::SCAddress const& addr, addr.liquidityPoolId().data(), addr.liquidityPoolId().size())), field); return; +#ifdef CAP_0084_MUXED_CONTRACT + case stellar::SC_ADDRESS_TYPE_MUXED_CONTRACT: + ar.setNextName(field); + ar.startNode(); + xdr::archive(ar, addr.muxedContract().id, "id"); + xdr::archive(ar, + stellar::strKey::toStrKey(stellar::strKey::STRKEY_CONTRACT, + addr.muxedContract().contractId) + .value, + "contractId"); + ar.finishNode(); + return; +#endif default: // Unknown address type - serialize as "Unknown(type_id)" xdr::archive(ar, diff --git a/test-tx-meta-baseline-next/InvokeHostFunctionTests.json b/test-tx-meta-baseline-next/InvokeHostFunctionTests.json index f1c1e2b3f4..80085b5c43 100644 --- a/test-tx-meta-baseline-next/InvokeHostFunctionTests.json +++ b/test-tx-meta-baseline-next/InvokeHostFunctionTests.json @@ -1359,19 +1359,19 @@ "Stellar asset contract transfer with CAP-67 address types" : [ "+cR3oq2qY0I=", - "Rs/PGnv73JY=", - "10hZi1wChI0=", - "NjESxGWSAbY=", + "nf41aXcp3cc=", + "OtySRiV3oo0=", + "+WE3Fz5pS1M=", "bFkjDfabs9w=", - "N+Zof/XqwL8=", - "g6OoL0u5VkM=", + "EhSVUb6F5Q8=", + "c3zLocFSVRo=", "+cR3oq2qY0I=", - "Rs/PGnv73JY=", - "10hZi1wChI0=", - "NjESxGWSAbY=", + "nf41aXcp3cc=", + "OtySRiV3oo0=", + "+WE3Fz5pS1M=", "bFkjDfabs9w=", - "N+Zof/XqwL8=", - "g6OoL0u5VkM=" + "EhSVUb6F5Q8=", + "c3zLocFSVRo=" ], "Trustline stellar asset contract|protocol version 20" : [ From 840d7673e6d3916d0514c50e89449721e875c665 Mon Sep 17 00:00:00 2001 From: Siddharth Suresh Date: Sat, 27 Jun 2026 00:56:53 -0700 Subject: [PATCH 2/2] Fix formatting (clang-format + rustfmt) for CAP-0084 changes --- src/rust/src/soroban_module_cache.rs | 4 ++-- .../test/InvokeHostFunctionTests.cpp | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/rust/src/soroban_module_cache.rs b/src/rust/src/soroban_module_cache.rs index 75c08ba4c1..d4bf9f145a 100644 --- a/src/rust/src/soroban_module_cache.rs +++ b/src/rust/src/soroban_module_cache.rs @@ -14,12 +14,12 @@ // current-protocol cache as soon as we start, as well as the next-protocol // cache (if it exists) so that we can upgrade without stalling. +#[cfg(feature = "next")] +use crate::soroban_proto_all::p28; use crate::{ rust_bridge::CxxBuf, soroban_proto_all::{get_host_module_for_protocol, p23, p24, p25, p26, p27, protocol_agnostic}, }; -#[cfg(feature = "next")] -use crate::soroban_proto_all::p28; pub(crate) struct SorobanModuleCache { pub(crate) p23_cache: p23::soroban_proto_any::ProtocolSpecificModuleCache, diff --git a/src/transactions/test/InvokeHostFunctionTests.cpp b/src/transactions/test/InvokeHostFunctionTests.cpp index 23dbcea05b..766056d332 100644 --- a/src/transactions/test/InvokeHostFunctionTests.cpp +++ b/src/transactions/test/InvokeHostFunctionTests.cpp @@ -698,17 +698,16 @@ TEST_CASE("Stellar asset contract transfer with CAP-67 address types", // The destination is the SAC-transfer contract wrapped in a muxed // contract address; the SAC de-muxes to the underlying contract for // the balance and surfaces the id via the `to_muxed_id` event. - REQUIRE(client.transfer( - a1, - makeMuxedContractAddress( - transferContract.getAddress().contractId(), - 987'654'321'987'654'321ULL), - 400'000'000)); + REQUIRE( + client.transfer(a1, + makeMuxedContractAddress( + transferContract.getAddress().contractId(), + 987'654'321'987'654'321ULL), + 400'000'000)); REQUIRE(*client.lastEvent() == - client.makeTransferEvent(a1Address, - transferContract.getAddress(), - 400'000'000, - 987'654'321'987'654'321ULL)); + client.makeTransferEvent( + a1Address, transferContract.getAddress(), 400'000'000, + 987'654'321'987'654'321ULL)); } if (!useNativeAsset) {