From 3cc1aea0e30ca146e9f76a0d3d34cb3934e1d6ad Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 13 Oct 2026 11:37:32 +0000 Subject: [PATCH 01/15] update xdr and sdk crates for qualified spec names --- Cargo.lock | 146 +++++++--------- Cargo.toml | 52 ++++-- cmd/crates/soroban-spec-tools/src/contract.rs | 2 +- cmd/crates/soroban-spec-tools/src/event.rs | 2 +- cmd/crates/soroban-spec-tools/src/lib.rs | 6 +- .../tests/fixtures/bye/Cargo.toml | 2 +- .../tests/fixtures/hello/Cargo.toml | 2 +- .../tests/fixtures/test-wasms/auth/Cargo.toml | 2 +- .../test-wasms/constructor/Cargo.toml | 2 +- .../test-wasms/custom_account/Cargo.toml | 2 +- .../test-wasms/custom_type/Cargo.toml | 2 +- .../test-wasms/empty_constructor/Cargo.toml | 2 +- .../test-wasms/hello_world/Cargo.toml | 2 +- .../tests/fixtures/test-wasms/swap/Cargo.toml | 2 +- .../fixtures/test-wasms/token/Cargo.toml | 2 +- .../test-wasms/token_renamed/Cargo.toml | 2 +- .../workspace-with-qualified-names/Cargo.toml | 18 ++ .../contracts/names/Cargo.toml | 12 ++ .../contracts/names/src/lib.rs | 48 ++++++ cmd/crates/soroban-test/tests/it/build.rs | 109 +++++++++++- .../src/commands/contract/arg_parsing.rs | 12 +- .../src/commands/contract/build.rs | 160 +++++++++++++++--- .../src/commands/contract/info/interface.rs | 10 +- .../Cargo.toml.removeextension | 2 +- deny.toml | 14 +- 25 files changed, 466 insertions(+), 149 deletions(-) create mode 100644 cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml create mode 100644 cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/Cargo.toml create mode 100644 cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 6006a70278..530da71f1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1748,7 +1748,7 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "doc-gen" -version = "28.1.0" +version = "30.0.0" dependencies = [ "clap-markdown", "soroban-cli", @@ -5240,9 +5240,8 @@ dependencies = [ [[package]] name = "soroban-builtin-sdk-macros" -version = "28.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ffd329211a50add3965a8f4a8f70e24fc5c8268c945566ab963029b12dce40" +version = "29.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" dependencies = [ "itertools 0.13.0", "proc-macro2", @@ -5252,7 +5251,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "28.1.0" +version = "30.0.0" dependencies = [ "assert_fs", "async-compression", @@ -5332,9 +5331,8 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "28.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610bb12ee937a56c2b629f8eb16efb7e47607cba4e79ab0c24132b9a53dd19a0" +version = "29.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" dependencies = [ "arbitrary", "crate-git-revision 0.0.9", @@ -5351,9 +5349,8 @@ dependencies = [ [[package]] name = "soroban-env-guest" -version = "28.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d383176b27bb286f718ab0ff5713bd9b01132089151266359bd9b20f38684cf" +version = "29.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" dependencies = [ "soroban-env-common", "static_assertions", @@ -5361,9 +5358,8 @@ dependencies = [ [[package]] name = "soroban-env-host" -version = "28.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36d7e5920c200939164cc58038224e2d90d7e2fabbfa505d6e2129d648dce7e2" +version = "29.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -5398,9 +5394,8 @@ dependencies = [ [[package]] name = "soroban-env-macros" -version = "28.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "077600bb175ea54592c1ac5983b8fb34ec9ab7a65f298af11d687b61e9d646a4" +version = "29.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" dependencies = [ "itertools 0.13.0", "proc-macro2", @@ -5413,13 +5408,12 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "28.1.0" +version = "30.0.0" [[package]] name = "soroban-ledger-snapshot" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5caeb0a4c8af6d04dc1dfbf96199e0d50ae086c7d54c9001abe78bb891fc44f" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "serde", "serde_json", @@ -5429,11 +5423,20 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "soroban-meta" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +dependencies = [ + "stellar-xdr", + "thiserror 1.0.69", + "wasmparser 0.116.1", +] + [[package]] name = "soroban-sdk" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4946477e75667215a25b652b0febb446485686c944d364c117c903e3fb98bab" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "arbitrary", "bytes-lit", @@ -5443,21 +5446,23 @@ dependencies = [ "ed25519-dalek", "rand 0.8.7", "rustc_version", + "semver", "serde", "serde_json", "soroban-env-guest", "soroban-env-host", "soroban-ledger-snapshot", "soroban-sdk-macros", - "stellar-strkey 0.0.16", + "soroban-spec", + "stellar-strkey 0.0.18", + "stellar-xdr", "visibility", ] [[package]] name = "soroban-sdk-macros" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168f2d2c3fd4da57584c71e0a8315a8e656486495bc53e18c93b8ec4db085438" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "darling 0.20.11", "heck 0.5.0", @@ -5475,12 +5480,10 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f48c8e183fc140ccd89e1fe1663cc605fb18641967c0bb591f64887599fde59" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "base64 0.22.1", - "sha2 0.10.9", "stellar-xdr", "thiserror 1.0.69", "wasmparser 0.116.1", @@ -5488,14 +5491,14 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40cd0021887fd047e9f63cea36da35b202881bc0e0dbcc067a146137ca46f192" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "prettyplease", "proc-macro2", "quote", "sha2 0.10.9", + "soroban-meta", "soroban-spec", "stellar-xdr", "syn 2.0.118", @@ -5504,7 +5507,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "28.1.0" +version = "30.0.0" dependencies = [ "base64 0.21.7", "escape-bytes", @@ -5524,7 +5527,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "28.1.0" +version = "30.0.0" dependencies = [ "heck 0.4.1", "include_dir", @@ -5542,7 +5545,7 @@ dependencies = [ [[package]] name = "soroban-test" -version = "28.1.0" +version = "30.0.0" dependencies = [ "assert_cmd", "assert_fs", @@ -5580,18 +5583,16 @@ dependencies = [ [[package]] name = "soroban-token-sdk" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c9f00a6e59a79908624907924c2ecc037f6b3874cdca580e864b167d302a97" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "soroban-sdk", ] [[package]] name = "soroban-token-spec" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f3216ca17b7b8dd6d69311d3ec56eea68a37a96ba9bb6dbdea0f6b0c93a21ad" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -5600,8 +5601,7 @@ dependencies = [ [[package]] name = "soroban-wasmi" version = "0.31.1-soroban.20.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710403de32d0e0c35375518cb995d4fc056d0d48966f2e56ea471b8cb8fc9719" +source = "git+https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3dee30dc41ebe21972399e0a73a41944aa0" dependencies = [ "smallvec", "spin", @@ -5640,29 +5640,27 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-asset-spec" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f2d090d948334a7e69c0731b31f89c88f4aefa7465efbd9de9b24677065fb6" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" dependencies = [ "soroban-sdk", - "soroban-token-sdk", "soroban-token-spec", ] [[package]] name = "stellar-bye" -version = "28.1.0" +version = "30.0.0" [[package]] name = "stellar-cli" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "28.1.0" +version = "30.0.0" dependencies = [ "async-trait", "hex", @@ -5718,17 +5716,6 @@ dependencies = [ "data-encoding", ] -[[package]] -name = "stellar-strkey" -version = "0.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084afcb0d458c3d5d5baa2d294b18f881e62cc258ef539d8fdf68be7dbe45520" -dependencies = [ - "crate-git-revision 0.0.6", - "data-encoding", - "heapless 0.8.0", -] - [[package]] name = "stellar-strkey" version = "0.0.18" @@ -5749,8 +5736,7 @@ dependencies = [ [[package]] name = "stellar-xdr" version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d09ff8b9f919b084f664003c4c546ac66a76affd5429460dbe29f4b326f8e" +source = "git+https://github.com/stellar/rs-stellar-xdr?rev=e0d289adf4ad2483a10bcc8df743126974d77301#e0d289adf4ad2483a10bcc8df743126974d77301" dependencies = [ "arbitrary", "base64 0.22.1", @@ -6011,56 +5997,56 @@ dependencies = [ [[package]] name = "test_auth" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_constructor" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_account" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_types" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_empty_constructor" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_hello_world" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_swap" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_token" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -6068,14 +6054,14 @@ dependencies = [ [[package]] name = "test_token_renamed" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_udt" -version = "28.1.0" +version = "30.0.0" dependencies = [ "soroban-sdk", ] @@ -6940,15 +6926,13 @@ dependencies = [ [[package]] name = "wasmi_arena" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" +version = "0.4.0" +source = "git+https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3dee30dc41ebe21972399e0a73a41944aa0" [[package]] name = "wasmi_core" version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" +source = "git+https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3dee30dc41ebe21972399e0a73a41944aa0" dependencies = [ "downcast-rs", "libm", diff --git a/Cargo.toml b/Cargo.toml index a4e1970f5f..41cdf5d507 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,53 +21,68 @@ exclude = [ ] [workspace.package] -version = "28.1.0" +version = "30.0.0" rust-version = "1.93.0" # Dependencies located in this repo: [workspace.dependencies.soroban-cli] -version = "=28.1.0" +version = "=30.0.0" path = "cmd/soroban-cli" default-features = false [workspace.dependencies.soroban-spec-typescript] -version = "28.1.0" +version = "30.0.0" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "28.1.0" +version = "30.0.0" path = "./cmd/crates/soroban-spec-tools" [workspace.dependencies.stellar-ledger] -version = "=28.1.0" +version = "=30.0.0" path = "cmd/crates/stellar-ledger" # Dependencies from the rs-stellar-xdr repo: [workspace.dependencies.stellar-xdr] version = "28.0.0" -# Dependencies from the rs-stellar-env repo: +# Dependencies from the rs-soroban-env repo, pinned to the rev that the +# rs-soroban-sdk revision below uses, so that both share one soroban-env-host: [workspace.dependencies.soroban-env-host] -version = "28.0.2" +version = "=29.0.0" +git = "https://github.com/stellar/rs-soroban-env" +rev = "cb32250d926bd7188f3a6f9075bd48c44550dcac" -# Dependencies from the rs-soroban-sdk repo: +# Dependencies from the rs-soroban-sdk repo, pinned to a rev of main: [workspace.dependencies.soroban-spec] -version = "28.0.0" +version = "30.0.0" +git = "https://github.com/stellar/rs-soroban-sdk" +rev = "a2e51be61dc5c179595ba5b26da7da724e253886" [workspace.dependencies.soroban-spec-rust] -version = "28.0.0" +version = "30.0.0" +git = "https://github.com/stellar/rs-soroban-sdk" +rev = "a2e51be61dc5c179595ba5b26da7da724e253886" [workspace.dependencies.soroban-sdk] -version = "28.0.0" +version = "30.0.0" +git = "https://github.com/stellar/rs-soroban-sdk" +rev = "a2e51be61dc5c179595ba5b26da7da724e253886" [workspace.dependencies.soroban-token-sdk] -version = "28.0.0" +version = "30.0.0" +git = "https://github.com/stellar/rs-soroban-sdk" +rev = "a2e51be61dc5c179595ba5b26da7da724e253886" [workspace.dependencies.stellar-asset-spec] -version = "28.0.0" +version = "30.0.0" +git = "https://github.com/stellar/rs-soroban-sdk" +rev = "a2e51be61dc5c179595ba5b26da7da724e253886" [workspace.dependencies.soroban-ledger-snapshot] -version = "28.0.0" +version = "30.0.0" +git = "https://github.com/stellar/rs-soroban-sdk" +rev = "a2e51be61dc5c179595ba5b26da7da724e253886" # Dependencies from the rs-stellar-rpc-client repo: [workspace.dependencies.soroban-rpc] @@ -118,6 +133,15 @@ testcontainers = "0.27.2" httpmock = "0.7.0" astral-tokio-tar = "0.6.0" +[patch.crates-io] +# Pinned to a rev of rs-stellar-xdr main, pending a release containing the const +# XDR encoding and the widened user-defined type name limit that a fully +# qualified type name needs. This has to be a patch rather than a git revision on +# the dependency itself, because stellar-rpc-client is published and so brings +# its own stellar-xdr from crates.io, which only a patch redirects onto the same +# copy the rest of the graph uses. +stellar-xdr = { git = "https://github.com/stellar/rs-stellar-xdr", rev = "e0d289adf4ad2483a10bcc8df743126974d77301" } + [profile.release] overflow-checks = true diff --git a/cmd/crates/soroban-spec-tools/src/contract.rs b/cmd/crates/soroban-spec-tools/src/contract.rs index bf877dccc1..faa59260c5 100644 --- a/cmd/crates/soroban-spec-tools/src/contract.rs +++ b/cmd/crates/soroban-spec-tools/src/contract.rs @@ -316,7 +316,7 @@ fn indent(s: &str, n: usize) -> String { .join("\n") } -fn format_name(lib: &StringM<80>, name: &StringM<60>) -> String { +fn format_name(lib: &StringM<80>, name: &StringM<1024>) -> String { if lib.is_empty() { sanitize(&name.to_utf8_string_lossy()) } else { diff --git a/cmd/crates/soroban-spec-tools/src/event.rs b/cmd/crates/soroban-spec-tools/src/event.rs index 496cdb1ccf..3cd5fc1df6 100644 --- a/cmd/crates/soroban-spec-tools/src/event.rs +++ b/cmd/crates/soroban-spec-tools/src/event.rs @@ -294,7 +294,7 @@ mod tests { ScSpecEventV0 { doc: StringM::default(), lib: StringM::default(), - name: make_symbol(name), + name: name.try_into().unwrap(), prefix_topics: prefix_topics .into_iter() .map(make_symbol) diff --git a/cmd/crates/soroban-spec-tools/src/lib.rs b/cmd/crates/soroban-spec-tools/src/lib.rs index a3e1893a20..0a05202dd7 100644 --- a/cmd/crates/soroban-spec-tools/src/lib.rs +++ b/cmd/crates/soroban-spec-tools/src/lib.rs @@ -374,7 +374,7 @@ impl Spec { Ok(val) } - fn parse_udt(&self, name: &StringM<60>, value: &Value) -> Result { + fn parse_udt(&self, name: &StringM<1024>, value: &Value) -> Result { let name = &name.to_utf8_string_lossy(); match (self.find(name)?, value) { (ScSpecEntry::UdtStructV0(strukt), Value::Object(map)) => { @@ -687,7 +687,7 @@ impl Spec { /// # Panics /// /// May panic - pub fn udt_to_json(&self, name: &StringM<60>, sc_obj: &ScVal) -> Result { + pub fn udt_to_json(&self, name: &StringM<1024>, sc_obj: &ScVal) -> Result { let name = &name.to_utf8_string_lossy(); let udt = self.find(name)?; Ok(match (sc_obj, udt) { @@ -2456,7 +2456,7 @@ mod tests { ScSpecEventV0 { doc: StringM::default(), lib: StringM::default(), - name: ScSymbol(name.try_into().unwrap()), + name: name.try_into().unwrap(), prefix_topics: VecM::default(), params: VecM::default(), data_format: stellar_xdr::ScSpecEventDataFormat::SingleValue, diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml index 2fb527a0e7..1d6a5da00a 100644 --- a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stellar-bye" -version = "28.1.0" +version = "30.0.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index 47c736ce1d..a13a870f9b 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "28.1.0" +version = "30.0.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/auth/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/auth/Cargo.toml index c1525d84d2..294918b421 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/auth/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/auth/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_auth" -version = "28.1.0" +version = "30.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml index 1a62fe4797..2e5b111529 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_constructor" -version = "28.1.0" +version = "30.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index 7ca0cffdae..6421fbb081 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_account" -version = "28.1.0" +version = "30.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index 79c6917aa5..edb89274de 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_types" -version = "28.1.0" +version = "30.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/empty_constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/empty_constructor/Cargo.toml index 480bcf5ac9..1d0c196671 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/empty_constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/empty_constructor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_empty_constructor" -version = "28.1.0" +version = "30.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index 5f7a42d901..7b86d45d1e 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_hello_world" -version = "28.1.0" +version = "30.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml index 4d790bf80c..9d479af342 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_swap" -version = "28.1.0" +version = "30.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index 23cc948922..87af7bc976 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_token" -version = "28.1.0" +version = "30.0.0" description = "Soroban standard token contract" authors = ["Stellar Development Foundation "] license = "Apache-2.0" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token_renamed/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token_renamed/Cargo.toml index 87d6d7f806..26e7b83cf2 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token_renamed/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token_renamed/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_token_renamed" -version = "28.1.0" +version = "30.0.0" description = "A SEP-41-shaped token whose parameters use non-canonical names" authors = ["Stellar Development Foundation "] license = "Apache-2.0" diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml new file mode 100644 index 0000000000..1d89dbd6b4 --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml @@ -0,0 +1,18 @@ +[workspace] +resolver = "2" +members = [ + "contracts/*", +] + +[workspace.dependencies] +soroban-sdk = { git = "https://github.com/stellar/rs-soroban-sdk", rev = "a2e51be61dc5c179595ba5b26da7da724e253886" } + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/Cargo.toml new file mode 100644 index 0000000000..f5e1bbe92b --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "names" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/src/lib.rs new file mode 100644 index 0000000000..bd6def2f84 --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/contracts/names/src/lib.rs @@ -0,0 +1,48 @@ +#![no_std] +use soroban_sdk::{contract, contractevent, contractimpl, Env}; + +pub mod a { + use soroban_sdk::contracttype; + + #[contracttype] + pub struct State { + pub count: u32, + } +} + +pub mod b { + use soroban_sdk::contracttype; + + #[contracttype] + pub struct State { + pub enabled: bool, + } + + #[contracttype] + pub struct Wrapper { + pub state: State, + } +} + +#[contractevent] +pub struct Updated { + pub count: u32, +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn get_a(_env: Env, state: a::State) -> a::State { + state + } + + pub fn get_b(_env: Env, wrapper: b::Wrapper) -> b::State { + wrapper.state + } + + pub fn update(env: Env, count: u32) { + Updated { count }.publish(&env); + } +} diff --git a/cmd/crates/soroban-test/tests/it/build.rs b/cmd/crates/soroban-test/tests/it/build.rs index ffabfbe038..18c27dc6c8 100644 --- a/cmd/crates/soroban-test/tests/it/build.rs +++ b/cmd/crates/soroban-test/tests/it/build.rs @@ -512,7 +512,7 @@ fn filter_and_dedup_spec_removes_duplicates() { .unwrap(), }); - // Build markers for the struct so it passes the filter + // Build markers for the struct so it passes the markers filter let mut markers = std::collections::HashSet::new(); markers.insert(soroban_spec::shaking::generate_marker_for_entry( &used_struct, @@ -527,7 +527,8 @@ fn filter_and_dedup_spec_removes_duplicates() { used_struct.clone(), ]; - let result_xdr = filter_and_dedup_spec(entries, &markers).unwrap(); + let result_xdr = + filter_and_dedup_spec(entries, &markers, soroban_spec::shaking::Model::Markers).unwrap(); // Parse back the entries from the XDR let result_entries: Vec = @@ -554,11 +555,16 @@ fn filter_and_dedup_spec_removes_duplicates() { fn build_with_spec_shaking_has_feature_meta() { let (_spec, meta) = build_spec_shaking_fixture(); - let version = soroban_spec::shaking::spec_shaking_version_for_meta(&meta); + let model = soroban_spec::shaking::model_for_meta(&meta); + // The fixture builds against a published soroban-sdk, which records spec + // shaking version 2. The workspace's `[patch.crates-io]` does not reach a + // contract built in a temp dir, so this covers the markers rules end to + // end, and the SDK's own test contract covers the references rules. assert_eq!( - version, 2, - "contractmeta should indicate spec shaking version 2" + model, + soroban_spec::shaking::Model::Markers, + "contractmeta should select the markers model" ); } @@ -1348,3 +1354,96 @@ fn contract_archive_dirty_tree_errors() { "no archive should be written for a dirty tree" ); } + +#[test] +fn build_reduces_qualified_names_and_rewrites_references() { + let sandbox = TestEnv::default(); + let outdir = sandbox.dir().join("out"); + let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let fixture_path = cargo_dir.join("tests/fixtures/workspace-with-qualified-names"); + let temp = TempDir::new().unwrap(); + let dir_path = temp.path(); + fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap(); + let dir_path = dir_path.join("workspace-with-qualified-names"); + + // The two `State` types collide once reduced to their last segment, and the + // build warns about the one it numbers. + sandbox + .new_assert_cmd("contract") + .current_dir(&dir_path) + .arg("build") + .arg("--out-dir") + .arg(&outdir) + .assert() + .success() + .stderr(predicate::str::contains( + "names: reduced type and event names collided and were disambiguated with a numeric suffix:", + )) + .stderr(predicate::str::contains("::names::b::State -> State2")); + + let wasm = std::fs::read(dir_path.join(&outdir).join("names.wasm")).unwrap(); + let spec = Spec::new(&wasm).unwrap(); + + let udt = |name: &str| { + soroban_cli::xdr::ScSpecTypeDef::Udt(soroban_cli::xdr::ScSpecTypeUdt { + name: name.try_into().unwrap(), + }) + }; + + let mut structs = Vec::new(); + let mut events = Vec::new(); + let mut functions = Vec::new(); + for entry in &spec.spec { + match entry { + ScSpecEntry::UdtStructV0(s) => structs.push(( + s.name.to_utf8_string_lossy(), + s.fields.iter().map(|f| f.type_.clone()).collect::>(), + )), + ScSpecEntry::EventV0(e) => events.push(e.name.to_utf8_string_lossy()), + ScSpecEntry::FunctionV0(f) => functions.push(( + f.name.to_utf8_string_lossy(), + f.inputs.iter().map(|i| i.type_.clone()).collect::>(), + f.outputs.to_vec(), + )), + _ => {} + } + } + structs.sort_by(|a, b| a.0.cmp(&b.0)); + functions.sort_by(|a, b| a.0.cmp(&b.0)); + + // `a::State` sorts before `b::State` by its full name, so keeps the name, and + // `b::State` is numbered. Every name is reduced to its last segment. + assert_eq!( + structs, + [ + ( + "State".to_string(), + vec![soroban_cli::xdr::ScSpecTypeDef::U32] + ), + ( + "State2".to_string(), + vec![soroban_cli::xdr::ScSpecTypeDef::Bool] + ), + ("Wrapper".to_string(), vec![udt("State2")]), + ] + ); + assert_eq!(events, ["Updated"]); + + // The references in the functions are rewritten to the reduced names. + assert_eq!( + functions, + [ + ("get_a".to_string(), vec![udt("State")], vec![udt("State")]), + ( + "get_b".to_string(), + vec![udt("Wrapper")], + vec![udt("State2")] + ), + ( + "update".to_string(), + vec![soroban_cli::xdr::ScSpecTypeDef::U32], + vec![] + ), + ] + ); +} diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index 2951c7c40c..ad4c7ea3d6 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -1139,7 +1139,7 @@ mod tests { }; // Build a minimal Spec with a union type: enum MyEnum { Unit } - let union_name: StringM<60> = "MyEnum".try_into().unwrap(); + let union_name: StringM<1024> = "MyEnum".try_into().unwrap(); let case_name: StringM<60> = "Unit".try_into().unwrap(); let spec = Spec(Some(vec![ScSpecEntry::UdtUnionV0(ScSpecUdtUnionV0 { doc: StringM::default(), @@ -1188,7 +1188,7 @@ mod tests { ScSpecUdtUnionCaseV0, ScSpecUdtUnionCaseVoidV0, ScSpecUdtUnionV0, StringM, }; - let union_name: StringM<60> = "MyEnum".try_into().unwrap(); + let union_name: StringM<1024> = "MyEnum".try_into().unwrap(); let spec = Spec(Some(vec![ScSpecEntry::UdtUnionV0(ScSpecUdtUnionV0 { doc: StringM::default(), lib: StringM::default(), @@ -1236,7 +1236,7 @@ mod tests { ScSpecUdtUnionCaseV0, ScSpecUdtUnionV0, StringM, }; - let union_name: StringM<60> = "MyEnum".try_into().unwrap(); + let union_name: StringM<1024> = "MyEnum".try_into().unwrap(); let spec = Spec(Some(vec![ScSpecEntry::UdtUnionV0(ScSpecUdtUnionV0 { doc: StringM::default(), lib: StringM::default(), @@ -1296,7 +1296,7 @@ mod tests { use stellar_xdr::{ ScSpecEntry, ScSpecTypeUdt, ScSpecUdtStructFieldV0, ScSpecUdtStructV0, StringM, }; - let struct_name: StringM<60> = name.try_into().unwrap(); + let struct_name: StringM<1024> = name.try_into().unwrap(); let fields_xdr: Vec = fields .iter() .map(|(n, t)| ScSpecUdtStructFieldV0 { @@ -1430,7 +1430,7 @@ mod tests { ScSpecUdtUnionV0, StringM, }; - let union_name: StringM<60> = "Choice".try_into().unwrap(); + let union_name: StringM<1024> = "Choice".try_into().unwrap(); let spec = Spec(Some(vec![ScSpecEntry::UdtUnionV0(ScSpecUdtUnionV0 { doc: StringM::default(), lib: StringM::default(), @@ -1468,7 +1468,7 @@ mod tests { ScSpecUdtUnionV0, StringM, }; - let union_name: StringM<60> = "OneOf".try_into().unwrap(); + let union_name: StringM<1024> = "OneOf".try_into().unwrap(); let spec = Spec(Some(vec![ScSpecEntry::UdtUnionV0(ScSpecUdtUnionV0 { doc: StringM::default(), lib: StringM::default(), diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index e45e6def1d..3681559519 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -242,6 +242,9 @@ pub enum Error { #[error(transparent)] Xdr(#[from] stellar_xdr::Error), + #[error("{0}")] + ReduceSpec(String), + #[cfg(feature = "additional-libs")] #[error(transparent)] Optimize(#[from] optimize::Error), @@ -370,7 +373,9 @@ impl Cmd { } // Set env var to inform the SDK that this CLI supports spec - // optimization using markers. Current and new SDK versions no + // optimization. The var says only that this CLI shakes; which + // rules it shakes a given contract by comes from the model that + // contract's meta selects. Current and new SDK versions no // longer read this var, relying on the CLI version below // instead, but it must keep being set for past SDK versions that // require it. @@ -399,7 +404,10 @@ impl Cmd { .join(&file); self.inject_meta(&target_file_path)?; - Self::filter_spec(&target_file_path)?; + let model = Self::filter_spec(&target_file_path)?; + if model == soroban_spec::shaking::Model::References { + Self::reduce_spec(&print, &p.name, &target_file_path)?; + } let final_path = if let Some(out_dir) = &self.out_dir { fs::create_dir_all(out_dir).map_err(Error::CreatingOutDir)?; @@ -529,17 +537,19 @@ impl Cmd { fs::write(target_file_path, wasm_bytes).map_err(Error::WritingWasmFile) } - /// Filters unused types and events from the contract spec. - /// - /// This removes: - /// - Type definitions that are not referenced by any function - /// - Events that don't have corresponding markers in the WASM data section - /// (events that are defined but never published) + /// Filters unused types and events from the contract spec, and returns the + /// model the contract's spec is shaken by. /// - /// The SDK embeds markers in the data section for types/events that are - /// actually used. These markers survive dead code elimination, so we can - /// detect which spec entries are truly needed. - fn filter_spec(target_file_path: &PathBuf) -> Result<(), Error> { + /// The SDK that built the contract selects the model, which says which + /// entries carry a marker and so what a missing marker means. Read it from + /// the contract's meta and shake by its rules rather than the newest known: + /// a soroban-sdk v30 or later contract marks only the events it publishes + /// and the errors it panics with, and every other type is settled by + /// following the references to it, while a contract recording spec + /// shaking version 2 marks every used type, so markers alone say what is + /// used. Any other contract records nothing to shake by, and its spec is + /// left alone. + fn filter_spec(target_file_path: &PathBuf) -> Result { use soroban_spec_tools::contract::Spec; use soroban_spec_tools::wasm::replace_custom_section; @@ -548,23 +558,90 @@ impl Cmd { // Parse the spec from the wasm let spec = Spec::new(&wasm_bytes)?; - // Check if the contract meta indicates spec shaking v2 is enabled. - if soroban_spec::shaking::spec_shaking_version_for_meta(&spec.meta) != 2 { - return Ok(()); + // Read the model the contract is shaken by, which selects the rules + // below. Nothing to shake by under the none model, so leave it alone. + let model = soroban_spec::shaking::model_for_meta(&spec.meta); + if model == soroban_spec::shaking::Model::None { + return Ok(model); } // Extract markers from the WASM data section let markers = soroban_spec::shaking::find_all(&wasm_bytes); - // Filter spec entries (types, events) based on markers, and + // Filter spec entries (types, events) by that model's rules, and // deduplicate any exact duplicate entries. - let filtered_xdr = filter_and_dedup_spec(spec.spec.clone(), &markers)?; + let filtered_xdr = filter_and_dedup_spec(spec.spec.clone(), &markers, model)?; // Replace the contractspecv0 section with the filtered version let new_wasm = replace_custom_section(&wasm_bytes, "contractspecv0", &filtered_xdr) .map_err(|e| Error::WasmParsing(e.to_string()))?; // Write the modified wasm back + fs::remove_file(target_file_path).map_err(Error::DeletingArtifact)?; + fs::write(target_file_path, new_wasm).map_err(Error::WritingWasmFile)?; + Ok(model) + } + + /// Reduces user-defined type names in the contract spec to their simple + /// form, rewriting the `contractspecv0` section in place. + /// + /// Contract specs may name user-defined types by their fully qualified path + /// (e.g. `my_contract::inner::State`). This follows each to its simple name + /// (e.g. `State`), rewriting every reference, so the on-chain spec and every + /// downstream tool see the short names. Names that would collide are + /// disambiguated with a numeric suffix, which is warned about. + /// + /// Runs only for contracts shaken by the references model, the soroban-sdk + /// v30 or later contracts whose specs name types by their fully qualified + /// path, and after `filter_spec` so only the entries that survive shaking + /// are reduced. + fn reduce_spec(print: &Print, name: &str, target_file_path: &PathBuf) -> Result<(), Error> { + use soroban_spec_tools::contract::Spec; + use soroban_spec_tools::wasm::replace_custom_section; + + let wasm_bytes = fs::read(target_file_path).map_err(Error::ReadingWasmFile)?; + let spec = Spec::new(&wasm_bytes)?; + + // The error names entries of the spec, so sanitize it before it is + // printed, as the spec is untrusted input. + let reduced = soroban_spec::reduce::reduce(&spec.spec) + .map_err(|e| Error::ReduceSpec(sanitize(&e.to_string())))?; + + // If every name was already simple, leave the wasm untouched. + if reduced.renames().all(|r| !r.renamed()) { + return Ok(()); + } + + let collisions: Vec<_> = reduced.renames().filter(|r| r.collision()).collect(); + if !collisions.is_empty() { + use std::fmt::Write as _; + let mut msg = format!( + "{name}: reduced type and event names collided and were disambiguated with a numeric suffix:" + ); + for rename in collisions { + let _ = write!( + msg, + "\n {} -> {}", + sanitize(&String::from_utf8_lossy(&rename.from)), + sanitize(&String::from_utf8_lossy(&rename.to)), + ); + } + print.warnln(msg); + } + + // Encode the reduced entries and replace the contractspecv0 section. + let mut reduced_xdr = Vec::new(); + let mut writer = Limited::new( + Cursor::new(&mut reduced_xdr), + Limits::depth(XDR_DEPTH_LIMIT), + ); + for entry in reduced.into_entries() { + entry.write_xdr(&mut writer)?; + } + + let new_wasm = replace_custom_section(&wasm_bytes, "contractspecv0", &reduced_xdr) + .map_err(|e| Error::WasmParsing(e.to_string()))?; + fs::remove_file(target_file_path).map_err(Error::DeletingArtifact)?; fs::write(target_file_path, new_wasm).map_err(Error::WritingWasmFile) } @@ -895,15 +972,17 @@ fn check_overflow_checks(doc: &toml_edit::DocumentMut, profile: &str) -> Result< } } -/// Filters spec entries based on markers and deduplicates exact duplicates. +/// Filters spec entries down to those the contract needs, by the rules of the +/// model its spec is shaken by, and deduplicates exact duplicates. /// -/// Functions are always kept. Other entries (types, events) are kept only if a -/// matching marker exists. Exact duplicate entries (identical XDR) are collapsed +/// Which entries survive is decided by `soroban_spec::shaking::filter` for the +/// given model. Exact duplicate entries (identical XDR) are then collapsed /// to a single occurrence. #[allow(clippy::implicit_hasher)] pub fn filter_and_dedup_spec( entries: Vec, markers: &HashSet, + model: soroban_spec::shaking::Model, ) -> Result, Error> { let mut seen = HashSet::new(); let mut filtered_xdr = Vec::new(); @@ -911,7 +990,7 @@ pub fn filter_and_dedup_spec( Cursor::new(&mut filtered_xdr), Limits::depth(XDR_DEPTH_LIMIT), ); - for entry in soroban_spec::shaking::filter(entries, markers) { + for entry in soroban_spec::shaking::filter(entries, markers, model) { let entry_xdr = entry.to_xdr(Limits::depth(XDR_DEPTH_LIMIT))?; if seen.insert(entry_xdr) { entry.write_xdr(&mut writer)?; @@ -970,6 +1049,45 @@ mod tests { assert!(Cmd::try_parse_from(["build", "--pull"]).is_err()); } + #[test] + fn reduce_spec_shortens_qualified_names_in_wasm() { + use soroban_spec_tools::contract::Spec; + use soroban_spec_tools::wasm::replace_custom_section; + use stellar_xdr::{ScSpecEntry, ScSpecUdtStructV0, VecM}; + + // A spec with a single struct whose name is fully qualified. + let entry = ScSpecEntry::UdtStructV0(ScSpecUdtStructV0 { + doc: StringM::default(), + lib: StringM::default(), + name: "mycrate::mymod::MyType".to_string().try_into().unwrap(), + fields: VecM::default(), + }); + let mut spec_xdr = Vec::new(); + entry + .write_xdr(&mut Limited::new( + Cursor::new(&mut spec_xdr), + Limits::depth(XDR_DEPTH_LIMIT), + )) + .unwrap(); + + // Embed the spec in a minimal (empty) wasm module and write it out. + let wasm = replace_custom_section(b"\0asm\x01\0\0\0", "contractspecv0", &spec_xdr).unwrap(); + let path = env::temp_dir().join(format!("reduce_spec_test_{}.wasm", std::process::id())); + fs::write(&path, &wasm).unwrap(); + + Cmd::reduce_spec(&Print::new(true), "pkg", &path).unwrap(); + + let out = fs::read(&path).unwrap(); + fs::remove_file(&path).ok(); + let spec = Spec::new(&out).unwrap(); + + assert_eq!(spec.spec.len(), 1); + let ScSpecEntry::UdtStructV0(s) = &spec.spec[0] else { + panic!("expected a struct entry, got {:?}", spec.spec[0]); + }; + assert_eq!(s.name.to_vec(), b"MyType".to_vec()); + } + #[test] fn serialize_command_shell_escapes_args_with_metacharacters() { let raw_arg = "--manifest-path=/path/to/contract;touch PWNED;#/Cargo.toml"; diff --git a/cmd/soroban-cli/src/commands/contract/info/interface.rs b/cmd/soroban-cli/src/commands/contract/info/interface.rs index a2dfa1de38..980e4eabfe 100644 --- a/cmd/soroban-cli/src/commands/contract/info/interface.rs +++ b/cmd/soroban-cli/src/commands/contract/info/interface.rs @@ -50,7 +50,7 @@ impl Cmd { let print = Print::new(global_args.quiet); let Fetched { contract, .. } = fetch(&self.common, &print).await?; - let (base64, spec) = match contract { + let (base64, spec, sdk_major_version) = match contract { shared::Contract::Wasm { wasm_bytes } => { let spec = Spec::new(&wasm_bytes)?; @@ -58,10 +58,12 @@ impl Cmd { return Err(NoInterfacePresent()); } - (spec.spec_base64.unwrap(), spec.spec) + let sdk_major_version = soroban_spec_rust::sdk_major_version_from_meta(&spec.meta); + (spec.spec_base64.unwrap(), spec.spec, sdk_major_version) } shared::Contract::StellarAssetContract => { - Spec::spec_to_base64(stellar_asset_spec::xdr())? + let (base64, spec) = Spec::spec_to_base64(stellar_asset_spec::xdr())?; + (base64, spec, None) } }; @@ -75,7 +77,7 @@ impl Cmd { // emitting spec strings as `Literal::string` or rustdocs, this // path becomes a terminal-escape-injection vector and must be // sanitized before printing. - InfoOutput::Rust => soroban_spec_rust::generate_without_file(&spec)? + InfoOutput::Rust => soroban_spec_rust::generate_without_file(&spec, sdk_major_version)? .to_formatted_string() .expect("Unexpected spec format error"), }; diff --git a/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension b/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension index 27fc38e124..1b2b2b1ea3 100644 --- a/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension +++ b/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension @@ -5,7 +5,7 @@ members = [ ] [workspace.dependencies] -soroban-sdk = "28" +soroban-sdk = "30" [profile.release] opt-level = "z" diff --git a/deny.toml b/deny.toml index f7396708ce..31ea88c715 100644 --- a/deny.toml +++ b/deny.toml @@ -230,7 +230,19 @@ allow-registry = ["https://github.com/rust-lang/crates.io-index"] # List of URLs for allowed Git repositories allow-git = [ # Only used by the unpublished doc-gen crate, temporarily until PR is merged: https://github.com/ConnorGray/clap-markdown/pull/48 - "https://github.com/ConnorGray/clap-markdown?rev=42956b342cef3325d9060fc43995d595e7c8aa66" + "https://github.com/ConnorGray/clap-markdown?rev=42956b342cef3325d9060fc43995d595e7c8aa66", + + # Temporary pins, remove once released: + # rs-stellar-xdr main, which widens the user-defined type name limit so a + # fully qualified type name fits. + "https://github.com/stellar/rs-stellar-xdr?rev=e0d289adf4ad2483a10bcc8df743126974d77301", + # rs-soroban-sdk main, which names user-defined types in contract specs by + # their fully qualified path. + "https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886", + # The rs-soroban-env rev that rs-soroban-sdk main uses, and the git + # dependencies of the env it brings in. + "https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac", + "https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0", ] [sources.allow-org] From 773ce64824b6624d8b60130cce4de7a52a205601 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 13 Oct 2026 12:11:21 +0000 Subject: [PATCH 02/15] run quickstart on protocol 29 in ci --- .github/workflows/bindings-ts.yml | 2 +- .github/workflows/ledger-emulator.yml | 2 +- .github/workflows/rpc-tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index 7f5ae7bf1b..8207598079 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -27,7 +27,7 @@ jobs: - uses: stellar/quickstart@main with: tag: latest - protocol_version: 28 + protocol_version: 29 - uses: actions/setup-node@v7.0.0 with: node-version: "20.x" diff --git a/.github/workflows/ledger-emulator.yml b/.github/workflows/ledger-emulator.yml index 6a449775eb..85aa56c071 100644 --- a/.github/workflows/ledger-emulator.yml +++ b/.github/workflows/ledger-emulator.yml @@ -37,7 +37,7 @@ jobs: - uses: stellar/quickstart@main with: tag: latest - protocol_version: 28 + protocol_version: 29 - uses: actions/checkout@v7 - uses: stellar/actions/rust-cache@main diff --git a/.github/workflows/rpc-tests.yml b/.github/workflows/rpc-tests.yml index d01c849211..ad7b1ef51e 100644 --- a/.github/workflows/rpc-tests.yml +++ b/.github/workflows/rpc-tests.yml @@ -34,7 +34,7 @@ jobs: - uses: stellar/quickstart@main with: tag: latest - protocol_version: 28 + protocol_version: 29 - uses: actions/checkout@v7 - uses: stellar/actions/rust-cache@main - run: rustup update From 45d876cc5cedd8b9007adbf683eee4f11b66b36d Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 13 Oct 2026 13:27:09 +0000 Subject: [PATCH 03/15] decide whether to filter spec outside filter_spec --- .../src/commands/contract/build.rs | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index 3681559519..cc0fdc2583 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -404,7 +404,10 @@ impl Cmd { .join(&file); self.inject_meta(&target_file_path)?; - let model = Self::filter_spec(&target_file_path)?; + let model = Self::spec_shaking_model(&target_file_path)?; + if model != soroban_spec::shaking::Model::None { + Self::filter_spec(&target_file_path)?; + } if model == soroban_spec::shaking::Model::References { Self::reduce_spec(&print, &p.name, &target_file_path)?; } @@ -537,8 +540,18 @@ impl Cmd { fs::write(target_file_path, wasm_bytes).map_err(Error::WritingWasmFile) } - /// Filters unused types and events from the contract spec, and returns the - /// model the contract's spec is shaken by. + /// Reads the model the contract's spec is shaken by from its meta. + fn spec_shaking_model( + target_file_path: &PathBuf, + ) -> Result { + use soroban_spec_tools::contract::Spec; + + let wasm_bytes = fs::read(target_file_path).map_err(Error::ReadingWasmFile)?; + let spec = Spec::new(&wasm_bytes)?; + Ok(soroban_spec::shaking::model_for_meta(&spec.meta)) + } + + /// Filters unused types and events from the contract spec. /// /// The SDK that built the contract selects the model, which says which /// entries carry a marker and so what a missing marker means. Read it from @@ -547,9 +560,9 @@ impl Cmd { /// and the errors it panics with, and every other type is settled by /// following the references to it, while a contract recording spec /// shaking version 2 marks every used type, so markers alone say what is - /// used. Any other contract records nothing to shake by, and its spec is - /// left alone. - fn filter_spec(target_file_path: &PathBuf) -> Result { + /// used. Any other contract records nothing to shake by, and is not + /// filtered. + fn filter_spec(target_file_path: &PathBuf) -> Result<(), Error> { use soroban_spec_tools::contract::Spec; use soroban_spec_tools::wasm::replace_custom_section; @@ -559,11 +572,8 @@ impl Cmd { let spec = Spec::new(&wasm_bytes)?; // Read the model the contract is shaken by, which selects the rules - // below. Nothing to shake by under the none model, so leave it alone. + // below. let model = soroban_spec::shaking::model_for_meta(&spec.meta); - if model == soroban_spec::shaking::Model::None { - return Ok(model); - } // Extract markers from the WASM data section let markers = soroban_spec::shaking::find_all(&wasm_bytes); @@ -578,8 +588,7 @@ impl Cmd { // Write the modified wasm back fs::remove_file(target_file_path).map_err(Error::DeletingArtifact)?; - fs::write(target_file_path, new_wasm).map_err(Error::WritingWasmFile)?; - Ok(model) + fs::write(target_file_path, new_wasm).map_err(Error::WritingWasmFile) } /// Reduces user-defined type names in the contract spec to their simple From 2f94acfc565300cf53331bacd0382be67241595f Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 13 Oct 2026 15:13:21 +0000 Subject: [PATCH 04/15] filter and reduce spec in memory and write once --- cmd/crates/soroban-test/tests/it/build.rs | 10 +- .../src/commands/contract/build.rs | 163 +++++++----------- 2 files changed, 61 insertions(+), 112 deletions(-) diff --git a/cmd/crates/soroban-test/tests/it/build.rs b/cmd/crates/soroban-test/tests/it/build.rs index 18c27dc6c8..dab3fe1532 100644 --- a/cmd/crates/soroban-test/tests/it/build.rs +++ b/cmd/crates/soroban-test/tests/it/build.rs @@ -482,7 +482,7 @@ fn build_with_spec_shaking_preserves_all_functions() { fn filter_and_dedup_spec_removes_duplicates() { use soroban_cli::commands::contract::build::filter_and_dedup_spec; use soroban_cli::xdr::{ - ReadXdr, ScSpecEntry, ScSpecFunctionInputV0, ScSpecFunctionV0, ScSpecTypeDef, + ScSpecEntry, ScSpecFunctionInputV0, ScSpecFunctionV0, ScSpecTypeDef, ScSpecUdtStructFieldV0, ScSpecUdtStructV0, StringM, VecM, }; @@ -527,15 +527,9 @@ fn filter_and_dedup_spec_removes_duplicates() { used_struct.clone(), ]; - let result_xdr = + let result_entries = filter_and_dedup_spec(entries, &markers, soroban_spec::shaking::Model::Markers).unwrap(); - // Parse back the entries from the XDR - let result_entries: Vec = - ScSpecEntry::read_xdr_iter(&mut Limited::new(Cursor::new(result_xdr), Limits::none())) - .collect::, _>>() - .unwrap(); - // Should have exactly 1 function + 1 struct, no duplicates assert_eq!( result_entries.len(), diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index cc0fdc2583..16e4e0afb8 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -404,12 +404,15 @@ impl Cmd { .join(&file); self.inject_meta(&target_file_path)?; - let model = Self::spec_shaking_model(&target_file_path)?; + let wasm_bytes = fs::read(&target_file_path).map_err(Error::ReadingWasmFile)?; + let spec = soroban_spec_tools::contract::Spec::new(&wasm_bytes)?; + let model = soroban_spec::shaking::model_for_meta(&spec.meta); if model != soroban_spec::shaking::Model::None { - Self::filter_spec(&target_file_path)?; - } - if model == soroban_spec::shaking::Model::References { - Self::reduce_spec(&print, &p.name, &target_file_path)?; + let mut entries = Self::filter_spec(&wasm_bytes, spec.spec, model)?; + if model == soroban_spec::shaking::Model::References { + entries = Self::reduce_spec(&print, &p.name, &entries)?; + } + Self::write_spec(&target_file_path, &wasm_bytes, entries)?; } let final_path = if let Some(out_dir) = &self.out_dir { @@ -540,59 +543,32 @@ impl Cmd { fs::write(target_file_path, wasm_bytes).map_err(Error::WritingWasmFile) } - /// Reads the model the contract's spec is shaken by from its meta. - fn spec_shaking_model( - target_file_path: &PathBuf, - ) -> Result { - use soroban_spec_tools::contract::Spec; - - let wasm_bytes = fs::read(target_file_path).map_err(Error::ReadingWasmFile)?; - let spec = Spec::new(&wasm_bytes)?; - Ok(soroban_spec::shaking::model_for_meta(&spec.meta)) - } - - /// Filters unused types and events from the contract spec. + /// Filters unused types and events from the contract spec entries by the + /// rules of the given model. /// /// The SDK that built the contract selects the model, which says which - /// entries carry a marker and so what a missing marker means. Read it from - /// the contract's meta and shake by its rules rather than the newest known: - /// a soroban-sdk v30 or later contract marks only the events it publishes - /// and the errors it panics with, and every other type is settled by - /// following the references to it, while a contract recording spec - /// shaking version 2 marks every used type, so markers alone say what is - /// used. Any other contract records nothing to shake by, and is not - /// filtered. - fn filter_spec(target_file_path: &PathBuf) -> Result<(), Error> { - use soroban_spec_tools::contract::Spec; - use soroban_spec_tools::wasm::replace_custom_section; - - let wasm_bytes = fs::read(target_file_path).map_err(Error::ReadingWasmFile)?; - - // Parse the spec from the wasm - let spec = Spec::new(&wasm_bytes)?; - - // Read the model the contract is shaken by, which selects the rules - // below. - let model = soroban_spec::shaking::model_for_meta(&spec.meta); - + /// entries carry a marker and so what a missing marker means. Shake by its + /// rules rather than the newest known: a soroban-sdk v30 or later contract + /// marks only the events it publishes and the errors it panics with, and + /// every other type is settled by following the references to it, while a + /// contract recording spec shaking version 2 marks every used type, so + /// markers alone say what is used. Any other contract records nothing to + /// shake by, and is not filtered. + fn filter_spec( + wasm_bytes: &[u8], + entries: Vec, + model: soroban_spec::shaking::Model, + ) -> Result, Error> { // Extract markers from the WASM data section - let markers = soroban_spec::shaking::find_all(&wasm_bytes); + let markers = soroban_spec::shaking::find_all(wasm_bytes); // Filter spec entries (types, events) by that model's rules, and // deduplicate any exact duplicate entries. - let filtered_xdr = filter_and_dedup_spec(spec.spec.clone(), &markers, model)?; - - // Replace the contractspecv0 section with the filtered version - let new_wasm = replace_custom_section(&wasm_bytes, "contractspecv0", &filtered_xdr) - .map_err(|e| Error::WasmParsing(e.to_string()))?; - - // Write the modified wasm back - fs::remove_file(target_file_path).map_err(Error::DeletingArtifact)?; - fs::write(target_file_path, new_wasm).map_err(Error::WritingWasmFile) + filter_and_dedup_spec(entries, &markers, model) } - /// Reduces user-defined type names in the contract spec to their simple - /// form, rewriting the `contractspecv0` section in place. + /// Reduces user-defined type names in the contract spec entries to their + /// simple form. /// /// Contract specs may name user-defined types by their fully qualified path /// (e.g. `my_contract::inner::State`). This follows each to its simple name @@ -604,23 +580,16 @@ impl Cmd { /// v30 or later contracts whose specs name types by their fully qualified /// path, and after `filter_spec` so only the entries that survive shaking /// are reduced. - fn reduce_spec(print: &Print, name: &str, target_file_path: &PathBuf) -> Result<(), Error> { - use soroban_spec_tools::contract::Spec; - use soroban_spec_tools::wasm::replace_custom_section; - - let wasm_bytes = fs::read(target_file_path).map_err(Error::ReadingWasmFile)?; - let spec = Spec::new(&wasm_bytes)?; - + fn reduce_spec( + print: &Print, + name: &str, + entries: &[stellar_xdr::ScSpecEntry], + ) -> Result, Error> { // The error names entries of the spec, so sanitize it before it is // printed, as the spec is untrusted input. - let reduced = soroban_spec::reduce::reduce(&spec.spec) + let reduced = soroban_spec::reduce::reduce(entries) .map_err(|e| Error::ReduceSpec(sanitize(&e.to_string())))?; - // If every name was already simple, leave the wasm untouched. - if reduced.renames().all(|r| !r.renamed()) { - return Ok(()); - } - let collisions: Vec<_> = reduced.renames().filter(|r| r.collision()).collect(); if !collisions.is_empty() { use std::fmt::Write as _; @@ -638,17 +607,25 @@ impl Cmd { print.warnln(msg); } - // Encode the reduced entries and replace the contractspecv0 section. - let mut reduced_xdr = Vec::new(); - let mut writer = Limited::new( - Cursor::new(&mut reduced_xdr), - Limits::depth(XDR_DEPTH_LIMIT), - ); - for entry in reduced.into_entries() { + Ok(reduced.into_entries().collect()) + } + + /// Encodes the spec entries, replaces the `contractspecv0` section of the + /// wasm with them, and writes the wasm. + fn write_spec( + target_file_path: &PathBuf, + wasm_bytes: &[u8], + entries: Vec, + ) -> Result<(), Error> { + use soroban_spec_tools::wasm::replace_custom_section; + + let mut spec_xdr = Vec::new(); + let mut writer = Limited::new(Cursor::new(&mut spec_xdr), Limits::depth(XDR_DEPTH_LIMIT)); + for entry in entries { entry.write_xdr(&mut writer)?; } - let new_wasm = replace_custom_section(&wasm_bytes, "contractspecv0", &reduced_xdr) + let new_wasm = replace_custom_section(wasm_bytes, "contractspecv0", &spec_xdr) .map_err(|e| Error::WasmParsing(e.to_string()))?; fs::remove_file(target_file_path).map_err(Error::DeletingArtifact)?; @@ -992,20 +969,16 @@ pub fn filter_and_dedup_spec( entries: Vec, markers: &HashSet, model: soroban_spec::shaking::Model, -) -> Result, Error> { +) -> Result, Error> { let mut seen = HashSet::new(); - let mut filtered_xdr = Vec::new(); - let mut writer = Limited::new( - Cursor::new(&mut filtered_xdr), - Limits::depth(XDR_DEPTH_LIMIT), - ); + let mut filtered = Vec::new(); for entry in soroban_spec::shaking::filter(entries, markers, model) { let entry_xdr = entry.to_xdr(Limits::depth(XDR_DEPTH_LIMIT))?; if seen.insert(entry_xdr) { - entry.write_xdr(&mut writer)?; + filtered.push(entry); } } - Ok(filtered_xdr) + Ok(filtered) } #[cfg(test)] @@ -1059,9 +1032,7 @@ mod tests { } #[test] - fn reduce_spec_shortens_qualified_names_in_wasm() { - use soroban_spec_tools::contract::Spec; - use soroban_spec_tools::wasm::replace_custom_section; + fn reduce_spec_shortens_qualified_names() { use stellar_xdr::{ScSpecEntry, ScSpecUdtStructV0, VecM}; // A spec with a single struct whose name is fully qualified. @@ -1071,28 +1042,12 @@ mod tests { name: "mycrate::mymod::MyType".to_string().try_into().unwrap(), fields: VecM::default(), }); - let mut spec_xdr = Vec::new(); - entry - .write_xdr(&mut Limited::new( - Cursor::new(&mut spec_xdr), - Limits::depth(XDR_DEPTH_LIMIT), - )) - .unwrap(); - - // Embed the spec in a minimal (empty) wasm module and write it out. - let wasm = replace_custom_section(b"\0asm\x01\0\0\0", "contractspecv0", &spec_xdr).unwrap(); - let path = env::temp_dir().join(format!("reduce_spec_test_{}.wasm", std::process::id())); - fs::write(&path, &wasm).unwrap(); - - Cmd::reduce_spec(&Print::new(true), "pkg", &path).unwrap(); - - let out = fs::read(&path).unwrap(); - fs::remove_file(&path).ok(); - let spec = Spec::new(&out).unwrap(); - - assert_eq!(spec.spec.len(), 1); - let ScSpecEntry::UdtStructV0(s) = &spec.spec[0] else { - panic!("expected a struct entry, got {:?}", spec.spec[0]); + + let entries = Cmd::reduce_spec(&Print::new(true), "pkg", &[entry]).unwrap(); + + assert_eq!(entries.len(), 1); + let ScSpecEntry::UdtStructV0(s) = &entries[0] else { + panic!("expected a struct entry, got {:?}", entries[0]); }; assert_eq!(s.name.to_vec(), b"MyType".to_vec()); } From 86159f54121d8627e86bc6972b94165cad379288 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 13 Oct 2026 15:18:27 +0000 Subject: [PATCH 05/15] inline filter_spec into its call site --- .../src/commands/contract/build.rs | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index 16e4e0afb8..7d11cb82e0 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -406,9 +406,21 @@ impl Cmd { self.inject_meta(&target_file_path)?; let wasm_bytes = fs::read(&target_file_path).map_err(Error::ReadingWasmFile)?; let spec = soroban_spec_tools::contract::Spec::new(&wasm_bytes)?; + // The SDK that built the contract selects the model, which says + // which entries carry a marker and so what a missing marker + // means. Shake by its rules rather than the newest known: a + // soroban-sdk v30 or later contract marks only the events it + // publishes and the errors it panics with, and every other type + // is settled by following the references to it, while a + // contract recording spec shaking version 2 marks every used + // type, so markers alone say what is used. Any other contract + // records nothing to shake by, and is not filtered. let model = soroban_spec::shaking::model_for_meta(&spec.meta); if model != soroban_spec::shaking::Model::None { - let mut entries = Self::filter_spec(&wasm_bytes, spec.spec, model)?; + // Filter unused types and events by that model's rules, and + // deduplicate any exact duplicate entries. + let markers = soroban_spec::shaking::find_all(&wasm_bytes); + let mut entries = filter_and_dedup_spec(spec.spec, &markers, model)?; if model == soroban_spec::shaking::Model::References { entries = Self::reduce_spec(&print, &p.name, &entries)?; } @@ -543,30 +555,6 @@ impl Cmd { fs::write(target_file_path, wasm_bytes).map_err(Error::WritingWasmFile) } - /// Filters unused types and events from the contract spec entries by the - /// rules of the given model. - /// - /// The SDK that built the contract selects the model, which says which - /// entries carry a marker and so what a missing marker means. Shake by its - /// rules rather than the newest known: a soroban-sdk v30 or later contract - /// marks only the events it publishes and the errors it panics with, and - /// every other type is settled by following the references to it, while a - /// contract recording spec shaking version 2 marks every used type, so - /// markers alone say what is used. Any other contract records nothing to - /// shake by, and is not filtered. - fn filter_spec( - wasm_bytes: &[u8], - entries: Vec, - model: soroban_spec::shaking::Model, - ) -> Result, Error> { - // Extract markers from the WASM data section - let markers = soroban_spec::shaking::find_all(wasm_bytes); - - // Filter spec entries (types, events) by that model's rules, and - // deduplicate any exact duplicate entries. - filter_and_dedup_spec(entries, &markers, model) - } - /// Reduces user-defined type names in the contract spec entries to their /// simple form. /// @@ -578,7 +566,7 @@ impl Cmd { /// /// Runs only for contracts shaken by the references model, the soroban-sdk /// v30 or later contracts whose specs name types by their fully qualified - /// path, and after `filter_spec` so only the entries that survive shaking + /// path, and after filtering so only the entries that survive shaking /// are reduced. fn reduce_spec( print: &Print, From 140bc42350ade21d9ea90f763327519212eb6326 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:12:38 +0000 Subject: [PATCH 06/15] mention sdk type names in reduce collision warning --- cmd/crates/soroban-test/tests/it/build.rs | 2 +- cmd/soroban-cli/src/commands/contract/build.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/crates/soroban-test/tests/it/build.rs b/cmd/crates/soroban-test/tests/it/build.rs index dab3fe1532..1301d87352 100644 --- a/cmd/crates/soroban-test/tests/it/build.rs +++ b/cmd/crates/soroban-test/tests/it/build.rs @@ -1371,7 +1371,7 @@ fn build_reduces_qualified_names_and_rewrites_references() { .assert() .success() .stderr(predicate::str::contains( - "names: reduced type and event names collided and were disambiguated with a numeric suffix:", + "names: reduced type and event names collided with each other or with SDK type names and were disambiguated with a numeric suffix:", )) .stderr(predicate::str::contains("::names::b::State -> State2")); diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index 7d11cb82e0..3165ed681a 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -562,7 +562,8 @@ impl Cmd { /// (e.g. `my_contract::inner::State`). This follows each to its simple name /// (e.g. `State`), rewriting every reference, so the on-chain spec and every /// downstream tool see the short names. Names that would collide are - /// disambiguated with a numeric suffix, which is warned about. + /// disambiguated with a numeric suffix, which is warned about. A name also + /// counts as colliding when it is the name of an SDK type. /// /// Runs only for contracts shaken by the references model, the soroban-sdk /// v30 or later contracts whose specs name types by their fully qualified @@ -582,7 +583,7 @@ impl Cmd { if !collisions.is_empty() { use std::fmt::Write as _; let mut msg = format!( - "{name}: reduced type and event names collided and were disambiguated with a numeric suffix:" + "{name}: reduced type and event names collided with each other or with SDK type names and were disambiguated with a numeric suffix:" ); for rename in collisions { let _ = write!( From 5bc663dcf0bb67ea9fc29d23d0471598708eb1fb Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 14 Oct 2026 16:12:39 +0000 Subject: [PATCH 07/15] suggest lto setting when reduced spec has undefined names --- .../src/commands/contract/build.rs | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index 3165ed681a..d165b70389 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -422,7 +422,7 @@ impl Cmd { let markers = soroban_spec::shaking::find_all(&wasm_bytes); let mut entries = filter_and_dedup_spec(spec.spec, &markers, model)?; if model == soroban_spec::shaking::Model::References { - entries = Self::reduce_spec(&print, &p.name, &entries)?; + entries = Self::reduce_spec(&print, &p.name, &self.profile, &entries)?; } Self::write_spec(&target_file_path, &wasm_bytes, entries)?; } @@ -572,12 +572,23 @@ impl Cmd { fn reduce_spec( print: &Print, name: &str, + profile: &str, entries: &[stellar_xdr::ScSpecEntry], ) -> Result, Error> { // The error names entries of the spec, so sanitize it before it is // printed, as the spec is untrusted input. - let reduced = soroban_spec::reduce::reduce(entries) - .map_err(|e| Error::ReduceSpec(sanitize(&e.to_string())))?; + let reduced = soroban_spec::reduce::reduce(entries).map_err(|e| { + let mut msg = sanitize(&e.to_string()); + // An entry the spec refers to but does not define is commonly + // caused by building without link-time optimization. + if matches!(e, soroban_spec::reduce::Error::UndefinedName(_)) { + msg = format!( + "{msg}. Check that [profile.{profile}] in the Cargo.toml does not have \ + `lto` disabled, it should be set to \"thin\" or \"fat\"." + ); + } + Error::ReduceSpec(msg) + })?; let collisions: Vec<_> = reduced.renames().filter(|r| r.collision()).collect(); if !collisions.is_empty() { @@ -1032,7 +1043,7 @@ mod tests { fields: VecM::default(), }); - let entries = Cmd::reduce_spec(&Print::new(true), "pkg", &[entry]).unwrap(); + let entries = Cmd::reduce_spec(&Print::new(true), "pkg", "release", &[entry]).unwrap(); assert_eq!(entries.len(), 1); let ScSpecEntry::UdtStructV0(s) = &entries[0] else { @@ -1041,6 +1052,37 @@ mod tests { assert_eq!(s.name.to_vec(), b"MyType".to_vec()); } + #[test] + fn reduce_spec_undefined_name_suggests_lto() { + use stellar_xdr::{ + ScSpecEntry, ScSpecTypeDef, ScSpecTypeUdt, ScSpecUdtStructFieldV0, ScSpecUdtStructV0, + }; + + // A struct with a field referring to a qualified type the spec does + // not define. + let entry = ScSpecEntry::UdtStructV0(ScSpecUdtStructV0 { + doc: StringM::default(), + lib: StringM::default(), + name: "mycrate::MyType".to_string().try_into().unwrap(), + fields: vec![ScSpecUdtStructFieldV0 { + doc: StringM::default(), + name: "f".to_string().try_into().unwrap(), + type_: ScSpecTypeDef::Udt(ScSpecTypeUdt { + name: "mycrate::Missing".to_string().try_into().unwrap(), + }), + }] + .try_into() + .unwrap(), + }); + + let err = Cmd::reduce_spec(&Print::new(true), "pkg", "release", &[entry]).unwrap_err(); + + let msg = err.to_string(); + assert!(msg.contains("mycrate::Missing"), "{msg}"); + assert!(msg.contains("[profile.release]"), "{msg}"); + assert!(msg.contains("lto"), "{msg}"); + } + #[test] fn serialize_command_shell_escapes_args_with_metacharacters() { let raw_arg = "--manifest-path=/path/to/contract;touch PWNED;#/Cargo.toml"; From 8947ca0f0883d90263df0f01deb5fe6e20c0b896 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 14 Oct 2026 16:17:02 +0000 Subject: [PATCH 08/15] include true in lto suggestion --- cmd/soroban-cli/src/commands/contract/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index d165b70389..dd13c1d1d1 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -584,7 +584,7 @@ impl Cmd { if matches!(e, soroban_spec::reduce::Error::UndefinedName(_)) { msg = format!( "{msg}. Check that [profile.{profile}] in the Cargo.toml does not have \ - `lto` disabled, it should be set to \"thin\" or \"fat\"." + `lto` disabled, it should be set to `true`, \"thin\", or \"fat\"." ); } Error::ReduceSpec(msg) From d8cdc51dc87183b556d91826647cab02b8d449b5 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 14 Oct 2026 21:40:33 +0000 Subject: [PATCH 09/15] sanitize rust generation errors before printing --- .../src/commands/contract/bindings/rust.rs | 7 +++++-- .../src/commands/contract/info/interface.rs | 13 +++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/bindings/rust.rs b/cmd/soroban-cli/src/commands/contract/bindings/rust.rs index 9de94065b0..ebc9ca7ce9 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/rust.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/rust.rs @@ -2,6 +2,7 @@ use std::fmt::Debug; use clap::Parser; use soroban_spec_rust::{self, ToFormattedString}; +use soroban_spec_tools::sanitize; use crate::wasm; @@ -15,7 +16,7 @@ pub struct Cmd { #[derive(thiserror::Error, Debug)] pub enum Error { #[error("generate rust from file: {0}")] - GenerateRustFromFile(soroban_spec_rust::GenerateFromFileError), + GenerateRustFromFile(String), #[error("format rust error: {0}")] FormatRust(String), } @@ -23,8 +24,10 @@ pub enum Error { impl Cmd { pub fn run(&self) -> Result<(), Error> { let wasm_path_str = self.wasm.wasm.to_string_lossy(); + // The error can name entries of the spec, so sanitize it before it is + // printed, as the spec is untrusted input. let code = soroban_spec_rust::generate_from_file(&wasm_path_str, None) - .map_err(Error::GenerateRustFromFile)?; + .map_err(|e| Error::GenerateRustFromFile(sanitize(&e.to_string())))?; match code.to_formatted_string() { Ok(formatted) => { println!("{formatted}"); diff --git a/cmd/soroban-cli/src/commands/contract/info/interface.rs b/cmd/soroban-cli/src/commands/contract/info/interface.rs index 980e4eabfe..4509c2e561 100644 --- a/cmd/soroban-cli/src/commands/contract/info/interface.rs +++ b/cmd/soroban-cli/src/commands/contract/info/interface.rs @@ -8,6 +8,7 @@ use clap::Parser; use soroban_spec_rust::ToFormattedString; use soroban_spec_tools::contract; use soroban_spec_tools::contract::Spec; +use soroban_spec_tools::sanitize; #[derive(Parser, Debug, Clone)] pub struct Cmd { @@ -41,8 +42,8 @@ pub enum Error { NoInterfacePresent(), #[error(transparent)] Json(#[from] serde_json::Error), - #[error(transparent)] - Generate(#[from] soroban_spec_rust::GenerateError), + #[error("{0}")] + Generate(String), } impl Cmd { @@ -76,8 +77,12 @@ impl Cmd { // rejects non-identifier bytes. If a future revision starts // emitting spec strings as `Literal::string` or rustdocs, this // path becomes a terminal-escape-injection vector and must be - // sanitized before printing. - InfoOutput::Rust => soroban_spec_rust::generate_without_file(&spec, sdk_major_version)? + // sanitized before printing. Names are reduced before they reach + // `format_ident!`, and reduce errors embed the raw names, so the + // error is sanitized before it is printed, as the spec is + // untrusted input. + InfoOutput::Rust => soroban_spec_rust::generate_without_file(&spec, sdk_major_version) + .map_err(|e| Error::Generate(sanitize(&e.to_string())))? .to_formatted_string() .expect("Unexpected spec format error"), }; From b7731cca2080157c6227c4006c8be72fb777f051 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Thu, 15 Oct 2026 21:07:43 +0000 Subject: [PATCH 10/15] build test wasms with stellar contract build --- Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a335069189..4641ae5dc2 100644 --- a/Makefile +++ b/Makefile @@ -38,10 +38,14 @@ build-snapshot: typescript-bindings-fixtures build: cargo build -VERSION = $(shell cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "soroban-cli") | .version') +TEST_WASM_PACKAGES = $(shell cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name | startswith("test_")) | .name') +# Build the test wasms with the CLI, so that their specs are shaken and their +# names reduced as they are for any contract built with `stellar contract build`. build-test-wasms: - SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 STELLAR_CLI_VERSION=$(VERSION) cargo build --package 'test_*' --profile test-wasms --target wasm32v1-none + for p in $(TEST_WASM_PACKAGES); do \ + cargo run --bin stellar -- contract build --package $$p --profile test-wasms || exit 1; \ + done build-test: build-test-wasms build-fixtures install From de1bac7b669e085ca69a8979caf14bc230cbb9dd Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 16 Oct 2026 15:02:16 +0000 Subject: [PATCH 11/15] update to protocol 30 sdk and rpc client --- Cargo.lock | 294 +++++++++++++----- Cargo.toml | 31 +- cmd/crates/soroban-spec-tools/src/lib.rs | 30 +- .../workspace-with-qualified-names/Cargo.toml | 2 +- .../src/commands/contract/arg_parsing.rs | 4 +- .../commands/contract/bindings/typescript.rs | 2 +- .../src/commands/contract/info/interface.rs | 2 +- cmd/soroban-cli/src/commands/strkey.rs | 3 +- cmd/soroban-cli/src/get_spec.rs | 2 +- cmd/soroban-cli/src/signer/mod.rs | 5 + 10 files changed, 264 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb0ec68ca3..2a7962e8ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "generic-array", ] @@ -1046,7 +1046,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "inout", ] @@ -1107,6 +1107,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "codespan-reporting" version = "0.12.0" @@ -1238,6 +1244,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "core-foundation" version = "0.9.4" @@ -1282,17 +1294,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crate-git-revision" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c521bf1f43d31ed2f73441775ed31935d77901cb3451e44b38a1c1612fcbaf98" -dependencies = [ - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "crate-git-revision" version = "0.0.9" @@ -1373,6 +1374,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "csv" version = "1.3.1" @@ -1419,6 +1429,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03bb0e1cc970d482d121d9a1744999169b69a07470b3d644a7894e53fcaf4574" +dependencies = [ + "cmov", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1618,7 +1637,17 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", + "const-oid 0.9.6", + "zeroize", +] + +[[package]] +name = "der" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a878c850e9e421b20262e9b41f9c860e4785fa07541c266b62ff9d1ef998a80a" +dependencies = [ + "const-oid 0.10.2", "zeroize", ] @@ -1682,11 +1711,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", - "crypto-common", + "const-oid 0.9.6", + "crypto-common 0.1.6", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "crypto-common 0.2.2", +] + [[package]] name = "directories" version = "5.0.1" @@ -1804,12 +1842,12 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", + "der 0.7.10", "digest 0.10.7", "elliptic-curve", "rfc6979", - "signature", - "spki", + "signature 2.2.0", + "spki 0.7.3", ] [[package]] @@ -1818,8 +1856,8 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.10.2", + "signature 2.2.0", ] [[package]] @@ -1867,7 +1905,7 @@ dependencies = [ "ff", "generic-array", "group", - "pkcs8", + "pkcs8 0.10.2", "rand_core 0.6.4", "sec1", "subtle", @@ -2602,6 +2640,16 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +[[package]] +name = "hybrid-array" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" +dependencies = [ + "ctutils", + "typenum", +] + [[package]] name = "hyper" version = "0.14.32" @@ -3165,7 +3213,7 @@ dependencies = [ "elliptic-curve", "once_cell", "sha2 0.10.9", - "signature", + "signature 2.2.0", ] [[package]] @@ -3177,6 +3225,16 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "keccak" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + [[package]] name = "keyring" version = "3.6.3" @@ -3454,6 +3512,21 @@ dependencies = [ "windows-sys 0.61.0", ] +[[package]] +name = "ml-dsa" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add6b9d92e496f16f4526d68ff29da1483aba4b119baeab8bed3b9e3544a6f3d" +dependencies = [ + "crypto-common 0.2.2", + "ctutils", + "hybrid-array", + "module-lattice", + "pkcs8 0.11.0", + "shake", + "signature 3.0.0", +] + [[package]] name = "mockito" version = "1.7.0" @@ -3478,6 +3551,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "module-lattice" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c61b87c9683ab7cb1c6871d261ad5479b6b10ceb52c4352aaca3b5d35a8febe" +dependencies = [ + "ctutils", + "hybrid-array", + "num-traits", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -3933,8 +4017,18 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", - "spki", + "der 0.7.10", + "spki 0.7.3", +] + +[[package]] +name = "pkcs8" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" +dependencies = [ + "der 0.8.2", + "spki 0.8.1", ] [[package]] @@ -4782,9 +4876,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", - "der", + "der 0.7.10", "generic-array", - "pkcs8", + "pkcs8 0.10.2", "subtle", "zeroize", ] @@ -5113,7 +5207,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ "digest 0.10.7", - "keccak", + "keccak 0.1.6", +] + +[[package]] +name = "shake" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09057cb2149ad4cbd2da1e26b351f9a4c354219421229c69c3063e6f61947c4a" +dependencies = [ + "digest 0.11.3", + "keccak 0.2.2", + "sponge-cursor", ] [[package]] @@ -5172,6 +5277,15 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "signature" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" +dependencies = [ + "digest 0.11.3", +] + [[package]] name = "similar" version = "2.7.0" @@ -5240,8 +5354,8 @@ dependencies = [ [[package]] name = "soroban-builtin-sdk-macros" -version = "29.0.0" -source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=6e6c4a87f46c7fdab0c2e2be82901b1e32378223#6e6c4a87f46c7fdab0c2e2be82901b1e32378223" dependencies = [ "itertools 0.13.0", "proc-macro2", @@ -5261,7 +5375,7 @@ dependencies = [ "chrono", "clap", "clap_complete", - "crate-git-revision 0.0.9", + "crate-git-revision", "csv", "directories", "dotenvy", @@ -5307,7 +5421,7 @@ dependencies = [ "stellar-asset-spec", "stellar-ledger", "stellar-rpc-client", - "stellar-strkey 0.0.18", + "stellar-strkey 1.0.0", "stellar-xdr", "tar", "tempfile", @@ -5331,11 +5445,11 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "29.0.0" -source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=6e6c4a87f46c7fdab0c2e2be82901b1e32378223#6e6c4a87f46c7fdab0c2e2be82901b1e32378223" dependencies = [ "arbitrary", - "crate-git-revision 0.0.9", + "crate-git-revision", "ethnum", "num-derive", "num-traits", @@ -5349,8 +5463,8 @@ dependencies = [ [[package]] name = "soroban-env-guest" -version = "29.0.0" -source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=6e6c4a87f46c7fdab0c2e2be82901b1e32378223#6e6c4a87f46c7fdab0c2e2be82901b1e32378223" dependencies = [ "soroban-env-common", "static_assertions", @@ -5358,8 +5472,8 @@ dependencies = [ [[package]] name = "soroban-env-host" -version = "29.0.0" -source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=6e6c4a87f46c7fdab0c2e2be82901b1e32378223#6e6c4a87f46c7fdab0c2e2be82901b1e32378223" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -5375,6 +5489,7 @@ dependencies = [ "hex-literal", "hmac", "k256", + "ml-dsa", "num-derive", "num-integer", "num-traits", @@ -5388,14 +5503,14 @@ dependencies = [ "soroban-env-common", "soroban-wasmi", "static_assertions", - "stellar-strkey 0.0.13", + "stellar-strkey 1.0.0", "wasmparser 0.116.1", ] [[package]] name = "soroban-env-macros" -version = "29.0.0" -source = "git+https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac#cb32250d926bd7188f3a6f9075bd48c44550dcac" +version = "30.0.0" +source = "git+https://github.com/stellar/rs-soroban-env?rev=6e6c4a87f46c7fdab0c2e2be82901b1e32378223#6e6c4a87f46c7fdab0c2e2be82901b1e32378223" dependencies = [ "itertools 0.13.0", "proc-macro2", @@ -5413,7 +5528,7 @@ version = "30.0.0" [[package]] name = "soroban-ledger-snapshot" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "serde", "serde_json", @@ -5426,7 +5541,7 @@ dependencies = [ [[package]] name = "soroban-meta" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "stellar-xdr", "thiserror 1.0.69", @@ -5436,11 +5551,11 @@ dependencies = [ [[package]] name = "soroban-sdk" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "arbitrary", "bytes-lit", - "crate-git-revision 0.0.9", + "crate-git-revision", "ctor", "derive_arbitrary", "ed25519-dalek", @@ -5454,7 +5569,7 @@ dependencies = [ "soroban-ledger-snapshot", "soroban-sdk-macros", "soroban-spec", - "stellar-strkey 0.0.18", + "stellar-strkey 1.0.0", "stellar-xdr", "visibility", ] @@ -5462,7 +5577,7 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "darling 0.20.11", "heck 0.5.0", @@ -5481,7 +5596,7 @@ dependencies = [ [[package]] name = "soroban-spec" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "base64 0.22.1", "stellar-xdr", @@ -5492,7 +5607,7 @@ dependencies = [ [[package]] name = "soroban-spec-rust" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "prettyplease", "proc-macro2", @@ -5518,7 +5633,7 @@ dependencies = [ "serde", "serde_json", "soroban-spec", - "stellar-strkey 0.0.18", + "stellar-strkey 1.0.0", "stellar-xdr", "thiserror 1.0.69", "wasm-encoder 0.235.0", @@ -5567,7 +5682,7 @@ dependencies = [ "soroban-spec-tools", "stellar-ledger", "stellar-rpc-client", - "stellar-strkey 0.0.18", + "stellar-strkey 1.0.0", "test-case", "testcontainers", "thiserror 1.0.69", @@ -5584,7 +5699,7 @@ dependencies = [ [[package]] name = "soroban-token-sdk" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "soroban-sdk", ] @@ -5592,16 +5707,18 @@ dependencies = [ [[package]] name = "soroban-token-spec" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "soroban-sdk", + "soroban-spec", "soroban-token-sdk", ] [[package]] name = "soroban-wasmi" -version = "0.31.1-soroban.20.0.1" -source = "git+https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3dee30dc41ebe21972399e0a73a41944aa0" +version = "0.31.1-soroban.29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c596eadd9cbbbef8a33972972bd3c482de5ad44f42a3e8f2c69be21ec8e6d00" dependencies = [ "smallvec", "spin", @@ -5623,9 +5740,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.10", ] +[[package]] +name = "spki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9" +dependencies = [ + "base64ct", + "der 0.8.2", +] + +[[package]] +name = "sponge-cursor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -5641,9 +5774,10 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-asset-spec" version = "30.0.0" -source = "git+https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886#a2e51be61dc5c179595ba5b26da7da724e253886" +source = "git+https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79#b4f41ba11aa95586cc8b5a1376c224a39596ec79" dependencies = [ "soroban-sdk", + "soroban-spec", "soroban-token-spec", ] @@ -5672,7 +5806,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "stellar-strkey 0.0.18", + "stellar-strkey 1.0.0", "stellar-xdr", "test-case", "testcontainers", @@ -5684,8 +5818,7 @@ dependencies = [ [[package]] name = "stellar-rpc-client" version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808ecdeac737f975c52e0fd21236a56c02921ead20858dd818b870d63a53edc5" +source = "git+https://github.com/stellar/rs-stellar-rpc-client?rev=d7fb0fc5fb71748dd54adc135a75fa06aa59c949#d7fb0fc5fb71748dd54adc135a75fa06aa59c949" dependencies = [ "clap", "hex", @@ -5698,7 +5831,7 @@ dependencies = [ "serde_json", "serde_with", "sha2 0.10.9", - "stellar-strkey 0.0.18", + "stellar-strkey 1.0.0", "stellar-xdr", "termcolor", "termcolor_output", @@ -5708,22 +5841,24 @@ dependencies = [ [[package]] name = "stellar-strkey" -version = "0.0.13" +version = "0.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee1832fb50c651ad10f734aaf5d31ca5acdfb197a6ecda64d93fcdb8885af913" +checksum = "0f34ff61c0ca6f1c2b4169e8d1633417bd9225f58b6175e4e317204565d16277" dependencies = [ - "crate-git-revision 0.0.6", + "crate-git-revision", "data-encoding", + "heapless 0.9.3", + "zeroize", ] [[package]] name = "stellar-strkey" -version = "0.0.18" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f34ff61c0ca6f1c2b4169e8d1633417bd9225f58b6175e4e317204565d16277" +checksum = "5038ed2bf4e11842210d118f65791d8ca4747622daddd222338b3d06b6051bc1" dependencies = [ "clap", - "crate-git-revision 0.0.9", + "crate-git-revision", "data-encoding", "heapless 0.9.3", "serde", @@ -5735,14 +5870,15 @@ dependencies = [ [[package]] name = "stellar-xdr" -version = "28.0.0" -source = "git+https://github.com/stellar/rs-stellar-xdr?rev=e0d289adf4ad2483a10bcc8df743126974d77301#e0d289adf4ad2483a10bcc8df743126974d77301" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f2fb2008b42fc746c0f6b46e375600068dd91f07748e9f1737c6341a2255f2" dependencies = [ "arbitrary", "base64 0.22.1", "cfg_eval", "clap", - "crate-git-revision 0.0.9", + "crate-git-revision", "escape-bytes", "ethnum", "hex", @@ -5753,7 +5889,7 @@ dependencies = [ "serde_json", "serde_with", "sha2 0.10.9", - "stellar-strkey 0.0.13", + "stellar-strkey 1.0.0", "thiserror 1.0.69", ] @@ -6510,9 +6646,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.18.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "uds_windows" @@ -6581,7 +6717,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "subtle", ] @@ -6926,13 +7062,15 @@ dependencies = [ [[package]] name = "wasmi_arena" -version = "0.4.0" -source = "git+https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3dee30dc41ebe21972399e0a73a41944aa0" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" [[package]] name = "wasmi_core" version = "0.13.0" -source = "git+https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0#0ed3f3dee30dc41ebe21972399e0a73a41944aa0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" dependencies = [ "downcast-rs", "libm", diff --git a/Cargo.toml b/Cargo.toml index 41cdf5d507..95b3c502c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,54 +44,56 @@ path = "cmd/crates/stellar-ledger" # Dependencies from the rs-stellar-xdr repo: [workspace.dependencies.stellar-xdr] -version = "28.0.0" +version = "30.0.0" # Dependencies from the rs-soroban-env repo, pinned to the rev that the # rs-soroban-sdk revision below uses, so that both share one soroban-env-host: [workspace.dependencies.soroban-env-host] -version = "=29.0.0" +version = "=30.0.0" git = "https://github.com/stellar/rs-soroban-env" -rev = "cb32250d926bd7188f3a6f9075bd48c44550dcac" +rev = "6e6c4a87f46c7fdab0c2e2be82901b1e32378223" # Dependencies from the rs-soroban-sdk repo, pinned to a rev of main: [workspace.dependencies.soroban-spec] version = "30.0.0" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "a2e51be61dc5c179595ba5b26da7da724e253886" +rev = "b4f41ba11aa95586cc8b5a1376c224a39596ec79" [workspace.dependencies.soroban-spec-rust] version = "30.0.0" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "a2e51be61dc5c179595ba5b26da7da724e253886" +rev = "b4f41ba11aa95586cc8b5a1376c224a39596ec79" [workspace.dependencies.soroban-sdk] version = "30.0.0" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "a2e51be61dc5c179595ba5b26da7da724e253886" +rev = "b4f41ba11aa95586cc8b5a1376c224a39596ec79" [workspace.dependencies.soroban-token-sdk] version = "30.0.0" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "a2e51be61dc5c179595ba5b26da7da724e253886" +rev = "b4f41ba11aa95586cc8b5a1376c224a39596ec79" [workspace.dependencies.stellar-asset-spec] version = "30.0.0" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "a2e51be61dc5c179595ba5b26da7da724e253886" +rev = "b4f41ba11aa95586cc8b5a1376c224a39596ec79" [workspace.dependencies.soroban-ledger-snapshot] version = "30.0.0" git = "https://github.com/stellar/rs-soroban-sdk" -rev = "a2e51be61dc5c179595ba5b26da7da724e253886" +rev = "b4f41ba11aa95586cc8b5a1376c224a39596ec79" # Dependencies from the rs-stellar-rpc-client repo: [workspace.dependencies.soroban-rpc] package = "stellar-rpc-client" version = "28.0.0" +git = "https://github.com/stellar/rs-stellar-rpc-client" +rev = "d7fb0fc5fb71748dd54adc135a75fa06aa59c949" # Dependencies from elsewhere shared by crates: [workspace.dependencies] -stellar-strkey = "0.0.18" +stellar-strkey = "1.0.0" sep5 = "0.1.0" base64 = "0.21.2" thiserror = "1.0.46" @@ -133,15 +135,6 @@ testcontainers = "0.27.2" httpmock = "0.7.0" astral-tokio-tar = "0.6.0" -[patch.crates-io] -# Pinned to a rev of rs-stellar-xdr main, pending a release containing the const -# XDR encoding and the widened user-defined type name limit that a fully -# qualified type name needs. This has to be a patch rather than a git revision on -# the dependency itself, because stellar-rpc-client is published and so brings -# its own stellar-xdr from crates.io, which only a patch redirects onto the same -# copy the rest of the graph uses. -stellar-xdr = { git = "https://github.com/stellar/rs-stellar-xdr", rev = "e0d289adf4ad2483a10bcc8df743126974d77301" } - [profile.release] overflow-checks = true diff --git a/cmd/crates/soroban-spec-tools/src/lib.rs b/cmd/crates/soroban-spec-tools/src/lib.rs index 0a05202dd7..64b03da4b4 100644 --- a/cmd/crates/soroban-spec-tools/src/lib.rs +++ b/cmd/crates/soroban-spec-tools/src/lib.rs @@ -6,13 +6,13 @@ use itertools::Itertools; use serde_json::{json, Value}; use stellar_xdr::{ AccountId, BytesM, ContractExecutable, ContractExecutableExternalRef, ContractId, - Error as XdrError, Hash, Int128Parts, Int256Parts, MuxedEd25519Account, PublicKey, ScAddress, - ScBytes, ScContractInstance, ScMap, ScMapEntry, ScNonceKey, ScSpecEntry, ScSpecEventV0, - ScSpecFunctionV0, ScSpecTypeDef as ScType, ScSpecTypeMap, ScSpecTypeOption, ScSpecTypeResult, - ScSpecTypeTuple, ScSpecTypeUdt, ScSpecTypeVec, ScSpecUdtEnumV0, ScSpecUdtErrorEnumCaseV0, - ScSpecUdtErrorEnumV0, ScSpecUdtStructV0, ScSpecUdtUnionCaseTupleV0, ScSpecUdtUnionCaseV0, - ScSpecUdtUnionCaseVoidV0, ScSpecUdtUnionV0, ScString, ScSymbol, ScVal, ScVec, StringM, - UInt128Parts, UInt256Parts, Uint256, VecM, + Error as XdrError, Hash, Int128Parts, Int256Parts, MuxedContract, MuxedEd25519Account, + PublicKey, ScAddress, ScBytes, ScContractInstance, ScMap, ScMapEntry, ScNonceKey, ScSpecEntry, + ScSpecEventV0, ScSpecFunctionV0, ScSpecTypeDef as ScType, ScSpecTypeMap, ScSpecTypeOption, + ScSpecTypeResult, ScSpecTypeTuple, ScSpecTypeUdt, ScSpecTypeVec, ScSpecUdtEnumV0, + ScSpecUdtErrorEnumCaseV0, ScSpecUdtErrorEnumV0, ScSpecUdtStructV0, ScSpecUdtUnionCaseTupleV0, + ScSpecUdtUnionCaseV0, ScSpecUdtUnionCaseVoidV0, ScSpecUdtUnionV0, ScString, ScSymbol, ScVal, + ScVec, StringM, UInt128Parts, UInt256Parts, Uint256, VecM, }; pub mod contract; @@ -1172,6 +1172,16 @@ fn sc_address_to_json(v: &ScAddress) -> Value { id: *id, } )), + ScAddress::MuxedContract(MuxedContract { + id, + contract_id: ContractId(h), + }) => Value::String(format!( + "{}", + stellar_strkey::MuxedContract { + contract_id: h.0, + id: *id, + } + )), ScAddress::ClaimableBalance(_) => todo!("ClaimableBalance is not supported"), ScAddress::LiquidityPool(_) => todo!("LiquidityPool is not supported"), } @@ -1193,6 +1203,12 @@ fn sc_address_from_json(s: &str) -> Result { id: m.id, }), )), + stellar_strkey::Strkey::MuxedContract(m) => { + Some(ScVal::Address(ScAddress::MuxedContract(MuxedContract { + id: m.id, + contract_id: ContractId(Hash(m.contract_id)), + }))) + } _ => None, })? .ok_or(Error::InvalidValue(Some(ScType::Address))) diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml index 1d89dbd6b4..b1f241e74c 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/workspace-with-qualified-names/Cargo.toml @@ -5,7 +5,7 @@ members = [ ] [workspace.dependencies] -soroban-sdk = { git = "https://github.com/stellar/rs-soroban-sdk", rev = "a2e51be61dc5c179595ba5b26da7da724e253886" } +soroban-sdk = { git = "https://github.com/stellar/rs-soroban-sdk", rev = "b4f41ba11aa95586cc8b5a1376c224a39596ec79" } [profile.release] opt-level = "z" diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index e6df8e4ead..193f4f8d86 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -553,7 +553,9 @@ fn resolve_address( )?; match addr { xdr::ScAddress::Account(account) => account.to_string(), - contract @ xdr::ScAddress::Contract(_) => contract.to_string(), + contract @ (xdr::ScAddress::Contract(_) | xdr::ScAddress::MuxedContract(_)) => { + contract.to_string() + } stellar_xdr::ScAddress::MuxedAccount(account) => account.to_string(), stellar_xdr::ScAddress::ClaimableBalance(_) | stellar_xdr::ScAddress::LiquidityPool(_) => { diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index 516dad2ceb..8ebe7cd9f7 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -66,7 +66,7 @@ impl Cmd { let spec = match contract { contract_spec::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?.spec, contract_spec::Contract::StellarAssetContract => { - soroban_spec::read::parse_raw(stellar_asset_spec::xdr())? + soroban_spec::read::parse_raw(&stellar_asset_spec::xdr())? } }; diff --git a/cmd/soroban-cli/src/commands/contract/info/interface.rs b/cmd/soroban-cli/src/commands/contract/info/interface.rs index 4509c2e561..12d2a3130c 100644 --- a/cmd/soroban-cli/src/commands/contract/info/interface.rs +++ b/cmd/soroban-cli/src/commands/contract/info/interface.rs @@ -63,7 +63,7 @@ impl Cmd { (spec.spec_base64.unwrap(), spec.spec, sdk_major_version) } shared::Contract::StellarAssetContract => { - let (base64, spec) = Spec::spec_to_base64(stellar_asset_spec::xdr())?; + let (base64, spec) = Spec::spec_to_base64(&stellar_asset_spec::xdr())?; (base64, spec, None) } }; diff --git a/cmd/soroban-cli/src/commands/strkey.rs b/cmd/soroban-cli/src/commands/strkey.rs index c6b8eed39b..6766a32305 100644 --- a/cmd/soroban-cli/src/commands/strkey.rs +++ b/cmd/soroban-cli/src/commands/strkey.rs @@ -59,8 +59,7 @@ fn decode_arg(input: &str, opts: &RunOpts) -> Result<(), decode::Error> { let json = if let Ok(k) = Strkey::from_str(input) { serde_json::to_string_pretty(&Decoded(&k)).unwrap() } else { - let pk = ed25519::PrivateKey::from_str(input) - .map_err(|e| decode::Error::Decode(input.to_string(), e))?; + let pk = ed25519::PrivateKey::from_str(input).map_err(decode::Error::Decode)?; if !opts.quiet { warn_private_key(); } diff --git a/cmd/soroban-cli/src/get_spec.rs b/cmd/soroban-cli/src/get_spec.rs index e7a6a05c8b..780d70e2fb 100644 --- a/cmd/soroban-cli/src/get_spec.rs +++ b/cmd/soroban-cli/src/get_spec.rs @@ -62,7 +62,7 @@ pub async fn get_remote_contract_spec( // resolve to a Wasm hash whose spec is fetched (and cached) the same way. Ok(match executable { ContractExecutable::StellarAsset => { - soroban_spec::read::parse_raw(stellar_asset_spec::xdr())? + soroban_spec::read::parse_raw(&stellar_asset_spec::xdr())? } ContractExecutable::Wasm(hash) => { get_spec_for_wasm_hash(&client, &hash, global_args).await? diff --git a/cmd/soroban-cli/src/signer/mod.rs b/cmd/soroban-cli/src/signer/mod.rs index 45584ad28e..c63c50666a 100644 --- a/cmd/soroban-cli/src/signer/mod.rs +++ b/cmd/soroban-cli/src/signer/mod.rs @@ -144,6 +144,11 @@ pub async fn sign_soroban_authorizations( ), }); } + ScAddress::MuxedContract(_) => { + return Err(Error::MissingSignerForAddress { + address: address.to_string(), + }); + } }; // Auth entries should not request a signature from the tx source account via the `Address` credential type From 1be6c27960228072b0ce805076af1b5f840f94b8 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 16 Oct 2026 15:04:09 +0000 Subject: [PATCH 12/15] allow new git pins in deny.toml --- deny.toml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/deny.toml b/deny.toml index 31ea88c715..828588ccd1 100644 --- a/deny.toml +++ b/deny.toml @@ -233,16 +233,15 @@ allow-git = [ "https://github.com/ConnorGray/clap-markdown?rev=42956b342cef3325d9060fc43995d595e7c8aa66", # Temporary pins, remove once released: - # rs-stellar-xdr main, which widens the user-defined type name limit so a - # fully qualified type name fits. - "https://github.com/stellar/rs-stellar-xdr?rev=e0d289adf4ad2483a10bcc8df743126974d77301", - # rs-soroban-sdk main, which names user-defined types in contract specs by - # their fully qualified path. - "https://github.com/stellar/rs-soroban-sdk?rev=a2e51be61dc5c179595ba5b26da7da724e253886", - # The rs-soroban-env rev that rs-soroban-sdk main uses, and the git - # dependencies of the env it brings in. - "https://github.com/stellar/rs-soroban-env?rev=cb32250d926bd7188f3a6f9075bd48c44550dcac", - "https://github.com/stellar/wasmi?rev=0ed3f3dee30dc41ebe21972399e0a73a41944aa0", + # rs-soroban-sdk with stellar/rs-soroban-sdk#2139, which names user-defined + # types in contract specs by their fully qualified path and reduces the names + # in the token and asset specs. + "https://github.com/stellar/rs-soroban-sdk?rev=b4f41ba11aa95586cc8b5a1376c224a39596ec79", + # The rs-soroban-env rev that the rs-soroban-sdk rev above uses. + "https://github.com/stellar/rs-soroban-env?rev=6e6c4a87f46c7fdab0c2e2be82901b1e32378223", + # rs-stellar-rpc-client with stellar/rs-stellar-rpc-client#121, which updates + # it to stellar-xdr 30. + "https://github.com/stellar/rs-stellar-rpc-client?rev=d7fb0fc5fb71748dd54adc135a75fa06aa59c949", ] [sources.allow-org] From 6ad833b632e954b0c5176297319f73f4194eea99 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 16 Oct 2026 15:15:04 +0000 Subject: [PATCH 13/15] test against quickstart nightly-next protocol 30 --- .github/workflows/bindings-ts.yml | 6 ++++-- .github/workflows/rpc-tests.yml | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index 4710c97143..dedbe86682 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -24,10 +24,12 @@ jobs: - sys: ${{ github.event_name != 'push' && !startsWith(github.ref_name, 'release/') && 'macos-15-large' }} runs-on: ${{ matrix.sys }} steps: + # Protocol 30 is not yet in a quickstart release, so run the next + # protocol from core master. - uses: stellar/quickstart@main with: - tag: latest - protocol_version: 29 + tag: nightly-next + protocol_version: 30 - uses: actions/setup-node@v7.1.0 with: node-version: "20.x" diff --git a/.github/workflows/rpc-tests.yml b/.github/workflows/rpc-tests.yml index ad7b1ef51e..d00609cc67 100644 --- a/.github/workflows/rpc-tests.yml +++ b/.github/workflows/rpc-tests.yml @@ -31,10 +31,12 @@ jobs: env: TEST_THREADS: ${{ contains(matrix.sys, 'macos') && '2' || '4' }} # macOS has limited resources steps: + # Protocol 30 is not yet in a quickstart release, so run the next + # protocol from core master. - uses: stellar/quickstart@main with: - tag: latest - protocol_version: 29 + tag: nightly-next + protocol_version: 30 - uses: actions/checkout@v7 - uses: stellar/actions/rust-cache@main - run: rustup update From 0f0d219b80e2822c17c2fb7d297b1e2279aec1cd Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 16 Oct 2026 15:32:25 +0000 Subject: [PATCH 14/15] test against quickstart nightly protocol 30 --- .github/workflows/bindings-ts.yml | 6 +++--- .github/workflows/ledger-emulator.yml | 6 ++++-- .github/workflows/rpc-tests.yml | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index dedbe86682..bca4f200a3 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -24,11 +24,11 @@ jobs: - sys: ${{ github.event_name != 'push' && !startsWith(github.ref_name, 'release/') && 'macos-15-large' }} runs-on: ${{ matrix.sys }} steps: - # Protocol 30 is not yet in a quickstart release, so run the next - # protocol from core master. + # Protocol 30 is not yet in a quickstart release, so run it from + # core master. - uses: stellar/quickstart@main with: - tag: nightly-next + tag: nightly protocol_version: 30 - uses: actions/setup-node@v7.1.0 with: diff --git a/.github/workflows/ledger-emulator.yml b/.github/workflows/ledger-emulator.yml index 85aa56c071..0298061c06 100644 --- a/.github/workflows/ledger-emulator.yml +++ b/.github/workflows/ledger-emulator.yml @@ -34,10 +34,12 @@ jobs: CI_TESTS: true TEST_THREADS: ${{ contains(matrix.sys, 'macos') && '--test-threads=1' || '' }} # macOS has limited resources, so we run tests (that rely on `testcontainers`) with 1 thread steps: + # Protocol 30 is not yet in a quickstart release, so run it from + # core master. - uses: stellar/quickstart@main with: - tag: latest - protocol_version: 29 + tag: nightly + protocol_version: 30 - uses: actions/checkout@v7 - uses: stellar/actions/rust-cache@main diff --git a/.github/workflows/rpc-tests.yml b/.github/workflows/rpc-tests.yml index d00609cc67..4b0b5629ee 100644 --- a/.github/workflows/rpc-tests.yml +++ b/.github/workflows/rpc-tests.yml @@ -31,11 +31,11 @@ jobs: env: TEST_THREADS: ${{ contains(matrix.sys, 'macos') && '2' || '4' }} # macOS has limited resources steps: - # Protocol 30 is not yet in a quickstart release, so run the next - # protocol from core master. + # Protocol 30 is not yet in a quickstart release, so run it from + # core master. - uses: stellar/quickstart@main with: - tag: nightly-next + tag: nightly protocol_version: 30 - uses: actions/checkout@v7 - uses: stellar/actions/rust-cache@main From 43b54be3b206d241f64142b6d7d1e96e80d33c79 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 16 Oct 2026 16:16:32 +0000 Subject: [PATCH 15/15] test against quickstart pr1001-nightly image --- .github/workflows/bindings-ts.yml | 6 +++--- .github/workflows/ledger-emulator.yml | 6 +++--- .github/workflows/rpc-tests.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index bca4f200a3..91b0fd416e 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -24,11 +24,11 @@ jobs: - sys: ${{ github.event_name != 'push' && !startsWith(github.ref_name, 'release/') && 'macos-15-large' }} runs-on: ${{ matrix.sys }} steps: - # Protocol 30 is not yet in a quickstart release, so run it from - # core master. + # Protocol 30 is not yet in a quickstart release, so run the image built + # by stellar/quickstart#1001, which adds the protocol 30 config settings. - uses: stellar/quickstart@main with: - tag: nightly + tag: pr1001-nightly protocol_version: 30 - uses: actions/setup-node@v7.1.0 with: diff --git a/.github/workflows/ledger-emulator.yml b/.github/workflows/ledger-emulator.yml index 0298061c06..94f1489174 100644 --- a/.github/workflows/ledger-emulator.yml +++ b/.github/workflows/ledger-emulator.yml @@ -34,11 +34,11 @@ jobs: CI_TESTS: true TEST_THREADS: ${{ contains(matrix.sys, 'macos') && '--test-threads=1' || '' }} # macOS has limited resources, so we run tests (that rely on `testcontainers`) with 1 thread steps: - # Protocol 30 is not yet in a quickstart release, so run it from - # core master. + # Protocol 30 is not yet in a quickstart release, so run the image built + # by stellar/quickstart#1001, which adds the protocol 30 config settings. - uses: stellar/quickstart@main with: - tag: nightly + tag: pr1001-nightly protocol_version: 30 - uses: actions/checkout@v7 diff --git a/.github/workflows/rpc-tests.yml b/.github/workflows/rpc-tests.yml index 4b0b5629ee..21487a4a3f 100644 --- a/.github/workflows/rpc-tests.yml +++ b/.github/workflows/rpc-tests.yml @@ -31,11 +31,11 @@ jobs: env: TEST_THREADS: ${{ contains(matrix.sys, 'macos') && '2' || '4' }} # macOS has limited resources steps: - # Protocol 30 is not yet in a quickstart release, so run it from - # core master. + # Protocol 30 is not yet in a quickstart release, so run the image built + # by stellar/quickstart#1001, which adds the protocol 30 config settings. - uses: stellar/quickstart@main with: - tag: nightly + tag: pr1001-nightly protocol_version: 30 - uses: actions/checkout@v7 - uses: stellar/actions/rust-cache@main