diff --git a/.github/workflows/downstream-project-spl.yml b/.github/workflows/downstream-project-spl.yml index 017a13ce5b88c7..3d4887cf817804 100644 --- a/.github/workflows/downstream-project-spl.yml +++ b/.github/workflows/downstream-project-spl.yml @@ -39,6 +39,7 @@ env: jobs: check: if: github.repository == 'anza-xyz/agave' + if: false runs-on: ubuntu-latest timeout-minutes: 60 strategy: @@ -77,6 +78,7 @@ jobs: test_cli: if: github.repository == 'anza-xyz/agave' + if: false runs-on: ubuntu-latest timeout-minutes: 60 strategy: @@ -107,6 +109,7 @@ jobs: cargo-test-sbf: if: github.repository == 'anza-xyz/agave' + if: false runs-on: ubuntu-latest timeout-minutes: 60 strategy: @@ -148,7 +151,8 @@ jobs: run: | source ci/downstream-projects/common.sh cd "${{ matrix.programs }}" - $CARGO_TEST_SBF --arch v0 --manifest-path program/Cargo.toml + $CARGO_BUILD_SBF --arch v0 --manifest-path program/Cargo.toml + RUSTFLAGS="-Awarnings" SBF_OUT_DIR="../target/deploy" cargo test --features test-sbf --manifest-path program/Cargo.toml - name: Test SBPFv1 shell: bash @@ -156,7 +160,8 @@ jobs: source ci/downstream-projects/common.sh cd "${{ matrix.programs }}" rm -rf target/deploy target/sbpf* - $CARGO_TEST_SBF --arch v1 --manifest-path program/Cargo.toml + $CARGO_BUILD_SBF --arch v1 --manifest-path program/Cargo.toml + RUSTFLAGS="-Awarnings" SBF_OUT_DIR="../target/deploy" cargo test --features test-sbf --manifest-path program/Cargo.toml - name: Test SBPFv2 shell: bash @@ -164,7 +169,8 @@ jobs: source ci/downstream-projects/common.sh cd "${{ matrix.programs }}" rm -rf target/deploy target/sbpf* - $CARGO_TEST_SBF --arch v2 --manifest-path program/Cargo.toml + $CARGO_BUILD_SBF --arch v2 --manifest-path program/Cargo.toml + RUSTFLAGS="-Awarnings" SBF_OUT_DIR="../target/deploy" cargo test --features test-sbf --manifest-path program/Cargo.toml - name: Test SBPFv3 shell: bash @@ -172,4 +178,5 @@ jobs: source ci/downstream-projects/common.sh cd "${{ matrix.programs }}" rm -rf target/deploy target/sbpf* - $CARGO_TEST_SBF --arch v3 --manifest-path program/Cargo.toml + $CARGO_BUILD_SBF --arch v3 --manifest-path program/Cargo.toml + RUSTFLAGS="-Awarnings" SBF_OUT_DIR="../target/deploy" cargo test --features test-sbf --manifest-path program/Cargo.toml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9d2f180d06b497..2a2cae1184d30c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,6 +47,7 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + token: ${{ secrets.VERSION_BUMP_PAT }} - name: Parse Info id: parse_info diff --git a/.github/workflows/svm-exampls.yml b/.github/workflows/svm-examples.yml similarity index 96% rename from .github/workflows/svm-exampls.yml rename to .github/workflows/svm-examples.yml index 46bbbf3163fbcb..d31007e53b42f8 100644 --- a/.github/workflows/svm-exampls.yml +++ b/.github/workflows/svm-examples.yml @@ -44,7 +44,7 @@ jobs: - name: Run build run: | cd svm/examples - cargo build --tests + cargo build - name: Run tests run: | diff --git a/.mergify.yml b/.mergify.yml index 309f34ed4eb0e9..2ff48f54615b28 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -104,9 +104,9 @@ pull_request_rules: - automerge comment: message: automerge label removed due to a CI failure - - name: v2.1 feature-gate backport + - name: v2.2 feature-gate backport conditions: - - label=v2.1 + - label=v2.2 - label=feature-gate actions: backport: @@ -117,10 +117,10 @@ pull_request_rules: labels: - feature-gate branches: - - v2.1 - - name: v2.1 non-feature-gate backport + - v2.2 + - name: v2.2 non-feature-gate backport conditions: - - label=v2.1 + - label=v2.2 - label!=feature-gate actions: backport: @@ -128,10 +128,10 @@ pull_request_rules: title: "{{ destination_branch }}: {{ title }} (backport of #{{ number }})" ignore_conflicts: true branches: - - v2.1 - - name: v2.1 backport warning comment + - v2.2 + - name: v2.2 backport warning comment conditions: - - label=v2.1 + - label=v2.2 actions: comment: message: > @@ -142,9 +142,9 @@ pull_request_rules: refactoring, plumbing, cleanup, etc that are not strictly necessary to achieve the goal. Any of the latter should go only into master and ride the normal stabilization schedule. - - name: v2.2 feature-gate backport + - name: v2.3 feature-gate backport conditions: - - label=v2.2 + - label=v2.3 - label=feature-gate actions: backport: @@ -154,10 +154,10 @@ pull_request_rules: labels: - feature-gate branches: - - v2.2 - - name: v2.2 non-feature-gate backport + - v2.3 + - name: v2.3 non-feature-gate backport conditions: - - label=v2.2 + - label=v2.3 - label!=feature-gate actions: backport: @@ -165,10 +165,10 @@ pull_request_rules: title: "{{ destination_branch }}: {{ title }} (backport of #{{ number }})" ignore_conflicts: true branches: - - v2.2 - - name: v2.2 backport warning comment + - v2.3 + - name: v2.3 backport warning comment conditions: - - label=v2.2 + - label=v2.3 actions: comment: message: > diff --git a/CHANGELOG.md b/CHANGELOG.md index 9282b9de03949e..5d7cf2fbbd4fb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm and follows a [Backwards Compatibility Policy](https://docs.solanalabs.com/backwards-compatibility) Release channels have their own copy of this changelog: -* [edge - v2.3](#edge-channel) -* [beta - v2.2](https://github.com/anza-xyz/agave/blob/v2.2/CHANGELOG.md) -* [stable - v2.1](https://github.com/anza-xyz/agave/blob/v2.1/CHANGELOG.md) +* [edge - v3.0](#edge-channel) +* [beta - v2.3](https://github.com/anza-xyz/agave/blob/v2.3/CHANGELOG.md) +* [stable - v2.2](https://github.com/anza-xyz/agave/blob/v2.2/CHANGELOG.md) -## 2.3.0 - Unreleased +## 3.0.0 - Unreleased + + +## 2.3.0 ### Validator diff --git a/Cargo.lock b/Cargo.lock index a4b6cb8b28930a..4e13fb284632e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ [[package]] name = "agave-accounts-hash-cache-tool" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "anyhow", @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "agave-banking-stage-ingress-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "solana-perf", @@ -101,7 +101,7 @@ dependencies = [ [[package]] name = "agave-cargo-registry" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 2.33.3", "flate2", @@ -133,7 +133,7 @@ dependencies = [ [[package]] name = "agave-feature-set" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "solana-epoch-schedule", @@ -147,7 +147,7 @@ dependencies = [ [[package]] name = "agave-geyser-plugin-interface" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-clock", @@ -159,7 +159,7 @@ dependencies = [ [[package]] name = "agave-install" -version = "2.3.0" +version = "3.0.0" dependencies = [ "atty", "bincode", @@ -172,7 +172,7 @@ dependencies = [ "dirs-next", "indicatif", "nix", - "reqwest 0.12.15", + "reqwest 0.12.19", "scopeguard", "semver 1.0.26", "serde", @@ -180,6 +180,7 @@ dependencies = [ "serde_yaml 0.8.26", "serde_yaml 0.9.34+deprecated", "solana-clap-utils", + "solana-config-interface", "solana-config-program-client", "solana-hash", "solana-keypair", @@ -201,7 +202,7 @@ dependencies = [ [[package]] name = "agave-ledger-tool" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -242,6 +243,7 @@ dependencies = [ "solana-gossip", "solana-hash", "solana-inflation", + "solana-instruction", "solana-keypair", "solana-ledger", "solana-loader-v3-interface 5.0.0", @@ -268,7 +270,7 @@ dependencies = [ "solana-svm-feature-set", "solana-system-interface", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-status", "solana-type-overrides", "solana-unified-scheduler-pool", @@ -282,7 +284,7 @@ dependencies = [ [[package]] name = "agave-precompiles" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -308,7 +310,7 @@ dependencies = [ [[package]] name = "agave-reserved-account-keys" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-frozen-abi", @@ -321,7 +323,7 @@ dependencies = [ [[package]] name = "agave-store-histogram" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 2.33.3", "solana-version", @@ -329,7 +331,7 @@ dependencies = [ [[package]] name = "agave-store-tool" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "clap 2.33.3", @@ -343,7 +345,7 @@ dependencies = [ [[package]] name = "agave-thread-manager" -version = "2.3.0" +version = "3.0.0" dependencies = [ "affinity", "agave-thread-manager", @@ -366,7 +368,7 @@ dependencies = [ [[package]] name = "agave-transaction-view" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-transaction-view", "bincode", @@ -388,7 +390,7 @@ dependencies = [ [[package]] name = "agave-validator" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-geyser-plugin-interface", "assert_cmd", @@ -476,7 +478,7 @@ dependencies = [ [[package]] name = "agave-watchtower" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 2.33.3", "humantime", @@ -497,7 +499,7 @@ dependencies = [ [[package]] name = "agave-xdp" -version = "2.3.0" +version = "3.0.0" dependencies = [ "aya", "caps", @@ -1019,7 +1021,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.6.0", "hyper-util", "itoa", "matchit", @@ -1180,7 +1182,7 @@ dependencies = [ "bitflags 2.9.1", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "proc-macro2", @@ -1302,7 +1304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" dependencies = [ "borsh-derive 0.10.3", - "hashbrown 0.13.2", + "hashbrown 0.12.3", ] [[package]] @@ -2955,7 +2957,7 @@ dependencies = [ [[package]] name = "gen-headers" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "regex", @@ -2963,7 +2965,7 @@ dependencies = [ [[package]] name = "gen-syscall-list" -version = "2.3.0" +version = "3.0.0" dependencies = [ "regex", ] @@ -3240,6 +3242,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" + [[package]] name = "hex" version = "0.4.3" @@ -3353,9 +3361,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -3401,9 +3409,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -3459,7 +3467,7 @@ checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.5.1", + "hyper 1.6.0", "hyper-util", "rustls 0.23.27", "rustls-pki-types", @@ -3496,16 +3504,21 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.5.1", + "hyper 1.6.0", + "ipnet", + "libc", + "percent-encoding 2.3.1", "pin-project-lite", "socket2", "tokio", @@ -3777,9 +3790,19 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "is-terminal" @@ -4565,11 +4588,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.1", "libc", ] @@ -5237,7 +5260,7 @@ dependencies = [ [[package]] name = "proto" -version = "2.3.0" +version = "3.0.0" dependencies = [ "protobuf-src", "tonic-build", @@ -5557,7 +5580,7 @@ dependencies = [ [[package]] name = "rbpf-cli" -version = "2.3.0" +version = "3.0.0" [[package]] name = "rdrand" @@ -5673,7 +5696,7 @@ dependencies = [ "percent-encoding 2.3.1", "pin-project-lite", "rustls 0.21.12", - "rustls-pemfile 1.0.0", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -5694,9 +5717,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" dependencies = [ "async-compression", "base64 0.22.1", @@ -5707,7 +5730,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.1", + "hyper 1.6.0", "hyper-rustls 0.27.5", "hyper-util", "ipnet", @@ -5719,7 +5742,6 @@ dependencies = [ "pin-project-lite", "quinn", "rustls 0.23.27", - "rustls-pemfile 2.1.3", "rustls-pki-types", "serde", "serde_json", @@ -5729,13 +5751,13 @@ dependencies = [ "tokio-rustls 0.26.2", "tokio-util 0.7.15", "tower 0.5.2", + "tower-http", "tower-service", "url 2.5.4", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.8", - "windows-registry", + "webpki-roots 1.0.0", ] [[package]] @@ -5747,7 +5769,7 @@ dependencies = [ "anyhow", "async-trait", "http 1.1.0", - "reqwest 0.12.15", + "reqwest 0.12.19", "serde", "thiserror 1.0.69", "tower-service", @@ -5925,16 +5947,6 @@ dependencies = [ "base64 0.13.1", ] -[[package]] -name = "rustls-pemfile" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.11.0" @@ -6499,9 +6511,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -6546,7 +6558,7 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "assert_matches", @@ -6590,7 +6602,7 @@ dependencies = [ [[package]] name = "solana-account-decoder-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bs58", @@ -6604,9 +6616,9 @@ dependencies = [ [[package]] name = "solana-account-info" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c17d606a298a205fae325489fbed88ee6dc4463c111672172327e741c8905d" +checksum = "c8f5152a288ef1912300fc6efa6c2d1f9bb55d9398eb6c72326360b8063987da" dependencies = [ "bincode", "serde", @@ -6617,7 +6629,7 @@ dependencies = [ [[package]] name = "solana-accounts-bench" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 2.33.3", "log", @@ -6634,7 +6646,7 @@ dependencies = [ [[package]] name = "solana-accounts-cluster-bench" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 2.33.3", "log", @@ -6679,8 +6691,9 @@ dependencies = [ [[package]] name = "solana-accounts-db" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "agave-reserved-account-keys", "ahash 0.8.11", "assert_matches", "bincode", @@ -6738,6 +6751,7 @@ dependencies = [ "solana-reward-info", "solana-sdk-ids", "solana-sha256-hasher", + "solana-signature", "solana-signer", "solana-slot-hashes", "solana-slot-history", @@ -6747,7 +6761,7 @@ dependencies = [ "solana-sysvar", "solana-time-utils", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-vote-program", "spl-generic-token", @@ -6788,7 +6802,7 @@ dependencies = [ [[package]] name = "solana-banking-bench" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "assert_matches", @@ -6824,23 +6838,27 @@ dependencies = [ [[package]] name = "solana-banks-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "borsh 1.5.7", "futures 0.3.31", "solana-account", "solana-banks-interface", "solana-banks-server", + "solana-clock", "solana-commitment-config", + "solana-hash", "solana-message", - "solana-program", + "solana-program-pack", "solana-pubkey", + "solana-rent", "solana-runtime", "solana-signature", "solana-signer", "solana-system-interface", + "solana-sysvar", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "tarpc", "thiserror 2.0.12", @@ -6850,7 +6868,7 @@ dependencies = [ [[package]] name = "solana-banks-interface" -version = "2.3.0" +version = "3.0.0" dependencies = [ "serde", "serde_derive", @@ -6862,14 +6880,14 @@ dependencies = [ "solana-pubkey", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "tarpc", ] [[package]] name = "solana-banks-server" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -6897,7 +6915,7 @@ dependencies = [ [[package]] name = "solana-bench-streamer" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 3.2.23", "crossbeam-channel", @@ -6908,7 +6926,7 @@ dependencies = [ [[package]] name = "solana-bench-tps" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "chrono", @@ -6974,7 +6992,7 @@ dependencies = [ [[package]] name = "solana-bench-vote" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "clap 2.33.3", @@ -7031,7 +7049,7 @@ dependencies = [ [[package]] name = "solana-bloom" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bv", "fnv", @@ -7075,7 +7093,7 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "bincode", @@ -7094,7 +7112,7 @@ dependencies = [ "solana-bpf-loader-program", "solana-clock", "solana-cpi", - "solana-curve25519", + "solana-curve25519 3.0.0", "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", @@ -7125,7 +7143,7 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "static_assertions", "test-case", @@ -7134,7 +7152,7 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program-tests" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "bincode", @@ -7154,7 +7172,7 @@ dependencies = [ [[package]] name = "solana-bucket-map" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bv", "bytemuck", @@ -7174,7 +7192,7 @@ dependencies = [ [[package]] name = "solana-builtins" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-bpf-loader-program", @@ -7193,7 +7211,7 @@ dependencies = [ [[package]] name = "solana-builtins-default-costs" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "ahash 0.8.11", @@ -7213,7 +7231,7 @@ dependencies = [ [[package]] name = "solana-cargo-build-sbf" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_cmd", "bzip2", @@ -7223,7 +7241,7 @@ dependencies = [ "log", "predicates", "regex", - "reqwest 0.12.15", + "reqwest 0.12.19", "semver 1.0.26", "serial_test", "solana-file-download", @@ -7234,7 +7252,7 @@ dependencies = [ [[package]] name = "solana-cargo-test-sbf" -version = "2.3.0" +version = "3.0.0" dependencies = [ "cargo_metadata", "clap 3.2.23", @@ -7246,7 +7264,7 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "chrono", @@ -7276,7 +7294,7 @@ dependencies = [ [[package]] name = "solana-clap-v3-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "chrono", @@ -7308,7 +7326,7 @@ dependencies = [ [[package]] name = "solana-cli" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -7325,13 +7343,14 @@ dependencies = [ "log", "num-traits", "pretty-hex", - "reqwest 0.12.15", + "reqwest 0.12.19", "semver 1.0.26", "serde", "serde_derive", "serde_json", "solana-account", "solana-account-decoder", + "solana-address-lookup-table-interface", "solana-borsh", "solana-bpf-loader-program", "solana-clap-utils", @@ -7342,6 +7361,7 @@ dependencies = [ "solana-cluster-type", "solana-commitment-config", "solana-compute-budget-interface", + "solana-config-interface", "solana-config-program-client", "solana-connection-cache", "solana-decode-error", @@ -7365,7 +7385,6 @@ dependencies = [ "solana-offchain-message", "solana-packet", "solana-presigner", - "solana-program", "solana-program-runtime", "solana-pubkey", "solana-pubsub-client", @@ -7404,7 +7423,7 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "dirs-next", @@ -7418,7 +7437,7 @@ dependencies = [ [[package]] name = "solana-cli-output" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "agave-reserved-account-keys", @@ -7445,16 +7464,16 @@ dependencies = [ "solana-message", "solana-native-token", "solana-packet", - "solana-program", "solana-pubkey", "solana-rpc-client-api", "solana-sdk-ids", "solana-signature", "solana-signer", + "solana-stake-interface", "solana-system-interface", "solana-sysvar", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-vote-program", @@ -7463,7 +7482,7 @@ dependencies = [ [[package]] name = "solana-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -7509,7 +7528,7 @@ dependencies = [ [[package]] name = "solana-client-test" -version = "2.3.0" +version = "3.0.0" dependencies = [ "futures-util", "serde_json", @@ -7586,8 +7605,6 @@ checksum = "7ace9fea2daa28354d107ea879cff107181d85cd4e0f78a2bedb10e1a428c97e" dependencies = [ "serde", "serde_derive", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", ] @@ -7603,7 +7620,7 @@ dependencies = [ [[package]] name = "solana-compute-budget" -version = "2.3.0" +version = "3.0.0" dependencies = [ "qualifier_attr", "solana-fee-structure", @@ -7613,7 +7630,7 @@ dependencies = [ [[package]] name = "solana-compute-budget-instruction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -7629,10 +7646,10 @@ dependencies = [ "solana-keypair", "solana-message", "solana-packet", - "solana-program", "solana-pubkey", "solana-sdk-ids", "solana-signer", + "solana-stake-interface", "solana-svm-transaction", "solana-system-interface", "solana-transaction", @@ -7647,22 +7664,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8432d2c4c22d0499aa06d62e4f7e333f81777b3d7c96050ae9e5cb71a8c3aee4" dependencies = [ "borsh 1.5.7", - "serde", - "serde_derive", "solana-instruction", "solana-sdk-ids", ] [[package]] name = "solana-compute-budget-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-program-runtime", ] [[package]] name = "solana-compute-budget-program-bench" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "criterion", @@ -7675,22 +7690,40 @@ dependencies = [ "solana-svm-transaction", ] +[[package]] +name = "solana-config-interface" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbdbcfedb467322ac9686ca61da0a1fdede2fd99a01fb2ed52b49452abd22e0" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-short-vec", + "solana-system-interface", +] + [[package]] name = "solana-config-program-client" -version = "0.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53aceac36f105fd4922e29b4f0c1f785b69d7b3e7e387e384b8985c8e0c3595e" +checksum = "ef9867b9ffae6e48a97ce6349e7796fcb34084298e909a8fa1fe427f41b52fd4" dependencies = [ "bincode", "borsh 0.10.3", "kaigan", "serde", + "solana-config-interface", "solana-program", ] [[package]] name = "solana-connection-cache" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -7715,7 +7748,7 @@ dependencies = [ [[package]] name = "solana-core" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "agave-feature-set", @@ -7735,6 +7768,7 @@ dependencies = [ "criterion", "crossbeam-channel", "dashmap", + "derive_more 1.0.0", "etcd-client", "fs_extra", "futures 0.3.31", @@ -7813,7 +7847,6 @@ dependencies = [ "solana-runtime", "solana-runtime-transaction", "solana-sanitize", - "solana-sdk", "solana-sdk-ids", "solana-send-transaction-service", "solana-sha256-hasher", @@ -7865,7 +7898,7 @@ dependencies = [ [[package]] name = "solana-cost-model" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -7925,7 +7958,21 @@ dependencies = [ [[package]] name = "solana-curve25519" -version = "2.3.0" +version = "2.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def3cfe5279edb64fc39111cff6dcf77b01fbfba2c02c13ced41e6a48baf4cbe" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-define-syscall", + "subtle", + "thiserror 2.0.12", +] + +[[package]] +name = "solana-curve25519" +version = "3.0.0" dependencies = [ "bytemuck", "bytemuck_derive", @@ -7963,7 +8010,7 @@ dependencies = [ [[package]] name = "solana-dos" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "clap 3.2.23", @@ -8006,7 +8053,7 @@ dependencies = [ [[package]] name = "solana-download-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-clock", @@ -8017,9 +8064,9 @@ dependencies = [ [[package]] name = "solana-ed25519-program" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0fc717048fdbe5d2ee7d673d73e6a30a094002f4a29ca7630ac01b6bddec04" +checksum = "a1feafa1691ea3ae588f99056f4bdd1293212c7ece28243d7da257c443e84753" dependencies = [ "bytemuck", "bytemuck_derive", @@ -8032,7 +8079,7 @@ dependencies = [ [[package]] name = "solana-ed25519-program-tests" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "ed25519-dalek", @@ -8048,7 +8095,7 @@ dependencies = [ [[package]] name = "solana-entry" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-reserved-account-keys", "assert_matches", @@ -8097,8 +8144,6 @@ checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" dependencies = [ "serde", "serde_derive", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", "solana-sdk-ids", "solana-sdk-macro", @@ -8154,7 +8199,7 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "clap 2.33.3", @@ -8224,8 +8269,6 @@ dependencies = [ "ahash 0.8.11", "lazy_static", "solana-epoch-schedule", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", "solana-pubkey", "solana-sha256-hasher", @@ -8233,7 +8276,7 @@ dependencies = [ [[package]] name = "solana-fee" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-fee-structure", @@ -8255,9 +8298,9 @@ dependencies = [ [[package]] name = "solana-fee-structure" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f45f94a88efdb512805563181dfa1c85c60a21b6e6d602bf24a2ea88f9399d6e" +checksum = "33adf673581c38e810bf618f745bf31b683a0a4a4377682e6aaac5d9a058dd4e" dependencies = [ "serde", "serde_derive", @@ -8311,7 +8354,7 @@ dependencies = [ [[package]] name = "solana-genesis" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "base64 0.22.1", @@ -8371,8 +8414,6 @@ dependencies = [ "solana-cluster-type", "solana-epoch-schedule", "solana-fee-calculator", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", "solana-inflation", "solana-keypair", @@ -8390,7 +8431,7 @@ dependencies = [ [[package]] name = "solana-genesis-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-accounts-db", @@ -8402,7 +8443,7 @@ dependencies = [ [[package]] name = "solana-geyser-plugin-manager" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-geyser-plugin-interface", "bs58", @@ -8431,7 +8472,7 @@ dependencies = [ [[package]] name = "solana-gossip" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "anyhow", @@ -8551,9 +8592,9 @@ dependencies = [ [[package]] name = "solana-instruction" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce496a475e5062ba5de97215ab39d9c358f9c9df4bb7f3a45a1f1a8bd9065ed" +checksum = "47298e2ce82876b64f71e9d13a46bc4b9056194e7f9937ad3084385befa50885" dependencies = [ "bincode", "borsh 1.5.7", @@ -8600,7 +8641,7 @@ dependencies = [ [[package]] name = "solana-keygen" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bs58", "clap 3.2.23", @@ -8656,7 +8697,7 @@ dependencies = [ [[package]] name = "solana-lattice-hash" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "blake3", @@ -8669,7 +8710,7 @@ dependencies = [ [[package]] name = "solana-ledger" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -8755,7 +8796,7 @@ dependencies = [ "solana-time-utils", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-vote", @@ -8835,7 +8876,7 @@ dependencies = [ [[package]] name = "solana-loader-v4-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "log", @@ -8855,13 +8896,13 @@ dependencies = [ "solana-sbpf", "solana-sdk-ids", "solana-sysvar", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", ] [[package]] name = "solana-local-cluster" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "crossbeam-channel", @@ -8927,7 +8968,7 @@ dependencies = [ [[package]] name = "solana-log-analyzer" -version = "2.3.0" +version = "3.0.0" dependencies = [ "byte-unit", "clap 3.2.23", @@ -8940,7 +8981,7 @@ dependencies = [ [[package]] name = "solana-log-collector" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", ] @@ -8960,15 +9001,15 @@ dependencies = [ [[package]] name = "solana-measure" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-memory-management" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-merkle-tree" -version = "2.3.0" +version = "3.0.0" dependencies = [ "fast-math", "hex", @@ -8978,9 +9019,9 @@ dependencies = [ [[package]] name = "solana-message" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6bf99c4570173710107a1f233f3bee226feea5fc817308707d4f7cb100a72d" +checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b" dependencies = [ "bincode", "blake3", @@ -8988,11 +9029,8 @@ dependencies = [ "serde", "serde_derive", "solana-bincode", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", "solana-instruction", - "solana-logger", "solana-pubkey", "solana-sanitize", "solana-sdk-ids", @@ -9004,14 +9042,14 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "env_logger", "gethostname", "log", "rand 0.8.5", - "reqwest 0.12.15", + "reqwest 0.12.19", "serial_test", "solana-cluster-type", "solana-sha256-hasher", @@ -9036,7 +9074,7 @@ checksum = "307fb2f78060995979e9b4f68f833623565ed4e55d3725f100454ce78a99a1a3" [[package]] name = "solana-net-shaper" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 3.2.23", "rand 0.8.5", @@ -9048,7 +9086,7 @@ dependencies = [ [[package]] name = "solana-net-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "bincode", @@ -9102,10 +9140,10 @@ dependencies = [ [[package]] name = "solana-notifier" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", - "reqwest 0.12.15", + "reqwest 0.12.19", "serde_json", "solana-hash", ] @@ -9144,7 +9182,7 @@ dependencies = [ [[package]] name = "solana-perf" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "assert_matches", @@ -9189,11 +9227,12 @@ dependencies = [ [[package]] name = "solana-poh" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "bincode", "core_affinity", + "criterion", "crossbeam-channel", "log", "qualifier_attr", @@ -9221,7 +9260,7 @@ dependencies = [ [[package]] name = "solana-poh-bench" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 3.2.23", "log", @@ -9243,13 +9282,11 @@ checksum = "d650c3b4b9060082ac6b0efbbb66865089c58405bfb45de449f3f2b91eccee75" dependencies = [ "serde", "serde_derive", - "solana-frozen-abi", - "solana-frozen-abi-macro", ] [[package]] name = "solana-poseidon" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ark-bn254", "light-poseidon", @@ -9259,9 +9296,9 @@ dependencies = [ [[package]] name = "solana-precompile-error" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff64daa2933c22982b323d88d0cdf693201ef56ac381ae16737fd5f579e07d6" +checksum = "4d87b2c1f5de77dfe2b175ee8dd318d196aaca4d0f66f02842f80c852811f9f8" dependencies = [ "num-traits", "solana-decode-error", @@ -9336,8 +9373,6 @@ dependencies = [ "solana-example-mocks", "solana-feature-gate-interface", "solana-fee-calculator", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", "solana-instruction", "solana-instructions-sysvar", @@ -9391,9 +9426,9 @@ dependencies = [ [[package]] name = "solana-program-error" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8ae2c1a8d0d4ae865882d5770a7ebca92bab9c685e43f0461682c6c05a35bfa" +checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" dependencies = [ "borsh 1.5.7", "num-traits", @@ -9407,11 +9442,10 @@ dependencies = [ [[package]] name = "solana-program-memory" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b0268f6c89825fb634a34bd0c3b8fdaeaecfc3728be1d622a8ee6dd577b60d4" +checksum = "10a3ff409c17fba997b67e4e3eb996467221c62fb737fed995e4c3accefc2ab5" dependencies = [ - "num-traits", "solana-define-syscall", ] @@ -9432,7 +9466,7 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "base64 0.22.1", @@ -9471,7 +9505,7 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "test-case", "thiserror 2.0.12", @@ -9479,7 +9513,7 @@ dependencies = [ [[package]] name = "solana-program-test" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -9514,6 +9548,7 @@ dependencies = [ "solana-msg", "solana-native-token", "solana-poh-config", + "solana-program", "solana-program-entrypoint", "solana-program-error", "solana-program-runtime", @@ -9521,9 +9556,7 @@ dependencies = [ "solana-rent", "solana-runtime", "solana-sbpf", - "solana-sdk", "solana-sdk-ids", - "solana-sdk-macro", "solana-signer", "solana-stable-layout", "solana-stake-interface", @@ -9534,7 +9567,7 @@ dependencies = [ "solana-sysvar-id", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-vote-program", "spl-generic-token", @@ -9575,7 +9608,7 @@ dependencies = [ [[package]] name = "solana-pubsub-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "crossbeam-channel", @@ -9602,7 +9635,7 @@ dependencies = [ [[package]] name = "solana-quic-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-lock", "async-trait", @@ -9643,14 +9676,14 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "2.3.0" +version = "3.0.0" dependencies = [ "num_cpus", ] [[package]] name = "solana-remote-wallet" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "console", @@ -9715,18 +9748,6 @@ dependencies = [ "solana-reward-info", ] -[[package]] -name = "solana-reserved-account-keys" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b293f4246626c0e0a991531f08848a713ada965612e99dc510963f04d12cae7" -dependencies = [ - "lazy_static", - "solana-feature-set", - "solana-pubkey", - "solana-sdk-ids", -] - [[package]] name = "solana-reward-info" version = "2.2.1" @@ -9735,13 +9756,11 @@ checksum = "18205b69139b1ae0ab8f6e11cdcb627328c0814422ad2482000fa2ca54ae4a2f" dependencies = [ "serde", "serde_derive", - "solana-frozen-abi", - "solana-frozen-abi-macro", ] [[package]] name = "solana-rpc" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -9809,6 +9828,7 @@ dependencies = [ "solana-rpc-client-api", "solana-runtime", "solana-runtime-transaction", + "solana-sdk-ids", "solana-send-transaction-service", "solana-sha256-hasher", "solana-signature", @@ -9825,7 +9845,7 @@ dependencies = [ "solana-time-utils", "solana-tpu-client", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-validator-exit", @@ -9847,7 +9867,7 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "async-trait", @@ -9860,7 +9880,7 @@ dependencies = [ "jsonrpc-core", "jsonrpc-http-server", "log", - "reqwest 0.12.15", + "reqwest 0.12.19", "reqwest-middleware", "semver 1.0.26", "serde", @@ -9878,7 +9898,6 @@ dependencies = [ "solana-instruction", "solana-keypair", "solana-message", - "solana-program", "solana-pubkey", "solana-rpc-client-api", "solana-signature", @@ -9888,17 +9907,18 @@ dependencies = [ "solana-transaction-error", "solana-transaction-status-client-types", "solana-version", + "solana-vote-interface", "static_assertions", "tokio", ] [[package]] name = "solana-rpc-client-api" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "jsonrpc-core", - "reqwest 0.12.15", + "reqwest 0.12.19", "reqwest-middleware", "serde", "serde_derive", @@ -9914,7 +9934,7 @@ dependencies = [ [[package]] name = "solana-rpc-client-nonce-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "clap 2.33.3", @@ -9943,7 +9963,7 @@ dependencies = [ [[package]] name = "solana-rpc-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bs58", @@ -9968,14 +9988,14 @@ dependencies = [ [[package]] name = "solana-rpc-test" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "bs58", "crossbeam-channel", "futures-util", "log", - "reqwest 0.12.15", + "reqwest 0.12.19", "serde", "serde_json", "solana-account-decoder", @@ -10006,7 +10026,7 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-precompiles", @@ -10099,7 +10119,6 @@ dependencies = [ "solana-perf", "solana-poh-config", "solana-precompile-error", - "solana-program", "solana-program-runtime", "solana-pubkey", "solana-rayon-threadlimit", @@ -10109,9 +10128,7 @@ dependencies = [ "solana-reward-info", "solana-runtime", "solana-runtime-transaction", - "solana-sdk", "solana-sdk-ids", - "solana-sdk-macro", "solana-secp256k1-program", "solana-seed-derivable", "solana-serde", @@ -10134,7 +10151,7 @@ dependencies = [ "solana-time-utils", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status-client-types", "solana-unified-scheduler-logic", @@ -10156,7 +10173,7 @@ dependencies = [ [[package]] name = "solana-runtime-transaction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -10172,7 +10189,6 @@ dependencies = [ "solana-instruction", "solana-keypair", "solana-message", - "solana-program", "solana-pubkey", "solana-sdk-ids", "solana-signature", @@ -10182,6 +10198,7 @@ dependencies = [ "solana-system-transaction", "solana-transaction", "solana-transaction-error", + "solana-vote-interface", "thiserror 2.0.12", ] @@ -10210,77 +10227,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "solana-sdk" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8af90d2ce445440e0548fa4a5f96fe8b265c22041a68c942012ffadd029667d" -dependencies = [ - "bincode", - "bs58", - "getrandom 0.1.16", - "js-sys", - "serde", - "serde_json", - "solana-account", - "solana-bn254", - "solana-client-traits", - "solana-cluster-type", - "solana-commitment-config", - "solana-compute-budget-interface", - "solana-decode-error", - "solana-derivation-path", - "solana-ed25519-program", - "solana-epoch-info", - "solana-epoch-rewards-hasher", - "solana-feature-set", - "solana-fee-structure", - "solana-genesis-config", - "solana-hard-forks", - "solana-inflation", - "solana-instruction", - "solana-keypair", - "solana-message", - "solana-native-token", - "solana-nonce-account", - "solana-offchain-message", - "solana-packet", - "solana-poh-config", - "solana-precompile-error", - "solana-precompiles", - "solana-presigner", - "solana-program", - "solana-program-memory", - "solana-pubkey", - "solana-quic-definitions", - "solana-rent-collector", - "solana-rent-debits", - "solana-reserved-account-keys", - "solana-reward-info", - "solana-sanitize", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-secp256k1-program", - "solana-secp256k1-recover", - "solana-secp256r1-program", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-serde", - "solana-serde-varint", - "solana-short-vec", - "solana-shred-version", - "solana-signature", - "solana-signer", - "solana-system-transaction", - "solana-time-utils", - "solana-transaction", - "solana-transaction-context 2.2.1", - "solana-transaction-error", - "solana-validator-exit", - "thiserror 2.0.12", - "wasm-bindgen", -] - [[package]] name = "solana-sdk-ids" version = "2.2.1" @@ -10333,9 +10279,9 @@ dependencies = [ [[package]] name = "solana-secp256r1-program" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cda2aa1bbaceda14763c4f142a00b486f2f262cfd901bd0410649ad0404d5f7" +checksum = "cf903cbdc36a161533812f90acfccdb434ed48982bd5dd71f3217930572c4a80" dependencies = [ "bytemuck", "openssl", @@ -10373,7 +10319,7 @@ dependencies = [ [[package]] name = "solana-send-transaction-service" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "crossbeam-channel", @@ -10534,7 +10480,7 @@ dependencies = [ [[package]] name = "solana-stake-accounts" -version = "2.3.0" +version = "3.0.0" dependencies = [ "clap 2.33.3", "solana-account", @@ -10586,7 +10532,7 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -10615,7 +10561,7 @@ dependencies = [ "solana-svm-feature-set", "solana-sysvar", "solana-sysvar-id", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "solana-vote-interface", "solana-vote-program", @@ -10624,7 +10570,7 @@ dependencies = [ [[package]] name = "solana-stake-program-tests" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -10647,7 +10593,7 @@ dependencies = [ [[package]] name = "solana-storage-bigtable" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-reserved-account-keys", "backoff", @@ -10680,7 +10626,7 @@ dependencies = [ "solana-system-transaction", "solana-time-utils", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "thiserror 2.0.12", @@ -10691,7 +10637,7 @@ dependencies = [ [[package]] name = "solana-storage-proto" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "bs58", @@ -10707,7 +10653,7 @@ dependencies = [ "solana-serde", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "tonic-build", @@ -10715,7 +10661,7 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "async-channel", @@ -10763,7 +10709,7 @@ dependencies = [ [[package]] name = "solana-svm" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -10817,7 +10763,6 @@ dependencies = [ "solana-rent-collector", "solana-rent-debits", "solana-sbpf", - "solana-sdk", "solana-sdk-ids", "solana-secp256k1-program", "solana-secp256r1-program", @@ -10837,7 +10782,7 @@ dependencies = [ "solana-sysvar-id", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-type-overrides", "spl-generic-token", @@ -10848,7 +10793,7 @@ dependencies = [ [[package]] name = "solana-svm-callback" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-precompile-error", @@ -10857,7 +10802,7 @@ dependencies = [ [[package]] name = "solana-svm-conformance" -version = "2.3.0" +version = "3.0.0" dependencies = [ "prost", "prost-build", @@ -10866,11 +10811,11 @@ dependencies = [ [[package]] name = "solana-svm-feature-set" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-svm-rent-collector" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-clock", @@ -10879,13 +10824,13 @@ dependencies = [ "solana-rent", "solana-rent-collector", "solana-sdk-ids", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", ] [[package]] name = "solana-svm-transaction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-hash", "solana-message", @@ -10917,7 +10862,7 @@ dependencies = [ [[package]] name = "solana-system-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -10945,7 +10890,7 @@ dependencies = [ "solana-svm-feature-set", "solana-system-interface", "solana-sysvar", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", ] @@ -10983,8 +10928,6 @@ dependencies = [ "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", "solana-instruction", "solana-instructions-sysvar", @@ -11015,7 +10958,7 @@ dependencies = [ [[package]] name = "solana-test-validator" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "base64 0.22.1", @@ -11062,7 +11005,7 @@ dependencies = [ [[package]] name = "solana-thin-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "log", @@ -11096,7 +11039,7 @@ checksum = "6af261afb0e8c39252a04d026e3ea9c405342b08c871a2ad8aa5448e068c784c" [[package]] name = "solana-timings" -version = "2.3.0" +version = "3.0.0" dependencies = [ "eager", "enum-iterator", @@ -11105,7 +11048,7 @@ dependencies = [ [[package]] name = "solana-tls-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "rustls 0.23.27", "solana-keypair", @@ -11116,7 +11059,7 @@ dependencies = [ [[package]] name = "solana-tokens" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "bincode", @@ -11163,7 +11106,7 @@ dependencies = [ [[package]] name = "solana-tps-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-account", @@ -11194,7 +11137,7 @@ dependencies = [ [[package]] name = "solana-tpu-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -11226,7 +11169,7 @@ dependencies = [ [[package]] name = "solana-tpu-client-next" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "crossbeam-channel", @@ -11267,12 +11210,9 @@ dependencies = [ "serde_derive", "solana-bincode", "solana-feature-set", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-hash", "solana-instruction", "solana-keypair", - "solana-logger", "solana-message", "solana-precompiles", "solana-pubkey", @@ -11288,23 +11228,7 @@ dependencies = [ [[package]] name = "solana-transaction-context" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5022de04cbba05377f68bf848c8c1322ead733f88a657bf792bb40f3257b8218" -dependencies = [ - "bincode", - "serde", - "serde_derive", - "solana-account", - "solana-instruction", - "solana-pubkey", - "solana-rent", - "solana-signature", -] - -[[package]] -name = "solana-transaction-context" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "serde", @@ -11318,13 +11242,13 @@ dependencies = [ "solana-sdk-ids", "solana-signature", "solana-system-interface", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "static_assertions", ] [[package]] name = "solana-transaction-dos" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "clap 2.33.3", @@ -11375,7 +11299,7 @@ dependencies = [ [[package]] name = "solana-transaction-metrics-tracker" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -11393,7 +11317,7 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "agave-reserved-account-keys", @@ -11437,7 +11361,7 @@ dependencies = [ [[package]] name = "solana-transaction-status-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -11451,14 +11375,14 @@ dependencies = [ "solana-reward-info", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "thiserror 2.0.12", ] [[package]] name = "solana-turbine" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-xdp", @@ -11515,7 +11439,7 @@ dependencies = [ [[package]] name = "solana-type-overrides" -version = "2.3.0" +version = "3.0.0" dependencies = [ "futures 0.3.31", "rand 0.8.5", @@ -11524,7 +11448,7 @@ dependencies = [ [[package]] name = "solana-udp-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "solana-connection-cache", @@ -11539,7 +11463,7 @@ dependencies = [ [[package]] name = "solana-unified-scheduler-logic" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "solana-instruction", @@ -11553,7 +11477,7 @@ dependencies = [ [[package]] name = "solana-unified-scheduler-pool" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "aquamarine", @@ -11592,7 +11516,7 @@ dependencies = [ [[package]] name = "solana-upload-perf" -version = "2.3.0" +version = "3.0.0" dependencies = [ "serde_json", "solana-metrics", @@ -11606,7 +11530,7 @@ checksum = "7bbf6d7a3c0b28dd5335c52c0e9eae49d0ae489a8f324917faf0ded65a812c1d" [[package]] name = "solana-version" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "rand 0.8.5", @@ -11621,7 +11545,7 @@ dependencies = [ [[package]] name = "solana-vortexor" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "assert_matches", @@ -11675,7 +11599,7 @@ dependencies = [ [[package]] name = "solana-vortexor-receiver" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "solana-perf", @@ -11684,7 +11608,7 @@ dependencies = [ [[package]] name = "solana-vote" -version = "2.3.0" +version = "3.0.0" dependencies = [ "arbitrary", "bincode", @@ -11745,7 +11669,7 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -11777,7 +11701,7 @@ dependencies = [ "solana-signer", "solana-slot-hashes", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-vote-interface", "test-case", "thiserror 2.0.12", @@ -11785,7 +11709,7 @@ dependencies = [ [[package]] name = "solana-wen-restart" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "assert_matches", @@ -11806,7 +11730,6 @@ dependencies = [ "solana-keypair", "solana-ledger", "solana-logger", - "solana-program", "solana-pubkey", "solana-runtime", "solana-shred-version", @@ -11815,13 +11738,14 @@ dependencies = [ "solana-time-utils", "solana-timings", "solana-vote", + "solana-vote-interface", "solana-vote-program", "tempfile", ] [[package]] name = "solana-zk-elgamal-proof-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bytemuck", "criterion", @@ -11832,12 +11756,12 @@ dependencies = [ "solana-log-collector", "solana-program-runtime", "solana-sdk-ids", - "solana-zk-sdk", + "solana-zk-sdk 3.0.0", ] [[package]] name = "solana-zk-elgamal-proof-program-tests" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bytemuck", "solana-account", @@ -11851,12 +11775,12 @@ dependencies = [ "solana-system-interface", "solana-transaction", "solana-transaction-error", - "solana-zk-sdk", + "solana-zk-sdk 3.0.0", ] [[package]] name = "solana-zk-keygen" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bs58", "clap 3.2.23", @@ -11875,7 +11799,44 @@ dependencies = [ [[package]] name = "solana-zk-sdk" -version = "2.3.0" +version = "2.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15045540c315a9b8ea056323e73320e76098dfdaac9e65b1b33fe9c2f3c9b9e1" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "js-sys", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-derivation-path", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", + "subtle", + "thiserror 2.0.12", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-zk-sdk" +version = "3.0.0" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -11911,7 +11872,7 @@ dependencies = [ [[package]] name = "solana-zk-token-proof-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bytemuck", @@ -11928,7 +11889,7 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "2.3.0" +version = "3.0.0" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -11945,7 +11906,7 @@ dependencies = [ "serde_derive", "serde_json", "sha3", - "solana-curve25519", + "solana-curve25519 3.0.0", "solana-derivation-path", "solana-instruction", "solana-keypair", @@ -12056,7 +12017,7 @@ dependencies = [ "solana-sdk-ids", "solana-system-interface", "solana-sysvar", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-pod", "spl-token-confidential-transfer-proof-extraction", ] @@ -12116,7 +12077,7 @@ dependencies = [ "solana-program-error", "solana-program-option", "solana-pubkey", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "thiserror 2.0.12", ] @@ -12226,7 +12187,7 @@ dependencies = [ "solana-security-txt", "solana-system-interface", "solana-sysvar", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-elgamal-registry", "spl-memo", "spl-pod", @@ -12249,8 +12210,8 @@ checksum = "94ab20faf7b5edaa79acd240e0f21d5a2ef936aa99ed98f698573a2825b299c4" dependencies = [ "base64 0.22.1", "bytemuck", - "solana-curve25519", - "solana-zk-sdk", + "solana-curve25519 2.2.15", + "solana-zk-sdk 2.2.15", ] [[package]] @@ -12261,14 +12222,14 @@ checksum = "fe2629860ff04c17bafa9ba4bed8850a404ecac81074113e1f840dbd0ebb7bd6" dependencies = [ "bytemuck", "solana-account-info", - "solana-curve25519", + "solana-curve25519 2.2.15", "solana-instruction", "solana-instructions-sysvar", "solana-msg", "solana-program-error", "solana-pubkey", "solana-sdk-ids", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-pod", "thiserror 2.0.12", ] @@ -12280,7 +12241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae5b124840d4aed474cef101d946a798b806b46a509ee4df91021e1ab1cef3ef" dependencies = [ "curve25519-dalek 4.1.3", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "thiserror 2.0.12", ] @@ -13066,7 +13027,7 @@ dependencies = [ "percent-encoding 2.3.1", "pin-project", "prost", - "rustls-pemfile 1.0.0", + "rustls-pemfile", "tokio", "tokio-rustls 0.24.1", "tokio-stream", @@ -13125,6 +13086,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.1", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -13618,6 +13597,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.2.2" @@ -13698,7 +13686,7 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-result 0.1.1", + "windows-result", "windows-targets 0.52.6", ] @@ -13708,17 +13696,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result 0.3.1", - "windows-strings", - "windows-targets 0.53.0", -] - [[package]] name = "windows-result" version = "0.1.1" @@ -13728,24 +13705,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-result" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -13821,29 +13780,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -13862,12 +13805,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -13886,12 +13823,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -13910,24 +13841,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -13946,12 +13865,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -13970,12 +13883,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -13994,12 +13901,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -14018,12 +13919,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" version = "0.5.16" diff --git a/Cargo.toml b/Cargo.toml index de92aaedc1e2e0..64595a07ca96f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,19 +1,3 @@ -[profile.release-with-debug] -inherits = "release" -debug = true -split-debuginfo = "packed" -lto = false # Preserve the 'thin local LTO' for this build. - -[profile.release] -split-debuginfo = "unpacked" -lto = "thin" - -[profile.release-with-lto] -inherits = "release" -split-debuginfo = "unpacked" -lto = "thin" -codegen-units = 1 - [workspace] members = [ "account-decoder", @@ -165,13 +149,16 @@ exclude = ["programs/sbf", "svm/examples", "svm/tests/example-programs"] resolver = "2" [workspace.package] -version = "2.3.0" +version = "3.0.0" authors = ["Anza Maintainers "] repository = "https://github.com/anza-xyz/agave" homepage = "https://anza.xyz/" license = "Apache-2.0" edition = "2021" +[workspace.lints.rust] +warnings = "deny" + [workspace.lints.rust.unexpected_cfgs] level = "warn" check-cfg = [ @@ -179,9 +166,6 @@ check-cfg = [ 'cfg(feature, values("frozen-abi", "no-entrypoint"))', ] -[workspace.lints.rust] -warnings = "deny" - # Clippy lint configuration that can not be applied in clippy.toml [workspace.lints.clippy] arithmetic_side_effects = "deny" @@ -191,18 +175,19 @@ used_underscore_binding = "deny" [workspace.dependencies] Inflector = "0.11.4" -axum = "0.7.9" -aya = "0.13" -agave-banking-stage-ingress-types = { path = "banking-stage-ingress-types", version = "=2.3.0" } -agave-feature-set = { path = "feature-set", version = "=2.3.0" } -agave-precompiles = { path = "precompiles", version = "=2.3.0" } -agave-reserved-account-keys = { path = "reserved-account-keys", version = "=2.3.0" } -agave-transaction-view = { path = "transaction-view", version = "=2.3.0" } -agave-xdp = { path = "xdp", version = "=2.3.0" } -aquamarine = "0.6.0" aes-gcm-siv = "0.11.1" +agave-banking-stage-ingress-types = { path = "banking-stage-ingress-types", version = "=3.0.0" } +agave-cargo-registry = { path = "cargo-registry", version = "=3.0.0" } +agave-feature-set = { path = "feature-set", version = "=3.0.0" } +agave-geyser-plugin-interface = { path = "geyser-plugin-interface", version = "=3.0.0" } +agave-precompiles = { path = "precompiles", version = "=3.0.0" } +agave-reserved-account-keys = { path = "reserved-account-keys", version = "=3.0.0" } +agave-thread-manager = { path = "thread-manager", version = "=3.0.0" } +agave-transaction-view = { path = "transaction-view", version = "=3.0.0" } +agave-xdp = { path = "xdp", version = "=3.0.0" } ahash = "0.8.11" anyhow = "1.0.98" +aquamarine = "0.6.0" arbitrary = "1.4.1" ark-bn254 = "0.4.0" ark-ec = "0.4.0" @@ -217,6 +202,8 @@ async-channel = "1.9.0" async-lock = "3.4.0" async-trait = "0.1.88" atty = "0.2.11" +axum = "0.7.9" +aya = "0.13" backoff = "0.4.0" base64 = "0.22.1" bincode = "1.3.3" @@ -233,18 +220,18 @@ bytes = "1.10" bzip2 = "0.4.4" caps = "0.5.5" cargo_metadata = "0.15.4" -cfg_eval = "0.1.2" cfg-if = "1.0.0" +cfg_eval = "0.1.2" chrono = { version = "0.4.41", default-features = false } chrono-humanize = "0.2.3" clap = "2.33.1" +# Remove this dependency when procedural macros will support non-inline modules. +conditional-mod = "0.1.0" console = "0.15.11" console_error_panic_hook = "0.1.7" console_log = "0.2.2" const_format = "0.2.34" core_affinity = "0.5.10" -# Remove this dependency when procedural macros will support non-inline modules. -conditional-mod = "0.1.0" criterion = "0.5.1" criterion-stats = "0.3.0" crossbeam-channel = "0.5.15" @@ -269,8 +256,8 @@ env_logger = "0.9.3" etcd-client = "0.11.1" fast-math = "0.1" fd-lock = "3.0.13" -flate2 = "1.0.31" five8_const = "0.1.4" +flate2 = "1.0.31" fnv = "1.0.7" fs_extra = "1.3.0" futures = "0.3.31" @@ -324,7 +311,7 @@ nix = "0.30.1" num-bigint = "0.4.6" num-derive = "0.4" num-traits = "0.2" -num_cpus = "1.16.0" +num_cpus = "1.17.0" num_enum = "0.7.3" openssl = "0.10" parking_lot = "0.12" @@ -353,7 +340,7 @@ rand_chacha0-2 = { package = "rand_chacha", version = "0.2.2" } rayon = "1.10.0" reed-solomon-erasure = "6.0.0" regex = "1.11.1" -reqwest = { version = "0.12.15", default-features = false } +reqwest = { version = "0.12.19", default-features = false } reqwest-middleware = "0.4.2" rolling-file = "0.2.0" rpassword = "7.4" @@ -377,209 +364,203 @@ siphasher = "1.0.1" slab = "0.4.9" smallvec = "1.15.0" smpl_jwt = "0.7.1" -socket2 = "0.5.9" +socket2 = "0.5.10" soketto = "0.7" solana-account = "2.2.1" -solana-account-decoder = { path = "account-decoder", version = "=2.3.0" } -solana-account-decoder-client-types = { path = "account-decoder-client-types", version = "=2.3.0" } -solana-account-info = "2.2.1" -solana-accounts-db = { path = "accounts-db", version = "=2.3.0" } +solana-account-decoder = { path = "account-decoder", version = "=3.0.0" } +solana-account-decoder-client-types = { path = "account-decoder-client-types", version = "=3.0.0" } +solana-account-info = "2.3.0" +solana-accounts-db = { path = "accounts-db", version = "=3.0.0" } solana-address-lookup-table-interface = "2.2.2" solana-atomic-u64 = "2.2.1" -solana-banks-client = { path = "banks-client", version = "=2.3.0" } -solana-banks-interface = { path = "banks-interface", version = "=2.3.0" } -solana-banks-server = { path = "banks-server", version = "=2.3.0" } -solana-bench-tps = { path = "bench-tps", version = "=2.3.0" } +solana-banks-client = { path = "banks-client", version = "=3.0.0" } +solana-banks-interface = { path = "banks-interface", version = "=3.0.0" } +solana-banks-server = { path = "banks-server", version = "=3.0.0" } +solana-bench-tps = { path = "bench-tps", version = "=3.0.0" } solana-big-mod-exp = "2.2.1" solana-bincode = "2.2.1" solana-blake3-hasher = "2.2.1" -solana-bloom = { path = "bloom", version = "=2.3.0" } +solana-bloom = { path = "bloom", version = "=3.0.0" } solana-bn254 = "2.2.2" solana-borsh = "2.2.1" -solana-bpf-loader-program = { path = "programs/bpf_loader", version = "=2.3.0" } -solana-bucket-map = { path = "bucket_map", version = "=2.3.0" } -solana-builtins = { path = "builtins", version = "=2.3.0" } -solana-builtins-default-costs = { path = "builtins-default-costs", version = "=2.3.0" } -agave-cargo-registry = { path = "cargo-registry", version = "=2.3.0" } -agave-thread-manager = { path = "thread-manager", version = "=2.3.0" } -solana-clap-utils = { path = "clap-utils", version = "=2.3.0" } -solana-clap-v3-utils = { path = "clap-v3-utils", version = "=2.3.0" } -solana-cli = { path = "cli", version = "=2.3.0" } -solana-cli-config = { path = "cli-config", version = "=2.3.0" } -solana-cli-output = { path = "cli-output", version = "=2.3.0" } -solana-client = { path = "client", version = "=2.3.0" } +solana-bpf-loader-program = { path = "programs/bpf_loader", version = "=3.0.0" } +solana-bucket-map = { path = "bucket_map", version = "=3.0.0" } +solana-builtins = { path = "builtins", version = "=3.0.0" } +solana-builtins-default-costs = { path = "builtins-default-costs", version = "=3.0.0" } +solana-clap-utils = { path = "clap-utils", version = "=3.0.0" } +solana-clap-v3-utils = { path = "clap-v3-utils", version = "=3.0.0" } +solana-cli = { path = "cli", version = "=3.0.0" } +solana-cli-config = { path = "cli-config", version = "=3.0.0" } +solana-cli-output = { path = "cli-output", version = "=3.0.0" } +solana-client = { path = "client", version = "=3.0.0" } solana-client-traits = "2.2.1" solana-clock = "2.2.2" solana-cluster-type = "2.2.1" solana-commitment-config = "2.2.1" -solana-compute-budget = { path = "compute-budget", version = "=2.3.0" } -solana-compute-budget-instruction = { path = "compute-budget-instruction", version = "=2.3.0" } +solana-compute-budget = { path = "compute-budget", version = "=3.0.0" } +solana-compute-budget-instruction = { path = "compute-budget-instruction", version = "=3.0.0" } solana-compute-budget-interface = "2.2.2" -solana-compute-budget-program = { path = "programs/compute-budget", version = "=2.3.0" } -solana-config-program-client = "0.0.2" -solana-connection-cache = { path = "connection-cache", version = "=2.3.0", default-features = false } -solana-core = { path = "core", version = "=2.3.0" } -solana-cost-model = { path = "cost-model", version = "=2.3.0" } +solana-compute-budget-program = { path = "programs/compute-budget", version = "=3.0.0" } +solana-config-interface = "1.0.0" +solana-config-program-client = "1.1.0" +solana-connection-cache = { path = "connection-cache", version = "=3.0.0", default-features = false } +solana-core = { path = "core", version = "=3.0.0" } +solana-cost-model = { path = "cost-model", version = "=3.0.0" } solana-cpi = "2.2.1" -solana-curve25519 = { path = "curves/curve25519", version = "=2.3.0" } +solana-curve25519 = { path = "curves/curve25519", version = "=3.0.0" } solana-decode-error = "2.2.1" solana-define-syscall = "2.3.0" solana-derivation-path = "2.2.1" -solana-download-utils = { path = "download-utils", version = "=2.3.0" } -solana-ed25519-program = "2.2.2" -solana-entry = { path = "entry", version = "=2.3.0" } -solana-program-entrypoint = "2.2.1" +solana-download-utils = { path = "download-utils", version = "=3.0.0" } +solana-ed25519-program = "2.2.3" +solana-entry = { path = "entry", version = "=3.0.0" } solana-epoch-info = "2.2.1" solana-epoch-rewards = "2.2.1" solana-epoch-rewards-hasher = "2.2.1" solana-epoch-schedule = "2.2.1" solana-example-mocks = "2.2.1" -solana-faucet = { path = "faucet", version = "=2.3.0" } +solana-faucet = { path = "faucet", version = "=3.0.0" } solana-feature-gate-client = "0.0.2" solana-feature-gate-interface = "2.2.2" +solana-fee = { path = "fee", version = "=3.0.0" } solana-fee-calculator = "2.2.1" -solana-fee = { path = "fee", version = "=2.3.0" } -solana-fee-structure = "2.2.1" +solana-fee-structure = "2.3.0" +solana-file-download = "2.2.1" solana-frozen-abi = "2.2.2" solana-frozen-abi-macro = "2.2.1" -solana-tps-client = { path = "tps-client", version = "=2.3.0" } -solana-file-download = "2.2.1" -solana-genesis = { path = "genesis", version = "=2.3.0" } +solana-genesis = { path = "genesis", version = "=3.0.0" } solana-genesis-config = "2.2.1" -solana-genesis-utils = { path = "genesis-utils", version = "=2.3.0" } -agave-geyser-plugin-interface = { path = "geyser-plugin-interface", version = "=2.3.0" } -solana-geyser-plugin-manager = { path = "geyser-plugin-manager", version = "=2.3.0" } -solana-gossip = { path = "gossip", version = "=2.3.0" } +solana-genesis-utils = { path = "genesis-utils", version = "=3.0.0" } +solana-geyser-plugin-manager = { path = "geyser-plugin-manager", version = "=3.0.0" } +solana-gossip = { path = "gossip", version = "=3.0.0" } solana-hard-forks = "2.2.1" solana-hash = "2.3.0" solana-inflation = "2.2.1" -solana-instruction = "2.2.1" +solana-instruction = "2.3.0" solana-instructions-sysvar = "2.2.2" solana-keccak-hasher = "2.2.1" solana-keypair = "2.2.1" solana-last-restart-slot = "2.2.1" -solana-lattice-hash = { path = "lattice-hash", version = "=2.3.0" } -solana-ledger = { path = "ledger", version = "=2.3.0" } +solana-lattice-hash = { path = "lattice-hash", version = "=3.0.0" } +solana-ledger = { path = "ledger", version = "=3.0.0" } solana-loader-v2-interface = "2.2.1" solana-loader-v3-interface = "5.0.0" solana-loader-v4-interface = "2.2.1" -solana-loader-v4-program = { path = "programs/loader-v4", version = "=2.3.0" } -solana-local-cluster = { path = "local-cluster", version = "=2.3.0" } -solana-log-collector = { path = "log-collector", version = "=2.3.0" } +solana-loader-v4-program = { path = "programs/loader-v4", version = "=3.0.0" } +solana-local-cluster = { path = "local-cluster", version = "=3.0.0" } +solana-log-collector = { path = "log-collector", version = "=3.0.0" } solana-logger = "2.3.1" -solana-measure = { path = "measure", version = "=2.3.0" } -solana-merkle-tree = { path = "merkle-tree", version = "=2.3.0" } -solana-message = "2.3.0" -solana-metrics = { path = "metrics", version = "=2.3.0" } +solana-measure = { path = "measure", version = "=3.0.0" } +solana-merkle-tree = { path = "merkle-tree", version = "=3.0.0" } +solana-message = "2.4.0" +solana-metrics = { path = "metrics", version = "=3.0.0" } solana-msg = "2.2.1" solana-native-token = "2.2.2" -solana-net-utils = { path = "net-utils", version = "=2.3.0" } +solana-net-utils = { path = "net-utils", version = "=3.0.0" } solana-nohash-hasher = "0.2.1" solana-nonce = "2.2.1" solana-nonce-account = "2.2.1" -solana-notifier = { path = "notifier", version = "=2.3.0" } +solana-notifier = { path = "notifier", version = "=3.0.0" } solana-offchain-message = "2.2.1" -solana-package-metadata = "2.2.1" -solana-package-metadata-macro = "2.2.1" solana-packet = "2.2.1" -solana-perf = { path = "perf", version = "=2.3.0" } -solana-poh = { path = "poh", version = "=2.3.0" } +solana-perf = { path = "perf", version = "=3.0.0" } +solana-poh = { path = "poh", version = "=3.0.0" } solana-poh-config = "2.2.1" -solana-poseidon = { path = "poseidon", version = "=2.3.0" } -solana-precompile-error = "2.2.1" +solana-poseidon = { path = "poseidon", version = "=3.0.0" } +solana-precompile-error = "2.2.2" solana-presigner = "2.2.1" solana-program = { version = "2.2.1", default-features = false } -solana-program-error = "2.2.1" -solana-program-memory = "2.2.1" +solana-program-entrypoint = "2.2.1" +solana-program-error = "2.2.2" +solana-program-memory = "2.3.0" solana-program-option = "2.2.1" solana-program-pack = "2.2.1" -solana-program-runtime = { path = "program-runtime", version = "=2.3.0" } -solana-program-test = { path = "program-test", version = "=2.3.0" } +solana-program-runtime = { path = "program-runtime", version = "=3.0.0" } +solana-program-test = { path = "program-test", version = "=3.0.0" } solana-pubkey = { version = "2.4.0", default-features = false } -solana-pubsub-client = { path = "pubsub-client", version = "=2.3.0" } -solana-quic-client = { path = "quic-client", version = "=2.3.0" } +solana-pubsub-client = { path = "pubsub-client", version = "=3.0.0" } +solana-quic-client = { path = "quic-client", version = "=3.0.0" } solana-quic-definitions = "2.2.1" -solana-rayon-threadlimit = { path = "rayon-threadlimit", version = "=2.3.0" } -solana-remote-wallet = { path = "remote-wallet", version = "=2.3.0", default-features = false } +solana-rayon-threadlimit = { path = "rayon-threadlimit", version = "=3.0.0" } +solana-remote-wallet = { path = "remote-wallet", version = "=3.0.0", default-features = false } solana-rent = "2.2.1" solana-rent-collector = "2.2.1" solana-rent-debits = "2.2.1" solana-reward-info = "2.2.1" +solana-rpc = { path = "rpc", version = "=3.0.0" } +solana-rpc-client = { path = "rpc-client", version = "=3.0.0", default-features = false } +solana-rpc-client-api = { path = "rpc-client-api", version = "=3.0.0" } +solana-rpc-client-nonce-utils = { path = "rpc-client-nonce-utils", version = "=3.0.0" } +solana-rpc-client-types = { path = "rpc-client-types", version = "=3.0.0" } +solana-runtime = { path = "runtime", version = "=3.0.0" } +solana-runtime-transaction = { path = "runtime-transaction", version = "=3.0.0" } solana-sanitize = "2.2.1" -solana-secp256r1-program = "2.2.2" +solana-sbpf = "=0.11.1" +solana-sdk-ids = "2.2.1" +solana-secp256k1-program = "2.2.1" +solana-secp256k1-recover = "2.2.1" +solana-secp256r1-program = "2.2.3" solana-seed-derivable = "2.2.1" solana-seed-phrase = "2.2.1" +solana-send-transaction-service = { path = "send-transaction-service", version = "=3.0.0" } solana-serde = "2.2.1" solana-serde-varint = "2.2.2" solana-serialize-utils = "2.2.1" solana-sha256-hasher = "2.2.1" +solana-short-vec = "2.2.1" +solana-shred-version = "2.2.1" solana-signature = { version = "2.3.0", default-features = false } solana-signer = "2.2.1" solana-slot-hashes = "2.2.1" solana-slot-history = "2.2.1" -solana-time-utils = "2.2.1" -solana-timings = { path = "timings", version = "=2.3.0" } -solana-tls-utils = { path = "tls-utils", version = "=2.3.0" } -solana-unified-scheduler-logic = { path = "unified-scheduler-logic", version = "=2.3.0" } -solana-unified-scheduler-pool = { path = "unified-scheduler-pool", version = "=2.3.0" } -solana-rpc = { path = "rpc", version = "=2.3.0" } -solana-rpc-client = { path = "rpc-client", version = "=2.3.0", default-features = false } -solana-rpc-client-api = { path = "rpc-client-api", version = "=2.3.0" } -solana-rpc-client-types = { path = "rpc-client-types", version = "=2.3.0" } -solana-rpc-client-nonce-utils = { path = "rpc-client-nonce-utils", version = "=2.3.0" } -solana-runtime = { path = "runtime", version = "=2.3.0" } -solana-runtime-transaction = { path = "runtime-transaction", version = "=2.3.0" } -solana-sbpf = "=0.11.1" -solana-sdk = { version = "2.2.2", default-features = false } -solana-sdk-ids = "2.2.1" -solana-sdk-macro = "2.2.1" -solana-secp256k1-program = "2.2.1" -solana-secp256k1-recover = "2.2.1" -solana-send-transaction-service = { path = "send-transaction-service", version = "=2.3.0" } -solana-short-vec = "2.2.1" -solana-shred-version = "2.2.1" solana-stable-layout = "2.2.1" solana-stake-interface = { version = "1.2.1" } -solana-stake-program = { path = "programs/stake", version = "=2.3.0" } -solana-storage-bigtable = { path = "storage-bigtable", version = "=2.3.0" } -solana-storage-proto = { path = "storage-proto", version = "=2.3.0" } -solana-streamer = { path = "streamer", version = "=2.3.0" } -solana-svm = { path = "svm", version = "=2.3.0" } -solana-svm-callback = { path = "svm-callback", version = "=2.3.0" } -solana-svm-conformance = { path = "svm-conformance", version = "=2.3.0" } -solana-svm-feature-set = { path = "svm-feature-set", version = "=2.3.0" } -solana-svm-rent-collector = { path = "svm-rent-collector", version = "=2.3.0" } -solana-svm-transaction = { path = "svm-transaction", version = "=2.3.0" } +solana-stake-program = { path = "programs/stake", version = "=3.0.0" } +solana-storage-bigtable = { path = "storage-bigtable", version = "=3.0.0" } +solana-storage-proto = { path = "storage-proto", version = "=3.0.0" } +solana-streamer = { path = "streamer", version = "=3.0.0" } +solana-svm = { path = "svm", version = "=3.0.0" } +solana-svm-callback = { path = "svm-callback", version = "=3.0.0" } +solana-svm-conformance = { path = "svm-conformance", version = "=3.0.0" } +solana-svm-feature-set = { path = "svm-feature-set", version = "=3.0.0" } +solana-svm-rent-collector = { path = "svm-rent-collector", version = "=3.0.0" } +solana-svm-transaction = { path = "svm-transaction", version = "=3.0.0" } solana-system-interface = "1.0" -solana-system-program = { path = "programs/system", version = "=2.3.0" } +solana-system-program = { path = "programs/system", version = "=3.0.0" } solana-system-transaction = "2.2.1" solana-sysvar = "2.2.2" solana-sysvar-id = "2.2.1" -solana-test-validator = { path = "test-validator", version = "=2.3.0" } -solana-thin-client = { path = "thin-client", version = "=2.3.0" } +solana-test-validator = { path = "test-validator", version = "=3.0.0" } +solana-thin-client = { path = "thin-client", version = "=3.0.0" } +solana-time-utils = "2.2.1" +solana-timings = { path = "timings", version = "=3.0.0" } +solana-tls-utils = { path = "tls-utils", version = "=3.0.0" } +solana-tps-client = { path = "tps-client", version = "=3.0.0" } +solana-tpu-client = { path = "tpu-client", version = "=3.0.0", default-features = false } +solana-tpu-client-next = { path = "tpu-client-next", version = "=3.0.0" } solana-transaction = "2.2.2" +solana-transaction-context = { path = "transaction-context", version = "=3.0.0", features = ["bincode", "debug-signature"] } solana-transaction-error = "2.2.1" -solana-tpu-client = { path = "tpu-client", version = "=2.3.0", default-features = false } -solana-tpu-client-next = { path = "tpu-client-next", version = "=2.3.0" } -solana-transaction-context = { path = "transaction-context", version = "=2.3.0", features = ["bincode", "debug-signature"] } -solana-transaction-status = { path = "transaction-status", version = "=2.3.0" } -solana-transaction-status-client-types = { path = "transaction-status-client-types", version = "=2.3.0" } -solana-transaction-metrics-tracker = { path = "transaction-metrics-tracker", version = "=2.3.0" } -solana-turbine = { path = "turbine", version = "=2.3.0" } -solana-type-overrides = { path = "type-overrides", version = "=2.3.0" } -solana-udp-client = { path = "udp-client", version = "=2.3.0" } +solana-transaction-metrics-tracker = { path = "transaction-metrics-tracker", version = "=3.0.0" } +solana-transaction-status = { path = "transaction-status", version = "=3.0.0" } +solana-transaction-status-client-types = { path = "transaction-status-client-types", version = "=3.0.0" } +solana-turbine = { path = "turbine", version = "=3.0.0" } +solana-type-overrides = { path = "type-overrides", version = "=3.0.0" } +solana-udp-client = { path = "udp-client", version = "=3.0.0" } +solana-unified-scheduler-logic = { path = "unified-scheduler-logic", version = "=3.0.0" } +solana-unified-scheduler-pool = { path = "unified-scheduler-pool", version = "=3.0.0" } solana-validator-exit = "2.2.1" -solana-version = { path = "version", version = "=2.3.0" } -solana-vortexor-receiver = { path = "vortexor-receiver", version = "=2.3.0" } -solana-vote = { path = "vote", version = "=2.3.0" } +solana-version = { path = "version", version = "=3.0.0" } +solana-vortexor-receiver = { path = "vortexor-receiver", version = "=3.0.0" } +solana-vote = { path = "vote", version = "=3.0.0" } solana-vote-interface = "2.2.5" -solana-vote-program = { path = "programs/vote", version = "=2.3.0", default-features = false } -solana-wen-restart = { path = "wen-restart", version = "=2.3.0" } -solana-zk-elgamal-proof-program = { path = "programs/zk-elgamal-proof", version = "=2.3.0" } -solana-zk-keygen = { path = "zk-keygen", version = "=2.3.0" } -solana-zk-sdk = { path = "zk-sdk", version = "=2.3.0" } -solana-zk-token-proof-program = { path = "programs/zk-token-proof", version = "=2.3.0" } -solana-zk-token-sdk = { path = "zk-token-sdk", version = "=2.3.0" } +solana-vote-program = { path = "programs/vote", version = "=3.0.0", default-features = false } +solana-wen-restart = { path = "wen-restart", version = "=3.0.0" } +solana-zk-elgamal-proof-program = { path = "programs/zk-elgamal-proof", version = "=3.0.0" } +solana-zk-keygen = { path = "zk-keygen", version = "=3.0.0" } +solana-zk-sdk = { path = "zk-sdk", version = "=3.0.0" } +solana-zk-token-proof-program = { path = "programs/zk-token-proof", version = "=3.0.0" } +solana-zk-token-sdk = { path = "zk-token-sdk", version = "=3.0.0" } spl-associated-token-account = "7.0.0" spl-generic-token = "1.0.1" spl-instruction-padding = "0.3.0" @@ -632,6 +613,22 @@ x509-parser = "0.14.0" zeroize = { version = "1.7", default-features = false } zstd = "0.13.3" +[profile.release-with-debug] +inherits = "release" +debug = true +strip = false +split-debuginfo = "off" + +[profile.release] +split-debuginfo = "unpacked" +lto = "thin" + +[profile.release-with-lto] +inherits = "release" +split-debuginfo = "unpacked" +lto = "thin" +codegen-units = 1 + # curve25519-dalek uses the simd backend by default in v4 if possible, # which has very slow performance on some platforms with opt-level 0, # which is the default for dev and test builds. diff --git a/account-decoder-client-types/Cargo.toml b/account-decoder-client-types/Cargo.toml index 93b8b922b6cd6d..433ecc37929e7c 100644 --- a/account-decoder-client-types/Cargo.toml +++ b/account-decoder-client-types/Cargo.toml @@ -9,6 +9,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + +[features] +zstd = ["dep:zstd"] + [dependencies] base64 = { workspace = true } bs58 = { workspace = true, features = ["std"] } @@ -18,11 +26,3 @@ serde_json = { workspace = true } solana-account = { workspace = true } solana-pubkey = { workspace = true } zstd = { workspace = true, optional = true } - -[features] -zstd = ["dep:zstd"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] -all-features = true -rustdoc-args = ["--cfg=docsrs"] diff --git a/account-decoder/Cargo.toml b/account-decoder/Cargo.toml index 1fa09e52d80eee..eb8f97da89a49c 100644 --- a/account-decoder/Cargo.toml +++ b/account-decoder/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] Inflector = { workspace = true } base64 = { workspace = true } @@ -56,8 +59,5 @@ solana-hash = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } spl-pod = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [lints] workspace = true diff --git a/account-decoder/src/validator_info.rs b/account-decoder/src/validator_info.rs index 9d35b6d75cfa89..e0552d0c76c742 100644 --- a/account-decoder/src/validator_info.rs +++ b/account-decoder/src/validator_info.rs @@ -1,7 +1,6 @@ -use solana_config_program_client::instructions_bincode::ConfigState; - pub const MAX_SHORT_FIELD_LENGTH: usize = 80; pub const MAX_LONG_FIELD_LENGTH: usize = 300; +/// Maximum size of validator configuration data (`ValidatorInfo`). pub const MAX_VALIDATOR_INFO: u64 = 576; solana_pubkey::declare_id!("Va1idator1nfo111111111111111111111111111111"); @@ -10,9 +9,3 @@ solana_pubkey::declare_id!("Va1idator1nfo111111111111111111111111111111"); pub struct ValidatorInfo { pub info: String, } - -impl ConfigState for ValidatorInfo { - fn max_space() -> u64 { - MAX_VALIDATOR_INFO - } -} diff --git a/accounts-bench/Cargo.toml b/accounts-bench/Cargo.toml index 7b893ecce1647a..1cfe16a4052ba5 100644 --- a/accounts-bench/Cargo.toml +++ b/accounts-bench/Cargo.toml @@ -8,6 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [] + [dependencies] clap = { workspace = true } log = { workspace = true } @@ -20,9 +26,3 @@ solana-measure = { workspace = true } solana-pubkey = { workspace = true } solana-rent-collector = { workspace = true } solana-version = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [] diff --git a/accounts-cluster-bench/Cargo.toml b/accounts-cluster-bench/Cargo.toml index 90058f4b885444..e0906f3c783d35 100644 --- a/accounts-cluster-bench/Cargo.toml +++ b/accounts-cluster-bench/Cargo.toml @@ -8,6 +8,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] clap = { workspace = true } log = { workspace = true } @@ -50,6 +53,3 @@ solana-native-token = { workspace = true } solana-poh-config = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-test-validator = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/accounts-db/Cargo.toml b/accounts-db/Cargo.toml index bb16ec4664c436..012b56e7e45c73 100644 --- a/accounts-db/Cargo.toml +++ b/accounts-db/Cargo.toml @@ -9,6 +9,32 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_accounts_db" + +[features] +dev-context-only-utils = [ + "dep:qualifier_attr", + "dep:solana-keypair", + "dep:solana-rent", + "dep:solana-signer", + "dep:solana-stake-program", + "dep:solana-vote-program", + "solana-account/dev-context-only-utils", + "solana-pubkey/rand", + "solana-transaction/dev-context-only-utils", +] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-fee-calculator/frozen-abi", + "solana-vote-program/frozen-abi", +] + [dependencies] ahash = { workspace = true } bincode = { workspace = true } @@ -80,11 +106,8 @@ tar = { workspace = true } tempfile = { workspace = true } thiserror = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_accounts_db" - [dev-dependencies] +agave-reserved-account-keys = { workspace = true } assert_matches = { workspace = true } criterion = { workspace = true } libsecp256k1 = { workspace = true } @@ -97,34 +120,13 @@ solana-compute-budget = { workspace = true } solana-instruction = { workspace = true } solana-logger = { workspace = true } solana-sdk-ids = { workspace = true } +solana-signature = { workspace = true, features = ["rand"] } solana-slot-history = { workspace = true } static_assertions = { workspace = true } strum = { workspace = true, features = ["derive"] } strum_macros = { workspace = true } test-case = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [ - "dep:qualifier_attr", - "dep:solana-keypair", - "dep:solana-rent", - "dep:solana-signer", - "dep:solana-stake-program", - "dep:solana-vote-program", - "solana-account/dev-context-only-utils", - "solana-pubkey/rand", - "solana-transaction/dev-context-only-utils", -] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-fee-calculator/frozen-abi", - "solana-vote-program/frozen-abi", -] - [[bench]] name = "bench_accounts_file" harness = false diff --git a/accounts-db/accounts-hash-cache-tool/Cargo.toml b/accounts-db/accounts-hash-cache-tool/Cargo.toml index 525641902038b1..8413e5c5da492a 100644 --- a/accounts-db/accounts-hash-cache-tool/Cargo.toml +++ b/accounts-db/accounts-hash-cache-tool/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +dev-context-only-utils = [] + [dependencies] ahash = { workspace = true } anyhow = { workspace = true } @@ -20,6 +23,3 @@ solana-accounts-db = { workspace = true } solana-clap-utils = { workspace = true } solana-pubkey = { workspace = true } solana-version = { workspace = true } - -[features] -dev-context-only-utils = [] diff --git a/accounts-db/benches/bench_lock_accounts.rs b/accounts-db/benches/bench_lock_accounts.rs index 00d4805f54de13..c6ecea9fd26f60 100644 --- a/accounts-db/benches/bench_lock_accounts.rs +++ b/accounts-db/benches/bench_lock_accounts.rs @@ -62,16 +62,21 @@ fn create_test_transactions(lock_count: usize, read_conflicts: bool) -> Vec = transactions.chunks(batch_size).collect(); + let batch_results = vec![Ok(()); batch_size].into_iter(); group.bench_function(name.as_str(), move |b| { b.iter(|| { for batch in &transaction_batches { - let results = - accounts.lock_accounts(black_box(batch.iter()), MAX_TX_ACCOUNT_LOCKS); + let results = accounts.lock_accounts( + black_box(batch.iter()), + batch_results.clone(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); accounts.unlock_accounts(batch.iter().zip(&results)); } }) diff --git a/accounts-db/src/account_locks.rs b/accounts-db/src/account_locks.rs index 43796937b8cc42..113b41231dd737 100644 --- a/accounts-db/src/account_locks.rs +++ b/accounts-db/src/account_locks.rs @@ -5,13 +5,13 @@ use { solana_message::AccountKeys, solana_pubkey::Pubkey, solana_transaction::sanitized::MAX_TX_ACCOUNT_LOCKS, - solana_transaction_error::TransactionError, + solana_transaction_error::{TransactionError, TransactionResult}, std::{cell::RefCell, collections::hash_map}, }; #[derive(Debug, Default)] pub struct AccountLocks { - write_locks: AHashSet, + write_locks: AHashMap, readonly_locks: AHashMap, } @@ -20,29 +20,40 @@ impl AccountLocks { /// The bool in the tuple indicates if the account is writable. /// Returns an error if any of the accounts are already locked in a way /// that conflicts with the requested lock. + /// NOTE this is the pre-SIMD83 logic and can be removed once SIMD83 is active. pub fn try_lock_accounts<'a>( &mut self, keys: impl Iterator + Clone, - ) -> Result<(), TransactionError> { - for (key, writable) in keys.clone() { - if writable { - if !self.can_write_lock(key) { - return Err(TransactionError::AccountInUse); - } - } else if !self.can_read_lock(key) { - return Err(TransactionError::AccountInUse); - } - } + ) -> TransactionResult<()> { + self.can_lock_accounts(keys.clone())?; + self.lock_accounts(keys); - for (key, writable) in keys { - if writable { - self.lock_write(key); - } else { - self.lock_readonly(key); + Ok(()) + } + + /// Lock accounts for all transactions in a batch which don't conflict + /// with existing locks. Returns a vector of `TransactionResult` indicating + /// success or failure for each transaction in the batch. + /// NOTE this is the SIMD83 logic; after the feature is active, it becomes + /// the only logic, and this note can be removed with the feature gate. + pub fn try_lock_transaction_batch<'a>( + &mut self, + mut validated_batch_keys: Vec< + TransactionResult + Clone>, + >, + ) -> Vec> { + validated_batch_keys.iter_mut().for_each(|validated_keys| { + if let Ok(ref keys) = validated_keys { + if let Err(e) = self.can_lock_accounts(keys.clone()) { + *validated_keys = Err(e); + } } - } + }); - Ok(()) + validated_batch_keys + .into_iter() + .map(|available_keys| available_keys.map(|keys| self.lock_accounts(keys))) + .collect() } /// Unlock the account keys in `keys` after a transaction. @@ -59,6 +70,33 @@ impl AccountLocks { } } + fn can_lock_accounts<'a>( + &self, + keys: impl Iterator, + ) -> TransactionResult<()> { + for (key, writable) in keys { + if writable { + if !self.can_write_lock(key) { + return Err(TransactionError::AccountInUse); + } + } else if !self.can_read_lock(key) { + return Err(TransactionError::AccountInUse); + } + } + + Ok(()) + } + + fn lock_accounts<'a>(&mut self, keys: impl Iterator) { + for (key, writable) in keys { + if writable { + self.lock_write(key); + } else { + self.lock_readonly(key); + } + } + } + #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))] fn is_locked_readonly(&self, key: &Pubkey) -> bool { self.readonly_locks.get(key).is_some_and(|count| *count > 0) @@ -66,7 +104,7 @@ impl AccountLocks { #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))] fn is_locked_write(&self, key: &Pubkey) -> bool { - self.write_locks.contains(key) + self.write_locks.get(key).is_some_and(|count| *count > 0) } fn can_read_lock(&self, key: &Pubkey) -> bool { @@ -84,7 +122,7 @@ impl AccountLocks { } fn lock_write(&mut self, key: &Pubkey) { - self.write_locks.insert(*key); + *self.write_locks.entry(*key).or_default() += 1; } fn unlock_readonly(&mut self, key: &Pubkey) { @@ -103,11 +141,18 @@ impl AccountLocks { } fn unlock_write(&mut self, key: &Pubkey) { - let removed = self.write_locks.remove(key); - debug_assert!( - removed, - "Attempted to remove a write-lock for a key that wasn't write-locked" - ); + if let hash_map::Entry::Occupied(mut occupied_entry) = self.write_locks.entry(*key) { + let count = occupied_entry.get_mut(); + *count -= 1; + if *count == 0 { + occupied_entry.remove_entry(); + } + } else { + debug_assert!( + false, + "Attempted to remove a write-lock for a key that wasn't write-locked" + ); + } } } @@ -115,7 +160,7 @@ impl AccountLocks { pub fn validate_account_locks( account_keys: AccountKeys, tx_account_lock_limit: usize, -) -> Result<(), TransactionError> { +) -> TransactionResult<()> { if account_keys.len() > tx_account_lock_limit { Err(TransactionError::TooManyAccountLocks) } else if has_duplicates(account_keys) { diff --git a/accounts-db/src/account_storage_reader.rs b/accounts-db/src/account_storage_reader.rs new file mode 100644 index 00000000000000..355d122cf3c8c0 --- /dev/null +++ b/accounts-db/src/account_storage_reader.rs @@ -0,0 +1,416 @@ +use { + crate::{ + account_info::Offset, + accounts_db::AccountStorageEntry, + accounts_file::{AccountsFile, InternalsForArchive}, + }, + solana_clock::Slot, + std::{ + fs::File, + io::{self, Read, Seek, SeekFrom}, + }, +}; + +/// A wrapper type around `AccountStorageEntry` that implements the `Read` trait. +/// This type skips over the data in accounts contained in the obsolete accounts structure +pub struct AccountStorageReader<'a> { + sorted_obsolete_accounts: Vec<(Offset, usize)>, + current_offset: usize, + file: Option, + internals: InternalsForArchive<'a>, + num_alive_bytes: usize, + num_total_bytes: usize, +} + +impl<'a> AccountStorageReader<'a> { + /// Creates a new `AccountStorageReader` from an `AccountStorageEntry`. + /// The obsolete accounts structure is sorted during initialization. + pub fn new(storage: &'a AccountStorageEntry, snapshot_slot: Option) -> io::Result { + let internals = storage.accounts.internals_for_archive(); + let num_total_bytes = storage.accounts.len(); + let num_alive_bytes = num_total_bytes - storage.get_obsolete_bytes(snapshot_slot); + + let mut sorted_obsolete_accounts = storage.get_obsolete_accounts(snapshot_slot); + + // Tiered storage is not compatible with obsolete acocunts at this time + if matches!(storage.accounts, AccountsFile::TieredStorage(_)) { + assert!( + sorted_obsolete_accounts.is_empty(), + "Obsolete accounts should be empty for TieredStorage" + ); + } + + // Convert the length to the size + sorted_obsolete_accounts + .iter_mut() + .for_each(|(_offset, len)| { + *len = storage.accounts.calculate_stored_size(*len); + }); + + sorted_obsolete_accounts + .sort_unstable_by(|(a_offset, _), (b_offset, _)| b_offset.cmp(a_offset)); + + let file = match internals { + InternalsForArchive::Mmap(_internals) => None, + InternalsForArchive::FileIo(path) => Some(File::open(path)?), + }; + + Ok(Self { + sorted_obsolete_accounts, + current_offset: 0, + file, + internals, + num_alive_bytes, + num_total_bytes, + }) + } + + pub fn len(&self) -> usize { + self.num_alive_bytes + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl Read for AccountStorageReader<'_> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let mut total_read = 0; + let buf_len = buf.len(); + + while total_read < buf_len { + let next_obsolete_account = self.sorted_obsolete_accounts.last(); + if let Some(&(obsolete_start, obsolete_size)) = next_obsolete_account { + if self.current_offset == obsolete_start { + self.current_offset += obsolete_size.min(self.num_total_bytes - obsolete_start); + self.sorted_obsolete_accounts.pop(); + continue; + } + } + + // Cannot read beyond the end of the buffer + let bytes_left_in_buffer = buf_len.saturating_sub(total_read); + + // Cannot read beyond the next obsolete account or the end of the file + let bytes_to_read_from_file = if let Some((obsolete_start, _)) = next_obsolete_account { + obsolete_start.saturating_sub(self.current_offset) + } else { + self.num_total_bytes.saturating_sub(self.current_offset) + }; + + let bytes_to_read = bytes_left_in_buffer.min(bytes_to_read_from_file); + + let read_size = match self.internals { + InternalsForArchive::Mmap(data) => (&data + [self.current_offset..self.current_offset + bytes_to_read]) + .read(&mut buf[total_read..][..bytes_to_read])?, + + InternalsForArchive::FileIo(_) => { + let file = &mut self + .file + .as_mut() + .expect("File is opened during initialization"); + file.seek(SeekFrom::Start(self.current_offset as u64))?; + file.read(&mut buf[total_read..][..bytes_to_read])? + } + }; + + if read_size == 0 { + break; // EOF + } + + self.current_offset += read_size; + total_read += read_size; + } + + Ok(total_read) + } +} + +#[cfg(test)] +mod tests { + use { + super::*, + crate::{ + accounts_db::{get_temp_accounts_paths, AccountStorageEntry}, + accounts_file::{AccountsFile, AccountsFileProvider, StorageAccess}, + }, + log::*, + rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}, + solana_account::AccountSharedData, + solana_pubkey::Pubkey, + std::iter, + test_case::test_case, + }; + + fn create_storage_for_storage_reader( + slot: Slot, + provider: AccountsFileProvider, + ) -> (AccountStorageEntry, Vec) { + let id = 0; + let (temp_dirs, paths) = get_temp_accounts_paths(1).unwrap(); + let file_size = 1024 * 1024; + ( + AccountStorageEntry::new(&paths[0], slot, id, file_size, provider), + temp_dirs, + ) + } + + #[test] + #[should_panic(expected = "Obsolete accounts should be empty for TieredStorage")] + fn test_account_storage_reader_tiered_storage_one_obsolete_account_should_panic() { + let (storage, _temp_dirs) = + create_storage_for_storage_reader(0, AccountsFileProvider::HotStorage); + + let account = AccountSharedData::new(1, 10, &Pubkey::new_unique()); + let account2 = AccountSharedData::new(1, 10, &Pubkey::new_unique()); + let slot = 0; + + let accounts = [ + (&Pubkey::new_unique(), &account), + (&Pubkey::new_unique(), &account2), + ]; + + storage.accounts.append_accounts(&(slot, &accounts[..]), 0); + + let offset = 0; + // Mark the obsolete accounts in storage + let mut size = storage.accounts.get_account_data_lens(&[0]); + storage.mark_account_obsolete(offset, size.pop().unwrap(), 0); + + _ = AccountStorageReader::new(&storage, None).unwrap(); + } + + #[test_case(AccountsFileProvider::AppendVec)] + #[test_case(AccountsFileProvider::HotStorage)] + fn test_account_storage_reader_no_obsolete_accounts(provider: AccountsFileProvider) { + let (storage, _temp_dirs) = create_storage_for_storage_reader(0, provider); + + let account = AccountSharedData::new(1, 10, &Pubkey::default()); + let account2 = AccountSharedData::new(1, 10, &Pubkey::default()); + let slot = 0; + + let accounts = [ + (&Pubkey::new_unique(), &account), + (&Pubkey::new_unique(), &account2), + ]; + + storage.accounts.append_accounts(&(slot, &accounts[..]), 0); + + let reader = AccountStorageReader::new(&storage, None).unwrap(); + assert_eq!(reader.len(), storage.accounts.len()); + } + + #[test_case(0, 0, StorageAccess::File)] + #[test_case(1, 0, StorageAccess::File)] + #[test_case(1, 1, StorageAccess::File)] + #[test_case(100, 0, StorageAccess::File)] + #[test_case(100, 10, StorageAccess::File)] + #[test_case(100, 100, StorageAccess::File)] + #[test_case(0, 0, StorageAccess::Mmap)] + #[test_case(1, 0, StorageAccess::Mmap)] + #[test_case(1, 1, StorageAccess::Mmap)] + #[test_case(100, 0, StorageAccess::Mmap)] + #[test_case(100, 10, StorageAccess::Mmap)] + #[test_case(100, 100, StorageAccess::Mmap)] + fn test_account_storage_reader_with_obsolete_accounts( + total_accounts: usize, + number_of_accounts_to_remove: usize, + storage_access: StorageAccess, + ) { + solana_logger::setup(); + let (storage, _temp_dirs) = + create_storage_for_storage_reader(0, AccountsFileProvider::AppendVec); + + let slot = 0; + + // Create a bunch of accounts and add them to the storage + let accounts: Vec<_> = + iter::repeat_with(|| AccountSharedData::new(1, 10, &Pubkey::default())) + .take(total_accounts) + .collect(); + + let accounts_to_append: Vec<_> = accounts + .into_iter() + .map(|account| (Pubkey::new_unique(), account)) + .collect(); + + let offsets = storage + .accounts + .append_accounts(&(slot, &accounts_to_append[..]), 0); + + // Generate a seed from entropy and log the original seed + let seed: u64 = rand::random(); + info!("Generated seed: {}", seed); + + // Use a seedable RNG with the generated seed for reproducibility + let mut rng = StdRng::seed_from_u64(seed); + + let obsolete_account_offset = offsets + .map(|offsets| { + offsets + .offsets + .choose_multiple(&mut rng, number_of_accounts_to_remove) + .cloned() + .collect::>() + }) + .unwrap_or_default(); + + assert_eq!(obsolete_account_offset.len(), number_of_accounts_to_remove); + + // Mark the obsolete accounts in storage + obsolete_account_offset.into_iter().for_each(|offset| { + let mut size = storage.accounts.get_account_data_lens(&[offset]); + storage.mark_account_obsolete(offset, size.pop().unwrap(), 0); + }); + + let storage = storage + .reopen_as_readonly(storage_access) + .unwrap_or(storage); + + // Assert that storage.accounts was reopened with the specified access type + match storage_access { + StorageAccess::File => assert!(matches!( + storage.accounts.internals_for_archive(), + InternalsForArchive::FileIo(_) + )), + StorageAccess::Mmap => assert!(matches!( + storage.accounts.internals_for_archive(), + InternalsForArchive::Mmap(_) + )), + } + + // Create the reader and check the length + let mut reader = AccountStorageReader::new(&storage, None).unwrap(); + let current_len = storage.accounts.len() - storage.get_obsolete_bytes(None); + assert_eq!(reader.len(), current_len); + + // Create a temporary directory and a file within it + let temp_dir = tempfile::tempdir().unwrap(); + let temp_file_path = temp_dir.path().join("output_file"); + let mut output_file = File::create(&temp_file_path).unwrap(); + + let bytes_written = io::copy(&mut reader, &mut output_file).unwrap(); + assert_eq!(bytes_written as usize, reader.len()); + + // Close the file + drop(output_file); + + // If the number of accounts left is not zero, create a new AccountsFile from the output file + // and verify that the number of accounts in the new file is correct + if (total_accounts - number_of_accounts_to_remove) != 0 { + let (accounts_file, num_accounts) = + AccountsFile::new_from_file(temp_file_path, current_len, StorageAccess::File) + .unwrap(); + + // Verify that the correct number of accounts were found in the file + assert_eq!( + num_accounts, + (total_accounts - number_of_accounts_to_remove) + ); + + // Create a new AccountStorageEntry from the output file + let new_storage = + AccountStorageEntry::new_existing(slot, 0, accounts_file, num_accounts); + + // Verify that the new storage has the same length as the reader + assert_eq!(new_storage.accounts.len(), reader.len()); + } + } + + #[test] + fn test_account_storage_reader_filter_by_slot() { + let (storage, _temp_dirs) = + create_storage_for_storage_reader(10, AccountsFileProvider::AppendVec); + let total_accounts = 30; + + let slot = 0; + + // Create a bunch of accounts and add them to the storage + let accounts: Vec<_> = + iter::repeat_with(|| AccountSharedData::new(1, 10, &Pubkey::default())) + .take(total_accounts) + .collect(); + + let accounts_to_append: Vec<_> = accounts + .into_iter() + .map(|account| (Pubkey::new_unique(), account)) + .collect(); + + let offsets = storage + .accounts + .append_accounts(&(slot, &accounts_to_append[..]), 0); + + // Generate a seed from entropy and log the original seed + let seed: u64 = rand::random(); + info!("Generated seed: {}", seed); + + // Use a seedable RNG with the generated seed for reproducibility + let mut rng = StdRng::seed_from_u64(seed); + + let max_offset = offsets + .as_ref() + .and_then(|offsets| offsets.offsets.iter().max().cloned()) + .unwrap(); + + let mut obsolete_account_offset = offsets + .map(|offsets| { + offsets + .offsets + .choose_multiple(&mut rng, total_accounts - 1) + .cloned() + .collect::>() + }) + .unwrap_or_default(); + + // Ensure that the last entry will be marked obsolete at some point + if !obsolete_account_offset.contains(&max_offset) { + // Replace a random obsolete account with the max offset + if let Some(random_index) = obsolete_account_offset.choose_mut(&mut rng) { + *random_index = max_offset; + } + } + + // Mark the obsolete accounts in storage at different slots + let mut slot_marked_dead = 0; + obsolete_account_offset.into_iter().for_each(|offset| { + let mut size = storage.accounts.get_account_data_lens(&[offset]); + storage.mark_account_obsolete(offset, size.pop().unwrap(), slot_marked_dead); + slot_marked_dead += 1; + }); + + // Create a temporary directory + let temp_dir = tempfile::tempdir().unwrap(); + + // Now iterate through all the possible snapshot slots and verify correctness + for snapshot_slot in 0..slot_marked_dead { + let mut reader = AccountStorageReader::new(&storage, Some(snapshot_slot)).unwrap(); + let current_len = + storage.accounts.len() - storage.get_obsolete_bytes(Some(snapshot_slot)); + assert_eq!(reader.len(), current_len); + + // Create a file to write the reader's output. It will get deleted by AccountsFile::drop() every + // iteration so it does not need a unique name + let temp_file_path = temp_dir.path().join("output_file"); + let mut output_file = File::create(&temp_file_path).unwrap(); + + let bytes_written = io::copy(&mut reader, &mut output_file).unwrap(); + assert_eq!(bytes_written as usize, reader.len()); + + // Close the file + drop(output_file); + + let (accounts_file, num_accounts) = + AccountsFile::new_from_file(temp_file_path, current_len, StorageAccess::File) + .unwrap(); + + // Create a new AccountStorageEntry from the output file + let new_storage = + AccountStorageEntry::new_existing(slot, 0, accounts_file, num_accounts); + + // Verify that the new storage has the same length as the reader + assert_eq!(new_storage.accounts.len(), reader.len()); + } + } +} diff --git a/accounts-db/src/accounts.rs b/accounts-db/src/accounts.rs index 01c9d75468e10a..9c06ee08305e9a 100644 --- a/accounts-db/src/accounts.rs +++ b/accounts-db/src/accounts.rs @@ -566,57 +566,39 @@ impl Accounts { } /// This function will prevent multiple threads from modifying the same account state at the - /// same time + /// same time, possibly excluding transactions based on prior results #[must_use] - pub fn lock_accounts<'a, Tx: SVMMessage + 'a>( - &self, - txs: impl Iterator, - tx_account_lock_limit: usize, - ) -> Vec> { - // Validate the account locks, then get iterator if successful validation. - let tx_account_locks_results: Vec> = txs - .map(|tx| { - validate_account_locks(tx.account_keys(), tx_account_lock_limit) - .map(|_| TransactionAccountLocksIterator::new(tx)) - }) - .collect(); - self.lock_accounts_inner(tx_account_locks_results) - } - - #[must_use] - pub fn lock_accounts_with_results<'a>( + pub fn lock_accounts<'a>( &self, txs: impl Iterator, results: impl Iterator>, tx_account_lock_limit: usize, + relax_intrabatch_account_locks: bool, ) -> Vec> { - // Validate the account locks, then get iterator if successful validation. - let tx_account_locks_results: Vec> = txs + // Validate the account locks, then get keys and is_writable if successful validation. + // We collect to fully evaluate before taking the account_locks mutex. + let validated_batch_keys = txs .zip(results) - .map(|(tx, result)| match result { - Ok(()) => validate_account_locks(tx.account_keys(), tx_account_lock_limit) - .map(|_| TransactionAccountLocksIterator::new(tx)), - Err(err) => Err(err), + .map(|(tx, result)| { + result + .and_then(|_| validate_account_locks(tx.account_keys(), tx_account_lock_limit)) + .map(|_| TransactionAccountLocksIterator::new(tx).accounts_with_is_writable()) }) - .collect(); - self.lock_accounts_inner(tx_account_locks_results) - } + .collect::>(); - #[must_use] - fn lock_accounts_inner( - &self, - tx_account_locks_results: Vec>>, - ) -> Vec> { let account_locks = &mut self.account_locks.lock().unwrap(); - tx_account_locks_results - .into_iter() - .map(|tx_account_locks_result| match tx_account_locks_result { - Ok(tx_account_locks) => { - account_locks.try_lock_accounts(tx_account_locks.accounts_with_is_writable()) - } - Err(err) => Err(err), - }) - .collect() + + if relax_intrabatch_account_locks { + account_locks.try_lock_transaction_batch(validated_batch_keys) + } else { + validated_batch_keys + .into_iter() + .map(|result_validated_tx_keys| match result_validated_tx_keys { + Ok(validated_tx_keys) => account_locks.try_lock_accounts(validated_tx_keys), + Err(e) => Err(e), + }) + .collect() + } } /// Once accounts are unlocked, new transactions that modify that state can enter the pipeline @@ -662,15 +644,18 @@ impl Accounts { mod tests { use { super::*, + agave_reserved_account_keys::ReservedAccountKeys, solana_account::{AccountSharedData, WritableAccount}, solana_address_lookup_table_interface::state::LookupTableMeta, solana_hash::Hash, + solana_instruction::{AccountMeta, Instruction}, solana_keypair::Keypair, solana_message::{ - compiled_instruction::CompiledInstruction, v0::MessageAddressTableLookup, Message, - MessageHeader, + compiled_instruction::CompiledInstruction, v0::MessageAddressTableLookup, + LegacyMessage, Message, MessageHeader, SanitizedMessage, }, solana_sdk_ids::native_loader, + solana_signature::Signature, solana_signer::{signers::Signers, Signer}, solana_transaction::{sanitized::MAX_TX_ACCOUNT_LOCKS, Transaction}, solana_transaction_error::TransactionError, @@ -680,6 +665,7 @@ mod tests { sync::atomic::{AtomicBool, AtomicU64, Ordering}, thread, time, }, + test_case::test_case, }; fn new_sanitized_tx( @@ -694,6 +680,23 @@ mod tests { )) } + fn sanitized_tx_from_metas(accounts: Vec) -> SanitizedTransaction { + let instruction = Instruction { + accounts, + program_id: Pubkey::default(), + data: vec![], + }; + + let message = Message::new(&[instruction], None); + + let sanitized_message = SanitizedMessage::Legacy(LegacyMessage::new( + message, + &ReservedAccountKeys::empty_key_set(), + )); + + SanitizedTransaction::new_for_tests(sanitized_message, vec![Signature::new_unique()], false) + } + #[test] fn test_hold_range_in_memory() { let accounts_db = AccountsDb::default_for_tests(); @@ -895,8 +898,9 @@ mod tests { assert_eq!(loaded, vec![]); } - #[test] - fn test_lock_accounts_with_duplicates() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_lock_accounts_with_duplicates(relax_intrabatch_account_locks: bool) { let accounts_db = AccountsDb::new_single_for_tests(); let accounts = Accounts::new(Arc::new(accounts_db)); @@ -911,12 +915,18 @@ mod tests { }; let tx = new_sanitized_tx(&[&keypair], message, Hash::default()); - let results = accounts.lock_accounts([tx].iter(), MAX_TX_ACCOUNT_LOCKS); + let results = accounts.lock_accounts( + [tx].iter(), + [Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); assert_eq!(results[0], Err(TransactionError::AccountLoadedTwice)); } - #[test] - fn test_lock_accounts_with_too_many_accounts() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_lock_accounts_with_too_many_accounts(relax_intrabatch_account_locks: bool) { let accounts_db = AccountsDb::new_single_for_tests(); let accounts = Accounts::new(Arc::new(accounts_db)); @@ -939,7 +949,12 @@ mod tests { }; let txs = vec![new_sanitized_tx(&[&keypair], message, Hash::default())]; - let results = accounts.lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS); + let results = accounts.lock_accounts( + txs.iter(), + vec![Ok(()); txs.len()].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); assert_eq!(results, vec![Ok(())]); accounts.unlock_accounts(txs.iter().zip(&results)); } @@ -961,13 +976,19 @@ mod tests { }; let txs = vec![new_sanitized_tx(&[&keypair], message, Hash::default())]; - let results = accounts.lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS); + let results = accounts.lock_accounts( + txs.iter(), + vec![Ok(()); txs.len()].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); assert_eq!(results[0], Err(TransactionError::TooManyAccountLocks)); } } - #[test] - fn test_accounts_locks() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_accounts_locks(relax_intrabatch_account_locks: bool) { let keypair0 = Keypair::new(); let keypair1 = Keypair::new(); let keypair2 = Keypair::new(); @@ -995,7 +1016,12 @@ mod tests { instructions, ); let tx = new_sanitized_tx(&[&keypair0], message, Hash::default()); - let results0 = accounts.lock_accounts([tx.clone()].iter(), MAX_TX_ACCOUNT_LOCKS); + let results0 = accounts.lock_accounts( + [tx.clone()].iter(), + [Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); assert_eq!(results0, vec![Ok(())]); assert!(accounts @@ -1025,7 +1051,12 @@ mod tests { ); let tx1 = new_sanitized_tx(&[&keypair1], message, Hash::default()); let txs = vec![tx0, tx1]; - let results1 = accounts.lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS); + let results1 = accounts.lock_accounts( + txs.iter(), + vec![Ok(()); txs.len()].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); assert_eq!( results1, vec![ @@ -1051,7 +1082,12 @@ mod tests { instructions, ); let tx = new_sanitized_tx(&[&keypair1], message, Hash::default()); - let results2 = accounts.lock_accounts([tx].iter(), MAX_TX_ACCOUNT_LOCKS); + let results2 = accounts.lock_accounts( + [tx].iter(), + [Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); assert_eq!( results2, vec![Ok(())] // Now keypair1 account can be locked as writable @@ -1065,8 +1101,9 @@ mod tests { .is_locked_readonly(&keypair1.pubkey())); } - #[test] - fn test_accounts_locks_multithreaded() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_accounts_locks_multithreaded(relax_intrabatch_account_locks: bool) { let counter = Arc::new(AtomicU64::new(0)); let exit = Arc::new(AtomicBool::new(false)); @@ -1113,9 +1150,12 @@ mod tests { let exit_clone = exit.clone(); thread::spawn(move || loop { let txs = vec![writable_tx.clone()]; - let results = accounts_clone - .clone() - .lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS); + let results = accounts_clone.clone().lock_accounts( + txs.iter(), + vec![Ok(()); txs.len()].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); for result in results.iter() { if result.is_ok() { counter_clone.clone().fetch_add(1, Ordering::Release); @@ -1129,9 +1169,12 @@ mod tests { let counter_clone = counter; for _ in 0..5 { let txs = vec![readonly_tx.clone()]; - let results = accounts_arc - .clone() - .lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS); + let results = accounts_arc.clone().lock_accounts( + txs.iter(), + vec![Ok(()); txs.len()].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); if results[0].is_ok() { let counter_value = counter_clone.clone().load(Ordering::Acquire); thread::sleep(time::Duration::from_millis(50)); @@ -1143,8 +1186,9 @@ mod tests { exit.store(true, Ordering::Relaxed); } - #[test] - fn test_demote_program_write_locks() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_demote_program_write_locks(relax_intrabatch_account_locks: bool) { let keypair0 = Keypair::new(); let keypair1 = Keypair::new(); let keypair2 = Keypair::new(); @@ -1172,7 +1216,12 @@ mod tests { instructions, ); let tx = new_sanitized_tx(&[&keypair0], message, Hash::default()); - let results0 = accounts.lock_accounts([tx].iter(), MAX_TX_ACCOUNT_LOCKS); + let results0 = accounts.lock_accounts( + [tx].iter(), + [Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); assert!(results0[0].is_ok()); // Instruction program-id account demoted to readonly @@ -1208,8 +1257,9 @@ mod tests { } } - #[test] - fn test_accounts_locks_with_results() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_accounts_locks_with_results(relax_intrabatch_account_locks: bool) { let keypair0 = Keypair::new(); let keypair1 = Keypair::new(); let keypair2 = Keypair::new(); @@ -1265,10 +1315,11 @@ mod tests { Ok(()), ]; - let results = accounts.lock_accounts_with_results( + let results = accounts.lock_accounts( txs.iter(), qos_results.into_iter(), MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, ); assert_eq!( @@ -1294,6 +1345,94 @@ mod tests { .is_locked_write(&keypair2.pubkey())); } + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_accounts_locks_intrabatch_conflicts(relax_intrabatch_account_locks: bool) { + let pubkey = Pubkey::new_unique(); + let account_data = AccountSharedData::new(1, 0, &Pubkey::default()); + let accounts_db = Arc::new(AccountsDb::new_single_for_tests()); + accounts_db.store_for_tests( + 0, + &[ + (&Pubkey::default(), &account_data), + (&pubkey, &account_data), + ], + ); + + let r_tx = sanitized_tx_from_metas(vec![AccountMeta { + pubkey, + is_writable: false, + is_signer: false, + }]); + + let w_tx = sanitized_tx_from_metas(vec![AccountMeta { + pubkey, + is_writable: true, + is_signer: false, + }]); + + // one w tx alone always works + let accounts = Accounts::new(accounts_db.clone()); + let results = accounts.lock_accounts( + [w_tx.clone()].iter(), + [Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); + + assert_eq!(results, vec![Ok(())]); + + // wr conflict cross-batch always fails + let results = accounts.lock_accounts( + [r_tx.clone()].iter(), + [Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); + + assert_eq!(results, vec![Err(TransactionError::AccountInUse)]); + + // ww conflict cross-batch always fails + let results = accounts.lock_accounts( + [w_tx.clone()].iter(), + [Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); + + assert_eq!(results, vec![Err(TransactionError::AccountInUse)]); + + // wr conflict in-batch succeeds or fails based on feature + let accounts = Accounts::new(accounts_db.clone()); + let results = accounts.lock_accounts( + [w_tx.clone(), r_tx.clone()].iter(), + [Ok(()), Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); + + if relax_intrabatch_account_locks { + assert_eq!(results, vec![Ok(()), Ok(())]); + } else { + assert_eq!(results, vec![Ok(()), Err(TransactionError::AccountInUse)]); + } + + // ww conflict in-batch succeeds or fails based on feature + let accounts = Accounts::new(accounts_db.clone()); + let results = accounts.lock_accounts( + [w_tx.clone(), r_tx.clone()].iter(), + [Ok(()), Ok(())].into_iter(), + MAX_TX_ACCOUNT_LOCKS, + relax_intrabatch_account_locks, + ); + + if relax_intrabatch_account_locks { + assert_eq!(results, vec![Ok(()), Ok(())]); + } else { + assert_eq!(results, vec![Ok(()), Err(TransactionError::AccountInUse)]); + } + } + #[test] fn huge_clean() { solana_logger::setup(); diff --git a/accounts-db/src/accounts_cache.rs b/accounts-db/src/accounts_cache.rs index 12fb4e0289a6a6..f46c836badf384 100644 --- a/accounts-db/src/accounts_cache.rs +++ b/accounts-db/src/accounts_cache.rs @@ -23,16 +23,24 @@ pub struct SlotCache { same_account_writes: AtomicU64, same_account_writes_size: AtomicU64, unique_account_writes_size: AtomicU64, + /// The size of account data stored in `cache` (just this slot), in bytes size: AtomicU64, + /// The size of account data stored in the whole AccountsCache, in bytes total_size: Arc, is_frozen: AtomicBool, + /// The number of accounts stored in `cache` (just this slot) + accounts_count: AtomicU64, + /// The number of accounts stored in the whole AccountsCache + total_accounts_count: Arc, } impl Drop for SlotCache { fn drop(&mut self) { - // broader cache no longer holds our size in memory + // broader cache no longer holds our size/counts in memory self.total_size - .fetch_sub(self.size.load(Ordering::Relaxed), Ordering::Relaxed); + .fetch_sub(*self.size.get_mut(), Ordering::Relaxed); + self.total_accounts_count + .fetch_sub(*self.accounts_count.get_mut(), Ordering::Relaxed); } } @@ -55,7 +63,12 @@ impl SlotCache { self.unique_account_writes_size.load(Ordering::Relaxed), i64 ), - ("size", self.size.load(Ordering::Relaxed), i64) + ("size", self.size.load(Ordering::Relaxed), i64), + ( + "accounts_count", + self.accounts_count.load(Ordering::Relaxed), + i64 + ) ); } @@ -88,6 +101,8 @@ impl SlotCache { self.total_size.fetch_add(data_len, Ordering::Relaxed); self.unique_account_writes_size .fetch_add(data_len, Ordering::Relaxed); + self.accounts_count.fetch_add(1, Ordering::Relaxed); + self.total_accounts_count.fetch_add(1, Ordering::Relaxed); } item } @@ -153,7 +168,10 @@ pub struct AccountsCache { // could have triggered a flush of this slot already maybe_unflushed_roots: RwLock>, max_flushed_root: AtomicU64, + /// The size of account data stored in the whole AccountsCache, in bytes total_size: Arc, + /// The number of accounts stored in the whole AccountsCache + total_accounts_counts: Arc, } impl AccountsCache { @@ -166,19 +184,10 @@ impl AccountsCache { size: AtomicU64::default(), total_size: Arc::clone(&self.total_size), is_frozen: AtomicBool::default(), + accounts_count: AtomicU64::new(0), + total_accounts_count: Arc::clone(&self.total_accounts_counts), }) } - fn unique_account_writes_size(&self) -> u64 { - self.cache - .iter() - .map(|item| { - let slot_cache = item.value(); - slot_cache - .unique_account_writes_size - .load(Ordering::Relaxed) - }) - .sum() - } pub fn size(&self) -> u64 { self.total_size.load(Ordering::Relaxed) } @@ -191,12 +200,12 @@ impl AccountsCache { i64 ), ("num_slots", self.cache.len(), i64), + ("total_size", self.size(), i64), ( - "total_unique_writes_size", - self.unique_account_writes_size(), + "total_accounts_count", + self.total_accounts_counts.load(Ordering::Relaxed), i64 ), - ("total_size", self.size(), i64), ); } diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index 1fde2b936d2069..fab7eb290f7323 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -1071,6 +1071,16 @@ pub struct AccountStorageEntry { /// account as "dead" twice. However, this should be fine. It just makes /// shrink more likely to visit this storage. zero_lamport_single_ref_offsets: RwLock>, + + /// Obsolete Accounts. These are accounts that are still present in the storage + /// but should be ignored during rebuild. They have been removed + /// from the accounts index, so they will not be picked up by scan. + /// Slot is the slot at which the account is no longer needed. + /// Two scenarios cause an account entry to be marked obsolete + /// 1. The account was rewritten to a newer slot + /// 2. The account was set to zero lamports and is older than the last + /// full snapshot. In this case, slot is set to the snapshot slot + obsolete_accounts: RwLock>, } impl AccountStorageEntry { @@ -1092,10 +1102,12 @@ impl AccountStorageEntry { count_and_status: SeqLock::new((0, AccountStorageStatus::Available)), alive_bytes: AtomicUsize::new(0), zero_lamport_single_ref_offsets: RwLock::default(), + obsolete_accounts: RwLock::default(), } } /// open a new instance of the storage that is readonly + #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))] fn reopen_as_readonly(&self, storage_access: StorageAccess) -> Option { if storage_access != StorageAccess::File { // if we are only using mmap, then no reason to re-open @@ -1110,6 +1122,7 @@ impl AccountStorageEntry { alive_bytes: AtomicUsize::new(self.alive_bytes()), accounts, zero_lamport_single_ref_offsets: RwLock::default(), + obsolete_accounts: RwLock::new(self.obsolete_accounts.read().unwrap().clone()), }) } @@ -1126,6 +1139,7 @@ impl AccountStorageEntry { count_and_status: SeqLock::new((0, AccountStorageStatus::Available)), alive_bytes: AtomicUsize::new(0), zero_lamport_single_ref_offsets: RwLock::default(), + obsolete_accounts: RwLock::default(), } } @@ -1162,6 +1176,44 @@ impl AccountStorageEntry { self.alive_bytes.load(Ordering::Acquire) } + /// Marks the account at the given offset as obsolete + pub fn mark_account_obsolete(&self, offset: Offset, data_len: usize, slot: Slot) { + self.obsolete_accounts + .write() + .unwrap() + .push((offset, data_len, slot)); + } + + /// Returns the accounts that were marked obsolete as of the passed in slot + /// or earlier. If slot is None, then slot will be assumed to be the max root + /// and all obsolete accounts will be returned. + pub fn get_obsolete_accounts(&self, slot: Option) -> Vec<(Offset, usize)> { + self.obsolete_accounts + .read() + .unwrap() + .iter() + .filter(|(_, _, obsolete_slot)| slot.is_none_or(|s| *obsolete_slot <= s)) + .map(|(offset, data_len, _)| (*offset, *data_len)) + .collect() + } + + /// Returns the number of bytes that were marked obsolete as of the passed + /// in slot or earlier. If slot is None, then slot will be assumed to be the + /// max root, and all obsolete bytes will be returned. + pub fn get_obsolete_bytes(&self, slot: Option) -> usize { + let obsolete_accounts = self.obsolete_accounts.read().unwrap(); + let obsolete_bytes = obsolete_accounts + .iter() + .filter(|(_, _, obsolete_slot)| slot.is_none_or(|s| *obsolete_slot <= s)) + .map(|(offset, data_len, _)| { + self.accounts + .calculate_stored_size(*data_len) + .min(self.accounts.len() - offset) + }) + .sum(); + obsolete_bytes + } + /// Return true if offset is "new" and inserted successfully. Otherwise, /// return false if the offset exists already. fn insert_zero_lamport_single_ref_account_offset(&self, offset: usize) -> bool { diff --git a/accounts-db/src/accounts_index_storage.rs b/accounts-db/src/accounts_index_storage.rs index 8e5353e6d4a94b..f91a55bd12b818 100644 --- a/accounts-db/src/accounts_index_storage.rs +++ b/accounts-db/src/accounts_index_storage.rs @@ -63,10 +63,18 @@ impl BgThreads { can_advance_age: bool, exit: Arc, ) -> Self { + let is_disk_index_enabled = storage.is_disk_index_enabled(); + let num_threads = if is_disk_index_enabled { + threads.get() + } else { + // no disk index, so only need 1 thread to report stats + 1 + }; + // stop signal used for THIS batch of bg threads let local_exit = Arc::new(AtomicBool::default()); let handles = Some( - (0..threads.get()) + (0..num_threads) .map(|idx| { // the first thread we start is special let can_advance_age = can_advance_age && idx == 0; diff --git a/accounts-db/src/append_vec.rs b/accounts-db/src/append_vec.rs index 0afbb31f1ff74d..d3431bda189a7f 100644 --- a/accounts-db/src/append_vec.rs +++ b/accounts-db/src/append_vec.rs @@ -1047,16 +1047,21 @@ impl AppendVec { } else if STORE_META_OVERHEAD + data_len <= BUFFER_SIZE { reader.set_required_data_len(STORE_META_OVERHEAD + data_len); } else { - const MAX_CAPACITY: usize = - STORE_META_OVERHEAD + MAX_PERMITTED_DATA_LENGTH as usize; - if data_overflow_buffer.is_empty() { - // Reserve to worst case to avoid multiple reallocations. - data_overflow_buffer.reserve_exact(MAX_CAPACITY); - // SAFETY: we only write to the uninitialized portion of the buffer via `copy_from_slice` and `read_into_buffer`. + const MAX_CAPACITY: usize = MAX_PERMITTED_DATA_LENGTH as usize; + // 128KiB covers a reasonably large distribution of typical account sizes. + // In a recent sample, 99.98% of accounts' data lengths were less than or equal to 128KiB. + const MIN_CAPACITY: usize = 1024 * 128; + let capacity = data_overflow_buffer.capacity(); + if data_len > capacity { + let next_cap = data_len + .next_power_of_two() + .clamp(MIN_CAPACITY, MAX_CAPACITY); + data_overflow_buffer.reserve_exact(next_cap - capacity); + // SAFETY: We only write to the uninitialized portion of the buffer via `copy_from_slice` and `read_into_buffer`. // Later, we ensure we only read from the initialized portion of the buffer. unsafe { - data_overflow_buffer.set_len(MAX_CAPACITY); - }; + data_overflow_buffer.set_len(next_cap); + } } // Copy already read data to overflow buffer. @@ -1603,14 +1608,6 @@ pub mod tests { impl AppendVec { /// return how many accounts in the storage fn accounts_count(&self) -> usize { - let mut count = 0; - self.scan_accounts_stored_meta(|_| { - count += 1; - }); - count - } - - fn store_accounts_no_data_count(&self) -> usize { let mut count = 0; self.scan_stored_accounts_no_data(|_| { count += 1; @@ -1726,13 +1723,12 @@ pub mod tests { assert_eq!(av.get_account_test(indexes[sample]).unwrap(), account); } trace!("random read time: {} ms", now.elapsed().as_millis()); - - let now = Instant::now(); assert_eq!(indexes.len(), size); assert_eq!(indexes[0], 0); - let mut sample = 0; assert_eq!(av.accounts_count(), size); - assert_eq!(av.store_accounts_no_data_count(), size); + + let mut sample = 0; + let now = Instant::now(); av.scan_accounts_stored_meta(|v| { let account = create_test_account(sample + 1); let recovered = v.to_account_shared_data(); diff --git a/accounts-db/src/blockhash_queue.rs b/accounts-db/src/blockhash_queue.rs index ba6bc2d111a3b6..bc7ff77d4c145a 100644 --- a/accounts-db/src/blockhash_queue.rs +++ b/accounts-db/src/blockhash_queue.rs @@ -144,7 +144,7 @@ impl BlockhashQueue { #[deprecated( since = "2.0.0", - note = "Please use `solana_program::clock::MAX_PROCESSING_AGE`" + note = "Please use `solana_clock::MAX_PROCESSING_AGE`" )] pub fn get_max_age(&self) -> usize { self.max_age diff --git a/accounts-db/src/bucket_map_holder_stats.rs b/accounts-db/src/bucket_map_holder_stats.rs index c2b7616cf47c73..ae9835d2ff53e5 100644 --- a/accounts-db/src/bucket_map_holder_stats.rs +++ b/accounts-db/src/bucket_map_holder_stats.rs @@ -225,7 +225,7 @@ impl BucketMapHolderStats { // sum of elapsed time in each thread let mut thread_time_elapsed_ms = elapsed_ms * storage.threads as u64; - if disk.is_some() { + if storage.is_disk_index_enabled() { if was_startup { // these stats only apply at startup datapoint_info!( diff --git a/accounts-db/src/lib.rs b/accounts-db/src/lib.rs index 7650059f793d53..8e4f4ffee45ea1 100644 --- a/accounts-db/src/lib.rs +++ b/accounts-db/src/lib.rs @@ -4,6 +4,7 @@ pub mod account_info; pub mod account_locks; pub mod account_storage; +pub mod account_storage_reader; pub mod accounts; mod accounts_cache; pub mod accounts_db; diff --git a/accounts-db/src/read_only_accounts_cache.rs b/accounts-db/src/read_only_accounts_cache.rs index 339362a137cb9e..a9bb230dfc27df 100644 --- a/accounts-db/src/read_only_accounts_cache.rs +++ b/accounts-db/src/read_only_accounts_cache.rs @@ -380,12 +380,11 @@ impl ReadOnlyAccountsCache { } let key = key_to_evict.expect("eviction sample should not be empty"); - #[cfg(not(feature = "dev-context-only-utils"))] - Self::do_remove(&key, cache, data_size); + let _entry = Self::do_remove(&key, cache, data_size); #[cfg(feature = "dev-context-only-utils")] { - let entry = Self::do_remove(&key, cache, data_size); - callback(&key, entry.unwrap()); + #[allow(clippy::used_underscore_binding)] + callback(&key, _entry.unwrap()); } num_evicts = num_evicts.saturating_add(1); } diff --git a/accounts-db/store-histogram/Cargo.toml b/accounts-db/store-histogram/Cargo.toml index 75cdea3eb1f362..e762b25c087b2b 100644 --- a/accounts-db/store-histogram/Cargo.toml +++ b/accounts-db/store-histogram/Cargo.toml @@ -9,9 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +dev-context-only-utils = [] + [dependencies] clap = { workspace = true } solana-version = { workspace = true } - -[features] -dev-context-only-utils = [] diff --git a/accounts-db/store-tool/Cargo.toml b/accounts-db/store-tool/Cargo.toml index 506758e0c01a9e..7b2c8c2e79706d 100644 --- a/accounts-db/store-tool/Cargo.toml +++ b/accounts-db/store-tool/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +dev-context-only-utils = [] + [dependencies] ahash = { workspace = true } clap = { workspace = true } @@ -18,6 +21,3 @@ solana-accounts-db = { workspace = true, features = ["dev-context-only-utils"] } solana-pubkey = { workspace = true } solana-system-interface = { workspace = true } solana-version = { workspace = true } - -[features] -dev-context-only-utils = [] diff --git a/banking-bench/Cargo.toml b/banking-bench/Cargo.toml index aa9f23ae452163..318f8ce3e0ca66 100644 --- a/banking-bench/Cargo.toml +++ b/banking-bench/Cargo.toml @@ -8,6 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [] + [dependencies] agave-banking-stage-ingress-types = { workspace = true } assert_matches = { workspace = true } @@ -39,9 +45,3 @@ solana-time-utils = { workspace = true } solana-tpu-client = { workspace = true } solana-transaction = { workspace = true } solana-version = { workspace = true } - -[features] -dev-context-only-utils = [] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/banks-client/Cargo.toml b/banks-client/Cargo.toml index cebe3d155d13cf..9749ef89482ea4 100644 --- a/banks-client/Cargo.toml +++ b/banks-client/Cargo.toml @@ -9,15 +9,27 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_banks_client" + [dependencies] borsh = { workspace = true } futures = { workspace = true } -solana-account = { workspace = true } +solana-account = { workspace = true, features = ["bincode"] } solana-banks-interface = { workspace = true } +solana-clock = { workspace = true } solana-commitment-config = { workspace = true } +solana-hash = { workspace = true } solana-message = { workspace = true } -solana-program = { workspace = true } +solana-program-pack = { workspace = true } +solana-pubkey = { workspace = true } +solana-rent = { workspace = true } solana-signature = { workspace = true } +solana-sysvar = { workspace = true, features = ["bincode"] } solana-transaction = { workspace = true } solana-transaction-context = { workspace = true } solana-transaction-error = { workspace = true } @@ -32,10 +44,3 @@ solana-pubkey = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-signer = { workspace = true } solana-system-interface = { workspace = true } - -[lib] -crate-type = ["lib"] -name = "solana_banks_client" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/banks-client/src/lib.rs b/banks-client/src/lib.rs index 9f5f22dce16acd..6068666f18f9fa 100644 --- a/banks-client/src/lib.rs +++ b/banks-client/src/lib.rs @@ -17,12 +17,15 @@ use { BanksRequest, BanksResponse, BanksTransactionResultWithMetadata, BanksTransactionResultWithSimulation, }, + solana_clock::Slot, solana_commitment_config::CommitmentLevel, + solana_hash::Hash, solana_message::Message, - solana_program::{ - clock::Slot, hash::Hash, program_pack::Pack, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, - }, + solana_program_pack::Pack, + solana_pubkey::Pubkey, + solana_rent::Rent, solana_signature::Signature, + solana_sysvar::Sysvar, solana_transaction::versioned::VersionedTransaction, tarpc::{ client::{self, NewClient, RequestDispatch}, diff --git a/banks-interface/Cargo.toml b/banks-interface/Cargo.toml index 8dc973d31e5dc7..a1178a7bfc54a9 100644 --- a/banks-interface/Cargo.toml +++ b/banks-interface/Cargo.toml @@ -9,10 +9,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_banks_interface" + [dependencies] serde = { workspace = true } serde_derive = { workspace = true } -solana-account = { workspace = true } +solana-account = { workspace = true, features = [ "serde" ] } solana-clock = { workspace = true } solana-commitment-config = { workspace = true, features = [ "serde" ] } solana-hash = { workspace = true } @@ -20,13 +27,6 @@ solana-message = { workspace = true, features = [ "serde" ] } solana-pubkey = { workspace = true } solana-signature = { workspace = true, features = [ "serde" ] } solana-transaction = { workspace = true, features = [ "serde" ] } -solana-transaction-context = { workspace = true } +solana-transaction-context = { workspace = true, features = [ "serde" ] } solana-transaction-error = { workspace = true, features = [ "serde" ] } tarpc = { workspace = true, features = ["full"] } - -[lib] -crate-type = ["lib"] -name = "solana_banks_interface" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/banks-interface/src/lib.rs b/banks-interface/src/lib.rs index c668a598af5fe6..c2cff6aa6b0295 100644 --- a/banks-interface/src/lib.rs +++ b/banks-interface/src/lib.rs @@ -38,6 +38,7 @@ pub struct TransactionStatus { pub struct TransactionSimulationDetails { pub logs: Vec, pub units_consumed: u64, + pub loaded_accounts_data_size: u32, pub return_data: Option, pub inner_instructions: Option>, } diff --git a/banks-server/Cargo.toml b/banks-server/Cargo.toml index d5ad0ce8358dff..3cd5fc9ca75a47 100644 --- a/banks-server/Cargo.toml +++ b/banks-server/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_banks_server" + [dependencies] agave-feature-set = { workspace = true } bincode = { workspace = true } @@ -32,10 +39,3 @@ solana-transaction-error = { workspace = true } tarpc = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] } tokio-serde = { workspace = true, features = ["bincode"] } - -[lib] -crate-type = ["lib"] -name = "solana_banks_server" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/banks-server/src/banks_server.rs b/banks-server/src/banks_server.rs index 1a54f6634bffc8..d5a1e0dfa938d6 100644 --- a/banks-server/src/banks_server.rs +++ b/banks-server/src/banks_server.rs @@ -188,6 +188,7 @@ fn simulate_transaction( logs, post_simulation_accounts: _, units_consumed, + loaded_accounts_data_size, return_data, inner_instructions, } = bank.simulate_transaction_unchecked(&sanitized_transaction, true); @@ -195,6 +196,7 @@ fn simulate_transaction( let simulation_details = TransactionSimulationDetails { logs, units_consumed, + loaded_accounts_data_size, return_data, inner_instructions, }; diff --git a/bench-streamer/Cargo.toml b/bench-streamer/Cargo.toml index 2af7ec8f39be94..70c97e1cf4ab6c 100644 --- a/bench-streamer/Cargo.toml +++ b/bench-streamer/Cargo.toml @@ -8,12 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] clap = { version = "3.1.5", features = ["cargo"] } crossbeam-channel = { workspace = true } solana-net-utils = { workspace = true } solana-streamer = { workspace = true } solana-version = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bench-tps/Cargo.toml b/bench-tps/Cargo.toml index ec8943227b4e24..6c7ee5fee062b5 100644 --- a/bench-tps/Cargo.toml +++ b/bench-tps/Cargo.toml @@ -8,6 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [] + [dependencies] chrono = { workspace = true } clap = { workspace = true } @@ -74,9 +80,3 @@ solana-sdk-ids = { workspace = true } solana-test-validator = { workspace = true } solana-tps-client = { workspace = true, features = ["bank-client"] } tempfile = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [] diff --git a/bench-vote/Cargo.toml b/bench-vote/Cargo.toml index 5241b029c7bc14..61b8bf6cbef9cb 100644 --- a/bench-vote/Cargo.toml +++ b/bench-vote/Cargo.toml @@ -8,6 +8,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] bincode = { workspace = true } clap = { workspace = true } @@ -26,6 +29,3 @@ solana-streamer = { workspace = true } solana-transaction = { workspace = true } solana-version = { workspace = true } solana-vote-program = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/bloom/Cargo.toml b/bloom/Cargo.toml index e7c33801d26aee..93f4520c747c0e 100644 --- a/bloom/Cargo.toml +++ b/bloom/Cargo.toml @@ -9,6 +9,20 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_bloom" + +[features] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-hash/frozen-abi", +] + [dependencies] bv = { workspace = true, features = ["serde"] } fnv = { workspace = true } @@ -30,19 +44,5 @@ solana-hash = { workspace = true } solana-sha256-hasher = { workspace = true } solana-signature = { workspace = true, features = ["std"] } -[lib] -crate-type = ["lib"] -name = "solana_bloom" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-hash/frozen-abi", -] - [lints] workspace = true diff --git a/bucket_map/Cargo.toml b/bucket_map/Cargo.toml index a21ba0fedb6683..55bea8fafbbaec 100644 --- a/bucket_map/Cargo.toml +++ b/bucket_map/Cargo.toml @@ -10,6 +10,10 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["lib"] +name = "solana_bucket_map" + [dependencies] bv = { workspace = true, features = ["serde"] } bytemuck = { workspace = true } @@ -29,9 +33,5 @@ rayon = { workspace = true } solana-logger = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } -[lib] -crate-type = ["lib"] -name = "solana_bucket_map" - [[bench]] name = "bucket_map" diff --git a/builtins-default-costs/Cargo.toml b/builtins-default-costs/Cargo.toml index 159edf3c7ba549..f7f0e85cc02c56 100644 --- a/builtins-default-costs/Cargo.toml +++ b/builtins-default-costs/Cargo.toml @@ -9,6 +9,18 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +# Add additional builtin programs here + +[lib] +crate-type = ["lib"] +name = "solana_builtins_default_costs" + +[features] +frozen-abi = ["dep:solana-frozen-abi", "solana-vote-program/frozen-abi"] +dev-context-only-utils = [] + [dependencies] agave-feature-set = { workspace = true } ahash = { workspace = true } @@ -24,25 +36,10 @@ solana-sdk-ids = { workspace = true } solana-stake-program = { workspace = true } solana-system-program = { workspace = true } solana-vote-program = { workspace = true } -# Add additional builtin programs here - -[lib] -crate-type = ["lib"] -name = "solana_builtins_default_costs" [dev-dependencies] rand = "0.8.5" static_assertions = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -frozen-abi = [ - "dep:solana-frozen-abi", - "solana-vote-program/frozen-abi", -] -dev-context-only-utils = [] - [lints] workspace = true diff --git a/cargo-registry/Cargo.toml b/cargo-registry/Cargo.toml index d91148e1f2790d..907c49040c57ed 100644 --- a/cargo-registry/Cargo.toml +++ b/cargo-registry/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [] + [dependencies] clap = { workspace = true } flate2 = { workspace = true } @@ -38,9 +44,3 @@ tokio = { workspace = true, features = ["full"] } toml = { workspace = true } [dev-dependencies] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [] diff --git a/ci/buildkite-pipeline.sh b/ci/buildkite-pipeline.sh index f71030cbe1b840..7623897b9d737f 100755 --- a/ci/buildkite-pipeline.sh +++ b/ci/buildkite-pipeline.sh @@ -191,6 +191,24 @@ all_test_steps() { # Full test suite .buildkite/scripts/build-stable.sh >> "$output_file" + # crate publish simulation + if affects \ + Cargo.lock$ \ + Cargo.toml$ \ + ^ci/publish-crate.sh \ + ; then + cat >> "$output_file" <<"EOF" + - command: "ci/publish-crate.sh --dry-run" + name: "publish-crate-simulation" + timeout_in_minutes: 180 + artifact_paths: "log-*.txt" + env: + CRATE_PUBLISH_TEST: "true" + agents: + queue: "check" +EOF + fi + # Docs tests if affects \ .rs$ \ diff --git a/ci/cargo/config.toml b/ci/cargo/config.toml new file mode 100644 index 00000000000000..18a2f71838eb8e --- /dev/null +++ b/ci/cargo/config.toml @@ -0,0 +1,9 @@ +[target.x86_64-unknown-linux-gnu] +# When building for linux, target the minimal supported CPU +rustflags = ["-Ctarget-cpu=x86-64-v2"] + +# registry configuration for crate publish test +[registries.kellnr] +index = "sparse+http://127.0.0.1:8000/api/v1/crates/" +credential-provider = ["cargo:token"] +token = "Zy9HhJ02RJmg0GCrgLfaCVfU6IwDfhXD" diff --git a/ci/change-crate-deps.py b/ci/change-crate-deps.py new file mode 100755 index 00000000000000..9ce59bdfd00a65 --- /dev/null +++ b/ci/change-crate-deps.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +# This script: +# - searches given manifest file for solana / agave dependencies +# - modifies each found line in the file by adding a custom registry parameter +# - writes the output back to the given manifest file +# + +import json +import os +import subprocess +import sys + +if len(sys.argv) != 3: + print('Usage: %s ' % sys.argv[0]) + +real_file = os.path.realpath(__file__) +ci_path = os.path.dirname(real_file) +src_root = os.path.dirname(ci_path) +cargo_toml = os.path.join(src_root, sys.argv[1]) +pkg_name = sys.argv[2] +version = os.environ.get('CI_TAG') + + +def load_metadata(): + cmd = f'{src_root}/cargo metadata --no-deps --format-version=1' + return json.loads(subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]) + + +def get_pkg_deps(package_name): + metadata = load_metadata() + dependency_graph = dict() + + for pkg in metadata['packages']: + dependency_graph[pkg['name']] = [ + x['name'] for x in pkg['dependencies'] if x['name'].startswith(('solana', 'agave')) and x['source'] is None + ] + return dependency_graph[package_name] + + +with open(cargo_toml, 'rb', 0) as file: + data = file.readlines() + deps = get_pkg_deps(pkg_name) + + for idx, line in enumerate(data): + split_line = line.decode().split(" =", 1) + if split_line[0] in deps and not split_line[1].startswith(' { registry'): + tmp = split_line[1].replace("workspace = true", "version = \"" + version + "\"") + tmp = tmp.replace("{", '').lstrip() + data[idx] = bytes(split_line[0] + ' = { registry = "kellnr", ' + tmp, 'utf-8') + +with open(cargo_toml, 'wb') as file: + file.writelines(data) diff --git a/ci/docker-run.sh b/ci/docker-run.sh index 427ee7b319e1c9..66d44b4458cd5c 100755 --- a/ci/docker-run.sh +++ b/ci/docker-run.sh @@ -94,6 +94,12 @@ if [[ -z "$SOLANA_DOCKER_RUN_NOSETUID" ]]; then ARGS+=(--user "$(id -u):$(id -g)") fi +if [[ -n "$CRATE_PUBLISH_TEST" ]]; then + ARGS+=( + --network container:kellnr + ) +fi + if [[ -n $SOLANA_ALLOCATE_TTY ]]; then # Colored output, progress bar and Ctrl-C: # https://stackoverflow.com/a/41099052/10242004 diff --git a/ci/docker/Dockerfile b/ci/docker/Dockerfile index 7d3fa3b8a0c1b4..514317b5ad72f7 100644 --- a/ci/docker/Dockerfile +++ b/ci/docker/Dockerfile @@ -82,7 +82,7 @@ RUN \ # uncomment once the dcou-parition related patch is upstreamed... # cargo install cargo-hack && \ cargo install --git https://github.com/anza-xyz/cargo-hack.git --rev 5e59c3ec6c661c02601487c0d4b2a2649fe06c9f cargo-hack && \ - cargo install cargo-sort && \ + cargo install cargo-sort@^2 && \ cargo install mdbook && \ cargo install mdbook-linkcheck && \ cargo install svgbob_cli && \ diff --git a/ci/env.sh b/ci/env.sh index 953e880e399b28..1fc62a1bd786de 100644 --- a/ci/env.sh +++ b/ci/env.sh @@ -50,6 +50,9 @@ if [[ -n $CI ]]; then else export CI_TAG=$BUILDKITE_TAG fi + if [[ -n $CRATE_PUBLISH_TEST ]]; then + export CRATE_PUBLISH_TEST=$CRATE_PUBLISH_TEST + fi elif [[ -n $APPVEYOR ]]; then export CI_BRANCH=$APPVEYOR_REPO_BRANCH export CI_BUILD_ID=$APPVEYOR_BUILD_ID diff --git a/ci/order-crates-for-publishing.py b/ci/order-crates-for-publishing.py index 6bfda2b29df0d0..1480a4ed0e516d 100755 --- a/ci/order-crates-for-publishing.py +++ b/ci/order-crates-for-publishing.py @@ -10,7 +10,7 @@ import os import json import subprocess -import sys; +import sys real_file = os.path.realpath(__file__) ci_path = os.path.dirname(real_file) @@ -82,7 +82,7 @@ def is_path_dev_dep(dependency): ) def should_add(package, dependency, wrong_self_dev_dependencies): - related_to_solana = dependency['name'].startswith('solana') + related_to_solana = dependency['name'].startswith(('solana','agave')) self_dev_dep_with_dev_context_only_utils = is_self_dev_dep_with_dev_context_only_utils( package, dependency, wrong_self_dev_dependencies ) @@ -102,10 +102,10 @@ def get_packages(): wrong_self_dev_dependencies = list() for pkg in metadata['packages']: - manifest_path[pkg['name']] = pkg['manifest_path']; + manifest_path[pkg['name']] = pkg['manifest_path'] dependency_graph[pkg['name']] = [ x['name'] for x in pkg['dependencies'] if should_add(pkg, x, wrong_self_dev_dependencies) - ]; + ] # Check for direct circular dependencies circular_dependencies = set() diff --git a/ci/publish-crate.sh b/ci/publish-crate.sh index 5d7f3b1e1e1c50..3cb41ddff89be3 100755 --- a/ci/publish-crate.sh +++ b/ci/publish-crate.sh @@ -1,21 +1,60 @@ #!/usr/bin/env bash -set -e + +# shellcheck disable=SC2317 +cleanup() { + ec=$? + docker container stop kellnr || true && docker container prune -f; + exit "$ec" +} + +err_handler() { + ec=$? + echo "ERROR line $1: $BASH_COMMAND" + exit "$ec" +} + +trap cleanup EXIT +trap err_handler ERR SIGINT + +set -Ee + cd "$(dirname "$0")/.." source ci/semver_bash/semver.sh source ci/rust-version.sh stable +DRY_RUN=false +if [[ $1 = --dry-run ]]; then + DRY_RUN=true + export CRATE_PUBLISH_TEST=true + shift +fi + +if $DRY_RUN; then + cp ci/cargo/config.toml .cargo/config.toml +fi + # shellcheck disable=SC2086 is_crate_version_uploaded() { name=$1 version=$2 - curl https://crates.io/api/v1/crates/${name}/${version} | \ - python3 -c "import sys,json; print('version' in json.load(sys.stdin));" + if $DRY_RUN; then + curl http://127.0.0.1:8000/api/v1/crates/${name}/crate_versions | \ + python3 -c "import sys,json; print(len(json.load(sys.stdin)['versions']) > 0);" + else + curl https://crates.io/api/v1/crates/${name}/${version} | \ + python3 -c "import sys,json; print('version' in json.load(sys.stdin));" + fi } # Only package/publish if this is a tagged release [[ -n $CI_TAG ]] || { +if $DRY_RUN; then + CI_TAG=$(grep '^version = "' Cargo.toml | cut -d "=" -f2 | xargs) + CRATES_IO_TOKEN="test" +else echo CI_TAG unset, skipped exit 0 +fi } semverParseInto "$CI_TAG" MAJOR MINOR PATCH SPECIAL @@ -37,10 +76,14 @@ done Cargo_tomls=$(ci/order-crates-for-publishing.py) +if $DRY_RUN; then + docker run --name kellnr -d ghcr.io/kellnr/kellnr:5 +fi + for Cargo_toml in $Cargo_tomls; do echo "--- $Cargo_toml" - # check the version which doesn't inherit from worksapce + # check the version which doesn't inherit from workspace if ! grep -q "^version = { workspace = true }$" "$Cargo_toml"; then echo "Warn: $Cargo_toml doesn't use the inherited version" grep -q "^version = \"$expectedCrateVersion\"$" "$Cargo_toml" || { @@ -62,10 +105,16 @@ for Cargo_toml in $Cargo_tomls; do fi ( - set -x - crate=$(dirname "$Cargo_toml") - cargoCommand="cargo publish --token $CRATES_IO_TOKEN" + if $DRY_RUN; then + ci/change-crate-deps.py "$Cargo_toml" "$crate_name" + + # token is a default value from the kellnr image https://kellnr.io/documentation#config-values + # registry value is defined in docker-run.sh script + cargoCommand="cargo publish --registry kellnr --token Zy9HhJ02RJmg0GCrgLfaCVfU6IwDfhXD --allow-dirty" + else + cargoCommand="cargo publish --token $CRATES_IO_TOKEN" + fi numRetries=10 for ((i = 1; i <= numRetries; i++)); do diff --git a/clap-utils/Cargo.toml b/clap-utils/Cargo.toml index da9298ca776777..a0e9f610816e4a 100644 --- a/clap-utils/Cargo.toml +++ b/clap-utils/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_clap_utils" + [dependencies] chrono = { workspace = true, features = ["default"] } clap = "2.33.0" @@ -37,9 +43,3 @@ assert_matches = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } solana-system-interface = { workspace = true, features = ["bincode"] } tempfile = { workspace = true } - -[lib] -name = "solana_clap_utils" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/clap-v3-utils/Cargo.toml b/clap-v3-utils/Cargo.toml index 1a2d15ce5986d3..4dce300b4f38f2 100644 --- a/clap-v3-utils/Cargo.toml +++ b/clap-v3-utils/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_clap_v3_utils" + [dependencies] chrono = { workspace = true, features = ["default"] } clap = { version = "3.2.23", features = ["cargo"] } @@ -40,9 +46,3 @@ assert_matches = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } solana-system-interface = { workspace = true, features = ["bincode"] } tempfile = { workspace = true } - -[lib] -name = "solana_clap_v3_utils" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/cli-config/Cargo.toml b/cli-config/Cargo.toml index 3a67a6ac35f045..dd322b07b68148 100644 --- a/cli-config/Cargo.toml +++ b/cli-config/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] dirs-next = { workspace = true } serde = { workspace = true } @@ -20,6 +23,3 @@ url = { workspace = true } [dev-dependencies] anyhow = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/cli-output/Cargo.toml b/cli-output/Cargo.toml index 3cc8cd9bc270eb..8af951f23c92b9 100644 --- a/cli-output/Cargo.toml +++ b/cli-output/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] Inflector = { workspace = true } agave-reserved-account-keys = { workspace = true } @@ -33,11 +36,11 @@ solana-hash = { workspace = true } solana-message = { workspace = true } solana-native-token = { workspace = true } solana-packet = { workspace = true } -solana-program = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client-api = { workspace = true } solana-sdk-ids = { workspace = true } solana-signature = { workspace = true } +solana-stake-interface = { workspace = true } solana-system-interface = { workspace = true } solana-sysvar = { workspace = true } solana-transaction = { workspace = true, features = ["verify"] } @@ -51,6 +54,3 @@ ed25519-dalek = { workspace = true } solana-keypair = { workspace = true } solana-signer = { workspace = true } solana-transaction-context = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/cli-output/src/cli_output.rs b/cli-output/src/cli_output.rs index a54baa18aaa521..4aad5021051af7 100644 --- a/cli-output/src/cli_output.rs +++ b/cli-output/src/cli_output.rs @@ -26,13 +26,13 @@ use { solana_epoch_info::EpochInfo, solana_hash::Hash, solana_native_token::lamports_to_sol, - solana_program::stake::state::{Authorized, Lockup}, solana_pubkey::Pubkey, solana_rpc_client_api::response::{ RpcAccountBalance, RpcContactInfo, RpcInflationGovernor, RpcInflationRate, RpcKeyedAccount, RpcSupply, RpcVoteAccountInfo, }, solana_signature::Signature, + solana_stake_interface::state::{Authorized, Lockup}, solana_sysvar::stake_history::StakeHistoryEntry, solana_transaction::{versioned::VersionedTransaction, Transaction}, solana_transaction_error::TransactionError, diff --git a/cli-output/src/display.rs b/cli-output/src/display.rs index f0d64c3087dcab..5613746c0fc1b4 100644 --- a/cli-output/src/display.rs +++ b/cli-output/src/display.rs @@ -11,9 +11,9 @@ use { solana_hash::Hash, solana_message::{compiled_instruction::CompiledInstruction, v0::MessageAddressTableLookup}, solana_native_token::lamports_to_sol, - solana_program::stake, solana_pubkey::Pubkey, solana_signature::Signature, + solana_stake_interface as stake, solana_transaction::versioned::{TransactionVersion, VersionedTransaction}, solana_transaction_error::TransactionError, solana_transaction_status::{ diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 6a980ac4173817..dfa9fe70e05675 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[[bin]] +name = "solana" +path = "src/main.rs" + [dependencies] agave-feature-set = { workspace = true } bincode = { workspace = true } @@ -31,6 +38,7 @@ serde_derive = { workspace = true } serde_json = { workspace = true } solana-account = "=2.2.1" solana-account-decoder = { workspace = true } +solana-address-lookup-table-interface = { workspace = true } solana-borsh = "=2.2.1" solana-bpf-loader-program = { workspace = true } solana-clap-utils = { workspace = true } @@ -41,6 +49,7 @@ solana-clock = "=2.2.2" solana-cluster-type = "=2.2.1" solana-commitment-config = "=2.2.1" solana-compute-budget-interface = { version = "=2.2.2", features = ["borsh"] } +solana-config-interface = "=1.0.0" solana-config-program-client = { workspace = true, features = ["serde"] } solana-connection-cache = { workspace = true } solana-decode-error = "=2.2.1" @@ -48,20 +57,19 @@ solana-epoch-schedule = "=2.2.1" solana-feature-gate-client = "=0.0.2" solana-feature-gate-interface = "=2.2.2" solana-fee-calculator = "=2.2.1" -solana-fee-structure = "=2.2.1" +solana-fee-structure = "=2.3.0" solana-hash = "=2.3.0" -solana-instruction = "=2.2.1" +solana-instruction = "=2.3.0" solana-keypair = "=2.2.1" solana-loader-v3-interface = { version = "=5.0.0", features = ["bincode"] } solana-loader-v4-interface = "=2.2.1" solana-loader-v4-program = { workspace = true } solana-logger = "=2.3.1" -solana-message = "=2.3.0" +solana-message = "=2.4.0" solana-native-token = "=2.2.2" solana-nonce = "=2.2.1" solana-offchain-message = { version = "=2.2.1", features = ["verify"] } solana-packet = "=2.2.1" -solana-program = { version = "=2.2.1", default-features = false } solana-program-runtime = { workspace = true } solana-pubkey = { version = "=2.4.0", default-features = false } solana-pubsub-client = { workspace = true } @@ -103,10 +111,3 @@ solana-streamer = { workspace = true } solana-test-validator = { workspace = true } tempfile = { workspace = true } test-case = { workspace = true } - -[[bin]] -name = "solana" -path = "src/main.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/cli/src/address_lookup_table.rs b/cli/src/address_lookup_table.rs index 7dc861d13636f1..cb5f1a45b4c0aa 100644 --- a/cli/src/address_lookup_table.rs +++ b/cli/src/address_lookup_table.rs @@ -2,19 +2,19 @@ use { crate::cli::{CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult}, clap::{App, AppSettings, Arg, ArgMatches, SubCommand}, solana_account::from_account, - solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*}, - solana_cli_output::{CliAddressLookupTable, CliAddressLookupTableCreated, CliSignature}, - solana_clock::Clock, - solana_commitment_config::CommitmentConfig, - solana_message::Message, - solana_program::address_lookup_table::{ - self, + solana_address_lookup_table_interface::{ + self as address_lookup_table, instruction::{ close_lookup_table, create_lookup_table, deactivate_lookup_table, extend_lookup_table, freeze_lookup_table, }, state::AddressLookupTable, }, + solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*}, + solana_cli_output::{CliAddressLookupTable, CliAddressLookupTableCreated, CliSignature}, + solana_clock::Clock, + solana_commitment_config::CommitmentConfig, + solana_message::Message, solana_pubkey::Pubkey, solana_remote_wallet::remote_wallet::RemoteWalletManager, solana_rpc_client::rpc_client::RpcClient, diff --git a/cli/src/cli.rs b/cli/src/cli.rs index a7d5d5cbf8074f..5a8791a668db84 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -20,7 +20,6 @@ use { solana_instruction::error::InstructionError, solana_keypair::{read_keypair_file, Keypair}, solana_offchain_message::OffchainMessage, - solana_program::stake::{instruction::LockupArgs, state::Lockup}, solana_pubkey::Pubkey, solana_remote_wallet::remote_wallet::RemoteWalletManager, solana_rpc_client::rpc_client::RpcClient, @@ -31,6 +30,7 @@ use { solana_rpc_client_nonce_utils::blockhash_query::BlockhashQuery, solana_signature::Signature, solana_signer::{Signer, SignerError}, + solana_stake_interface::{instruction::LockupArgs, state::Lockup}, solana_tps_client::{utils::create_connection_cache, TpsClient}, solana_tpu_client::tpu_client::{ TpuClient, TpuClientConfig, DEFAULT_TPU_CONNECTION_POOL_SIZE, DEFAULT_TPU_ENABLE_UDP, diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index c0275d4b05d3d7..b74868ce8867c1 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -33,7 +33,6 @@ use { solana_message::Message, solana_native_token::lamports_to_sol, solana_nonce::state::State as NonceState, - solana_program::stake::{self, state::StakeStateV2}, solana_pubkey::Pubkey, solana_pubsub_client::pubsub_client::PubsubClient, solana_remote_wallet::remote_wallet::RemoteWalletManager, @@ -53,6 +52,7 @@ use { solana_sdk_ids::sysvar::{self, stake_history}, solana_signature::Signature, solana_slot_history::{self as slot_history, SlotHistory}, + solana_stake_interface::{self as stake, state::StakeStateV2}, solana_system_interface::{instruction as system_instruction, MAX_PERMITTED_DATA_LENGTH}, solana_tps_client::TpsClient, solana_transaction::Transaction, diff --git a/cli/src/stake.rs b/cli/src/stake.rs index bc5300f6345e55..a9667033ca7b7b 100644 --- a/cli/src/stake.rs +++ b/cli/src/stake.rs @@ -37,12 +37,6 @@ use { solana_epoch_schedule::EpochSchedule, solana_message::Message, solana_native_token::Sol, - solana_program::stake::{ - self, - instruction::{self as stake_instruction, LockupArgs, StakeError}, - state::{Authorized, Lockup, Meta, StakeActivationStatus, StakeAuthorize, StakeStateV2}, - tools::{acceptable_reference_epoch_credits, eligible_for_deactivate_delinquent}, - }, solana_pubkey::Pubkey, solana_remote_wallet::remote_wallet::RemoteWalletManager, solana_rpc_client::rpc_client::RpcClient, @@ -56,6 +50,13 @@ use { system_program, sysvar::{clock, stake_history}, }, + solana_stake_interface::{ + self as stake, + error::StakeError, + instruction::{self as stake_instruction, LockupArgs}, + state::{Authorized, Lockup, Meta, StakeActivationStatus, StakeAuthorize, StakeStateV2}, + tools::{acceptable_reference_epoch_credits, eligible_for_deactivate_delinquent}, + }, solana_system_interface::{error::SystemError, instruction as system_instruction}, solana_sysvar::stake_history::StakeHistory, solana_transaction::Transaction, diff --git a/cli/src/validator_info.rs b/cli/src/validator_info.rs index 950710450d6f35..9920e0b2431b69 100644 --- a/cli/src/validator_info.rs +++ b/cli/src/validator_info.rs @@ -10,7 +10,7 @@ use { serde_json::{Map, Value}, solana_account::Account, solana_account_decoder::validator_info::{ - self, ValidatorInfo, MAX_LONG_FIELD_LENGTH, MAX_SHORT_FIELD_LENGTH, + self, ValidatorInfo, MAX_LONG_FIELD_LENGTH, MAX_SHORT_FIELD_LENGTH, MAX_VALIDATOR_INFO, }, solana_clap_utils::{ compute_budget::{compute_unit_price_arg, ComputeUnitLimit, COMPUTE_UNIT_PRICE_ARG}, @@ -20,11 +20,8 @@ use { keypair::DefaultSigner, }, solana_cli_output::{CliValidatorInfo, CliValidatorInfoVec}, - solana_config_program_client::{ - get_config_data, - instructions_bincode::{self as config_instruction, ConfigState}, - ConfigKeys, - }, + solana_config_interface::instruction::{self as config_instruction}, + solana_config_program_client::{get_config_data, ConfigKeys}, solana_keypair::Keypair, solana_message::Message, solana_pubkey::Pubkey, @@ -48,7 +45,7 @@ pub fn check_details_length(string: String) -> Result<(), String> { pub fn check_total_length(info: &ValidatorInfo) -> Result<(), String> { let size = serialized_size(&info).unwrap(); - let limit = ValidatorInfo::max_space(); + let limit = MAX_VALIDATOR_INFO; if size > limit { Err(format!( @@ -337,7 +334,7 @@ pub fn process_set_validator_info( (validator_info::id(), false), (config.signers[0].pubkey(), true), ]; - let data_len = ValidatorInfo::max_space() + let data_len = MAX_VALIDATOR_INFO .checked_add(serialized_size(&ConfigKeys { keys: keys.clone() }).unwrap()) .expect("ValidatorInfo and two keys fit into a u64"); let lamports = rpc_client.get_minimum_balance_for_rent_exemption(data_len as usize)?; @@ -360,16 +357,18 @@ pub fn process_set_validator_info( "Publishing info for Validator {:?}", config.signers[0].pubkey() ); - let mut instructions = config_instruction::create_account::( - &config.signers[0].pubkey(), - &info_pubkey, - lamports, - keys.clone(), - ) - .with_compute_unit_config(&ComputeUnitConfig { - compute_unit_price, - compute_unit_limit, - }); + let mut instructions = + config_instruction::create_account_with_max_config_space::( + &config.signers[0].pubkey(), + &info_pubkey, + lamports, + MAX_VALIDATOR_INFO, + keys.clone(), + ) + .with_compute_unit_config(&ComputeUnitConfig { + compute_unit_price, + compute_unit_limit, + }); instructions.extend_from_slice(&[config_instruction::store( &info_pubkey, true, @@ -661,7 +660,7 @@ mod tests { assert_eq!( serialized_size(&validator_info).unwrap(), - ValidatorInfo::max_space() + MAX_VALIDATOR_INFO ); } } diff --git a/client-test/Cargo.toml b/client-test/Cargo.toml index 3368bb6b06ae99..f1551e8e9a95d0 100644 --- a/client-test/Cargo.toml +++ b/client-test/Cargo.toml @@ -10,6 +10,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] futures-util = { workspace = true } serde_json = { workspace = true } @@ -46,6 +49,3 @@ solana-logger = { workspace = true } solana-net-utils = { workspace = true } solana-rpc = { workspace = true, features = ["dev-context-only-utils"] } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/client-test/tests/client.rs b/client-test/tests/client.rs index 6781f2de7bb7f2..8d8e938abc8405 100644 --- a/client-test/tests/client.rs +++ b/client-test/tests/client.rs @@ -135,11 +135,9 @@ fn test_account_subscription() { bank_forks.write().unwrap().insert(bank1); let bob = Keypair::new(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -253,12 +251,10 @@ fn test_block_subscription() { max_complete_transaction_status_slot, ); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); // setup RpcSubscriptions && PubSubService let subscriptions = Arc::new(RpcSubscriptions::new_for_tests_with_blockstore( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore.clone(), bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), @@ -341,11 +337,9 @@ fn test_program_subscription() { bank_forks.write().unwrap().insert(bank1); let bob = Keypair::new(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -427,11 +421,9 @@ fn test_root_subscription() { let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1); bank_forks.write().unwrap().insert(bank1); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -478,11 +470,9 @@ fn test_slot_subscription() { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, Arc::new(RwLock::new(BlockCommitmentCache::default())), optimistically_confirmed_bank, @@ -554,11 +544,9 @@ async fn test_slot_subscription_async() { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, Arc::new(RwLock::new(BlockCommitmentCache::default())), optimistically_confirmed_bank, diff --git a/client/Cargo.toml b/client/Cargo.toml index 986a926fd87761..b9bf4f9604e658 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] async-trait = { workspace = true } bincode = { workspace = true } @@ -52,6 +55,3 @@ tokio = { workspace = true, features = ["full"] } [dev-dependencies] crossbeam-channel = { workspace = true } solana-net-utils = { workspace = true, features = ["dev-context-only-utils"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/compute-budget-instruction/Cargo.toml b/compute-budget-instruction/Cargo.toml index 779418adb2ec0e..8971b9b619c6bf 100644 --- a/compute-budget-instruction/Cargo.toml +++ b/compute-budget-instruction/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_compute_budget_instruction" + +[features] +dev-context-only-utils = [] + [dependencies] agave-feature-set = { workspace = true } log = { workspace = true } @@ -24,10 +34,6 @@ solana-svm-transaction = { workspace = true } solana-transaction-error = { workspace = true } thiserror = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_compute_budget_instruction" - [dev-dependencies] bincode = { workspace = true } criterion = { workspace = true } @@ -36,17 +42,11 @@ solana-builtins-default-costs = { workspace = true, features = ["dev-context-onl solana-hash = { workspace = true } solana-keypair = { workspace = true } solana-message = { workspace = true } -solana-program = { workspace = true } solana-signer = { workspace = true } +solana-stake-interface = { workspace = true } solana-system-interface = { workspace = true } solana-transaction = { workspace = true, features = ["blake3"] } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [] - [[bench]] name = "process_compute_budget_instructions" harness = false diff --git a/compute-budget-instruction/src/compute_budget_instruction_details.rs b/compute-budget-instruction/src/compute_budget_instruction_details.rs index 23a0b4bd234759..c25847bd238f8a 100644 --- a/compute-budget-instruction/src/compute_budget_instruction_details.rs +++ b/compute-budget-instruction/src/compute_budget_instruction_details.rs @@ -516,7 +516,7 @@ mod test { fn test_builtin_program_migration() { let tx = build_sanitized_transaction(&[ Instruction::new_with_bincode(Pubkey::new_unique(), &(), vec![]), - solana_program::stake::instruction::delegate_stake( + solana_stake_interface::instruction::delegate_stake( &Pubkey::new_unique(), &Pubkey::new_unique(), &Pubkey::new_unique(), diff --git a/compute-budget/Cargo.toml b/compute-budget/Cargo.toml index 2a9a1b3e9d41df..d5a93b4958b9e9 100644 --- a/compute-budget/Cargo.toml +++ b/compute-budget/Cargo.toml @@ -9,6 +9,10 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +dev-context-only-utils = ["dep:qualifier_attr"] +frozen-abi = ["dep:solana-frozen-abi", "solana-fee-structure/frozen-abi"] + [dependencies] qualifier_attr = { workspace = true, optional = true } solana-fee-structure = { workspace = true } @@ -17,9 +21,5 @@ solana-frozen-abi = { workspace = true, optional = true, features = [ ] } solana-program-runtime = { workspace = true } -[features] -dev-context-only-utils = ["dep:qualifier_attr"] -frozen-abi = ["dep:solana-frozen-abi", "solana-fee-structure/frozen-abi"] - [lints] workspace = true diff --git a/core/Cargo.toml b/core/Cargo.toml index 40d48e24084626..85a0b12fcee584 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -10,8 +10,35 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[badges] -codecov = { repository = "solana-labs/solana", branch = "master", service = "github" } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [ + "solana-perf/dev-context-only-utils", + "solana-runtime/dev-context-only-utils", + "solana-streamer/dev-context-only-utils", +] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-accounts-db/frozen-abi", + "solana-bloom/frozen-abi", + "solana-compute-budget/frozen-abi", + "solana-cost-model/frozen-abi", + "solana-frozen-abi/frozen-abi", + "solana-gossip/frozen-abi", + "solana-ledger/frozen-abi", + "solana-packet/frozen-abi", + "solana-perf/frozen-abi", + "solana-program-runtime/frozen-abi", + "solana-runtime/frozen-abi", + "solana-short-vec/frozen-abi", + "solana-signature/frozen-abi", + "solana-svm/frozen-abi", + "solana-vote/frozen-abi", + "solana-vote-program/frozen-abi", +] [dependencies] agave-banking-stage-ingress-types = { workspace = true } @@ -30,6 +57,7 @@ chrono = { workspace = true, features = ["default", "serde"] } conditional-mod = { workspace = true } crossbeam-channel = { workspace = true } dashmap = { workspace = true, features = ["rayon", "raw-api"] } +derive_more = { workspace = true } etcd-client = { workspace = true, features = ["tls"] } futures = { workspace = true } histogram = { workspace = true } @@ -135,7 +163,7 @@ solana-vortexor-receiver = { workspace = true } solana-vote = { workspace = true } solana-vote-program = { workspace = true } solana-wen-restart = { workspace = true } -static_assertions ={ workspace = true } +static_assertions = { workspace = true } strum = { workspace = true, features = ["derive"] } strum_macros = { workspace = true } sys-info = { workspace = true } @@ -145,12 +173,19 @@ tokio = { workspace = true, features = ["full"] } tokio-util = { workspace = true } trees = { workspace = true } +[target.'cfg(not(any(target_env = "msvc", target_os = "freebsd")))'.dependencies] +jemallocator = { workspace = true } + +[target."cfg(unix)".dependencies] +sysctl = { workspace = true } + [dev-dependencies] agave-reserved-account-keys = { workspace = true } criterion = { workspace = true } fs_extra = { workspace = true } serde_json = { workspace = true } serial_test = { workspace = true } +solana-account = { workspace = true, features = ["dev-context-only-utils"] } # See order-crates-for-publishing.py for using this unusual `path = "."` solana-bpf-loader-program = { workspace = true } solana-compute-budget-interface = { workspace = true } @@ -164,7 +199,6 @@ solana-net-utils = { workspace = true, features = ["dev-context-only-utils"] } solana-poh = { workspace = true, features = ["dev-context-only-utils"] } solana-program-runtime = { workspace = true, features = ["metrics"] } solana-rpc = { workspace = true, features = ["dev-context-only-utils"] } -solana-sdk = { workspace = true, features = ["full", "dev-context-only-utils"] } solana-stake-program = { workspace = true } solana-system-program = { workspace = true } solana-unified-scheduler-logic = { workspace = true } @@ -176,36 +210,8 @@ spl-memo = { workspace = true, features = ["no-entrypoint"] } static_assertions = { workspace = true } test-case = { workspace = true } -[target."cfg(unix)".dependencies] -sysctl = { workspace = true } - -[target.'cfg(not(any(target_env = "msvc", target_os = "freebsd")))'.dependencies] -jemallocator = { workspace = true } - -[features] -dev-context-only-utils = [ - "solana-perf/dev-context-only-utils", - "solana-runtime/dev-context-only-utils", - "solana-streamer/dev-context-only-utils", -] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-accounts-db/frozen-abi", - "solana-bloom/frozen-abi", - "solana-compute-budget/frozen-abi", - "solana-cost-model/frozen-abi", - "solana-gossip/frozen-abi", - "solana-ledger/frozen-abi", - "solana-perf/frozen-abi", - "solana-program-runtime/frozen-abi", - "solana-runtime/frozen-abi", - "solana-sdk/frozen-abi", - "solana-short-vec/frozen-abi", - "solana-svm/frozen-abi", - "solana-vote/frozen-abi", - "solana-vote-program/frozen-abi", -] +[badges] +codecov = { repository = "solana-labs/solana", branch = "master", service = "github" } [[bench]] name = "banking_stage" @@ -224,8 +230,5 @@ harness = false name = "scheduler" harness = false -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [lints] workspace = true diff --git a/core/src/banking_stage/consume_worker.rs b/core/src/banking_stage/consume_worker.rs index 461f644e6edd1d..575d0ccd9b30b5 100644 --- a/core/src/banking_stage/consume_worker.rs +++ b/core/src/banking_stage/consume_worker.rs @@ -768,6 +768,7 @@ mod tests { thread::JoinHandle, }, tempfile::TempDir, + test_case::test_case, }; // Helper struct to create tests that hold channels, files, etc. @@ -787,7 +788,9 @@ mod tests { consumed_receiver: Receiver>>, } - fn setup_test_frame() -> ( + fn setup_test_frame( + relax_intrabatch_account_locks: bool, + ) -> ( TestFrame, ConsumeWorker>, ) { @@ -798,11 +801,15 @@ mod tests { } = create_slow_genesis_config(10_000); let (bank, bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config); // Warp to next epoch for MaxAge tests. - let bank = Arc::new(Bank::new_from_parent( + let mut bank = Bank::new_from_parent( bank.clone(), &Pubkey::new_unique(), bank.get_epoch_info().slots_in_epoch, - )); + ); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } + let bank = Arc::new(bank); let ledger_path = get_tmp_ledger_path_auto_delete!(); let blockstore = Blockstore::open(ledger_path.path()) @@ -861,7 +868,7 @@ mod tests { #[test] fn test_worker_consume_no_bank() { - let (test_frame, worker) = setup_test_frame(); + let (test_frame, worker) = setup_test_frame(true); let TestFrame { mint_keypair, genesis_config, @@ -905,7 +912,7 @@ mod tests { #[test] fn test_worker_consume_simple() { - let (test_frame, worker) = setup_test_frame(); + let (test_frame, worker) = setup_test_frame(true); let TestFrame { mint_keypair, genesis_config, @@ -952,9 +959,10 @@ mod tests { let _ = worker_thread.join().unwrap(); } - #[test] - fn test_worker_consume_self_conflicting() { - let (test_frame, worker) = setup_test_frame(); + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_worker_consume_self_conflicting(relax_intrabatch_account_locks: bool) { + let (test_frame, worker) = setup_test_frame(relax_intrabatch_account_locks); let TestFrame { mint_keypair, genesis_config, @@ -998,7 +1006,16 @@ mod tests { assert_eq!(consumed.work.batch_id, bid); assert_eq!(consumed.work.ids, vec![id1, id2]); assert_eq!(consumed.work.max_ages, vec![max_age, max_age]); - assert_eq!(consumed.retryable_indexes, vec![1]); // id2 is retryable since lock conflict + + // id2 succeeds with simd83, or is retryable due to lock conflict without simd83 + assert_eq!( + consumed.retryable_indexes, + if relax_intrabatch_account_locks { + vec![] + } else { + vec![1] + } + ); drop(test_frame); let _ = worker_thread.join().unwrap(); @@ -1006,7 +1023,7 @@ mod tests { #[test] fn test_worker_consume_multiple_messages() { - let (test_frame, worker) = setup_test_frame(); + let (test_frame, worker) = setup_test_frame(true); let TestFrame { mint_keypair, genesis_config, @@ -1081,7 +1098,7 @@ mod tests { #[test] fn test_worker_ttl() { - let (test_frame, worker) = setup_test_frame(); + let (test_frame, worker) = setup_test_frame(true); let TestFrame { mint_keypair, genesis_config, diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index d466ac47b7e09a..fd66ac995c8e07 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -531,6 +531,7 @@ mod tests { thread::{Builder, JoinHandle}, time::Duration, }, + test_case::test_case, }; fn execute_transactions_with_dummy_poh_service( @@ -832,8 +833,8 @@ mod tests { if let Ok(record) = record { let record_response = poh_recorder.write().unwrap().record( record.slot, - record.mixin, - record.transactions, + record.mixins, + record.transaction_batches, ); poh_recorder.write().unwrap().tick(); if record.sender.send(record_response).is_err() { @@ -1007,8 +1008,11 @@ mod tests { let _ = poh_simulator.join(); } - #[test] - fn test_bank_process_and_record_transactions_cost_tracker() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_bank_process_and_record_transactions_cost_tracker( + relax_intrabatch_account_locks: bool, + ) { solana_logger::setup(); let GenesisConfigInfo { genesis_config, @@ -1016,6 +1020,9 @@ mod tests { .. } = create_slow_genesis_config(10_000); let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } bank.ns_per_slot = u128::MAX; let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); let pubkey = solana_pubkey::new_rand(); @@ -1098,6 +1105,14 @@ mod tests { system_transaction::transfer(&mint_keypair, &pubkey, 2, genesis_config.hash()), ]); + let conflicting_transaction = sanitize_transactions(vec![system_transaction::transfer( + &Keypair::new(), + &pubkey, + 1, + genesis_config.hash(), + )]); + bank.try_lock_accounts(&conflicting_transaction); + let process_transactions_batch_output = consumer.process_and_record_transactions(&bank, &transactions); @@ -1162,22 +1177,46 @@ mod tests { let _ = poh_simulator.join(); } - #[test] - fn test_bank_process_and_record_transactions_account_in_use() { + #[test_case(false, false; "old::locked")] + #[test_case(false, true; "old::duplicate")] + #[test_case(true, false; "simd83::locked")] + #[test_case(true, true; "simd83::duplicate")] + fn test_bank_process_and_record_transactions_account_in_use( + relax_intrabatch_account_locks: bool, + use_duplicate_transaction: bool, + ) { solana_logger::setup(); let GenesisConfigInfo { genesis_config, mint_keypair, .. } = create_slow_genesis_config(10_000); - let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } + bank.ns_per_slot = u128::MAX; + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); let pubkey = solana_pubkey::new_rand(); let pubkey1 = solana_pubkey::new_rand(); let transactions = sanitize_transactions(vec![ system_transaction::transfer(&mint_keypair, &pubkey, 1, genesis_config.hash()), - system_transaction::transfer(&mint_keypair, &pubkey1, 1, genesis_config.hash()), + system_transaction::transfer( + &mint_keypair, + if use_duplicate_transaction { + &pubkey + } else { + &pubkey1 + }, + 1, + genesis_config.hash(), + ), ]); + assert_eq!( + transactions[0].message_hash() == transactions[1].message_hash(), + use_duplicate_transaction + ); let ledger_path = get_tmp_ledger_path_auto_delete!(); let blockstore = Blockstore::open(ledger_path.path()) @@ -1212,6 +1251,20 @@ mod tests { ); let consumer = Consumer::new(committer, recorder, QosService::new(1), None); + // with simd83 and no duplicate, we take a cross-batch lock on an account to create a conflict + // with a duplicate transaction and simd83 it comes from message hash equality in the batch + // without simd83 the conflict comes from locks in batch + if relax_intrabatch_account_locks && !use_duplicate_transaction { + let conflicting_transaction = + sanitize_transactions(vec![system_transaction::transfer( + &Keypair::new(), + &pubkey1, + 1, + genesis_config.hash(), + )]); + bank.try_lock_accounts(&conflicting_transaction); + } + let process_transactions_batch_output = consumer.process_and_record_transactions(&bank, &transactions); @@ -1237,8 +1290,14 @@ mod tests { processed_with_successful_result_count: 1, } ); - assert_eq!(retryable_transaction_indexes, vec![1]); assert!(commit_transactions_result.is_ok()); + + // with simd3, duplicate transactions are not retryable + if relax_intrabatch_account_locks && use_duplicate_transaction { + assert_eq!(retryable_transaction_indexes, Vec::::new()); + } else { + assert_eq!(retryable_transaction_indexes, vec![1]); + } } #[test] @@ -1297,30 +1356,48 @@ mod tests { ); } - #[test] - fn test_process_transactions_account_in_use() { + #[test_case(false, false; "old::locked")] + #[test_case(false, true; "old::duplicate")] + #[test_case(true, false; "simd83::locked")] + #[test_case(true, true; "simd83::duplicate")] + fn test_process_transactions_account_in_use( + relax_intrabatch_account_locks: bool, + use_duplicate_transaction: bool, + ) { solana_logger::setup(); let GenesisConfigInfo { genesis_config, mint_keypair, .. } = create_slow_genesis_config(10_000); - let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } + bank.ns_per_slot = u128::MAX; + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); // set cost tracker limits to MAX so it will not filter out TXs bank.write_cost_tracker() .unwrap() .set_limits(u64::MAX, u64::MAX, u64::MAX); - // Make all repetitive transactions that conflict on the `mint_keypair`, so only 1 should be executed - let transactions = vec![ - system_transaction::transfer( + let mut transactions = vec![]; + let destination = Pubkey::new_unique(); + let mut amount = 1; + + // Make distinct, or identical, transactions that conflict on the `mint_keypair` + for _ in 0..TARGET_NUM_TRANSACTIONS_PER_BATCH { + transactions.push(system_transaction::transfer( &mint_keypair, - &Pubkey::new_unique(), - 1, - genesis_config.hash() - ); - TARGET_NUM_TRANSACTIONS_PER_BATCH - ]; + &destination, + amount, + genesis_config.hash(), + )); + + if !use_duplicate_transaction { + amount += 1; + } + } let transactions_len = transactions.len(); let ProcessTransactionBatchOutput { @@ -1328,7 +1405,14 @@ mod tests { .. } = execute_transactions_with_dummy_poh_service(bank, transactions); - // All the transactions should have been replayed, but only 2 committed (first and last) + // If SIMD-83 is enabled *and* the transactions are distinct, all are executed. + // In the three other cases, only one is executed. In all four cases, all are attempted. + let execution_count = if relax_intrabatch_account_locks && !use_duplicate_transaction { + transactions_len + } else { + 1 + } as u64; + assert_eq!( execute_and_commit_transactions_output .transaction_counts @@ -1339,20 +1423,29 @@ mod tests { execute_and_commit_transactions_output .transaction_counts .processed_count, - 1 + execution_count ); assert_eq!( execute_and_commit_transactions_output .transaction_counts .processed_with_successful_result_count, - 1 + execution_count ); - // Everything except first of the transactions failed and are retryable - assert_eq!( - execute_and_commit_transactions_output.retryable_transaction_indexes, - (1..transactions_len).collect::>() - ); + // If SIMD-83 is enabled and the transactions are distinct, there are zero retryable (all executed). + // If SIMD-83 is enabled and the transactions are identical, there are zero retryable (marked AlreadyProcessed). + // If SIMD-83 is not enabled, all but the first are retryable (marked AccountInUse). + if relax_intrabatch_account_locks { + assert_eq!( + execute_and_commit_transactions_output.retryable_transaction_indexes, + Vec::::new() + ); + } else { + assert_eq!( + execute_and_commit_transactions_output.retryable_transaction_indexes, + (1..transactions_len).collect::>() + ); + } } #[test] diff --git a/core/src/banking_stage/decision_maker.rs b/core/src/banking_stage/decision_maker.rs index c355253236ffa7..7a88fbb44399ff 100644 --- a/core/src/banking_stage/decision_maker.rs +++ b/core/src/banking_stage/decision_maker.rs @@ -5,6 +5,7 @@ use { HOLD_TRANSACTIONS_SLOT_OFFSET, }, solana_pubkey::Pubkey, + solana_unified_scheduler_pool::{BankingStageMonitor, BankingStageStatus}, std::{ sync::{Arc, RwLock}, time::{Duration, Instant}, @@ -29,9 +30,10 @@ impl BufferedPacketsDecision { } } -#[derive(Clone)] +#[derive(Clone, derive_more::Debug)] pub struct DecisionMaker { my_pubkey: Pubkey, + #[debug("{poh_recorder:p}")] poh_recorder: Arc>, cached_decision: Option, @@ -134,6 +136,19 @@ impl DecisionMaker { } } +impl BankingStageMonitor for DecisionMaker { + fn status(&mut self) -> BankingStageStatus { + if matches!( + self.make_consume_or_forward_decision(), + BufferedPacketsDecision::Forward, + ) { + BankingStageStatus::Inactive + } else { + BankingStageStatus::Active + } + } +} + #[cfg(test)] mod tests { use { diff --git a/core/src/banking_stage/transaction_scheduler/greedy_scheduler.rs b/core/src/banking_stage/transaction_scheduler/greedy_scheduler.rs index 0ea873dbd4953a..7f2b5d4b0fa36e 100644 --- a/core/src/banking_stage/transaction_scheduler/greedy_scheduler.rs +++ b/core/src/banking_stage/transaction_scheduler/greedy_scheduler.rs @@ -282,12 +282,12 @@ mod test { }, crossbeam_channel::unbounded, itertools::Itertools, - solana_pubkey::Pubkey, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_compute_budget_interface::ComputeBudgetInstruction, solana_hash::Hash, - solana_message::Message, solana_keypair::Keypair, + solana_message::Message, + solana_pubkey::Pubkey, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_signer::Signer, solana_system_interface::instruction as system_instruction, solana_transaction::{sanitized::SanitizedTransaction, Transaction}, diff --git a/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs b/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs index c898dd737148bc..35a2bcfe837033 100644 --- a/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs +++ b/core/src/banking_stage/transaction_scheduler/prio_graph_scheduler.rs @@ -24,8 +24,8 @@ use { prio_graph::{AccessKind, GraphNode, PrioGraph}, solana_cost_model::block_cost_limits::MAX_BLOCK_UNITS, solana_measure::measure_us, - solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_pubkey::Pubkey, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_svm_transaction::svm_message::SVMMessage, std::num::Saturating, }; @@ -265,10 +265,10 @@ impl Scheduler for PrioGraphScheduler { >= self.config.target_transactions_per_batch { num_sent += self.common.send_batch( - &mut batches, - thread_id, - self.config.target_transactions_per_batch, - )?; + &mut batches, + thread_id, + self.config.target_transactions_per_batch, + )?; } // if the thread is at max_cu_per_thread, remove it from the schedulable threads @@ -291,7 +291,8 @@ impl Scheduler for PrioGraphScheduler { } // Send all non-empty batches - num_sent += self.common + num_sent += self + .common .send_batches(&mut batches, self.config.target_transactions_per_batch)?; // Refresh window budget and do chunked pops @@ -305,7 +306,8 @@ impl Scheduler for PrioGraphScheduler { } // Send batches for any remaining transactions - num_sent += self.common + num_sent += self + .common .send_batches(&mut batches, self.config.target_transactions_per_batch)?; // Push unschedulable ids back into the container @@ -433,12 +435,12 @@ mod tests { }, crossbeam_channel::{unbounded, Receiver}, itertools::Itertools, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_compute_budget_interface::ComputeBudgetInstruction, solana_hash::Hash, + solana_keypair::Keypair, solana_message::Message, solana_pubkey::Pubkey, - solana_keypair::Keypair, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_signer::Signer, solana_system_interface::instruction as system_instruction, solana_transaction::{sanitized::SanitizedTransaction, Transaction}, diff --git a/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs b/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs index b04689383ca17a..dc1c329b7213f9 100644 --- a/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs +++ b/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs @@ -25,19 +25,19 @@ use { core::time::Duration, crossbeam_channel::{RecvTimeoutError, TryRecvError}, solana_accounts_db::account_locks::validate_account_locks, + solana_address_lookup_table_interface::state::estimate_last_valid_slot, + solana_clock::{Epoch, Slot, MAX_PROCESSING_AGE}, solana_cost_model::cost_model::CostModel, + solana_fee_structure::FeeBudgetLimits, solana_measure::measure_us, solana_runtime::{bank::Bank, bank_forks::BankForks}, solana_runtime_transaction::{ runtime_transaction::RuntimeTransaction, transaction_meta::StaticMeta, transaction_with_meta::TransactionWithMeta, }, - solana_address_lookup_table_interface::state::estimate_last_valid_slot, - solana_clock::{Epoch, Slot, MAX_PROCESSING_AGE}, - solana_fee_structure::FeeBudgetLimits, - solana_transaction::sanitized::{MessageHash, SanitizedTransaction}, solana_svm::transaction_error_metrics::TransactionErrorMetrics, solana_svm_transaction::svm_message::SVMMessage, + solana_transaction::sanitized::{MessageHash, SanitizedTransaction}, std::{ num::Saturating, sync::{Arc, RwLock}, @@ -264,7 +264,8 @@ impl SanitizedTransactionReceiveAndBuffer { count_metrics.num_buffered += num_buffered; count_metrics.num_dropped_on_sanitization += num_dropped_on_sanitization; count_metrics.num_dropped_on_validate_locks += num_dropped_on_lock_validation; - count_metrics.num_dropped_on_receive_transaction_checks += num_dropped_on_transaction_checks; + count_metrics.num_dropped_on_receive_transaction_checks += + num_dropped_on_transaction_checks; }); } } @@ -661,13 +662,13 @@ mod tests { super::*, crate::banking_stage::tests::create_slow_genesis_config, crossbeam_channel::{unbounded, Receiver}, - solana_ledger::genesis_utils::GenesisConfigInfo, - solana_perf::packet::{to_packet_batches, Packet, PacketBatch, PinnedPacketBatch}, - solana_pubkey::Pubkey, solana_hash::Hash, + solana_keypair::Keypair, + solana_ledger::genesis_utils::GenesisConfigInfo, solana_message::{v0, AddressLookupTableAccount, VersionedMessage}, solana_packet::{Meta, PACKET_DATA_SIZE}, - solana_keypair::Keypair, + solana_perf::packet::{to_packet_batches, Packet, PacketBatch, PinnedPacketBatch}, + solana_pubkey::Pubkey, solana_signer::Signer, solana_system_interface::instruction as system_instruction, solana_system_transaction::transfer, @@ -749,8 +750,7 @@ mod tests { calculate_max_age(sanitized_epoch, current_slot - 1, current_slot), MaxAge { sanitized_epoch, - alt_invalidation_slot: current_slot - 1 - + solana_slot_hashes::get_entries() as u64, + alt_invalidation_slot: current_slot - 1 + solana_slot_hashes::get_entries() as u64, } ); diff --git a/core/src/banking_stage/transaction_scheduler/scheduler_common.rs b/core/src/banking_stage/transaction_scheduler/scheduler_common.rs index c01ac0bca1bda0..c03792915eeea6 100644 --- a/core/src/banking_stage/transaction_scheduler/scheduler_common.rs +++ b/core/src/banking_stage/transaction_scheduler/scheduler_common.rs @@ -282,12 +282,10 @@ mod tests { use { super::*, crate::banking_stage::transaction_scheduler::transaction_state_container::TransactionStateContainer, - crossbeam_channel::unbounded, - solana_keypair::Keypair, - solana_pubkey::Pubkey, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, - solana_hash::Hash, solana_system_transaction as system_transaction, solana_transaction::sanitized::SanitizedTransaction, - test_case::test_case, + crossbeam_channel::unbounded, solana_hash::Hash, solana_keypair::Keypair, + solana_pubkey::Pubkey, solana_runtime_transaction::runtime_transaction::RuntimeTransaction, + solana_system_transaction as system_transaction, + solana_transaction::sanitized::SanitizedTransaction, test_case::test_case, }; const NUM_WORKERS: usize = 4; diff --git a/core/src/banking_stage/transaction_scheduler/transaction_state.rs b/core/src/banking_stage/transaction_scheduler/transaction_state.rs index 019ee97770182d..ecf0debf3c7e37 100644 --- a/core/src/banking_stage/transaction_scheduler/transaction_state.rs +++ b/core/src/banking_stage/transaction_scheduler/transaction_state.rs @@ -88,11 +88,11 @@ impl TransactionState { mod tests { use { super::*, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_compute_budget_interface::ComputeBudgetInstruction, solana_hash::Hash, - solana_message::Message, solana_keypair::Keypair, + solana_message::Message, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_signer::Signer, solana_system_interface::instruction as system_instruction, solana_transaction::{sanitized::SanitizedTransaction, Transaction}, diff --git a/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs b/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs index f6914621b3cc2a..bfd1419dcf1420 100644 --- a/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs +++ b/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs @@ -7,10 +7,10 @@ use { itertools::MinMaxResult, min_max_heap::MinMaxHeap, slab::{Slab, VacantEntry}, + solana_packet::PACKET_DATA_SIZE, solana_runtime_transaction::{ runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta, }, - solana_packet::PACKET_DATA_SIZE, std::sync::Arc, }; @@ -346,15 +346,18 @@ mod tests { super::*, crate::banking_stage::scheduler_messages::MaxAge, agave_transaction_view::transaction_view::SanitizedTransactionView, - solana_perf::packet::Packet, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_compute_budget_interface::ComputeBudgetInstruction, solana_hash::Hash, - solana_message::Message, solana_keypair::Keypair, + solana_message::Message, + solana_perf::packet::Packet, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_signer::Signer, solana_system_interface::instruction as system_instruction, - solana_transaction::{sanitized::{MessageHash, SanitizedTransaction}, Transaction}, + solana_transaction::{ + sanitized::{MessageHash, SanitizedTransaction}, + Transaction, + }, std::collections::HashSet, }; diff --git a/core/src/banking_stage/unified_scheduler.rs b/core/src/banking_stage/unified_scheduler.rs index 1c96065d7b3285..cf981456211591 100644 --- a/core/src/banking_stage/unified_scheduler.rs +++ b/core/src/banking_stage/unified_scheduler.rs @@ -54,11 +54,15 @@ pub(crate) fn ensure_banking_stage_setup( let mut root_bank_cache = RootBankCache::new(bank_forks.clone()); let unified_receiver = channels.unified_receiver().clone(); let mut decision_maker = DecisionMaker::new(cluster_info.id(), poh_recorder.clone()); + let banking_stage_monitor = Box::new(decision_maker.clone()); let banking_packet_handler = Box::new( move |helper: &BankingStageHelper, batches: BankingPacketBatch| { let decision = decision_maker.make_consume_or_forward_decision(); if matches!(decision, BufferedPacketsDecision::Forward) { + // discard newly-arriving packets. note that already handled packets (thus buffered + // by scheduler internally) will be discarded as well via BankingStageMonitor api + // by solScCleaner. return; } let bank = root_bank_cache.root_bank(); @@ -92,5 +96,6 @@ pub(crate) fn ensure_banking_stage_setup( unified_receiver, banking_packet_handler, transaction_recorder, + banking_stage_monitor, ); } diff --git a/core/src/cluster_info_vote_listener.rs b/core/src/cluster_info_vote_listener.rs index 895efa02de8bbe..241480c7b614d9 100644 --- a/core/src/cluster_info_vote_listener.rs +++ b/core/src/cluster_info_vote_listener.rs @@ -1352,11 +1352,9 @@ mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), optimistically_confirmed_bank, @@ -1477,11 +1475,9 @@ mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), optimistically_confirmed_bank, @@ -1627,11 +1623,9 @@ mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), optimistically_confirmed_bank, diff --git a/core/src/forwarding_stage.rs b/core/src/forwarding_stage.rs index 06844582db9465..837ac9ad766a55 100644 --- a/core/src/forwarding_stage.rs +++ b/core/src/forwarding_stage.rs @@ -58,7 +58,7 @@ mod packet_container; /// * [`TpuClientNextClient`]: Relies on the `tpu-client-next` crate. pub enum ForwardingClientOption<'a> { ConnectionCache(Arc), - TpuClientNext((&'a Keypair, UdpSocket, RuntimeHandle)), + TpuClientNext((&'a Keypair, UdpSocket, RuntimeHandle, CancellationToken)), } /// Value chosen because it was used historically, at some point @@ -153,12 +153,14 @@ pub(crate) fn spawn_forwarding_stage( stake_identity, tpu_client_socket, runtime_handle, + cancel, )) => { let non_vote_client = TpuClientNextClient::new( runtime_handle, forward_address_getter, Some(stake_identity), tpu_client_socket, + cancel, ); let forwarding_stage = ForwardingStage::new( receiver, @@ -550,10 +552,10 @@ impl TpuClientNextClient { forward_address_getter: ForwardAddressGetter, stake_identity: Option<&Keypair>, bind_socket: UdpSocket, + cancel: CancellationToken, ) -> Self { // For now use large channel, the more suitable size to be found later. let (sender, receiver) = mpsc::channel(128); - let cancel = CancellationToken::new(); let leader_updater = forward_address_getter.clone(); let config = Self::create_config(bind_socket, stake_identity); diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index 05498d3b8d0702..ccc422e1b93c23 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -56,7 +56,6 @@ use { solana_poh::poh_recorder::{PohLeaderStatus, PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS}, solana_pubkey::Pubkey, solana_rpc::{ - block_meta_service::BlockMetaSender, optimistically_confirmed_bank_tracker::{BankNotification, BankNotificationSenderConfig}, rpc_subscriptions::RpcSubscriptions, slot_status_notifier::SlotStatusNotifier, @@ -281,7 +280,6 @@ pub struct ReplaySenders { pub rpc_subscriptions: Arc, pub slot_status_notifier: Option, pub transaction_status_sender: Option, - pub block_meta_sender: Option, pub entry_notification_sender: Option, pub bank_notification_sender: Option, pub ancestor_hashes_replay_update_sender: AncestorHashesReplayUpdateSender, @@ -582,7 +580,6 @@ impl ReplayStage { rpc_subscriptions, slot_status_notifier, transaction_status_sender, - block_meta_sender, entry_notification_sender, bank_notification_sender, ancestor_hashes_replay_update_sender, @@ -740,7 +737,6 @@ impl ReplayStage { &vote_account, &mut progress, transaction_status_sender.as_ref(), - block_meta_sender.as_ref(), entry_notification_sender.as_ref(), &verify_recyclers, &mut heaviest_subtree_fork_choice, @@ -3074,7 +3070,6 @@ impl ReplayStage { bank_forks: &RwLock, progress: &mut ProgressMap, transaction_status_sender: Option<&TransactionStatusSender>, - block_meta_sender: Option<&BlockMetaSender>, heaviest_subtree_fork_choice: &mut HeaviestSubtreeForkChoice, bank_notification_sender: &Option, rpc_subscriptions: &Arc, @@ -3309,7 +3304,6 @@ impl ReplayStage { .send(BankNotification::Frozen(bank.clone_without_scheduler())) .unwrap_or_else(|err| warn!("bank_notification_sender failed: {:?}", err)); } - blockstore_processor::send_block_meta(bank, block_meta_sender); let bank_hash = bank.hash(); if let Some(new_frozen_voters) = @@ -3374,7 +3368,6 @@ impl ReplayStage { vote_account: &Pubkey, progress: &mut ProgressMap, transaction_status_sender: Option<&TransactionStatusSender>, - block_meta_sender: Option<&BlockMetaSender>, entry_notification_sender: Option<&EntryNotifierSender>, verify_recyclers: &VerifyRecyclers, heaviest_subtree_fork_choice: &mut HeaviestSubtreeForkChoice, @@ -3459,7 +3452,6 @@ impl ReplayStage { bank_forks, progress, transaction_status_sender, - block_meta_sender, heaviest_subtree_fork_choice, bank_notification_sender, rpc_subscriptions, @@ -4506,11 +4498,9 @@ pub(crate) mod tests { OptimisticallyConfirmedBank::locked_from_bank_forks_root(bank_forks); let exit = Arc::new(AtomicBool::new(false)); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::default())), optimistically_confirmed_bank, @@ -5113,11 +5103,9 @@ pub(crate) mod tests { &PrioritizationFeeCache::new(0u64), ); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), block_commitment_cache, OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -5193,11 +5181,9 @@ pub(crate) mod tests { let exit = Arc::new(AtomicBool::new(false)); let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default())); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), block_commitment_cache.clone(), OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -9182,8 +9168,8 @@ pub(crate) mod tests { &blockstore, &replay_tx_thread_pool, &ProcessOptions::default(), - &recyclers, None, + &recyclers, None, ) .unwrap(); @@ -9225,7 +9211,6 @@ pub(crate) mod tests { &ProcessOptions::default(), None, None, - None, None, // snapshot_controller ) .unwrap(); diff --git a/core/src/tvu.rs b/core/src/tvu.rs index 20e8fa5a5dbd26..1b1714d0ce81b0 100644 --- a/core/src/tvu.rs +++ b/core/src/tvu.rs @@ -38,8 +38,7 @@ use { solana_poh::poh_recorder::PohRecorder, solana_pubkey::Pubkey, solana_rpc::{ - block_meta_service::BlockMetaSender, max_slots::MaxSlots, - optimistically_confirmed_bank_tracker::BankNotificationSenderConfig, + max_slots::MaxSlots, optimistically_confirmed_bank_tracker::BankNotificationSenderConfig, rpc_subscriptions::RpcSubscriptions, slot_status_notifier::SlotStatusNotifier, }, solana_runtime::{ @@ -143,7 +142,6 @@ impl Tvu { block_commitment_cache: Arc>, turbine_disabled: Arc, transaction_status_sender: Option, - block_meta_sender: Option, entry_notification_sender: Option, vote_tracker: Arc, retransmit_slots_sender: Sender, @@ -299,7 +297,6 @@ impl Tvu { rpc_subscriptions: rpc_subscriptions.clone(), slot_status_notifier, transaction_status_sender, - block_meta_sender, entry_notification_sender, bank_notification_sender, ancestor_hashes_replay_update_sender, @@ -524,7 +521,6 @@ pub mod tests { let (replay_vote_sender, _replay_vote_receiver) = unbounded(); let (_, gossip_confirmed_slots_receiver) = unbounded(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64)); let outstanding_repair_requests = Arc::>::default(); let cluster_slots = Arc::new(ClusterSlots::default()); @@ -563,7 +559,6 @@ pub mod tests { &Arc::new(RpcSubscriptions::new_for_tests( exit.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), block_commitment_cache.clone(), OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -577,7 +572,6 @@ pub mod tests { Arc::::default(), None, None, - None, Arc::::default(), retransmit_slots_sender, gossip_verified_vote_hash_receiver, diff --git a/core/src/validator.rs b/core/src/validator.rs index f7c995d1e3230c..17a617dc3d239a 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -85,7 +85,6 @@ use { solana_pubkey::Pubkey, solana_rayon_threadlimit::{get_max_thread_count, get_thread_count}, solana_rpc::{ - block_meta_service::{BlockMetaSender, BlockMetaService}, max_slots::MaxSlots, optimistically_confirmed_bank_tracker::{ BankNotificationSenderConfig, OptimisticallyConfirmedBank, @@ -146,6 +145,7 @@ use { strum_macros::{Display, EnumCount, EnumIter, EnumString, EnumVariantNames, IntoStaticStr}, thiserror::Error, tokio::runtime::Runtime as TokioRuntime, + tokio_util::sync::CancellationToken, }; const MAX_COMPLETED_DATA_SETS_IN_CHANNEL: usize = 100_000; @@ -366,7 +366,7 @@ impl Default for ValidatorConfig { replay_transactions_threads: NonZeroUsize::new(1).expect("1 is non-zero"), tvu_shred_sigverify_threads: NonZeroUsize::new(1).expect("1 is non-zero"), delay_leader_block_for_pending_fork: false, - use_tpu_client_next: false, + use_tpu_client_next: true, retransmit_xdp: None, } } @@ -479,9 +479,6 @@ struct TransactionHistoryServices { transaction_status_sender: Option, transaction_status_service: Option, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, - block_meta_sender: Option, - block_meta_service: Option, } /// A struct easing passing Validator TPU Configurations @@ -541,7 +538,6 @@ pub struct Validator { rpc_completed_slots_service: Option>, optimistically_confirmed_bank_tracker: Option, transaction_status_service: Option, - block_meta_service: Option, entry_notifier_service: Option, system_monitor_service: Option, sample_performance_service: Option, @@ -731,6 +727,8 @@ impl Validator { } } + // token used to cancel tpu-client-next. + let cancel_tpu_client_next = CancellationToken::new(); { let exit = exit.clone(); config @@ -738,6 +736,12 @@ impl Validator { .write() .unwrap() .register_exit(Box::new(move || exit.store(true, Ordering::Relaxed))); + let cancel_tpu_client_next = cancel_tpu_client_next.clone(); + config + .validator_exit + .write() + .unwrap() + .register_exit(Box::new(move || cancel_tpu_client_next.cancel())); } let accounts_update_notifier = geyser_plugin_service @@ -789,9 +793,6 @@ impl Validator { transaction_status_sender, transaction_status_service, max_complete_transaction_status_slot, - max_complete_rewards_slot, - block_meta_sender, - block_meta_service, }, blockstore_process_options, blockstore_root_scan, @@ -1011,7 +1012,6 @@ impl Validator { &leader_schedule_cache, &blockstore_process_options, transaction_status_sender.as_ref(), - block_meta_sender.clone(), entry_notification_sender, blockstore_root_scan, &snapshot_controller, @@ -1061,7 +1061,6 @@ impl Validator { let rpc_subscriptions = Arc::new(RpcSubscriptions::new_with_config( exit.clone(), max_complete_transaction_status_slot.clone(), - max_complete_rewards_slot.clone(), blockstore.clone(), bank_forks.clone(), block_commitment_cache.clone(), @@ -1177,6 +1176,7 @@ impl Validator { Arc::as_ref(&identity_keypair), node.sockets.rpc_sts_client, runtime_handle.clone(), + cancel_tpu_client_next.clone(), ) } else { let Some(connection_cache) = &connection_cache else { @@ -1204,7 +1204,6 @@ impl Validator { max_slots: max_slots.clone(), leader_schedule_cache: leader_schedule_cache.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, prioritization_fee_cache: prioritization_fee_cache.clone(), client_option, }; @@ -1518,7 +1517,6 @@ impl Validator { block_commitment_cache, config.turbine_disabled.clone(), transaction_status_sender.clone(), - block_meta_sender, entry_notification_sender.clone(), vote_tracker.clone(), retransmit_slots_sender, @@ -1595,6 +1593,7 @@ impl Validator { .take() .expect("Socket should exist."), runtime_handle.clone(), + cancel_tpu_client_next, )) }; let tpu = Tpu::new_with_client( @@ -1692,7 +1691,6 @@ impl Validator { rpc_completed_slots_service, optimistically_confirmed_bank_tracker, transaction_status_service, - block_meta_service, entry_notifier_service, system_monitor_service, sample_performance_service, @@ -1794,10 +1792,6 @@ impl Validator { .expect("transaction_status_service"); } - if let Some(block_meta_service) = self.block_meta_service { - block_meta_service.join().expect("block_meta_service"); - } - if let Some(system_monitor_service) = self.system_monitor_service { system_monitor_service .join() @@ -2120,7 +2114,9 @@ fn load_blockstore( config.account_paths.clone(), &config.snapshot_config, &process_options, - transaction_history_services.block_meta_sender.as_ref(), + transaction_history_services + .transaction_status_sender + .as_ref(), entry_notifier_service .as_ref() .map(|service| service.sender()), @@ -2164,7 +2160,6 @@ pub struct ProcessBlockStore<'a> { leader_schedule_cache: &'a LeaderScheduleCache, process_options: &'a blockstore_processor::ProcessOptions, transaction_status_sender: Option<&'a TransactionStatusSender>, - block_meta_sender: Option, entry_notification_sender: Option<&'a EntryNotifierSender>, blockstore_root_scan: Option, snapshot_controller: &'a SnapshotController, @@ -2184,7 +2179,6 @@ impl<'a> ProcessBlockStore<'a> { leader_schedule_cache: &'a LeaderScheduleCache, process_options: &'a blockstore_processor::ProcessOptions, transaction_status_sender: Option<&'a TransactionStatusSender>, - block_meta_sender: Option, entry_notification_sender: Option<&'a EntryNotifierSender>, blockstore_root_scan: BlockstoreRootScan, snapshot_controller: &'a SnapshotController, @@ -2200,7 +2194,6 @@ impl<'a> ProcessBlockStore<'a> { leader_schedule_cache, process_options, transaction_status_sender, - block_meta_sender, entry_notification_sender, blockstore_root_scan: Some(blockstore_root_scan), snapshot_controller, @@ -2238,7 +2231,6 @@ impl<'a> ProcessBlockStore<'a> { self.leader_schedule_cache, self.process_options, self.transaction_status_sender, - self.block_meta_sender.as_ref(), self.entry_notification_sender, Some(self.snapshot_controller), ) @@ -2544,22 +2536,10 @@ fn initialize_rpc_transaction_history_services( exit.clone(), )); - let max_complete_rewards_slot = Arc::new(AtomicU64::new(blockstore.max_root())); - let (block_meta_sender, block_meta_receiver) = unbounded(); - let block_meta_sender = Some(block_meta_sender); - let block_meta_service = Some(BlockMetaService::new( - block_meta_receiver, - blockstore, - max_complete_rewards_slot.clone(), - exit, - )); TransactionHistoryServices { transaction_status_sender, transaction_status_service, max_complete_transaction_status_slot, - max_complete_rewards_slot, - block_meta_sender, - block_meta_service, } } diff --git a/core/src/vote_simulator.rs b/core/src/vote_simulator.rs index 801c671e843a02..74a4b5620933ea 100644 --- a/core/src/vote_simulator.rs +++ b/core/src/vote_simulator.rs @@ -142,9 +142,8 @@ impl VoteSimulator { .any(|lockout| lockout.slot() == parent)); } } - while new_bank.tick_height() < new_bank.max_tick_height() { - new_bank.register_unique_tick(); - } + + new_bank.fill_bank_with_ticks_for_tests(); if !visit.node().has_no_child() || is_frozen { new_bank.set_block_id(Some(Hash::new_unique())); new_bank.freeze(); @@ -398,9 +397,7 @@ pub fn initialize_state( bank0.transfer(10_000, &mint_keypair, pubkey).unwrap(); } - while bank0.tick_height() < bank0.max_tick_height() { - bank0.register_unique_tick(); - } + bank0.fill_bank_with_ticks_for_tests(); bank0.freeze(); let mut progress = ProgressMap::default(); progress.insert( diff --git a/core/tests/snapshots.rs b/core/tests/snapshots.rs index b1d19b0f0e8c07..c7a41ad21472f0 100644 --- a/core/tests/snapshots.rs +++ b/core/tests/snapshots.rs @@ -496,9 +496,7 @@ fn test_bank_forks_incremental_snapshot( let tx = system_transaction::transfer(mint_keypair, &key, 0, bank.last_blockhash()); assert_eq!(bank.process_transaction(&tx), Ok(())); - while !bank.is_complete() { - bank.register_unique_tick(); - } + bank.fill_bank_with_ticks_for_tests(); bank_scheduler }; @@ -783,9 +781,7 @@ fn test_snapshots_with_background_services( let tx = system_transaction::transfer(mint_keypair, &key, 0, bank.last_blockhash()); assert_eq!(bank.process_transaction(&tx), Ok(())); - while !bank.is_complete() { - bank.register_unique_tick(); - } + bank.fill_bank_with_ticks_for_tests(); } // Call `BankForks::set_root()` to cause snapshots to be taken diff --git a/cost-model/Cargo.toml b/cost-model/Cargo.toml index 265bd6ec7cccf9..ed7856f71f9147 100644 --- a/cost-model/Cargo.toml +++ b/cost-model/Cargo.toml @@ -9,6 +9,29 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_cost_model" + +[features] +dev-context-only-utils = [ + "dep:solana-hash", + "dep:solana-message", + "dep:solana-signature", + "dep:solana-transaction", + "solana-compute-budget-interface/dev-context-only-utils", +] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-compute-budget/frozen-abi", + "solana-pubkey/frozen-abi", + "solana-vote-program/frozen-abi", +] + [dependencies] agave-feature-set = { workspace = true } ahash = { workspace = true } @@ -41,10 +64,6 @@ solana-transaction = { workspace = true, optional = true } solana-transaction-error = { workspace = true } solana-vote-program = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_cost_model" - [dev-dependencies] agave-reserved-account-keys = { workspace = true } itertools = { workspace = true } @@ -70,25 +89,6 @@ solana-vote = { workspace = true } static_assertions = { workspace = true } test-case = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [ - "dep:solana-hash", - "dep:solana-message", - "dep:solana-signature", - "dep:solana-transaction", - "solana-compute-budget-interface/dev-context-only-utils" -] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-compute-budget/frozen-abi", - "solana-pubkey/frozen-abi", - "solana-vote-program/frozen-abi" -] - [[bench]] name = "cost_tracker" diff --git a/curves/curve25519/Cargo.toml b/curves/curve25519/Cargo.toml index 597e8f25603517..7beb5dc7499bbc 100644 --- a/curves/curve25519/Cargo.toml +++ b/curves/curve25519/Cargo.toml @@ -19,11 +19,11 @@ bytemuck_derive = { workspace = true } subtle = { workspace = true } thiserror = { workspace = true } -[target.'cfg(target_os = "solana")'.dependencies] -solana-define-syscall = { workspace = true } - [target.'cfg(not(target_os = "solana"))'.dependencies] curve25519-dalek = { workspace = true, features = ["serde"] } +[target.'cfg(target_os = "solana")'.dependencies] +solana-define-syscall = { workspace = true } + [lints] workspace = true diff --git a/docs/src/runtime/zk-elgamal-proof.md b/docs/src/runtime/zk-elgamal-proof.md index e3372f03f383fb..f81ca7d49cd3e4 100644 --- a/docs/src/runtime/zk-elgamal-proof.md +++ b/docs/src/runtime/zk-elgamal-proof.md @@ -41,7 +41,7 @@ treatment of Pedersen commitment and the (twisted) ElGamal encryption schemes. - [Notes](https://github.com/solana-labs/solana/blob/master/docs/src/runtime/zk-docs/twisted_elgamal.pdf) on the twisted ElGamal encryption - A technical - [overview](https://github.com/solana-labs/solana-program-library/blob/master/token/zk-token-protocol-paper/part1.pdf) + [overview](https://github.com/solana-program/token-2022/blob/main/zk-token-protocol-paper/part1.pdf) of the SPL Token 2022 confidential extension - Pretty Good Confidentiality [research paper](https://eprint.iacr.org/2019/319) diff --git a/dos/Cargo.toml b/dos/Cargo.toml index 83e40d5ff1f94d..dce537a837b429 100644 --- a/dos/Cargo.toml +++ b/dos/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [] + [dependencies] bincode = { workspace = true } clap = { version = "3.1.5", features = ["derive", "cargo"] } @@ -35,7 +41,7 @@ solana-pubkey = { workspace = true } solana-quic-client = { workspace = true } solana-rpc = { workspace = true } solana-rpc-client = { workspace = true } -solana-signature = { workspace = true } +solana-signature = { workspace = true, features = ["rand"] } solana-signer = { workspace = true } solana-stake-interface = { workspace = true } solana-streamer = { workspace = true } @@ -46,13 +52,7 @@ solana-tpu-client = { workspace = true } solana-transaction = { workspace = true } solana-version = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [dev-dependencies] solana-core = { workspace = true, features = ["dev-context-only-utils"] } solana-local-cluster = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } - -[features] -dev-context-only-utils = [] diff --git a/download-utils/Cargo.toml b/download-utils/Cargo.toml index 78a64d1e510cde..7d725cec277de5 100644 --- a/download-utils/Cargo.toml +++ b/download-utils/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_download_utils" + [dependencies] log = { workspace = true } solana-clock = { workspace = true } @@ -18,10 +25,3 @@ solana-runtime = { workspace = true } [dev-dependencies] solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } - -[lib] -crate-type = ["lib"] -name = "solana_download_utils" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/entry/Cargo.toml b/entry/Cargo.toml index 7bca177c1c4b32..bf72e34fdf8ab8 100644 --- a/entry/Cargo.toml +++ b/entry/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_entry" + [dependencies] bincode = { workspace = true } crossbeam-channel = { workspace = true } @@ -42,12 +49,5 @@ solana-signer = { workspace = true } solana-system-transaction = { workspace = true } solana-transaction = { workspace = true, features = ["verify"] } -[lib] -crate-type = ["lib"] -name = "solana_entry" - [[bench]] name = "entry_sigverify" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/entry/src/poh.rs b/entry/src/poh.rs index 2573c596053b86..0bb96307ae9bcc 100644 --- a/entry/src/poh.rs +++ b/entry/src/poh.rs @@ -59,6 +59,8 @@ impl Poh { self.slot_start_time + Duration::from_nanos(offset_ns + offset_tick_ns) } + /// Return `true` if the caller needs to `tick()` next, i.e. if the + /// remaining_hashes is 1. pub fn hash(&mut self, max_num_hashes: u64) -> bool { let num_hashes = std::cmp::min(self.remaining_hashes - 1, max_num_hashes); @@ -69,7 +71,7 @@ impl Poh { self.remaining_hashes -= num_hashes; assert!(self.remaining_hashes > 0); - self.remaining_hashes == 1 // Return `true` if caller needs to `tick()` next + self.remaining_hashes == 1 } pub fn record(&mut self, mixin: Hash) -> Option { @@ -88,6 +90,41 @@ impl Poh { }) } + /// Returns `true` if the batches were recorded successfully and `false` if the batches + /// were not recorded because there were not enough hashes remaining to record all `mixins`. + /// If `true` is returned, the `entries` vector will be populated with the `PohEntry`s for each + /// batch. If `false` is returned, the `entries` vector will not be modified. + pub fn record_batches(&mut self, mixins: &[Hash], entries: &mut Vec) -> bool { + let num_mixins = mixins.len() as u64; + debug_assert_ne!(num_mixins, 0, "mixins.len() == 0"); + + if self.remaining_hashes < num_mixins + 1 { + return false; // Not enough hashes remaining to record all mixins + } + + entries.clear(); + entries.reserve(mixins.len()); + + // The first entry will have the current number of hashes plus one. + // All subsequent entries will have 1. + let mut num_hashes = self.num_hashes + 1; + entries.extend(mixins.iter().map(|mixin| { + self.hash = hashv(&[self.hash.as_ref(), mixin.as_ref()]); + let entry = PohEntry { + num_hashes, + hash: self.hash, + }; + + num_hashes = 1; + entry + })); + + self.num_hashes = 0; + self.remaining_hashes -= num_mixins; + + true + } + pub fn tick(&mut self) -> Option { self.hash = hash(self.hash.as_ref()); self.num_hashes += 1; @@ -330,4 +367,32 @@ mod tests { ); assert_eq!(poh.remaining_hashes, 9); } + + #[test] + fn test_poh_record_batches() { + let mut poh = Poh::new(Hash::default(), Some(10)); + assert!(!poh.hash(4)); + + let mut entries = Vec::with_capacity(3); + let dummy_hashes = [Hash::default(); 4]; + assert!(poh.record_batches(&dummy_hashes[..3], &mut entries,)); + assert_eq!(entries.len(), 3); + assert_eq!(entries[0].num_hashes, 5); + assert_eq!(entries[1].num_hashes, 1); + assert_eq!(entries[2].num_hashes, 1); + assert!(poh.remaining_hashes == 3); + + // Cannot record more than number of remaining hashes + assert!(!poh.record_batches(&dummy_hashes[..4], &mut entries,)); + + // Cannot record more than number of remaining hashes + assert!(!poh.record_batches(&dummy_hashes[..3], &mut entries,)); + + // Can record less than number of remaining hashes + assert!(poh.record_batches(&dummy_hashes[..2], &mut entries,)); + assert_eq!(entries.len(), 2); + assert_eq!(entries[0].num_hashes, 1); + assert_eq!(entries[1].num_hashes, 1); + assert!(poh.remaining_hashes == 1); + } } diff --git a/faucet/Cargo.toml b/faucet/Cargo.toml index 62b138e5be994d..b582e383db3d87 100644 --- a/faucet/Cargo.toml +++ b/faucet/Cargo.toml @@ -9,6 +9,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_faucet" + +[[bin]] +name = "solana-faucet" +path = "src/bin/faucet.rs" + [dependencies] bincode = { workspace = true } clap = { workspace = true } @@ -19,10 +30,10 @@ serde_derive = { workspace = true } solana-clap-utils = { workspace = true } solana-cli-config = { workspace = true } solana-hash = "=2.3.0" -solana-instruction = "=2.2.1" +solana-instruction = "=2.3.0" solana-keypair = "=2.2.1" solana-logger = "=2.3.1" -solana-message = "=2.3.0" +solana-message = "=2.4.0" solana-metrics = { workspace = true } solana-native-token = "=2.2.2" solana-packet = "=2.2.1" @@ -35,14 +46,3 @@ solana-version = { workspace = true } spl-memo = { version = "=6.0.0", features = ["no-entrypoint"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } - -[lib] -crate-type = ["lib"] -name = "solana_faucet" - -[[bin]] -name = "solana-faucet" -path = "src/bin/faucet.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/feature-set/Cargo.toml b/feature-set/Cargo.toml index 84151e85357609..871d272e7b34dc 100644 --- a/feature-set/Cargo.toml +++ b/feature-set/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agave-feature-set" -version = "2.3.0" +version = "3.0.0" description = "Solana runtime feature declarations" authors = { workspace = true } repository = { workspace = true } @@ -9,6 +9,9 @@ license = { workspace = true } edition = { workspace = true } readme = false +[features] +frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] + [dependencies] ahash = { workspace = true } solana-epoch-schedule = { workspace = true } @@ -23,8 +26,5 @@ solana-pubkey = { workspace = true, default-features = false } solana-sha256-hasher = { workspace = true } solana-svm-feature-set = { workspace = true } -[features] -frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] - [lints] workspace = true diff --git a/feature-set/src/lib.rs b/feature-set/src/lib.rs index bb0b5cc72deeb1..5e241b9d83df2f 100644 --- a/feature-set/src/lib.rs +++ b/feature-set/src/lib.rs @@ -153,6 +153,8 @@ impl FeatureSet { increase_tx_account_lock_limit: self.is_active(&increase_tx_account_lock_limit::id()), disable_rent_fees_collection: self.is_active(&disable_rent_fees_collection::id()), enable_extend_program_checked: self.is_active(&enable_extend_program_checked::id()), + formalize_loaded_transaction_data_size: self + .is_active(&formalize_loaded_transaction_data_size::id()), } } } @@ -1060,7 +1062,7 @@ pub mod drop_unchained_merkle_shreds { } pub mod relax_intrabatch_account_locks { - solana_pubkey::declare_id!("EbAhnReKK8Sf88CvAfAXbgKji8DV48rsp4q2sgHqgWef"); + solana_pubkey::declare_id!("ENTRYnPAoT5Swwx73YDGzMp3XnNH1kxacyvLosRHza1i"); } pub mod create_slashing_program { @@ -1095,6 +1097,10 @@ pub mod enable_extend_program_checked { solana_pubkey::declare_id!("2oMRZEDWT2tqtYMofhmmfQ8SsjqUFzT6sYXppQDavxwz"); } +pub mod formalize_loaded_transaction_data_size { + solana_pubkey::declare_id!("DeS7sR48ZcFTUmt5FFEVDr1v1bh73aAbZiZq3SYr8Eh8"); +} + pub static FEATURE_NAMES: LazyLock> = LazyLock::new(|| { [ (secp256k1_program_enabled::id(), "secp256k1 program"), @@ -1224,7 +1230,7 @@ pub static FEATURE_NAMES: LazyLock> = LazyLock::n (check_syscall_outputs_do_not_overlap::id(), "check syscall outputs do_not overlap #28600"), (enable_bpf_loader_set_authority_checked_ix::id(), "enable bpf upgradeable loader SetAuthorityChecked instruction #28424"), (enable_alt_bn128_syscall::id(), "add alt_bn128 syscalls #27961"), - (simplify_alt_bn128_syscall_error_codes::id(), "simplify alt_bn128 syscall error codes SIMD-0129"), + (simplify_alt_bn128_syscall_error_codes::id(), "SIMD-0129: simplify alt_bn128 syscall error codes"), (enable_program_redeployment_cooldown::id(), "enable program redeployment cooldown #29135"), (commission_updates_only_allowed_in_first_half_of_epoch::id(), "validator commission updates are only allowed in the first half of an epoch #29362"), (enable_turbine_fanout_experiments::id(), "enable turbine fanout experiments #29393"), @@ -1257,7 +1263,7 @@ pub static FEATURE_NAMES: LazyLock> = LazyLock::n (enable_poseidon_syscall::id(), "Enable Poseidon syscall"), (timely_vote_credits::id(), "use timeliness of votes in determining credits to award"), (remaining_compute_units_syscall_enabled::id(), "enable the remaining_compute_units syscall"), - (enable_loader_v4::id(), "Enable Loader-v4 SIMD-0167"), + (enable_loader_v4::id(), "SIMD-0167: Enable Loader-v4"), (require_rent_exempt_split_destination::id(), "Require stake split destination account to be rent exempt"), (better_error_codes_for_tx_lamport_check::id(), "better error codes for tx lamport check #33353"), (enable_alt_bn128_compression_syscall::id(), "add alt_bn128 compression syscalls"), @@ -1286,50 +1292,51 @@ pub static FEATURE_NAMES: LazyLock> = LazyLock::n (enable_tower_sync_ix::id(), "Enable tower sync vote instruction"), (chained_merkle_conflict_duplicate_proofs::id(), "generate duplicate proofs for chained merkle root conflicts"), (reward_full_priority_fee::id(), "Reward full priority fee to validators #34731"), - (abort_on_invalid_curve::id(), "Abort when elliptic curve syscalls invoked on invalid curve id SIMD-0137"), + (abort_on_invalid_curve::id(), "SIMD-0137: Abort when elliptic curve syscalls invoked on invalid curve id"), (get_sysvar_syscall_enabled::id(), "Enable syscall for fetching Sysvar bytes #615"), (migrate_feature_gate_program_to_core_bpf::id(), "Migrate Feature Gate program to Core BPF (programify) #1003"), (vote_only_full_fec_sets::id(), "vote only full fec sets"), (migrate_config_program_to_core_bpf::id(), "Migrate Config program to Core BPF #1378"), (enable_get_epoch_stake_syscall::id(), "Enable syscall: sol_get_epoch_stake #884"), (migrate_address_lookup_table_program_to_core_bpf::id(), "Migrate Address Lookup Table program to Core BPF #1651"), - (zk_elgamal_proof_program_enabled::id(), "Enable ZkElGamalProof program SIMD-0153"), + (zk_elgamal_proof_program_enabled::id(), "SIMD-0153: Enable ZkElGamalProof program"), (verify_retransmitter_signature::id(), "Verify retransmitter signature #1840"), (move_stake_and_move_lamports_ixs::id(), "Enable MoveStake and MoveLamports stake program instructions #1610"), - (ed25519_precompile_verify_strict::id(), "Use strict verification in ed25519 precompile SIMD-0152"), + (ed25519_precompile_verify_strict::id(), "SIMD-0152: Use strict verification in ed25519 precompile"), (vote_only_retransmitter_signed_fec_sets::id(), "vote only on retransmitter signed fec sets"), (move_precompile_verification_to_svm::id(), "SIMD-0159: Move precompile verification into SVM"), - (enable_transaction_loading_failure_fees::id(), "Enable fees for some additional transaction failures SIMD-0082"), + (enable_transaction_loading_failure_fees::id(), "SIMD-0082: Enable fees for some additional transaction failures"), (enable_turbine_extended_fanout_experiments::id(), "enable turbine extended fanout experiments #"), (deprecate_legacy_vote_ixs::id(), "Deprecate legacy vote instructions"), - (partitioned_epoch_rewards_superfeature::id(), "replaces enable_partitioned_epoch_reward to enable partitioned rewards at epoch boundary SIMD-0118"), - (disable_sbpf_v0_execution::id(), "Disables execution of SBPFv1 programs SIMD-0161"), + (partitioned_epoch_rewards_superfeature::id(), "SIMD-0118: replaces enable_partitioned_epoch_reward to enable partitioned rewards at epoch boundary"), + (disable_sbpf_v0_execution::id(), "SIMD-0161: Disables execution of SBPFv1 programs"), (reenable_sbpf_v0_execution::id(), "Re-enables execution of SBPFv1 programs"), - (enable_sbpf_v1_deployment_and_execution::id(), "Enables deployment and execution of SBPFv1 programs SIMD-0161"), - (enable_sbpf_v2_deployment_and_execution::id(), "Enables deployment and execution of SBPFv2 programs SIMD-0161"), - (enable_sbpf_v3_deployment_and_execution::id(), "Enables deployment and execution of SBPFv3 programs SIMD-0161"), - (remove_accounts_executable_flag_checks::id(), "Remove checks of accounts is_executable flag SIMD-0162"), + (enable_sbpf_v1_deployment_and_execution::id(), "SIMD-0161: Enables deployment and execution of SBPFv1 programs"), + (enable_sbpf_v2_deployment_and_execution::id(), "SIMD-0161: Enables deployment and execution of SBPFv2 programs"), + (enable_sbpf_v3_deployment_and_execution::id(), "SIMD-0161: Enables deployment and execution of SBPFv3 programs"), + (remove_accounts_executable_flag_checks::id(), "SIMD-0162: Remove checks of accounts is_executable flag"), (lift_cpi_caller_restriction::id(), "Lift the restriction in CPI that the caller must have the callee as an instruction account #2202"), (disable_account_loader_special_case::id(), "Disable account loader special case #3513"), - (accounts_lt_hash::id(), "enables lattice-based accounts hash SIMD-0215"), - (snapshots_lt_hash::id(), "snapshots use lattice-based accounts hash SIMD-0220"), - (remove_accounts_delta_hash::id(), "removes accounts delta hash SIMD-0223"), - (enable_secp256r1_precompile::id(), "Enable secp256r1 precompile SIMD-0075"), - (migrate_stake_program_to_core_bpf::id(), "Migrate Stake program to Core BPF SIMD-0196 #3655"), - (deplete_cu_meter_on_vm_failure::id(), "Deplete compute meter for vm errors SIMD-0182 #3993"), - (reserve_minimal_cus_for_builtin_instructions::id(), "Reserve minimal CUs for builtin instructions SIMD-170 #2562"), - (raise_block_limits_to_50m::id(), "Raise block limit to 50M SIMD-0207"), - (fix_alt_bn128_multiplication_input_length::id(), "fix alt_bn128 multiplication input length SIMD-0222 #3686"), + (accounts_lt_hash::id(), "SIMD-0215: enables lattice-based accounts hash"), + (snapshots_lt_hash::id(), "SIMD-0220: snapshots use lattice-based accounts hash"), + (remove_accounts_delta_hash::id(), "SIMD-0223: removes accounts delta hash"), + (enable_secp256r1_precompile::id(), "SIMD-0075: Enable secp256r1 precompile"), + (migrate_stake_program_to_core_bpf::id(), "SIMD-0196: Migrate Stake program to Core BPF #3655"), + (deplete_cu_meter_on_vm_failure::id(), "SIMD-0182: Deplete compute meter for vm errors #3993"), + (reserve_minimal_cus_for_builtin_instructions::id(), "SIMD-0170: Reserve minimal CUs for builtin instructions #2562"), + (raise_block_limits_to_50m::id(), "SIMD-0207: Raise block limit to 50M"), + (fix_alt_bn128_multiplication_input_length::id(), "SIMD-0222: fix alt_bn128 multiplication input length #3686"), (drop_unchained_merkle_shreds::id(), "drops unchained Merkle shreds #2149"), - (relax_intrabatch_account_locks::id(), "Allow batched transactions to read/write and write/write the same accounts SIMD-0083"), - (create_slashing_program::id(), "creates an enshrined slashing program SIMD-0204"), - (disable_partitioned_rent_collection::id(), "Disable partitioned rent collection SIMD-0175 #4562"), - (enable_vote_address_leader_schedule::id(), "Enable vote address leader schedule SIMD-0180 #4573"), + (relax_intrabatch_account_locks::id(), "SIMD-0083: Allow batched transactions to read/write and write/write the same accounts"), + (create_slashing_program::id(), "SIMD-0204: creates an enshrined slashing program"), + (disable_partitioned_rent_collection::id(), "SIMD-0175: Disable partitioned rent collection #4562"), + (enable_vote_address_leader_schedule::id(), "SIMD-0180: Enable vote address leader schedule #4573"), (require_static_nonce_account::id(), "SIMD-0242: Static Nonce Account Only"), - (raise_block_limits_to_60m::id(), "Raise block limit to 60M SIMD-0256"), + (raise_block_limits_to_60m::id(), "SIMD-0256: Raise block limit to 60M"), (mask_out_rent_epoch_in_vm_serialization::id(), "SIMD-0267: Sets rent_epoch to a constant in the VM"), (enshrine_slashing_program::id(), "SIMD-0204: Slashable event verification"), (enable_extend_program_checked::id(), "Enable ExtendProgramChecked instruction"), + (formalize_loaded_transaction_data_size::id(), "SIMD-0186: Loaded transaction data size specification"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter() diff --git a/genesis-utils/Cargo.toml b/genesis-utils/Cargo.toml index 6f11a8cad46d2a..f4040d34136bf0 100644 --- a/genesis-utils/Cargo.toml +++ b/genesis-utils/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_genesis_utils" + [dependencies] log = { workspace = true } solana-accounts-db = { workspace = true } @@ -16,10 +23,3 @@ solana-download-utils = { workspace = true } solana-genesis-config = { workspace = true } solana-hash = { workspace = true } solana-rpc-client = { workspace = true } - -[lib] -crate-type = ["lib"] -name = "solana_genesis_utils" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/genesis/Cargo.toml b/genesis/Cargo.toml index 0f6ff8a923f7a9..6448e450bc9ba2 100644 --- a/genesis/Cargo.toml +++ b/genesis/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_genesis" + +[[bin]] +name = "solana-genesis" +path = "src/main.rs" + [dependencies] agave-feature-set = { workspace = true } base64 = { workspace = true } @@ -54,13 +64,3 @@ tempfile = { workspace = true } solana-borsh = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } - -[[bin]] -name = "solana-genesis" -path = "src/main.rs" - -[lib] -name = "solana_genesis" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/geyser-plugin-interface/Cargo.toml b/geyser-plugin-interface/Cargo.toml index 465eca2c8bb6a7..6a39745cab0c6c 100644 --- a/geyser-plugin-interface/Cargo.toml +++ b/geyser-plugin-interface/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] log = { workspace = true, features = ["std"] } solana-clock = { workspace = true } @@ -16,6 +19,3 @@ solana-signature = { workspace = true } solana-transaction = { workspace = true } solana-transaction-status = { workspace = true } thiserror = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/geyser-plugin-manager/Cargo.toml b/geyser-plugin-manager/Cargo.toml index 54459d54aab829..2637384dc1a331 100644 --- a/geyser-plugin-manager/Cargo.toml +++ b/geyser-plugin-manager/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] agave-geyser-plugin-interface = { workspace = true } bs58 = { workspace = true } @@ -33,6 +36,3 @@ solana-transaction = { workspace = true } solana-transaction-status = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/gossip/Cargo.toml b/gossip/Cargo.toml index 7194df16469ff6..c51c6fb22fa6f1 100644 --- a/gossip/Cargo.toml +++ b/gossip/Cargo.toml @@ -9,6 +9,27 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[[bin]] +name = "solana-gossip" +path = "src/main.rs" + +[features] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-bloom/frozen-abi", + "solana-ledger/frozen-abi", + "solana-perf/frozen-abi", + "solana-runtime/frozen-abi", + "solana-short-vec/frozen-abi", + "solana-version/frozen-abi", + "solana-vote/frozen-abi", + "solana-vote-program/frozen-abi", +] + [dependencies] agave-feature-set = { workspace = true } arrayvec = { workspace = true } @@ -86,25 +107,12 @@ serial_test = { workspace = true } solana-net-utils = { workspace = true, features = ["dev-context-only-utils"] } solana-perf = { workspace = true, features = ["dev-context-only-utils"] } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } +solana-signature = { version = "=2.3.0", features = ["rand"] } solana-system-transaction = { workspace = true } solana-vote-interface = { workspace = true } static_assertions = { workspace = true } test-case = { workspace = true } -[features] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-bloom/frozen-abi", - "solana-ledger/frozen-abi", - "solana-perf/frozen-abi", - "solana-runtime/frozen-abi", - "solana-short-vec/frozen-abi", - "solana-version/frozen-abi", - "solana-vote/frozen-abi", - "solana-vote-program/frozen-abi", -] - [[bench]] name = "crds" @@ -118,12 +126,5 @@ name = "crds_shards" name = "weighted_shuffle" harness = false -[[bin]] -name = "solana-gossip" -path = "src/main.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [lints] workspace = true diff --git a/gossip/src/cluster_info.rs b/gossip/src/cluster_info.rs index 4d21b0dce8c6ff..ce51a0d5bbf899 100644 --- a/gossip/src/cluster_info.rs +++ b/gossip/src/cluster_info.rs @@ -19,6 +19,7 @@ use { contact_info::{self, ContactInfo, ContactInfoQuery, Error as ContactInfoError}, crds::{Crds, Cursor, GossipRoute}, crds_data::{self, CrdsData, EpochSlotsIndex, LowestSlot, SnapshotHashes, Vote, MAX_VOTES}, + crds_filter::{should_retain_crds_value, GossipFilterDirection, MIN_STAKE_TO_SKIP_PING}, crds_gossip::CrdsGossip, crds_gossip_error::CrdsGossipError, crds_gossip_pull::{ @@ -133,11 +134,6 @@ pub const DEFAULT_CONTACT_DEBUG_INTERVAL_MILLIS: u64 = 10_000; pub const DEFAULT_CONTACT_SAVE_INTERVAL_MILLIS: u64 = 60_000; // Limit number of unique pubkeys in the crds table. pub(crate) const CRDS_UNIQUE_PUBKEY_CAPACITY: usize = 8192; -/// Minimum stake that a node should have so that its CRDS values are -/// propagated through gossip (few types are exempted). -const MIN_STAKE_FOR_GOSSIP: u64 = solana_native_token::LAMPORTS_PER_SOL; -/// Minimum number of staked nodes for enforcing stakes in gossip. -const MIN_NUM_STAKED_NODES: usize = 500; // Must have at least one socket to monitor the TVU port pub const MINIMUM_NUM_TVU_RECEIVE_SOCKETS: NonZeroUsize = NonZeroUsize::new(1).unwrap(); @@ -177,42 +173,6 @@ pub struct ClusterInfo { socket_addr_space: SocketAddrSpace, } -// Returns false if the CRDS value should be discarded. -#[inline] -#[must_use] -fn should_retain_crds_value( - value: &CrdsValue, - stakes: &HashMap, - drop_unstaked_node_instance: bool, -) -> bool { - match value.data() { - CrdsData::ContactInfo(_) => true, - CrdsData::LegacyContactInfo(_) => true, - // May Impact new validators starting up without any stake yet. - CrdsData::Vote(_, _) => true, - // Unstaked nodes can still help repair. - CrdsData::EpochSlots(_, _) => true, - // Unstaked nodes can still serve snapshots. - CrdsData::LegacySnapshotHashes(_) | CrdsData::SnapshotHashes(_) => true, - // Otherwise unstaked voting nodes will show up with no version in - // the various dashboards. - CrdsData::Version(_) => true, - CrdsData::AccountsHashes(_) => true, - CrdsData::NodeInstance(_) if !drop_unstaked_node_instance => true, - CrdsData::LowestSlot(_, _) - | CrdsData::LegacyVersion(_) - | CrdsData::DuplicateShred(_, _) - | CrdsData::RestartHeaviestFork(_) - | CrdsData::RestartLastVotedForkSlots(_) - | CrdsData::NodeInstance(_) => { - stakes.len() < MIN_NUM_STAKED_NODES || { - let stake = stakes.get(&value.pubkey()).copied(); - stake.unwrap_or_default() >= MIN_STAKE_FOR_GOSSIP - } - } - } -} - impl ClusterInfo { pub fn new( contact_info: ContactInfo, @@ -1229,7 +1189,9 @@ impl ClusterInfo { stakes: &HashMap, ) -> impl Iterator { let now = timestamp(); - let self_info = CrdsValue::new(CrdsData::from(self.my_contact_info()), &self.keypair()); + let mut contact_info = self.my_contact_info(); + contact_info.set_wallclock(now); + let self_info = CrdsValue::new(CrdsData::from(contact_info), &self.keypair()); let max_bloom_filter_bytes = get_max_bloom_filter_bytes(&self_info); let mut pings = Vec::new(); let pulls = { @@ -1282,9 +1244,7 @@ impl ClusterInfo { self.flush_push_queue(); self.gossip .new_push_messages(&self_id, timestamp(), stakes, |value| { - should_retain_crds_value( - value, stakes, /*drop_unstaked_node_instance:*/ false, - ) + should_retain_crds_value(value, stakes, GossipFilterDirection::EgressPush) }) }; self.stats @@ -1692,7 +1652,9 @@ impl ClusterInfo { now, |value| { should_retain_crds_value( - value, stakes, /*drop_unstaked_node_instance:*/ true, + value, + stakes, + GossipFilterDirection::EgressPullResponse, ) }, self.my_shred_version(), @@ -2132,9 +2094,7 @@ impl ClusterInfo { &mut protocol { values.retain(|value| { - should_retain_crds_value( - value, stakes, /*drop_unstaked_node_instance:*/ false, - ) + should_retain_crds_value(value, stakes, GossipFilterDirection::Ingress) }); if values.is_empty() { return None; @@ -3003,7 +2963,7 @@ fn verify_gossip_addr( _ => return true, // If not a contact-info, nothing to verify. }; // For (sufficiently) staked nodes, don't bother with ping/pong. - if stakes.get(pubkey) >= Some(&MIN_STAKE_FOR_GOSSIP) { + if stakes.get(pubkey).copied() >= Some(MIN_STAKE_TO_SKIP_PING) { return true; } // Invalid addresses are not verifiable. diff --git a/gossip/src/cluster_info_metrics.rs b/gossip/src/cluster_info_metrics.rs index ce84180e6586cd..81579fdfcb378d 100644 --- a/gossip/src/cluster_info_metrics.rs +++ b/gossip/src/cluster_info_metrics.rs @@ -4,6 +4,7 @@ use { solana_clock::Slot, solana_measure::measure::Measure, solana_pubkey::Pubkey, + solana_signature::Signature, std::{ cmp::Reverse, collections::HashMap, @@ -704,3 +705,12 @@ where datapoint_trace!(name, ("slot", slot, i64), ("num_votes", num_votes, i64)); } } + +/// check if first leading_zeros bits of signature are 0 +#[inline] +pub(crate) fn should_report_message_signature(signature: &Signature, leading_zeros: u32) -> bool { + let Some(Ok(bytes)) = signature.as_ref().get(..8).map(<[u8; 8]>::try_from) else { + return false; + }; + u64::from_le_bytes(bytes).trailing_zeros() >= leading_zeros +} diff --git a/gossip/src/contact_info.rs b/gossip/src/contact_info.rs index c3ee9b405ef037..a9c47f2b575d58 100644 --- a/gossip/src/contact_info.rs +++ b/gossip/src/contact_info.rs @@ -1,6 +1,11 @@ pub use solana_client::connection_cache::Protocol; use { - crate::{crds_data::MAX_WALLCLOCK, legacy_contact_info::LegacyContactInfo}, + crate::{ + crds_data::MAX_WALLCLOCK, + define_tlv_enum, + legacy_contact_info::LegacyContactInfo, + tlv::{self, TlvDecodeError, TlvRecord}, + }, assert_matches::{assert_matches, debug_assert_matches}, serde::{Deserialize, Deserializer, Serialize}, solana_pubkey::Pubkey, @@ -39,8 +44,9 @@ const SOCKET_TAG_TPU_VOTE: u8 = 9; const SOCKET_TAG_TPU_VOTE_QUIC: u8 = 12; const SOCKET_TAG_TVU: u8 = 10; const SOCKET_TAG_TVU_QUIC: u8 = 11; -const_assert_eq!(SOCKET_CACHE_SIZE, 13); -const SOCKET_CACHE_SIZE: usize = SOCKET_TAG_TPU_VOTE_QUIC as usize + 1usize; +const SOCKET_TAG_ALPENGLOW: u8 = 13; +const_assert_eq!(SOCKET_CACHE_SIZE, 14); +const SOCKET_CACHE_SIZE: usize = SOCKET_TAG_ALPENGLOW as usize + 1usize; // An alias for a function that reads data from a ContactInfo entry stored in // the gossip CRDS table. @@ -105,8 +111,19 @@ struct SocketEntry { offset: u16, // Port offset with respect to the previous entry. } -#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] -enum Extension {} +define_tlv_enum!( + /// TLV encoded Extensions in ContactInfo messages + /// + /// On the wire each record is: [type: u8][len: varint][bytes] + /// Extensions with unknown types are skipped by tlv::parse, + /// so new types can be added without breaking legacy code, + /// and support by all clients is not required. + /// + /// Always add new TLV records to the end of this enum. + /// Never reorder or reuse a type. + /// Ensure new type collisions do not happen. + pub(crate) enum Extension {} +); // As part of deserialization, self.addrs and self.sockets should be cross // verified and self.cache needs to be populated. This type serves as a @@ -124,8 +141,9 @@ struct ContactInfoLite { addrs: Vec, #[serde(with = "short_vec")] sockets: Vec, + #[allow(dead_code)] #[serde(with = "short_vec")] - extensions: Vec, + extensions: Vec, } macro_rules! get_socket { @@ -212,7 +230,7 @@ impl ContactInfo { version: solana_version::Version::default(), addrs: Vec::::default(), sockets: Vec::::default(), - extensions: Vec::::default(), + extensions: Vec::default(), cache: EMPTY_SOCKET_ADDR_CACHE, } } @@ -268,6 +286,7 @@ impl ContactInfo { ); get_socket!(tpu_vote, SOCKET_TAG_TPU_VOTE, SOCKET_TAG_TPU_VOTE_QUIC); get_socket!(tvu, SOCKET_TAG_TVU, SOCKET_TAG_TVU_QUIC); + get_socket!(alpenglow, SOCKET_TAG_ALPENGLOW); set_socket!(set_gossip, SOCKET_TAG_GOSSIP); set_socket!(set_rpc, SOCKET_TAG_RPC); @@ -281,6 +300,7 @@ impl ContactInfo { set_socket!(@multi set_serve_repair, SOCKET_TAG_SERVE_REPAIR, SOCKET_TAG_SERVE_REPAIR_QUIC); set_socket!(@multi set_tpu_vote, SOCKET_TAG_TPU_VOTE, SOCKET_TAG_TPU_VOTE_QUIC); set_socket!(@multi set_tvu, SOCKET_TAG_TVU, SOCKET_TAG_TVU_QUIC); + set_socket!(set_alpenglow, SOCKET_TAG_ALPENGLOW); remove_socket!( remove_serve_repair, @@ -541,7 +561,7 @@ impl TryFrom for ContactInfo { version, addrs, sockets, - extensions, + extensions: tlv::parse(&extensions), cache: EMPTY_SOCKET_ADDR_CACHE, }; // Populate node.cache. @@ -737,6 +757,7 @@ mod tests { assert_matches!(ci.tpu_vote(Protocol::QUIC), None); assert_matches!(ci.tvu(Protocol::QUIC), None); assert_matches!(ci.tvu(Protocol::UDP), None); + assert_matches!(ci.alpenglow(), None); } #[test] @@ -864,6 +885,10 @@ mod tests { } assert_eq!(node.gossip().as_ref(), sockets.get(&SOCKET_TAG_GOSSIP)); assert_eq!(node.rpc().as_ref(), sockets.get(&SOCKET_TAG_RPC)); + assert_eq!( + node.alpenglow().as_ref(), + sockets.get(&SOCKET_TAG_ALPENGLOW) + ); assert_eq!( node.rpc_pubsub().as_ref(), sockets.get(&SOCKET_TAG_RPC_PUBSUB) diff --git a/gossip/src/crds.rs b/gossip/src/crds.rs index d4a62433f762d2..a808bb02b00b21 100644 --- a/gossip/src/crds.rs +++ b/gossip/src/crds.rs @@ -27,6 +27,7 @@ use { crate::{ + cluster_info_metrics::should_report_message_signature, contact_info::ContactInfo, crds_data::CrdsData, crds_entry::CrdsEntry, @@ -44,7 +45,6 @@ use { solana_clock::Slot, solana_hash::Hash, solana_pubkey::Pubkey, - solana_signature::Signature, std::{ cmp::Ordering, collections::{hash_map, BTreeMap, HashMap, VecDeque}, @@ -712,7 +712,8 @@ impl CrdsDataStats { return; }; - if should_report_message_signature(entry.value.signature()) { + if should_report_message_signature(entry.value.signature(), SIGNATURE_SAMPLE_LEADING_ZEROS) + { datapoint_info!( "gossip_crds_sample", ( @@ -779,15 +780,6 @@ impl CrdsStats { } } -/// check if first SIGNATURE_SAMPLE_LEADING_ZEROS bits of signature are 0 -#[inline] -fn should_report_message_signature(signature: &Signature) -> bool { - let Some(Ok(bytes)) = signature.as_ref().get(..8).map(<[u8; 8]>::try_from) else { - return false; - }; - u64::from_le_bytes(bytes).trailing_zeros() >= SIGNATURE_SAMPLE_LEADING_ZEROS -} - #[cfg(test)] mod tests { use { diff --git a/gossip/src/crds_filter.rs b/gossip/src/crds_filter.rs new file mode 100644 index 00000000000000..973a5020704cc1 --- /dev/null +++ b/gossip/src/crds_filter.rs @@ -0,0 +1,73 @@ +use { + crate::{crds_data::CrdsData, crds_value::CrdsValue}, + solana_pubkey::Pubkey, + std::collections::HashMap, +}; + +pub(crate) enum GossipFilterDirection { + Ingress, + EgressPush, + EgressPullResponse, +} + +/// Minimum number of staked nodes for enforcing stakes in gossip. +const MIN_NUM_STAKED_NODES: usize = 500; + +/// Minimum stake that a node should have so that all its CRDS values are +/// propagated through gossip (below this only subset of CRDS is propagated). +pub(crate) const MIN_STAKE_FOR_GOSSIP: u64 = solana_native_token::LAMPORTS_PER_SOL; +/// Minimum stake required for a node to bypass the initial ping check when joining gossip. +pub(crate) const MIN_STAKE_TO_SKIP_PING: u64 = 1000 * solana_native_token::LAMPORTS_PER_SOL; + +/// Returns false if the CRDS value should be discarded. +/// `direction` controls whether we are looking at +/// incoming packet (via Push or PullResponse) or +/// we are about to make a packet +#[inline] +#[must_use] +pub(crate) fn should_retain_crds_value( + value: &CrdsValue, + stakes: &HashMap, + direction: GossipFilterDirection, +) -> bool { + let retain_if_staked = || { + stakes.len() < MIN_NUM_STAKED_NODES || { + let stake = stakes.get(&value.pubkey()).copied(); + stake.unwrap_or_default() >= MIN_STAKE_FOR_GOSSIP + } + }; + + use GossipFilterDirection::*; + match value.data() { + // All nodes can send ContactInfo + CrdsData::ContactInfo(_) => true, + // Unstaked nodes can still serve snapshots. + CrdsData::SnapshotHashes(_) => true, + // Consensus related messages only allowed for staked nodes + CrdsData::DuplicateShred(_, _) + | CrdsData::LowestSlot(0, _) + | CrdsData::RestartHeaviestFork(_) + | CrdsData::RestartLastVotedForkSlots(_) => retain_if_staked(), + // Unstaked nodes can technically send EpochSlots, but we do not want them + // eating gossip bandwidth + CrdsData::EpochSlots(_, _) => match direction { + // always store if we have received them + // to avoid getting them again in PullResponses + Ingress => true, + // only forward if the origin is staked + EgressPush | EgressPullResponse => retain_if_staked(), + }, + CrdsData::Vote(_, _) => match direction { + Ingress | EgressPush => true, + EgressPullResponse => retain_if_staked(), + }, + // Fully deprecated messages + CrdsData::AccountsHashes(_) => false, + CrdsData::LegacyContactInfo(_) => false, + CrdsData::LegacySnapshotHashes(_) => false, + CrdsData::LegacyVersion(_) => false, + CrdsData::LowestSlot(1.., _) => false, + CrdsData::NodeInstance(_) => false, + CrdsData::Version(_) => false, + } +} diff --git a/gossip/src/lib.rs b/gossip/src/lib.rs index 843890f5615473..980d9609713f8d 100644 --- a/gossip/src/lib.rs +++ b/gossip/src/lib.rs @@ -7,6 +7,7 @@ pub mod contact_info; pub mod crds; pub mod crds_data; pub mod crds_entry; +mod crds_filter; pub mod crds_gossip; pub mod crds_gossip_error; pub mod crds_gossip_pull; @@ -22,6 +23,8 @@ pub mod epoch_specs; pub mod gossip_error; pub mod gossip_service; #[macro_use] +mod tlv; +#[macro_use] mod legacy_contact_info; pub mod ping_pong; mod protocol; diff --git a/gossip/src/ping_pong.rs b/gossip/src/ping_pong.rs index 9021eb45d02796..8147169fc71886 100644 --- a/gossip/src/ping_pong.rs +++ b/gossip/src/ping_pong.rs @@ -1,4 +1,5 @@ use { + crate::cluster_info_metrics::should_report_message_signature, lru::LruCache, rand::{CryptoRng, Rng}, serde_big_array::BigArray, @@ -12,13 +13,14 @@ use { std::{ borrow::Cow, hash::{Hash as _, Hasher}, - net::SocketAddr, + net::{IpAddr, SocketAddr}, time::{Duration, Instant}, }, }; const KEY_REFRESH_CADENCE: Duration = Duration::from_secs(60); const PING_PONG_HASH_PREFIX: &[u8] = "SOLANA_PING_PONG".as_bytes(); +const PONG_SIGNATURE_SAMPLE_LEADING_ZEROS: u32 = 5; // For backward compatibility we are using a const generic parameter here. // N should always be >= 8 and only the first 8 bytes are used. So the new code @@ -60,6 +62,8 @@ pub struct PingCache { pings: LruCache<(Pubkey, SocketAddr), Instant>, // Verified pong responses from remote nodes. pongs: LruCache<(Pubkey, SocketAddr), Instant>, + // Timestamp of last ping message sent to a remote IP. + ping_times: LruCache, } impl Ping { @@ -116,6 +120,10 @@ impl Pong { pub fn from(&self) -> &Pubkey { &self.from } + + pub(crate) fn signature(&self) -> &Signature { + &self.signature + } } impl Sanitize for Pong { @@ -161,6 +169,7 @@ impl PingCache { key_refresh: now, pings: LruCache::new(cap), pongs: LruCache::new(cap), + ping_times: LruCache::new(cap), } } @@ -177,6 +186,19 @@ impl PingCache { return false; }; self.pongs.put(remote_node, now); + if let Some(sent_time) = self.ping_times.pop(&socket.ip()) { + if should_report_message_signature( + pong.signature(), + PONG_SIGNATURE_SAMPLE_LEADING_ZEROS, + ) { + let rtt = now.saturating_duration_since(sent_time); + datapoint_info!( + "ping_rtt", + ("peer_ip", socket.ip().to_string(), String), + ("rtt_us", rtt.as_micros() as i64, i64), + ); + } + } true } @@ -199,6 +221,7 @@ impl PingCache { self.pings.put(remote_node, now); self.maybe_refresh_key(rng, now); let token = make_ping_token::(self.hashers[0], &remote_node); + self.ping_times.put(remote_node.1.ip(), Instant::now()); Some(Ping::new(token, keypair)) } diff --git a/gossip/src/tlv.rs b/gossip/src/tlv.rs new file mode 100644 index 00000000000000..1cc11fd6e09a7b --- /dev/null +++ b/gossip/src/tlv.rs @@ -0,0 +1,169 @@ +use { + serde::{Deserialize, Serialize}, + solana_short_vec as short_vec, +}; + +/// Type-Length-Value encoding wrapper for bincode +#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] +pub(crate) struct TlvRecord { + // type + pub(crate) typ: u8, + // length and serialized bytes of the value + #[serde(with = "short_vec")] + pub(crate) bytes: Vec, +} + +/// Macro that provides a quick and easy way to define TLV compatible enums +#[macro_export] +macro_rules! define_tlv_enum { + ( + $(#[$meta:meta])* + $vis:vis enum $enum_name:ident { + $($typ:literal => $variant:ident($inner:ty)),* $(,)? + } + ) => { + // add the doc-comment if present + $(#[$meta])* + // define the enum itself + #[derive(Debug, Clone, Eq, PartialEq)] + $vis enum $enum_name { + $( + $variant($inner), + )* + } + + // Serialize enum by first converting into TlvRecord, and then serializing that + impl serde::Serialize for $enum_name { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let tlv_rec = TlvRecord::try_from(self).map_err(|e| serde::ser::Error::custom(e))?; + tlv_rec.serialize(serializer) + } + } + + // define conversion from TLV wire format + impl TryFrom<&TlvRecord> for $enum_name { + type Error = TlvDecodeError; + fn try_from(value: &TlvRecord) -> Result { + match value.typ { + $( + $typ => Ok(Self::$variant(bincode::deserialize::<$inner>(&value.bytes)?)), + )* + _ => Err(TlvDecodeError::UnknownType(value.typ)), + } + } + } + // define conversion into TLV wire format + impl TryFrom<&$enum_name> for TlvRecord { + type Error = bincode::Error; + fn try_from(value: &$enum_name) -> Result { + use serde::ser::Error; + match value { + $( + $enum_name::$variant(inner) => Ok(TlvRecord { + typ: $typ, + bytes: bincode::serialize(inner)?, + }), + )* + #[allow(unreachable_patterns)] + _ => Err(bincode::Error::custom("Unsupported enum variant")), + } + } + } + }; +} + +#[derive(Debug, thiserror::Error)] +pub enum TlvDecodeError { + #[error("Unknown type: {0}")] + UnknownType(u8), + #[error("Malformed payload: {0}")] + MalformedPayload(#[from] bincode::Error), +} + +/// Parses a slice of serialized TLV records into a provided type. Unsupported +/// TLV records are ignored. +pub(crate) fn parse<'a, T: TryFrom<&'a TlvRecord>>(entries: &'a [TlvRecord]) -> Vec { + entries.iter().filter_map(|v| T::try_from(v).ok()).collect() +} + +#[cfg(test)] +mod tests { + use crate::{ + define_tlv_enum, + tlv::{TlvDecodeError, TlvRecord}, + }; + + define_tlv_enum! (pub(crate) enum ExtensionNew { + 1=>Test(u64), + 2=>LegacyString(String), + 3=>NewString(String), + }); + + define_tlv_enum! ( pub(crate) enum ExtensionLegacy { + 1=>Test(u64), + 2=>LegacyString(String), + }); + + /// Test that TLV encoded data is backwards-compatible, + /// i.e. that new TLV data can be decoded by a new + /// receiver where possible, and skipped otherwise + #[test] + fn test_tlv_backwards_compat() { + let new_tlv_data = vec![ + ExtensionNew::Test(42), + ExtensionNew::NewString(String::from("bla")), + ]; + + let new_bytes = bincode::serialize(&new_tlv_data).unwrap(); + let tlv_vec: Vec = bincode::deserialize(&new_bytes).unwrap(); + // check that both TLV are encoded correctly + let new: Vec = crate::tlv::parse(&tlv_vec); + assert!(matches!(new[0], ExtensionNew::Test(42))); + if let ExtensionNew::NewString(s) = &new[1] { + assert_eq!(s, "bla"); + } else { + panic!("Wrong deserialization") + }; + // Make sure legacy recover works correctly + let legacy: Vec = crate::tlv::parse(&tlv_vec); + assert!(matches!(legacy[0], ExtensionLegacy::Test(42))); + assert_eq!( + legacy.len(), + 1, + "Legacy parser should only recover 1 entry" + ) + } + + /// Test that TLV encoded data is forwards-compatible, + /// i.e. that legacy TLV data can be decoded by a new + /// receiver + #[test] + fn test_tlv_forward_compat() { + let legacy_tlv_data = vec![ + ExtensionLegacy::Test(42), + ExtensionLegacy::LegacyString(String::from("foo")), + ]; + let legacy_bytes = bincode::serialize(&legacy_tlv_data).unwrap(); + + let tlv_vec: Vec = bincode::deserialize(&legacy_bytes).unwrap(); + // Just in case make sure that legacy data is serialized correctly + let legacy: Vec = crate::tlv::parse(&tlv_vec); + assert!(matches!(legacy[0], ExtensionLegacy::Test(42))); + if let ExtensionLegacy::LegacyString(s) = &legacy[1] { + assert_eq!(s, "foo"); + } else { + panic!("Wrong deserialization") + }; + // Parse the same bytes using new parser + let new: Vec = crate::tlv::parse(&tlv_vec); + assert!(matches!(new[0], ExtensionNew::Test(42))); + if let ExtensionNew::LegacyString(s) = &new[1] { + assert_eq!(s, "foo"); + } else { + panic!("Wrong deserialization") + }; + } +} diff --git a/install/Cargo.toml b/install/Cargo.toml index bfcbc20ef51834..681d247c9c0fdd 100644 --- a/install/Cargo.toml +++ b/install/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] atty = { workspace = true } bincode = { workspace = true } @@ -29,11 +32,12 @@ serde_derive = { workspace = true } serde_yaml = { workspace = true } serde_yaml_08 = { package = "serde_yaml", version = "0.8.26" } solana-clap-utils = { workspace = true } -solana-config-program-client = { workspace = true, features = ["serde"] } +solana-config-interface = "=1.0.0" +solana-config-program-client = { version = "=1.1.0", features = ["serde"] } solana-hash = "=2.3.0" solana-keypair = "=2.2.1" solana-logger = "=2.3.1" -solana-message = "=2.3.0" +solana-message = "=2.4.0" solana-pubkey = { version = "=2.4.0", default-features = false } solana-rpc-client = { workspace = true } solana-sha256-hasher = { workspace = true } @@ -48,6 +52,3 @@ url = { workspace = true } [target."cfg(windows)".dependencies] winapi = { workspace = true, features = ["minwindef", "winuser"] } winreg = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/install/src/command.rs b/install/src/command.rs index c9f21c4c9e93d5..32005da6215f8b 100644 --- a/install/src/command.rs +++ b/install/src/command.rs @@ -9,10 +9,8 @@ use { crossbeam_channel::unbounded, indicatif::{ProgressBar, ProgressStyle}, serde_derive::{Deserialize, Serialize}, - solana_config_program_client::{ - get_config_data, - instructions_bincode::{self as config_instruction, ConfigState}, - }, + solana_config_interface::instruction::{self as config_instruction}, + solana_config_program_client::get_config_data, solana_hash::Hash, solana_keypair::{read_keypair_file, signable::Signable, Keypair}, solana_message::Message, @@ -229,14 +227,16 @@ fn new_update_manifest( let recent_blockhash = rpc_client.get_latest_blockhash()?; let lamports = rpc_client - .get_minimum_balance_for_rent_exemption(SignedUpdateManifest::max_space() as usize)?; - - let instructions = config_instruction::create_account::( - &from_keypair.pubkey(), - &update_manifest_keypair.pubkey(), - lamports, - vec![], // additional keys - ); + .get_minimum_balance_for_rent_exemption(SignedUpdateManifest::MAX_SPACE as usize)?; + + let instructions = + config_instruction::create_account_with_max_config_space::( + &from_keypair.pubkey(), + &update_manifest_keypair.pubkey(), + lamports, + SignedUpdateManifest::MAX_SPACE, + vec![], // additional keys + ); let message = Message::new(&instructions, Some(&from_keypair.pubkey())); let signers = [from_keypair, update_manifest_keypair]; let transaction = Transaction::new(&signers, message, recent_blockhash); diff --git a/install/src/update_manifest.rs b/install/src/update_manifest.rs index c186dc5250bceb..11bb12a7c4f257 100644 --- a/install/src/update_manifest.rs +++ b/install/src/update_manifest.rs @@ -1,6 +1,5 @@ use { serde_derive::{Deserialize, Serialize}, - solana_config_program_client::instructions_bincode::ConfigState, solana_hash::Hash, solana_keypair::signable::Signable, solana_pubkey::Pubkey, @@ -42,6 +41,8 @@ impl Signable for SignedUpdateManifest { } impl SignedUpdateManifest { + pub const MAX_SPACE: u64 = 256; // Enough space for a fully populated SignedUpdateManifest + pub fn deserialize( account_pubkey: &Pubkey, input: &[u8], @@ -55,9 +56,3 @@ impl SignedUpdateManifest { } } } - -impl ConfigState for SignedUpdateManifest { - fn max_space() -> u64 { - 256 // Enough space for a fully populated SignedUpdateManifest - } -} diff --git a/keygen/Cargo.toml b/keygen/Cargo.toml index bbd20b99dfd642..540f857dc074ba 100644 --- a/keygen/Cargo.toml +++ b/keygen/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[[bin]] +name = "solana-keygen" +path = "src/keygen.rs" + [dependencies] bs58 = { workspace = true } clap = { version = "3.1.5", features = ["cargo"] } @@ -18,9 +25,9 @@ serde_json = { workspace = true } solana-clap-v3-utils = { workspace = true } solana-cli-config = { workspace = true } solana-derivation-path = "=2.2.1" -solana-instruction = { version = "=2.2.1", features = ["bincode"] } +solana-instruction = { version = "=2.3.0", features = ["bincode"] } solana-keypair = "=2.2.1" -solana-message = { version = "=2.3.0", features = ["bincode"] } +solana-message = { version = "=2.4.0", features = ["bincode"] } solana-pubkey = { version = "=2.4.0", default-features = false } solana-remote-wallet = { workspace = true, features = ["default"] } solana-seed-derivable = "=2.2.1" @@ -31,10 +38,3 @@ tiny-bip39 = { workspace = true } [dev-dependencies] solana-pubkey = { workspace = true, features = ["rand"] } tempfile = { workspace = true } - -[[bin]] -name = "solana-keygen" -path = "src/keygen.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/ledger-tool/Cargo.toml b/ledger-tool/Cargo.toml index a75135d01c979a..8fc22f13065d63 100644 --- a/ledger-tool/Cargo.toml +++ b/ledger-tool/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [] + [dependencies] agave-feature-set = { workspace = true } agave-reserved-account-keys = { workspace = true } @@ -47,6 +53,7 @@ solana-geyser-plugin-manager = { workspace = true } solana-gossip = { workspace = true } solana-hash = { workspace = true } solana-inflation = { workspace = true } +solana-instruction = { workspace = true } solana-keypair = { workspace = true } solana-ledger = { workspace = true, features = ["dev-context-only-utils"] } solana-loader-v3-interface = { workspace = true } @@ -86,14 +93,8 @@ tokio = { workspace = true, features = ["full"] } [target.'cfg(not(any(target_env = "msvc", target_os = "freebsd")))'.dependencies] jemallocator = { workspace = true } -[dev-dependencies] -assert_cmd = { workspace = true } - -[features] -dev-context-only-utils = [] - [target."cfg(unix)".dependencies] signal-hook = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +[dev-dependencies] +assert_cmd = { workspace = true } diff --git a/ledger-tool/src/ledger_utils.rs b/ledger-tool/src/ledger_utils.rs index 3ab63b7803e050..7a908238fbf3ed 100644 --- a/ledger-tool/src/ledger_utils.rs +++ b/ledger-tool/src/ledger_utils.rs @@ -27,9 +27,7 @@ use { }, solana_measure::measure_time, solana_pubkey::Pubkey, - solana_rpc::{ - block_meta_service::BlockMetaService, transaction_status_service::TransactionStatusService, - }, + solana_rpc::transaction_status_service::TransactionStatusService, solana_runtime::{ accounts_background_service::{ AbsRequestHandlers, AccountsBackgroundService, PrunedBanksRequestHandler, @@ -294,58 +292,42 @@ pub fn load_and_process_ledger( let enable_rpc_transaction_history = arg_matches.is_present("enable_rpc_transaction_history"); - let ( - transaction_status_sender, - transaction_status_service, - block_meta_sender, - block_meta_service, - ) = if geyser_plugin_active || enable_rpc_transaction_history { - // Need Primary (R/W) access to insert transaction and rewards data; - // obtain Primary access if we do not already have it - let write_blockstore = if enable_rpc_transaction_history && !blockstore.is_primary_access() - { - Arc::new(open_blockstore( - blockstore.ledger_path(), - arg_matches, - AccessType::PrimaryForMaintenance, - )) + let (transaction_status_sender, transaction_status_service) = + if geyser_plugin_active || enable_rpc_transaction_history { + // Need Primary (R/W) access to insert transaction and rewards data; + // obtain Primary access if we do not already have it + let write_blockstore = + if enable_rpc_transaction_history && !blockstore.is_primary_access() { + Arc::new(open_blockstore( + blockstore.ledger_path(), + arg_matches, + AccessType::PrimaryForMaintenance, + )) + } else { + blockstore.clone() + }; + + let (transaction_status_sender, transaction_status_receiver) = unbounded(); + let transaction_status_service = TransactionStatusService::new( + transaction_status_receiver, + Arc::default(), + enable_rpc_transaction_history, + transaction_notifier, + write_blockstore.clone(), + arg_matches.is_present("enable_extended_tx_metadata_storage"), + tss_exit.clone(), + ); + + ( + Some(TransactionStatusSender { + sender: transaction_status_sender, + }), + Some(transaction_status_service), + ) } else { - blockstore.clone() + (transaction_status_sender, None) }; - let (transaction_status_sender, transaction_status_receiver) = unbounded(); - let transaction_status_service = TransactionStatusService::new( - transaction_status_receiver, - Arc::default(), - enable_rpc_transaction_history, - transaction_notifier, - write_blockstore.clone(), - arg_matches.is_present("enable_extended_tx_metadata_storage"), - tss_exit.clone(), - ); - - let (block_meta_sender, block_meta_receiver) = unbounded(); - // Nothing else will be interacting with max_complete_rewards_slot - let max_complete_rewards_slot = Arc::default(); - let block_meta_service = BlockMetaService::new( - block_meta_receiver, - write_blockstore, - max_complete_rewards_slot, - exit.clone(), - ); - - ( - Some(TransactionStatusSender { - sender: transaction_status_sender, - }), - Some(transaction_status_service), - Some(block_meta_sender), - Some(block_meta_service), - ) - } else { - (transaction_status_sender, None, None, None) - }; - let (bank_forks, leader_schedule_cache, starting_snapshot_hashes, ..) = bank_forks_utils::load_bank_forks( genesis_config, @@ -353,7 +335,7 @@ pub fn load_and_process_ledger( account_paths, &snapshot_config, &process_options, - block_meta_sender.as_ref(), + transaction_status_sender.as_ref(), None, // Maybe support this later, though accounts_update_notifier, exit.clone(), @@ -438,7 +420,6 @@ pub fn load_and_process_ledger( &leader_schedule_cache, &process_options, transaction_status_sender.as_ref(), - block_meta_sender.as_ref(), None, // entry_notification_sender Some(&snapshot_controller), ) @@ -454,9 +435,6 @@ pub fn load_and_process_ledger( if let Some(service) = transaction_status_service { service.quiesce_and_join_for_tests(tss_exit); } - if let Some(service) = block_meta_service { - service.join().unwrap(); - } result } diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index c7f26c05182b89..f13ea3b53600cd 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -45,6 +45,7 @@ use { solana_feature_gate_interface::{self as feature, Feature}, solana_genesis_config::ClusterType, solana_inflation::Inflation, + solana_instruction::TRANSACTION_LEVEL_STACK_HEIGHT, solana_ledger::{ blockstore::{banking_trace_path, create_new_ledger, Blockstore}, blockstore_options::{AccessType, LedgerColumnOptions}, @@ -754,7 +755,13 @@ fn record_transactions( let instructions = message .instructions() .iter() - .map(|ix| parse_ui_instruction(ix, &message.account_keys(), None)) + .map(|ix| { + parse_ui_instruction( + ix, + &message.account_keys(), + Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32), + ) + }) .collect(); let is_simple_vote_tx = tx.is_simple_vote_transaction(); @@ -2331,9 +2338,7 @@ fn main() { } if child_bank_required { - while !bank.is_complete() { - bank.register_unique_tick(); - } + bank.fill_bank_with_ticks_for_tests(); } let pre_capitalization = bank.capitalization(); diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index 9b600c4346b617..7e99d3146c75bb 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -9,6 +9,21 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_ledger" + +[features] +dev-context-only-utils = [] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-runtime/frozen-abi", +] + [dependencies] agave-feature-set = { workspace = true } agave-reserved-account-keys = { workspace = true } @@ -125,23 +140,12 @@ solana-perf = { workspace = true, features = ["dev-context-only-utils"] } solana-program-option = { workspace = true } solana-program-pack = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } +solana-signature = { workspace = true, features = ["rand"] } solana-vote = { workspace = true, features = ["dev-context-only-utils"] } spl-generic-token = { workspace = true } spl-pod = { workspace = true } test-case = { workspace = true } -[features] -dev-context-only-utils = [] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-runtime/frozen-abi", -] - -[lib] -crate-type = ["lib"] -name = "solana_ledger" - [[bench]] name = "blockstore" @@ -149,8 +153,5 @@ name = "blockstore" name = "make_shreds_from_entries" harness = false -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [lints] workspace = true diff --git a/ledger/src/bank_forks_utils.rs b/ledger/src/bank_forks_utils.rs index 96816099da1a84..d2e882471656a8 100644 --- a/ledger/src/bank_forks_utils.rs +++ b/ledger/src/bank_forks_utils.rs @@ -2,8 +2,7 @@ use { crate::{ blockstore::Blockstore, blockstore_processor::{ - self, BlockMetaSender, BlockstoreProcessorError, ProcessOptions, - TransactionStatusSender, + self, BlockstoreProcessorError, ProcessOptions, TransactionStatusSender, }, entry_notifier_service::EntryNotifierSender, leader_schedule_cache::LeaderScheduleCache, @@ -85,7 +84,6 @@ pub fn load( snapshot_config: &SnapshotConfig, process_options: ProcessOptions, transaction_status_sender: Option<&TransactionStatusSender>, - block_meta_sender: Option<&BlockMetaSender>, entry_notification_sender: Option<&EntryNotifierSender>, accounts_update_notifier: Option, exit: Arc, @@ -96,7 +94,7 @@ pub fn load( account_paths, snapshot_config, &process_options, - block_meta_sender, + transaction_status_sender, entry_notification_sender, accounts_update_notifier, exit, @@ -107,7 +105,6 @@ pub fn load( &leader_schedule_cache, &process_options, transaction_status_sender, - block_meta_sender, entry_notification_sender, None, // snapshot_controller ) @@ -123,7 +120,7 @@ pub fn load_bank_forks( account_paths: Vec, snapshot_config: &SnapshotConfig, process_options: &ProcessOptions, - block_meta_sender: Option<&BlockMetaSender>, + transaction_status_sender: Option<&TransactionStatusSender>, entry_notification_sender: Option<&EntryNotifierSender>, accounts_update_notifier: Option, exit: Arc, @@ -191,7 +188,7 @@ pub fn load_bank_forks( blockstore, account_paths, process_options, - block_meta_sender, + transaction_status_sender, entry_notification_sender, accounts_update_notifier, exit, diff --git a/ledger/src/bigtable_upload_service.rs b/ledger/src/bigtable_upload_service.rs index 0ffb02aac2475c..fbafe160afc86a 100644 --- a/ledger/src/bigtable_upload_service.rs +++ b/ledger/src/bigtable_upload_service.rs @@ -26,7 +26,6 @@ impl BigTableUploadService { blockstore: Arc, block_commitment_cache: Arc>, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, exit: Arc, ) -> Self { Self::new_with_config( @@ -35,7 +34,6 @@ impl BigTableUploadService { blockstore, block_commitment_cache, max_complete_transaction_status_slot, - max_complete_rewards_slot, ConfirmedBlockUploadConfig::default(), exit, ) @@ -47,7 +45,6 @@ impl BigTableUploadService { blockstore: Arc, block_commitment_cache: Arc>, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, config: ConfirmedBlockUploadConfig, exit: Arc, ) -> Self { @@ -61,7 +58,6 @@ impl BigTableUploadService { blockstore, block_commitment_cache, max_complete_transaction_status_slot, - max_complete_rewards_slot, config, exit, ) @@ -77,7 +73,6 @@ impl BigTableUploadService { blockstore: Arc, block_commitment_cache: Arc>, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, config: ConfirmedBlockUploadConfig, exit: Arc, ) { @@ -87,16 +82,12 @@ impl BigTableUploadService { break; } - // The highest slot eligible for upload is the highest root that has complete - // transaction-status metadata and rewards - let highest_complete_root = [ + // The highest slot eligible for upload is the highest root that + // has complete block metadata + let highest_complete_root = std::cmp::min( max_complete_transaction_status_slot.load(Ordering::SeqCst), - max_complete_rewards_slot.load(Ordering::SeqCst), block_commitment_cache.read().unwrap().root(), - ] - .into_iter() - .min() - .expect("root and max_complete slots exist"); + ); let end_slot = min( highest_complete_root, start_slot.saturating_add(config.max_num_slots_to_check as u64 * 2), diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 352e1ad5d7801a..73f0e568b04861 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -929,7 +929,6 @@ pub fn test_process_blockstore( opts, None, None, - None, Some(&snapshot_controller), ) .unwrap(); @@ -945,7 +944,7 @@ pub(crate) fn process_blockstore_for_bank_0( blockstore: &Blockstore, account_paths: Vec, opts: &ProcessOptions, - block_meta_sender: Option<&BlockMetaSender>, + transaction_status_sender: Option<&TransactionStatusSender>, entry_notification_sender: Option<&EntryNotifierSender>, accounts_update_notifier: Option, exit: Arc, @@ -979,8 +978,8 @@ pub(crate) fn process_blockstore_for_bank_0( blockstore, &replay_tx_thread_pool, opts, + transaction_status_sender, &VerifyRecyclers::default(), - block_meta_sender, entry_notification_sender, )?; @@ -995,7 +994,6 @@ pub fn process_blockstore_from_root( leader_schedule_cache: &LeaderScheduleCache, opts: &ProcessOptions, transaction_status_sender: Option<&TransactionStatusSender>, - block_meta_sender: Option<&BlockMetaSender>, entry_notification_sender: Option<&EntryNotifierSender>, snapshot_controller: Option<&SnapshotController>, ) -> result::Result<(), BlockstoreProcessorError> { @@ -1061,7 +1059,6 @@ pub fn process_blockstore_from_root( leader_schedule_cache, opts, transaction_status_sender, - block_meta_sender, entry_notification_sender, &mut timing, snapshot_controller, @@ -1771,8 +1768,8 @@ fn process_bank_0( blockstore: &Blockstore, replay_tx_thread_pool: &ThreadPool, opts: &ProcessOptions, + transaction_status_sender: Option<&TransactionStatusSender>, recyclers: &VerifyRecyclers, - block_meta_sender: Option<&BlockMetaSender>, entry_notification_sender: Option<&EntryNotifierSender>, ) -> result::Result<(), BlockstoreProcessorError> { assert_eq!(bank0.slot(), 0); @@ -1797,7 +1794,10 @@ fn process_bank_0( if blockstore.is_primary_access() { blockstore.insert_bank_hash(bank0.slot(), bank0.hash(), false); } - send_block_meta(bank0, block_meta_sender); + + if let Some(transaction_status_sender) = transaction_status_sender { + transaction_status_sender.send_transaction_status_freeze_message(bank0); + } Ok(()) } @@ -1874,7 +1874,6 @@ fn load_frozen_forks( leader_schedule_cache: &LeaderScheduleCache, opts: &ProcessOptions, transaction_status_sender: Option<&TransactionStatusSender>, - block_meta_sender: Option<&BlockMetaSender>, entry_notification_sender: Option<&EntryNotifierSender>, timing: &mut ExecuteTimings, snapshot_controller: Option<&SnapshotController>, @@ -1958,7 +1957,6 @@ fn load_frozen_forks( &recyclers, &mut progress, transaction_status_sender, - block_meta_sender, entry_notification_sender, None, timing, @@ -2149,7 +2147,6 @@ pub fn process_single_slot( recyclers: &VerifyRecyclers, progress: &mut ConfirmationProgress, transaction_status_sender: Option<&TransactionStatusSender>, - block_meta_sender: Option<&BlockMetaSender>, entry_notification_sender: Option<&EntryNotifierSender>, replay_vote_sender: Option<&ReplayVoteSender>, timing: &mut ExecuteTimings, @@ -2214,7 +2211,10 @@ pub fn process_single_slot( if blockstore.is_primary_access() { blockstore.insert_bank_hash(bank.slot(), bank.hash(), false); } - send_block_meta(bank, block_meta_sender); + + if let Some(transaction_status_sender) = transaction_status_sender { + transaction_status_sender.send_transaction_status_freeze_message(bank); + } Ok(()) } @@ -2223,7 +2223,7 @@ pub fn process_single_slot( #[derive(Debug)] pub enum TransactionStatusMessage { Batch(TransactionStatusBatch), - Freeze(Slot), + Freeze(Arc), } #[derive(Debug)] @@ -2274,27 +2274,19 @@ impl TransactionStatusSender { } pub fn send_transaction_status_freeze_message(&self, bank: &Arc) { - let slot = bank.slot(); - if let Err(e) = self.sender.send(TransactionStatusMessage::Freeze(slot)) { - trace!( - "Slot {} transaction_status send freeze message failed: {:?}", - slot, + if let Err(e) = self + .sender + .send(TransactionStatusMessage::Freeze(bank.clone())) + { + let slot = bank.slot(); + warn!( + "Slot {slot} transaction_status send freeze message failed: {:?}", e ); } } } -pub type BlockMetaSender = Sender>; - -pub fn send_block_meta(bank: &Arc, block_meta_sender: Option<&BlockMetaSender>) { - if let Some(block_meta_sender) = block_meta_sender { - block_meta_sender - .send(bank.clone()) - .unwrap_or_else(|err| warn!("block_meta_sender failed: {:?}", err)); - } -} - // used for tests only pub fn fill_blockstore_slot_with_ticks( blockstore: &Blockstore, @@ -3638,8 +3630,11 @@ pub mod tests { }); } - #[test] - fn test_process_entries_2nd_entry_collision_with_self_and_error() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_process_entries_2nd_entry_collision_with_self_and_error( + relax_intrabatch_account_locks: bool, + ) { solana_logger::setup(); let GenesisConfigInfo { @@ -3647,7 +3642,11 @@ pub mod tests { mint_keypair, .. } = create_genesis_config(1000); - let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); let keypair1 = Keypair::new(); let keypair2 = Keypair::new(); let keypair3 = Keypair::new(); @@ -3687,7 +3686,7 @@ pub mod tests { &mint_keypair.pubkey(), 2, bank.last_blockhash(), - ), // will collide with predecessor + ), // will collide with preceding entry ], ); // should now be: @@ -3710,28 +3709,100 @@ pub mod tests { &keypair2.pubkey(), 1, bank.last_blockhash(), - ), // should be fine + ), // will collide with preceding transaction ], ); - // would now be: + // if successful, becomes: // keypair1=0 // keypair2=3 // keypair3=3 - assert!(process_entries_for_tests_without_scheduler( + // succeeds following simd83 locking, fails otherwise + let result = process_entries_for_tests_without_scheduler( &bank, vec![ entry_1_to_mint, entry_2_to_3_and_1_to_mint, entry_conflict_itself, ], - ) - .is_err()); + ); - // last entry should have been aborted before par_execute_entries - assert_eq!(bank.get_balance(&keypair1.pubkey()), 2); - assert_eq!(bank.get_balance(&keypair2.pubkey()), 2); - assert_eq!(bank.get_balance(&keypair3.pubkey()), 2); + let balances = [ + bank.get_balance(&keypair1.pubkey()), + bank.get_balance(&keypair2.pubkey()), + bank.get_balance(&keypair3.pubkey()), + ]; + + if relax_intrabatch_account_locks { + assert!(result.is_ok()); + assert_eq!(balances, [0, 3, 3]); + } else { + assert!(result.is_err()); + assert_eq!(balances, [2, 2, 2]); + } + } + + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_process_entry_duplicate_transaction(relax_intrabatch_account_locks: bool) { + solana_logger::setup(); + + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config(1000); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); + let keypair1 = Keypair::new(); + let keypair2 = Keypair::new(); + + // fund: put some money in each of 1 and 2 + assert_matches!(bank.transfer(5, &mint_keypair, &keypair1.pubkey()), Ok(_)); + assert_matches!(bank.transfer(5, &mint_keypair, &keypair2.pubkey()), Ok(_)); + + // one entry, two instances of the same transaction. this entry is invalid + // without simd83: due to lock conflicts + // with simd83: due to message hash duplication + let entry_1_to_2_twice = next_entry( + &bank.last_blockhash(), + 1, + vec![ + system_transaction::transfer( + &keypair1, + &keypair2.pubkey(), + 1, + bank.last_blockhash(), + ), + system_transaction::transfer( + &keypair1, + &keypair2.pubkey(), + 1, + bank.last_blockhash(), + ), + ], + ); + // should now be: + // keypair1=5 + // keypair2=5 + + // succeeds following simd83 locking, fails otherwise + let result = process_entries_for_tests_without_scheduler(&bank, vec![entry_1_to_2_twice]); + + let balances = [ + bank.get_balance(&keypair1.pubkey()), + bank.get_balance(&keypair2.pubkey()), + ]; + + assert_eq!(balances, [5, 5]); + if relax_intrabatch_account_locks { + assert_eq!(result, Err(TransactionError::AlreadyProcessed)); + } else { + assert_eq!(result, Err(TransactionError::AccountInUse)); + } } #[test] @@ -4041,14 +4112,19 @@ pub mod tests { ); } - #[test] - fn test_update_transaction_statuses_fail() { + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_update_transaction_statuses_fail(relax_intrabatch_account_locks: bool) { let GenesisConfigInfo { genesis_config, mint_keypair, .. } = create_genesis_config(11_000); - let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); let keypair1 = Keypair::new(); let keypair2 = Keypair::new(); let success_tx = system_transaction::transfer( @@ -4057,7 +4133,7 @@ pub mod tests { 1, bank.last_blockhash(), ); - let fail_tx = system_transaction::transfer( + let test_tx = system_transaction::transfer( &mint_keypair, &keypair2.pubkey(), 2, @@ -4069,17 +4145,29 @@ pub mod tests { 1, vec![ success_tx, - fail_tx.clone(), // will collide + test_tx.clone(), // will collide ], ); + // succeeds with simd83, fails because of account locking conflict otherwise assert_eq!( process_entries_for_tests_without_scheduler(&bank, vec![entry_1_to_mint]), - Err(TransactionError::AccountInUse) + if relax_intrabatch_account_locks { + Ok(()) + } else { + Err(TransactionError::AccountInUse) + } ); - // Should not see duplicate signature error - assert_eq!(bank.process_transaction(&fail_tx), Ok(())); + // fails with simd83 as already processed, succeeds otherwise + assert_eq!( + bank.process_transaction(&test_tx), + if relax_intrabatch_account_locks { + Err(TransactionError::AlreadyProcessed) + } else { + Ok(()) + } + ); } #[test] @@ -4166,8 +4254,8 @@ pub mod tests { &blockstore, &replay_tx_thread_pool, &opts, - &recyclers, None, + &recyclers, None, ) .unwrap(); @@ -4202,7 +4290,6 @@ pub mod tests { &opts, None, None, - None, None, // snapshot_controller ) .unwrap(); diff --git a/local-cluster/Cargo.toml b/local-cluster/Cargo.toml index cbb8ccc6d637dc..36911ac92946b0 100644 --- a/local-cluster/Cargo.toml +++ b/local-cluster/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = [] + [dependencies] crossbeam-channel = { workspace = true } itertools = { workspace = true } @@ -75,9 +81,3 @@ solana-download-utils = { workspace = true } solana-ledger = { workspace = true, features = ["dev-context-only-utils"] } solana-local-cluster = { path = ".", features = ["dev-context-only-utils"] } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [] diff --git a/local-cluster/tests/local_cluster.rs b/local-cluster/tests/local_cluster.rs index 05dfa912503c11..9314b662b5fcff 100644 --- a/local-cluster/tests/local_cluster.rs +++ b/local-cluster/tests/local_cluster.rs @@ -2330,7 +2330,6 @@ fn create_snapshot_to_hard_fork( None, None, None, - None, Arc::default(), ) .unwrap(); diff --git a/log-analyzer/Cargo.toml b/log-analyzer/Cargo.toml index c40cce53aea91f..27c95c9b7ed5ba 100644 --- a/log-analyzer/Cargo.toml +++ b/log-analyzer/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[[bin]] +name = "solana-log-analyzer" +path = "src/main.rs" + [dependencies] byte-unit = { workspace = true } clap = { version = "3.1.5", features = ["cargo"] } @@ -17,10 +24,3 @@ serde_derive = { workspace = true } serde_json = { workspace = true } solana-logger = "=2.3.1" solana-version = { workspace = true } - -[[bin]] -name = "solana-log-analyzer" -path = "src/main.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/log-collector/Cargo.toml b/log-collector/Cargo.toml index e22c14c09f65e4..693d5fd6b4812f 100644 --- a/log-collector/Cargo.toml +++ b/log-collector/Cargo.toml @@ -9,8 +9,8 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -log = { workspace = true } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +log = { workspace = true } diff --git a/merkle-tree/Cargo.toml b/merkle-tree/Cargo.toml index cbd11a0e65797c..7993e255807e12 100644 --- a/merkle-tree/Cargo.toml +++ b/merkle-tree/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_merkle_tree" + [dependencies] fast-math = { workspace = true } solana-hash = { workspace = true } @@ -16,10 +23,3 @@ solana-sha256-hasher = { workspace = true } [dev-dependencies] hex = { workspace = true } - -[lib] -crate-type = ["lib"] -name = "solana_merkle_tree" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/metrics/Cargo.toml b/metrics/Cargo.toml index 716f4ee0ca041d..d81b5f61a73444 100644 --- a/metrics/Cargo.toml +++ b/metrics/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_metrics" + [dependencies] crossbeam-channel = { workspace = true } gethostname = { workspace = true } @@ -24,11 +30,5 @@ env_logger = { workspace = true } rand = { workspace = true } serial_test = { workspace = true } -[lib] -name = "solana_metrics" - [[bench]] name = "metrics" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/net-shaper/Cargo.toml b/net-shaper/Cargo.toml index 33c4e303873462..ff047038c29beb 100644 --- a/net-shaper/Cargo.toml +++ b/net-shaper/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[[bin]] +name = "solana-net-shaper" +path = "src/main.rs" + [dependencies] clap = { version = "3.1.5", features = ["cargo"] } rand = { workspace = true } @@ -16,10 +23,3 @@ serde = { workspace = true } serde_derive = { workspace = true } serde_json = { workspace = true } solana-logger = "=2.3.1" - -[[bin]] -name = "solana-net-shaper" -path = "src/main.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/net-utils/Cargo.toml b/net-utils/Cargo.toml index 89f91d22c740ce..f26dcbf7f7e207 100644 --- a/net-utils/Cargo.toml +++ b/net-utils/Cargo.toml @@ -10,8 +10,15 @@ license = { workspace = true } edition = { workspace = true } rust-version = "1.83.0" -[lints] -workspace = true +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_net_utils" + +[features] +default = [] +dev-context-only-utils = ["dep:pcap-file", "dep:hxdmp"] [dependencies] anyhow = { workspace = true } @@ -33,12 +40,5 @@ url = { workspace = true } [dev-dependencies] solana-logger = { workspace = true } -[features] -default = [] -dev-context-only-utils = ["dep:pcap-file", "dep:hxdmp"] - -[lib] -name = "solana_net_utils" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +[lints] +workspace = true diff --git a/notifier/Cargo.toml b/notifier/Cargo.toml index 270ba43d9c696c..ba5dcb2a74e3a4 100644 --- a/notifier/Cargo.toml +++ b/notifier/Cargo.toml @@ -9,14 +9,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_notifier" + [dependencies] log = { workspace = true } reqwest = { workspace = true, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] } serde_json = { workspace = true } solana-hash = { workspace = true } - -[lib] -name = "solana_notifier" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/perf/Cargo.toml b/perf/Cargo.toml index 05a46eceb9db92..aa43ba4ecd4c38 100644 --- a/perf/Cargo.toml +++ b/perf/Cargo.toml @@ -9,6 +9,30 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_perf" + +[features] +dev-context-only-utils = [ + "dep:solana-clock", + "dep:solana-keypair", + "dep:solana-signer", + "dep:solana-system-interface", + "dep:solana-system-transaction", + "dep:solana-transaction", + "dep:solana-vote-program", + "dep:solana-vote", +] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-short-vec/frozen-abi", + "solana-vote-program/frozen-abi", +] + [dependencies] ahash = { workspace = true } bincode = { workspace = true } @@ -51,9 +75,6 @@ caps = { workspace = true } libc = { workspace = true } nix = { workspace = true, features = ["user"] } -[lib] -name = "solana_perf" - [dev-dependencies] assert_matches = { workspace = true } rand_chacha = { workspace = true } @@ -61,33 +82,12 @@ solana-logger = { workspace = true } solana-perf = { path = ".", features = ["dev-context-only-utils"] } test-case = { workspace = true } -[features] -dev-context-only-utils = [ - "dep:solana-clock", - "dep:solana-keypair", - "dep:solana-signer", - "dep:solana-system-interface", - "dep:solana-system-transaction", - "dep:solana-transaction", - "dep:solana-vote-program", - "dep:solana-vote", -] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-short-vec/frozen-abi", - "solana-vote-program/frozen-abi", -] - [[bench]] name = "sigverify" [[bench]] name = "discard" -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [lints.rust.unexpected_cfgs] level = "warn" check-cfg = ['cfg(build_target_feature_avx)', 'cfg(build_target_feature_avx2)'] diff --git a/platform-tools-sdk/cargo-build-sbf/Cargo.toml b/platform-tools-sdk/cargo-build-sbf/Cargo.toml index 8c6ed2d2024bc7..e4b3c84bc8d9ec 100644 --- a/platform-tools-sdk/cargo-build-sbf/Cargo.toml +++ b/platform-tools-sdk/cargo-build-sbf/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[[bin]] +name = "cargo-build-sbf" +path = "src/main.rs" + +[features] +program = [] + [dependencies] bzip2 = { workspace = true } cargo_metadata = { workspace = true } @@ -27,10 +34,3 @@ tar = { workspace = true } assert_cmd = { workspace = true } predicates = { workspace = true } serial_test = { workspace = true } - -[features] -program = [] - -[[bin]] -name = "cargo-build-sbf" -path = "src/main.rs" diff --git a/platform-tools-sdk/cargo-build-sbf/src/main.rs b/platform-tools-sdk/cargo-build-sbf/src/main.rs index 651b9c1334aba4..979bac43e362fa 100644 --- a/platform-tools-sdk/cargo-build-sbf/src/main.rs +++ b/platform-tools-sdk/cargo-build-sbf/src/main.rs @@ -47,6 +47,7 @@ pub struct Config<'a> { jobs: Option, arch: &'a str, optimize_size: bool, + lto: bool, } impl Default for Config<'_> { @@ -78,6 +79,7 @@ impl Default for Config<'_> { jobs: None, arch: "v0", optimize_size: false, + lto: false, } } } @@ -553,6 +555,12 @@ fn invoke_cargo(config: &Config) { if config.optimize_size { target_rustflags = Cow::Owned(format!("{} -C opt-level=s", &target_rustflags)); } + if config.lto { + target_rustflags = Cow::Owned(format!( + "{} -C embed-bitcode=yes -C lto=fat", + &target_rustflags + )); + } if config.debug { // Replace with -Zsplit-debuginfo=packed when stabilized. target_rustflags = Cow::Owned(format!("{} -g", &target_rustflags)); @@ -878,6 +886,14 @@ fn main() { .takes_value(false) .help("Optimize program for size. This option may reduce program size, potentially increasing CU consumption.") ) + .arg( + Arg::new("lto") + .long("lto") + .takes_value(false) + .help("Enable Link-Time Optimization (LTO) for all crates being built. \ + This option may decrease program size and CU consumption. The default option is LTO \ + disabled, as one may get mixed results with it.") + ) .get_matches_from(args); let sbf_sdk: PathBuf = matches.value_of_t_or_exit("sbf_sdk"); @@ -948,6 +964,7 @@ fn main() { jobs: matches.value_of_t("jobs").ok(), arch: matches.value_of("arch").unwrap(), optimize_size: matches.is_present("optimize_size"), + lto: matches.is_present("lto"), }; let manifest_path: Option = matches.value_of_t("manifest_path").ok(); if config.verbose { diff --git a/platform-tools-sdk/cargo-build-sbf/tests/crates.rs b/platform-tools-sdk/cargo-build-sbf/tests/crates.rs index 469321c3dd54aa..7ccf3f4fec0f8f 100644 --- a/platform-tools-sdk/cargo-build-sbf/tests/crates.rs +++ b/platform-tools-sdk/cargo-build-sbf/tests/crates.rs @@ -97,7 +97,7 @@ fn test_out_dir() { #[serial] fn test_target_dir() { let target_dir = "./temp-target-dir"; - run_cargo_build("noop", &["--", "--target-dir", target_dir], false); + run_cargo_build("noop", &["--lto", "--", "--target-dir", target_dir], false); let cwd = env::current_dir().expect("Unable to get current working directory"); let normal_target_dir = cwd.join("tests").join("crates").join("noop").join("target"); assert!(!normal_target_dir.exists()); diff --git a/platform-tools-sdk/cargo-build-sbf/tests/crates/fail/Cargo.toml b/platform-tools-sdk/cargo-build-sbf/tests/crates/fail/Cargo.toml index 633b7f1fd18949..43be8bcdac4b0d 100644 --- a/platform-tools-sdk/cargo-build-sbf/tests/crates/fail/Cargo.toml +++ b/platform-tools-sdk/cargo-build-sbf/tests/crates/fail/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fail" -version = "2.3.0" +version = "3.0.0" description = "Solana SBF test program written in Rust" authors = ["Anza Maintainers "] repository = "https://github.com/anza-xyz/agave" @@ -10,10 +10,10 @@ edition = "2021" publish = false [dependencies] -solana-account-info = "=2.2.0" -solana-program-entrypoint = "=2.2.0" -solana-program-error = "=2.2.0" -solana-pubkey = "=2.2.0" +solana-account-info = "=2.3.0" +solana-program-entrypoint = "=2.2.1" +solana-program-error = "=2.2.2" +solana-pubkey = "=2.4.0" [lib] crate-type = ["cdylib"] diff --git a/platform-tools-sdk/cargo-build-sbf/tests/crates/noop/Cargo.toml b/platform-tools-sdk/cargo-build-sbf/tests/crates/noop/Cargo.toml index 384901d0305f21..fe40eb10d8f2e1 100644 --- a/platform-tools-sdk/cargo-build-sbf/tests/crates/noop/Cargo.toml +++ b/platform-tools-sdk/cargo-build-sbf/tests/crates/noop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "noop" -version = "2.3.0" +version = "3.0.0" description = "Solana SBF test program written in Rust" authors = ["Anza Maintainers "] repository = "https://github.com/anza-xyz/agave" @@ -10,10 +10,10 @@ edition = "2021" publish = false [dependencies] -solana-account-info = "=2.2.0" -solana-program-entrypoint = "=2.2.0" -solana-program-error = "=2.2.0" -solana-pubkey = "=2.2.0" +solana-account-info = "=2.3.0" +solana-program-entrypoint = "=2.2.1" +solana-program-error = "=2.2.2" +solana-pubkey = "=2.4.0" [lib] crate-type = ["cdylib"] diff --git a/platform-tools-sdk/cargo-build-sbf/tests/crates/package-metadata/Cargo.toml b/platform-tools-sdk/cargo-build-sbf/tests/crates/package-metadata/Cargo.toml index 8df6293e8cf121..d3bfe3ab5518e7 100644 --- a/platform-tools-sdk/cargo-build-sbf/tests/crates/package-metadata/Cargo.toml +++ b/platform-tools-sdk/cargo-build-sbf/tests/crates/package-metadata/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "package-metadata" -version = "2.3.0" +version = "3.0.0" description = "Solana SBF test program with tools version in package metadata" authors = ["Anza Maintainers "] repository = "https://github.com/anza-xyz/agave" @@ -14,11 +14,11 @@ tools-version = "v1.48" program-id = "MyProgram1111111111111111111111111111111111" [dependencies] -solana-account-info = "=2.2.0" -solana-package-metadata = "=2.2.0" -solana-program-entrypoint = "=2.2.0" -solana-program-error = "=2.2.0" -solana-pubkey = "=2.2.0" +solana-account-info = "=2.3.0" +solana-package-metadata = "=2.2.1" +solana-program-entrypoint = "=2.2.1" +solana-program-error = "=2.2.2" +solana-pubkey = "=2.4.0" [lib] crate-type = ["cdylib"] diff --git a/platform-tools-sdk/cargo-build-sbf/tests/crates/workspace-metadata/Cargo.toml b/platform-tools-sdk/cargo-build-sbf/tests/crates/workspace-metadata/Cargo.toml index e0fc469494bba5..755dd6e8856f36 100644 --- a/platform-tools-sdk/cargo-build-sbf/tests/crates/workspace-metadata/Cargo.toml +++ b/platform-tools-sdk/cargo-build-sbf/tests/crates/workspace-metadata/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workspace-metadata" -version = "2.3.0" +version = "3.0.0" description = "Solana SBF test program with tools version in workspace metadata" authors = ["Anza Maintainers "] repository = "https://github.com/anza-xyz/agave" @@ -10,10 +10,10 @@ edition = "2021" publish = false [dependencies] -solana-account-info = "=2.2.0" -solana-program-entrypoint = "=2.2.0" -solana-program-error = "=2.2.0" -solana-pubkey = "=2.2.0" +solana-account-info = "=2.3.0" +solana-program-entrypoint = "=2.2.1" +solana-program-error = "=2.2.2" +solana-pubkey = "=2.4.0" [lib] crate-type = ["cdylib"] diff --git a/platform-tools-sdk/cargo-test-sbf/Cargo.toml b/platform-tools-sdk/cargo-test-sbf/Cargo.toml index 80594997613f00..fa0fb2fe2cbc7c 100644 --- a/platform-tools-sdk/cargo-test-sbf/Cargo.toml +++ b/platform-tools-sdk/cargo-test-sbf/Cargo.toml @@ -9,6 +9,10 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[[bin]] +name = "cargo-test-sbf" +path = "src/main.rs" + [dependencies] cargo_metadata = { workspace = true } clap = { version = "3.1.5", features = ["cargo"] } @@ -16,7 +20,3 @@ itertools = { workspace = true } log = { workspace = true, features = ["std"] } regex = { workspace = true } solana-logger = "=2.3.1" - -[[bin]] -name = "cargo-test-sbf" -path = "src/main.rs" diff --git a/platform-tools-sdk/gen-headers/Cargo.toml b/platform-tools-sdk/gen-headers/Cargo.toml index 588bb11ee57c6d..35327f604fb828 100644 --- a/platform-tools-sdk/gen-headers/Cargo.toml +++ b/platform-tools-sdk/gen-headers/Cargo.toml @@ -8,10 +8,10 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -log = { workspace = true, features = ["std"] } -regex = { workspace = true } - [[bin]] name = "gen-headers" path = "src/main.rs" + +[dependencies] +log = { workspace = true, features = ["std"] } +regex = { workspace = true } diff --git a/poh-bench/Cargo.toml b/poh-bench/Cargo.toml index 77df7970107b91..e95e7a22a02cb4 100644 --- a/poh-bench/Cargo.toml +++ b/poh-bench/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] clap = { version = "3.1.5", features = ["cargo"] } log = { workspace = true } @@ -20,6 +23,3 @@ solana-perf = { workspace = true } solana-rayon-threadlimit = { workspace = true } solana-sha256-hasher = { workspace = true } solana-version = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/poh/Cargo.toml b/poh/Cargo.toml index ccffcdcdeec326..96abb25ac66a3e 100644 --- a/poh/Cargo.toml +++ b/poh/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_poh" + +[features] +dev-context-only-utils = [] + [dependencies] core_affinity = { workspace = true } crossbeam-channel = { workspace = true } @@ -30,6 +40,7 @@ thiserror = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } bincode = { workspace = true } +criterion = { workspace = true } rand = { workspace = true } solana-keypair = { workspace = true } solana-logger = { workspace = true } @@ -40,15 +51,9 @@ solana-sha256-hasher = { workspace = true } solana-signer = { workspace = true } solana-system-transaction = { workspace = true } -[features] -dev-context-only-utils = [] - -[lib] -crate-type = ["lib"] -name = "solana_poh" - [[bench]] name = "poh" -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +[[bench]] +name = "transaction_recorder" +harness = false diff --git a/poh/benches/poh.rs b/poh/benches/poh.rs index 5cbc4c164e4ca0..b12ac32ae8ab3b 100644 --- a/poh/benches/poh.rs +++ b/poh/benches/poh.rs @@ -111,15 +111,13 @@ fn bench_poh_recorder_record_transaction_index(bencher: &mut Bencher) { SanitizedTransaction::from_transaction_for_tests(test_tx()), ]; + let txs: Vec<_> = txs.iter().map(|tx| tx.to_versioned_transaction()).collect(); bencher.iter(|| { let _record_result = poh_recorder .record( bank.slot(), - test::black_box(h1), - test::black_box(&txs) - .iter() - .map(|tx| tx.to_versioned_transaction()) - .collect(), + vec![test::black_box(h1)], + vec![test::black_box(txs.clone())], ) .unwrap() .unwrap(); diff --git a/poh/benches/transaction_recorder.rs b/poh/benches/transaction_recorder.rs new file mode 100644 index 00000000000000..0b7d8e3489d8dc --- /dev/null +++ b/poh/benches/transaction_recorder.rs @@ -0,0 +1,129 @@ +use { + criterion::{criterion_group, criterion_main, Criterion}, + solana_hash::Hash, + solana_keypair::Keypair, + solana_ledger::{ + blockstore::Blockstore, genesis_utils::create_genesis_config, + get_tmp_ledger_path_auto_delete, leader_schedule_cache::LeaderScheduleCache, + }, + solana_poh::{ + poh_recorder::PohRecorder, + poh_service::{PohService, DEFAULT_HASHES_PER_BATCH, DEFAULT_PINNED_CPU_CORE}, + transaction_recorder::TransactionRecorder, + }, + solana_poh_config::PohConfig, + solana_pubkey::Pubkey, + solana_runtime::{bank::Bank, installed_scheduler_pool::BankWithScheduler}, + solana_transaction::versioned::VersionedTransaction, + std::{ + sync::{atomic::AtomicBool, Arc, RwLock}, + time::{Duration, Instant}, + }, +}; + +fn bench_record_transactions(c: &mut Criterion) { + // Relatively small non-zero number of transactions to use for the benchmark. + // Ensures we spend some time doing the hash work for entry recording. + const NUM_TRANSACTIONS: u64 = 16; + // Number of batches to process in each benchmark iteration. + // Each batch contains NUM_TRANSACTIONS transactions. + // This emulates a burst of work coming in from the scheduler. + const NUM_BATCHES: u64 = 32; + + // Setup the PohService. + let mut genesis_config_info = create_genesis_config(2); + genesis_config_info.genesis_config.ticks_per_slot = solana_clock::DEFAULT_TICKS_PER_SLOT; + genesis_config_info.genesis_config.poh_config = PohConfig { + target_tick_duration: Duration::from_micros( + solana_clock::DEFAULT_MS_PER_SLOT * 1_000 / solana_clock::DEFAULT_TICKS_PER_SLOT, + ), + target_tick_count: None, + hashes_per_tick: Some(solana_clock::DEFAULT_HASHES_PER_TICK), + }; + let exit = Arc::new(AtomicBool::new(false)); + let mut bank = Arc::new(Bank::new_for_tests(&genesis_config_info.genesis_config)); + let ledger_path = get_tmp_ledger_path_auto_delete!(); + let blockstore = Arc::new( + Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger"), + ); + let (mut poh_recorder, _entry_receiver) = PohRecorder::new( + bank.tick_height(), + bank.last_blockhash(), + bank.clone(), + None, + bank.ticks_per_slot(), + blockstore, + &Arc::new(LeaderScheduleCache::new_from_bank(&bank)), + &genesis_config_info.genesis_config.poh_config, + exit.clone(), + ); + poh_recorder.set_bank( + BankWithScheduler::new_without_scheduler(bank.clone()), + false, + ); + + let (record_sender, record_receiver) = crossbeam_channel::unbounded(); + let transaction_recorder = TransactionRecorder::new(record_sender, exit.clone()); + + let txs: Vec<_> = (0..NUM_TRANSACTIONS) + .map(|_| { + VersionedTransaction::from(solana_system_transaction::transfer( + &Keypair::new(), + &Pubkey::new_unique(), + 1, + Hash::new_unique(), + )) + }) + .collect(); + + let poh_recorder = Arc::new(RwLock::new(poh_recorder)); + let poh_service = PohService::new( + poh_recorder.clone(), + &genesis_config_info.genesis_config.poh_config, + exit.clone(), + bank.ticks_per_slot(), + DEFAULT_PINNED_CPU_CORE, + DEFAULT_HASHES_PER_BATCH, + record_receiver, + ); + + let mut group = c.benchmark_group("record_transactions"); + group.throughput(criterion::Throughput::Elements( + NUM_TRANSACTIONS * NUM_BATCHES, + )); + group.bench_function("record_transactions", |b| { + b.iter_custom(|iters| { + let mut total = Duration::ZERO; + + for _ in 0..iters { + let tx_batches: Vec<_> = (0..NUM_BATCHES).map(|_| txs.clone()).collect(); + poh_recorder.write().unwrap().clear_bank_for_test(); + bank = Arc::new(Bank::new_from_parent( + bank.clone(), + &Pubkey::default(), + bank.slot().wrapping_add(1), + )); + poh_recorder.write().unwrap().set_bank( + BankWithScheduler::new_without_scheduler(bank.clone()), + false, + ); + + let start = Instant::now(); + for txs in tx_batches { + let summary = transaction_recorder.record_transactions(bank.slot(), txs); + assert!(summary.result.is_ok()); + } + let elapsed = start.elapsed(); + total = total.saturating_add(elapsed); + } + + total + }) + }); + + exit.store(true, std::sync::atomic::Ordering::Relaxed); + poh_service.join().unwrap(); +} + +criterion_group!(benches, bench_record_transactions,); +criterion_main!(benches); diff --git a/poh/src/poh_recorder.rs b/poh/src/poh_recorder.rs index 99e648ec005d3b..cb9f3da5817291 100644 --- a/poh/src/poh_recorder.rs +++ b/poh/src/poh_recorder.rs @@ -20,7 +20,10 @@ use { crossbeam_channel::{unbounded, Receiver, SendError, Sender, TrySendError}, log::*, solana_clock::{Slot, NUM_CONSECUTIVE_LEADER_SLOTS}, - solana_entry::{entry::Entry, poh::Poh}, + solana_entry::{ + entry::Entry, + poh::{Poh, PohEntry}, + }, solana_hash::Hash, solana_ledger::{blockstore::Blockstore, leader_schedule_cache::LeaderScheduleCache}, solana_measure::measure_us, @@ -75,21 +78,21 @@ impl BankStart { type RecordResultSender = Sender>>; pub struct Record { - pub mixin: Hash, - pub transactions: Vec, + pub mixins: Vec, + pub transaction_batches: Vec>, pub slot: Slot, pub sender: RecordResultSender, } impl Record { pub fn new( - mixin: Hash, - transactions: Vec, + mixins: Vec, + transaction_batches: Vec>, slot: Slot, sender: RecordResultSender, ) -> Self { Self { - mixin, - transactions, + mixins, + transaction_batches, slot, sender, } @@ -188,6 +191,9 @@ pub struct PohRecorder { delay_leader_block_for_pending_fork: bool, last_reported_slot_for_pending_fork: Arc>, pub is_exited: Arc, + + // Allocation to hold PohEntrys recorded into PoHStream. + entries: Vec, } impl PohRecorder { @@ -272,6 +278,7 @@ impl PohRecorder { delay_leader_block_for_pending_fork, last_reported_slot_for_pending_fork: Arc::default(), is_exited, + entries: Vec::with_capacity(64), }, working_bank_receiver, ) @@ -294,12 +301,19 @@ impl PohRecorder { pub(crate) fn record( &mut self, bank_slot: Slot, - mixin: Hash, - transactions: Vec, + mixins: Vec, + transaction_batches: Vec>, ) -> Result> { // Entries without transactions are used to track real-time passing in the ledger and // cannot be generated by `record()` - assert!(!transactions.is_empty(), "No transactions provided"); + assert!( + mixins.len() == transaction_batches.len(), + "mismatched mixin and transaction batch lengths" + ); + assert!( + !transaction_batches.iter().any(|batch| batch.is_empty()), + "No transactions provided" + ); let ((), report_metrics_us) = measure_us!(self.metrics.report(bank_slot)); self.metrics.report_metrics_us += report_metrics_us; @@ -320,25 +334,35 @@ impl PohRecorder { let (mut poh_lock, poh_lock_us) = measure_us!(self.poh.lock().unwrap()); self.metrics.record_lock_contention_us += poh_lock_us; - let (record_mixin_res, record_mixin_us) = measure_us!(poh_lock.record(mixin)); + let (mixed_in, record_mixin_us) = + measure_us!(poh_lock.record_batches(&mixins, &mut self.entries)); self.metrics.record_us += record_mixin_us; drop(poh_lock); - if let Some(poh_entry) = record_mixin_res { - let num_transactions = transactions.len(); - let (send_entry_res, send_entry_us) = measure_us!({ - let entry = Entry { - num_hashes: poh_entry.num_hashes, - hash: poh_entry.hash, - transactions, - }; - let bank_clone = working_bank.bank.clone(); - self.working_bank_sender - .send((bank_clone, (entry, self.tick_height))) - }); - self.metrics.send_entry_us += send_entry_us; - send_entry_res?; + if mixed_in { + let num_transactions = transaction_batches + .iter() + .map(|batch| batch.len()) + .sum::(); + debug_assert_eq!(self.entries.len(), mixins.len()); + for (entry, transactions) in self.entries.drain(..).zip(transaction_batches) { + let (send_entry_res, send_batches_us) = + measure_us!(self.working_bank_sender.send(( + working_bank.bank.clone(), + ( + Entry { + num_hashes: entry.num_hashes, + hash: entry.hash, + transactions, + }, + self.tick_height, // `record_batches` guarantees that mixins are **not** split across ticks. + ), + ))); + self.metrics.send_entry_us += send_batches_us; + send_entry_res?; + } + let starting_transaction_index = working_bank.transaction_index.inspect(|transaction_index| { let next_starting_transaction_index = @@ -1203,7 +1227,7 @@ mod tests { // We haven't yet reached the minimum tick height for the working bank, // so record should fail assert_matches!( - poh_recorder.record(bank1.slot(), h1, vec![tx.into()]), + poh_recorder.record(bank1.slot(), vec![h1], vec![vec![tx.into()]]), Err(PohRecorderError::MinHeightNotReached) ); assert!(entry_receiver.try_recv().is_err()); @@ -1242,7 +1266,7 @@ mod tests { // However we hand over a bad slot so record fails let bad_slot = bank.slot() + 1; assert_matches!( - poh_recorder.record(bad_slot, h1, vec![tx.into()]), + poh_recorder.record(bad_slot, vec![h1], vec![vec![tx.into()]]), Err(PohRecorderError::MaxHeightReached) ); } @@ -1285,7 +1309,7 @@ mod tests { let tx = test_tx(); let h1 = hash(b"hello world!"); assert!(poh_recorder - .record(bank1.slot(), h1, vec![tx.into()]) + .record(bank1.slot(), vec![h1], vec![vec![tx.into()]]) .is_ok()); assert_eq!(poh_recorder.tick_cache.len(), 0); @@ -1327,7 +1351,7 @@ mod tests { let tx = test_tx(); let h1 = hash(b"hello world!"); assert!(poh_recorder - .record(bank.slot(), h1, vec![tx.into()]) + .record(bank.slot(), vec![h1], vec![vec![tx.into()]]) .is_err()); for _ in 0..num_ticks_to_max { let (_bank, (entry, _tick_height)) = entry_receiver.recv().unwrap(); @@ -1371,7 +1395,7 @@ mod tests { let tx1 = test_tx(); let h1 = hash(b"hello world!"); let record_result = poh_recorder - .record(bank.slot(), h1, vec![tx0.into(), tx1.into()]) + .record(bank.slot(), vec![h1], vec![vec![tx0.into(), tx1.into()]]) .unwrap() .unwrap(); assert_eq!(record_result, 0); @@ -1388,7 +1412,7 @@ mod tests { let tx = test_tx(); let h2 = hash(b"foobar"); let record_result = poh_recorder - .record(bank.slot(), h2, vec![tx.into()]) + .record(bank.slot(), vec![h2], vec![vec![tx.into()]]) .unwrap() .unwrap(); assert_eq!(record_result, 2); @@ -1625,7 +1649,7 @@ mod tests { let tx = test_tx(); let h1 = hash(b"hello world!"); assert!(poh_recorder - .record(bank.slot(), h1, vec![tx.into()]) + .record(bank.slot(), vec![h1], vec![vec![tx.into()]]) .is_err()); assert!(poh_recorder.working_bank.is_none()); diff --git a/poh/src/poh_service.rs b/poh/src/poh_service.rs index 2e353c4b1b5487..f10ba29620beae 100644 --- a/poh/src/poh_service.rs +++ b/poh/src/poh_service.rs @@ -197,8 +197,8 @@ impl PohService { .sender .send(poh_recorder.write().unwrap().record( record.slot, - record.mixin, - record.transactions, + record.mixins, + record.transaction_batches, )) .is_err() { @@ -260,8 +260,8 @@ impl PohService { loop { let res = poh_recorder_l.record( record.slot, - record.mixin, - std::mem::take(&mut record.transactions), + record.mixins, + std::mem::take(&mut record.transaction_batches), ); let (send_res, send_record_result_us) = measure_us!(record.sender.send(res)); debug_assert!(send_res.is_ok(), "Record wasn't sent."); @@ -464,11 +464,11 @@ mod tests { loop { // send some data let mut time = Measure::start("record"); - let res = - poh_recorder - .write() - .unwrap() - .record(bank.slot(), h1, vec![tx.clone()]); + let res = poh_recorder.write().unwrap().record( + bank.slot(), + vec![h1], + vec![vec![tx.clone()]], + ); if let Err(MaxHeightReached) = res { // Advance to the next slot. poh_recorder diff --git a/poh/src/transaction_recorder.rs b/poh/src/transaction_recorder.rs index 2a5089daddff97..bf088597fce21b 100644 --- a/poh/src/transaction_recorder.rs +++ b/poh/src/transaction_recorder.rs @@ -70,7 +70,8 @@ impl TransactionRecorder { let (hash, hash_us) = measure_us!(hash_transactions(&transactions)); record_transactions_timings.hash_us = Saturating(hash_us); - let (res, poh_record_us) = measure_us!(self.record(bank_slot, hash, transactions)); + let (res, poh_record_us) = + measure_us!(self.record(bank_slot, vec![hash], vec![transactions])); record_transactions_timings.poh_record_us = Saturating(poh_record_us); match res { @@ -106,14 +107,17 @@ impl TransactionRecorder { pub fn record( &self, bank_slot: Slot, - mixin: Hash, - transactions: Vec, + mixins: Vec, + transaction_batches: Vec>, ) -> Result> { // create a new channel so that there is only 1 sender and when it goes out of scope, the receiver fails let (result_sender, result_receiver) = bounded(1); - let res = - self.record_sender - .send(Record::new(mixin, transactions, bank_slot, result_sender)); + let res = self.record_sender.send(Record::new( + mixins, + transaction_batches, + bank_slot, + result_sender, + )); if res.is_err() { // If the channel is dropped, then the validator is shutting down so return that we are hitting // the max tick height to stop transaction processing and flush any transactions in the pipeline. diff --git a/poseidon/Cargo.toml b/poseidon/Cargo.toml index 021bf76716d03a..7b41042855b9ec 100644 --- a/poseidon/Cargo.toml +++ b/poseidon/Cargo.toml @@ -9,18 +9,18 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] thiserror = { workspace = true } -[target.'cfg(target_os = "solana")'.dependencies] -solana-define-syscall = { workspace = true } - [target.'cfg(not(target_os = "solana"))'.dependencies] ark-bn254 = { workspace = true } light-poseidon = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +[target.'cfg(target_os = "solana")'.dependencies] +solana-define-syscall = { workspace = true } [lints] workspace = true diff --git a/precompiles/Cargo.toml b/precompiles/Cargo.toml index aa30d02161ab8b..c2a5a854af7696 100644 --- a/precompiles/Cargo.toml +++ b/precompiles/Cargo.toml @@ -9,6 +9,11 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + [dependencies] agave-feature-set = { workspace = true } bincode = { workspace = true } @@ -34,10 +39,5 @@ solana-keccak-hasher = { workspace = true } solana-logger = { workspace = true } solana-secp256k1-program = { workspace = true, features = ["bincode"] } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] -all-features = true -rustdoc-args = ["--cfg=docsrs"] - [lints] workspace = true diff --git a/precompiles/benches/ed25519_instructions.rs b/precompiles/benches/ed25519_instructions.rs index b93f6402b2424a..18fcc7d5022e82 100644 --- a/precompiles/benches/ed25519_instructions.rs +++ b/precompiles/benches/ed25519_instructions.rs @@ -4,8 +4,9 @@ extern crate test; use { agave_feature_set::FeatureSet, agave_precompiles::ed25519::verify, + ed25519_dalek::ed25519::signature::Signer, rand0_7::{thread_rng, Rng}, - solana_ed25519_program::new_ed25519_instruction, + solana_ed25519_program::new_ed25519_instruction_with_signature, solana_instruction::Instruction, test::Bencher, }; @@ -20,7 +21,9 @@ fn create_test_instructions(message_length: u16) -> Vec { let mut rng = thread_rng(); let privkey = ed25519_dalek::Keypair::generate(&mut rng); let message: Vec = (0..message_length).map(|_| rng.gen_range(0, 255)).collect(); - new_ed25519_instruction(&privkey, &message) + let signature = privkey.sign(&message).to_bytes(); + let pubkey = privkey.public.to_bytes(); + new_ed25519_instruction_with_signature(&message, &signature, &pubkey) }) .collect() } diff --git a/precompiles/benches/secp256r1_instructions.rs b/precompiles/benches/secp256r1_instructions.rs index 9ab7c1402b0067..7583143ec732e3 100644 --- a/precompiles/benches/secp256r1_instructions.rs +++ b/precompiles/benches/secp256r1_instructions.rs @@ -5,12 +5,13 @@ use { agave_feature_set::FeatureSet, agave_precompiles::secp256r1::verify, openssl::{ + bn::BigNumContext, ec::{EcGroup, EcKey}, nid::Nid, }, rand0_7::{thread_rng, Rng}, solana_instruction::Instruction, - solana_secp256r1_program::new_secp256r1_instruction, + solana_secp256r1_program::{new_secp256r1_instruction_with_signature, sign_message}, test::Bencher, }; @@ -25,7 +26,22 @@ fn create_test_instructions(message_length: u16) -> Vec { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let secp_privkey = EcKey::generate(&group).unwrap(); let message: Vec = (0..message_length).map(|_| rng.gen_range(0, 255)).collect(); - new_secp256r1_instruction(&message, secp_privkey).unwrap() + let signature = + sign_message(&message, &secp_privkey.private_key_to_der().unwrap()).unwrap(); + let mut ctx = BigNumContext::new().unwrap(); + let pubkey = secp_privkey + .public_key() + .to_bytes( + &group, + openssl::ec::PointConversionForm::COMPRESSED, + &mut ctx, + ) + .unwrap(); + new_secp256r1_instruction_with_signature( + &message, + &signature, + &pubkey.try_into().unwrap(), + ) }) .collect() } diff --git a/precompiles/src/ed25519.rs b/precompiles/src/ed25519.rs index 9ddc52d91daf7d..6325d5267ef238 100644 --- a/precompiles/src/ed25519.rs +++ b/precompiles/src/ed25519.rs @@ -121,7 +121,7 @@ pub mod tests { hex, rand0_7::{thread_rng, Rng}, solana_ed25519_program::{ - new_ed25519_instruction, offsets_to_ed25519_instruction, DATA_START, + new_ed25519_instruction_with_signature, offsets_to_ed25519_instruction, DATA_START, }, solana_instruction::Instruction, std::vec, @@ -341,7 +341,10 @@ pub mod tests { let privkey = ed25519_dalek::Keypair::generate(&mut thread_rng()); let message_arr = b"hello"; - let mut instruction = new_ed25519_instruction(&privkey, message_arr); + let signature = privkey.sign(message_arr).to_bytes(); + let pubkey = privkey.public.to_bytes(); + let mut instruction = + new_ed25519_instruction_with_signature(message_arr, &signature, &pubkey); let feature_set = FeatureSet::all_enabled(); assert!(test_verify_with_alignment( @@ -446,7 +449,9 @@ pub mod tests { // sig created via ed25519_dalek: both pass let privkey = ed25519_dalek::Keypair::generate(&mut thread_rng()); let message_arr = b"hello"; - let instruction = new_ed25519_instruction(&privkey, message_arr); + let signature = privkey.sign(message_arr).to_bytes(); + let pubkey = privkey.public.to_bytes(); + let instruction = new_ed25519_instruction_with_signature(message_arr, &signature, &pubkey); let feature_set = FeatureSet::default(); assert!(test_verify_with_alignment( diff --git a/precompiles/src/secp256r1.rs b/precompiles/src/secp256r1.rs index 66e4018ac8a01b..bafe1d92bf6787 100644 --- a/precompiles/src/secp256r1.rs +++ b/precompiles/src/secp256r1.rs @@ -171,7 +171,9 @@ mod tests { super::*, crate::test_verify_with_alignment, bytemuck::bytes_of, - solana_secp256r1_program::{new_secp256r1_instruction, DATA_START, SECP256R1_ORDER}, + solana_secp256r1_program::{ + new_secp256r1_instruction_with_signature, sign_message, DATA_START, SECP256R1_ORDER, + }, }; fn test_case( @@ -360,7 +362,22 @@ mod tests { let message_arr = b"hello"; let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let signing_key = EcKey::generate(&group).unwrap(); - let mut instruction = new_secp256r1_instruction(message_arr, signing_key).unwrap(); + let signature = + sign_message(message_arr, &signing_key.private_key_to_der().unwrap()).unwrap(); + let mut ctx = BigNumContext::new().unwrap(); + let pubkey = signing_key + .public_key() + .to_bytes( + &group, + openssl::ec::PointConversionForm::COMPRESSED, + &mut ctx, + ) + .unwrap(); + let mut instruction = new_secp256r1_instruction_with_signature( + message_arr, + &signature, + &pubkey.try_into().unwrap(), + ); let feature_set = FeatureSet::all_enabled(); assert!(test_verify_with_alignment( @@ -392,7 +409,22 @@ mod tests { let message_arr = b"hello"; let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let signing_key = EcKey::generate(&group).unwrap(); - let mut instruction = new_secp256r1_instruction(message_arr, signing_key).unwrap(); + let signature = + sign_message(message_arr, &signing_key.private_key_to_der().unwrap()).unwrap(); + let mut ctx = BigNumContext::new().unwrap(); + let pubkey = signing_key + .public_key() + .to_bytes( + &group, + openssl::ec::PointConversionForm::COMPRESSED, + &mut ctx, + ) + .unwrap(); + let mut instruction = new_secp256r1_instruction_with_signature( + message_arr, + &signature, + &pubkey.try_into().unwrap(), + ); // To double check that the untampered low-S value signature passes let feature_set = FeatureSet::all_enabled(); @@ -436,7 +468,22 @@ mod tests { // Keep generating signatures until we get one with a 31-byte component loop { - let instruction = new_secp256r1_instruction(message_arr, signing_key.clone()).unwrap(); + let signature = + sign_message(message_arr, &signing_key.private_key_to_der().unwrap()).unwrap(); + let mut ctx = BigNumContext::new().unwrap(); + let pubkey = signing_key + .public_key() + .to_bytes( + &group, + openssl::ec::PointConversionForm::COMPRESSED, + &mut ctx, + ) + .unwrap(); + let instruction = new_secp256r1_instruction_with_signature( + message_arr, + &signature, + &pubkey.try_into().unwrap(), + ); // Extract r and s from the signature let signature_offset = DATA_START + COMPRESSED_PUBKEY_SERIALIZED_SIZE; @@ -465,18 +512,6 @@ mod tests { } } - #[test] - fn test_new_secp256r1_instruction_signing_key() { - solana_logger::setup(); - let message_arr = b"hello"; - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); - let signing_key = EcKey::generate(&group).unwrap(); - assert!(new_secp256r1_instruction(message_arr, signing_key).is_ok()); - - let incorrect_group = EcGroup::from_curve_name(Nid::X9_62_PRIME192V1).unwrap(); - let incorrect_key = EcKey::generate(&incorrect_group).unwrap(); - assert!(new_secp256r1_instruction(message_arr, incorrect_key).is_err()); - } #[test] fn test_secp256r1_order() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); diff --git a/program-runtime/Cargo.toml b/program-runtime/Cargo.toml index 72188a3e721cd4..aba0cc661f98bd 100644 --- a/program-runtime/Cargo.toml +++ b/program-runtime/Cargo.toml @@ -9,6 +9,20 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_program_runtime" + +[features] +dev-context-only-utils = [] +dummy-for-ci-check = ["metrics"] +frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] +metrics = ["dep:solana-metrics"] +shuttle-test = ["solana-type-overrides/shuttle-test", "solana-sbpf/shuttle-test"] + [dependencies] base64 = { workspace = true } bincode = { workspace = true } @@ -63,25 +77,5 @@ solana-transaction-context = { workspace = true, features = [ ] } test-case = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_program_runtime" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [] -dummy-for-ci-check = ["metrics"] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", -] -metrics = ["dep:solana-metrics"] -shuttle-test = [ - "solana-type-overrides/shuttle-test", - "solana-sbpf/shuttle-test", -] - [lints] workspace = true diff --git a/program-test/Cargo.toml b/program-test/Cargo.toml index bbe0f0424cd5d2..2ae9c86fab9663 100644 --- a/program-test/Cargo.toml +++ b/program-test/Cargo.toml @@ -27,7 +27,6 @@ solana-banks-server = { workspace = true } solana-clock = { workspace = true } solana-commitment-config = { workspace = true } solana-compute-budget = { workspace = true } -solana-cpi = { workspace = true } solana-epoch-rewards = { workspace = true } solana-epoch-schedule = { workspace = true } solana-fee-calculator = { workspace = true } @@ -49,9 +48,7 @@ solana-pubkey = { workspace = true } solana-rent = { workspace = true } solana-runtime = { workspace = true } solana-sbpf = { workspace = true } -solana-sdk = { workspace = true } solana-sdk-ids = { workspace = true } -solana-sdk-macro = { workspace = true } solana-signer = { workspace = true } solana-stable-layout = { workspace = true } solana-stake-interface = { workspace = true } @@ -69,5 +66,7 @@ thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } [dev-dependencies] +solana-cpi = { workspace = true } +solana-program = { workspace = true } solana-stake-program = { workspace = true } test-case = { workspace = true } diff --git a/program-test/src/lib.rs b/program-test/src/lib.rs index e947fb2c4612bd..8c81300f6db808 100644 --- a/program-test/src/lib.rs +++ b/program-test/src/lib.rs @@ -365,7 +365,7 @@ impl solana_sysvar::program_stubs::SyscallStubs for SyscallStubs { // Resize account_info data if account_info.data_len() != new_len { - account_info.realloc(new_len, false)?; + account_info.resize(new_len)?; } // Clone the data diff --git a/program-test/src/programs.rs b/program-test/src/programs.rs index a4e5183db4d26a..cfe3a4c1cd422d 100644 --- a/program-test/src/programs.rs +++ b/program-test/src/programs.rs @@ -7,10 +7,10 @@ use { }; mod spl_memo_1_0 { - solana_sdk_macro::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo"); + solana_pubkey::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo"); } mod spl_memo_3_0 { - solana_sdk_macro::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"); + solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"); } static SPL_PROGRAMS: &[(Pubkey, Pubkey, &[u8])] = &[ diff --git a/program-test/tests/cpi.rs b/program-test/tests/cpi.rs index 399820f346a3ec..36feba6352a9b4 100644 --- a/program-test/tests/cpi.rs +++ b/program-test/tests/cpi.rs @@ -1,14 +1,13 @@ use { solana_account_info::{next_account_info, AccountInfo}, - solana_cpi::invoke, solana_instruction::{AccountMeta, Instruction}, solana_keypair::Keypair, solana_msg::msg, + solana_program::{instruction::get_stack_height, program::invoke}, solana_program_entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE}, solana_program_test::{processor, ProgramTest}, solana_pubkey::Pubkey, solana_rent::Rent, - solana_sdk::instruction::get_stack_height, solana_signer::Signer, solana_system_interface::{instruction as system_instruction, program as system_program}, solana_sysvar::Sysvar, diff --git a/program-test/tests/realloc.rs b/program-test/tests/realloc.rs index 6fc6fffa3cd520..6b26c4b1fab73c 100644 --- a/program-test/tests/realloc.rs +++ b/program-test/tests/realloc.rs @@ -1,8 +1,8 @@ use { solana_account_info::{next_account_info, AccountInfo}, - solana_cpi::invoke, solana_instruction::{AccountMeta, Instruction}, solana_keypair::Keypair, + solana_program::program::invoke, solana_program_error::ProgramResult, solana_program_test::{processor, ProgramTest}, solana_pubkey::Pubkey, diff --git a/program-test/tests/return_data.rs b/program-test/tests/return_data.rs index 9e030e5d8f1671..c3fcf576c73ce4 100644 --- a/program-test/tests/return_data.rs +++ b/program-test/tests/return_data.rs @@ -5,10 +5,10 @@ use { solana_commitment_config::CommitmentLevel, solana_instruction::{AccountMeta, Instruction}, solana_msg::msg, + solana_program::program::{get_return_data, invoke, set_return_data}, solana_program_error::{ProgramError, ProgramResult}, solana_program_test::{processor, ProgramTest}, solana_pubkey::Pubkey, - solana_sdk::program::{get_return_data, invoke, set_return_data}, solana_signer::Signer, solana_transaction::Transaction, solana_transaction_context::TransactionReturnData, diff --git a/programs/bpf-loader-tests/Cargo.toml b/programs/bpf-loader-tests/Cargo.toml index f87a459f84e347..46e1def4e0d4cd 100644 --- a/programs/bpf-loader-tests/Cargo.toml +++ b/programs/bpf-loader-tests/Cargo.toml @@ -11,6 +11,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dev-dependencies] assert_matches = { workspace = true } bincode = { workspace = true } @@ -26,6 +29,3 @@ solana-signer = { workspace = true } solana-system-interface = { workspace = true } solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index e100cb92aa6bc8..074374745db3ba 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -9,6 +9,23 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_bpf_loader_program" + +[features] +default = ["metrics"] +metrics = ["solana-program-runtime/metrics"] +shuttle-test = [ + "solana-type-overrides/shuttle-test", + "solana-program-runtime/shuttle-test", + "solana-sbpf/shuttle-test", +] +svm-internal = [] + [dependencies] bincode = { workspace = true } libsecp256k1 = { workspace = true } @@ -69,10 +86,6 @@ solana-transaction-context = { workspace = true, features = ["dev-context-only-u static_assertions = { workspace = true } test-case = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_bpf_loader_program" - [[bench]] name = "serialization" harness = false @@ -80,16 +93,3 @@ harness = false [[bench]] name = "bpf_loader_upgradeable" harness = false - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -default = ["metrics"] -metrics = ["solana-program-runtime/metrics"] -shuttle-test = [ - "solana-type-overrides/shuttle-test", - "solana-program-runtime/shuttle-test", - "solana-sbpf/shuttle-test" -] -svm-internal = [] diff --git a/programs/bpf_loader/benches/bpf_loader_upgradeable.rs b/programs/bpf_loader/benches/bpf_loader_upgradeable.rs index efd8bada6904f9..23ee2f26ade4f5 100644 --- a/programs/bpf_loader/benches/bpf_loader_upgradeable.rs +++ b/programs/bpf_loader/benches/bpf_loader_upgradeable.rs @@ -3,12 +3,12 @@ use { solana_account::{state_traits::StateMut, AccountSharedData}, solana_bpf_loader_program::Entrypoint, solana_instruction::AccountMeta, - solana_program::{ - bpf_loader_upgradeable::{self, UpgradeableLoaderState}, - loader_upgradeable_instruction::UpgradeableLoaderInstruction, + solana_loader_v3_interface::{ + instruction::UpgradeableLoaderInstruction, state::UpgradeableLoaderState, }, solana_program_runtime::invoke_context::mock_process_instruction, solana_pubkey::Pubkey, + solana_sdk_ids::bpf_loader_upgradeable, }; #[derive(Default)] diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index cddd9a14079a3d..3553edad4885cf 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -1368,7 +1368,7 @@ fn common_extend_program( const PROGRAM_DATA_ACCOUNT_INDEX: IndexOfAccount = 0; const PROGRAM_ACCOUNT_INDEX: IndexOfAccount = 1; const AUTHORITY_ACCOUNT_INDEX: IndexOfAccount = 2; - // let system_program_account_index = if check_authority { 3 } else { 2 }; + // The unused `system_program_account_index` is 3 if `check_authority` and 2 otherwise. let optional_payer_account_index = if check_authority { 4 } else { 3 }; if additional_bytes == 0 { diff --git a/programs/bpf_loader/src/syscalls/cpi.rs b/programs/bpf_loader/src/syscalls/cpi.rs index 256c4a530752c9..ce92e6fa991e85 100644 --- a/programs/bpf_loader/src/syscalls/cpi.rs +++ b/programs/bpf_loader/src/syscalls/cpi.rs @@ -9,25 +9,10 @@ use { solana_transaction_context::BorrowedAccount, std::{mem, ptr}, }; -// consts inlined to avoid solana-program dep + const MAX_CPI_INSTRUCTION_DATA_LEN: u64 = 10 * 1024; -#[cfg(test)] -static_assertions::const_assert_eq!( - MAX_CPI_INSTRUCTION_DATA_LEN, - solana_program::syscalls::MAX_CPI_INSTRUCTION_DATA_LEN -); const MAX_CPI_INSTRUCTION_ACCOUNTS: u8 = u8::MAX; -#[cfg(test)] -static_assertions::const_assert_eq!( - MAX_CPI_INSTRUCTION_ACCOUNTS, - solana_program::syscalls::MAX_CPI_INSTRUCTION_ACCOUNTS -); const MAX_CPI_ACCOUNT_INFOS: usize = 128; -#[cfg(test)] -static_assertions::const_assert_eq!( - MAX_CPI_ACCOUNT_INFOS, - solana_program::syscalls::MAX_CPI_ACCOUNT_INFOS -); fn check_account_info_pointer( invoke_context: &InvokeContext, @@ -168,8 +153,7 @@ impl<'a> CallerAccount<'a> { return Err(SyscallError::InvalidPointer.into()); } } - let host_len_addr = - translate(memory_mapping, AccessType::Store, vm_len_addr, 8)? as *mut u64; + let ref_to_len_in_vm = translate_type_mut::(memory_mapping, vm_len_addr, false)?; let vm_data_addr = data.as_ptr() as u64; let serialized_data = if direct_mapping { @@ -194,9 +178,7 @@ impl<'a> CallerAccount<'a> { invoke_context.get_check_aligned(), )? }; - (serialized_data, vm_data_addr, unsafe { - &mut *host_len_addr - }) + (serialized_data, vm_data_addr, ref_to_len_in_vm) }; Ok(CallerAccount { @@ -291,12 +273,7 @@ impl<'a> CallerAccount<'a> { let vm_len_addr = vm_addr .saturating_add(&account_info.data_len as *const u64 as u64) .saturating_sub(account_info as *const _ as *const u64 as u64); - let host_len_addr = translate( - memory_mapping, - AccessType::Store, - vm_len_addr, - size_of::() as u64, - )?; + let ref_to_len_in_vm = translate_type_mut::(memory_mapping, vm_len_addr, false)?; Ok(CallerAccount { lamports, @@ -304,7 +281,7 @@ impl<'a> CallerAccount<'a> { original_data_len: account_metadata.original_data_len, serialized_data, vm_data_addr: account_info.data_addr, - ref_to_len_in_vm: unsafe { &mut *(host_len_addr as *mut u64) }, + ref_to_len_in_vm, }) } @@ -467,7 +444,7 @@ impl SyscallInvokeSigned for SyscallInvokeSignedRust { ) -> Result, Error> { let mut signers = Vec::new(); if signers_seeds_len > 0 { - let signers_seeds = translate_slice_of_slices::>( + let signers_seeds = translate_slice::>>( memory_mapping, signers_seeds_addr, signers_seeds_len, @@ -477,7 +454,7 @@ impl SyscallInvokeSigned for SyscallInvokeSignedRust { return Err(Box::new(SyscallError::TooManySigners)); } for signer_seeds in signers_seeds.iter() { - let untranslated_seeds = translate_slice_of_slices::( + let untranslated_seeds = translate_slice::>( memory_mapping, signer_seeds.ptr(), signer_seeds.len(), diff --git a/programs/bpf_loader/src/syscalls/logging.rs b/programs/bpf_loader/src/syscalls/logging.rs index a30e97c8489537..fc89cf5e321a8d 100644 --- a/programs/bpf_loader/src/syscalls/logging.rs +++ b/programs/bpf_loader/src/syscalls/logging.rs @@ -120,7 +120,7 @@ declare_builtin_function!( consume_compute_meter(invoke_context, execution_cost.syscall_base_cost)?; - let untranslated_fields = translate_slice_of_slices::( + let untranslated_fields = translate_slice::>( memory_mapping, addr, len, diff --git a/programs/bpf_loader/src/syscalls/mem_ops.rs b/programs/bpf_loader/src/syscalls/mem_ops.rs index 9be31712e364f3..7491f13d8ad333 100644 --- a/programs/bpf_loader/src/syscalls/mem_ops.rs +++ b/programs/bpf_loader/src/syscalls/mem_ops.rs @@ -108,11 +108,6 @@ declare_builtin_function!( n, invoke_context.get_check_aligned(), )?; - let cmp_result = translate_type_mut::( - memory_mapping, - cmp_result_addr, - invoke_context.get_check_aligned(), - )?; debug_assert_eq!(s1.len(), n as usize); debug_assert_eq!(s2.len(), n as usize); @@ -120,7 +115,13 @@ declare_builtin_function!( // memcmp is marked unsafe since it assumes that the inputs are at least // `n` bytes long. `s1` and `s2` are guaranteed to be exactly `n` bytes // long because `translate_slice` would have failed otherwise. - *cmp_result = unsafe { memcmp(s1, s2, n as usize) }; + let result = unsafe { memcmp(s1, s2, n as usize) }; + + *translate_type_mut::( + memory_mapping, + cmp_result_addr, + invoke_context.get_check_aligned(), + )? = result; } Ok(0) diff --git a/programs/bpf_loader/src/syscalls/mod.rs b/programs/bpf_loader/src/syscalls/mod.rs index 1d904a34500954..b8cd4071b4dd78 100644 --- a/programs/bpf_loader/src/syscalls/mod.rs +++ b/programs/bpf_loader/src/syscalls/mod.rs @@ -586,83 +586,77 @@ fn address_is_aligned(address: u64) -> bool { .expect("T to be non-zero aligned") } -fn translate( - memory_mapping: &MemoryMapping, - access_type: AccessType, - vm_addr: u64, - len: u64, -) -> Result { - memory_mapping - .map(access_type, vm_addr, len) - .map_err(|err| err.into()) - .into() +macro_rules! translate_inner { + ($memory_mapping:expr, $access_type:expr, $vm_addr:expr, $len:expr $(,)?) => { + Result::::from( + $memory_mapping + .map($access_type, $vm_addr, $len) + .map_err(|err| err.into()), + ) + }; } - -fn translate_type_inner<'a, T>( - memory_mapping: &MemoryMapping, - access_type: AccessType, - vm_addr: u64, - check_aligned: bool, -) -> Result<&'a mut T, Error> { - let host_addr = translate(memory_mapping, access_type, vm_addr, size_of::() as u64)?; - if !check_aligned { - Ok(unsafe { std::mem::transmute::(host_addr) }) - } else if !address_is_aligned::(host_addr) { - Err(SyscallError::UnalignedPointer.into()) - } else { - Ok(unsafe { &mut *(host_addr as *mut T) }) - } +macro_rules! translate_type_inner { + ($memory_mapping:expr, $access_type:expr, $vm_addr:expr, $T:ty, $check_aligned:expr $(,)?) => {{ + let host_addr = translate_inner!( + $memory_mapping, + $access_type, + $vm_addr, + size_of::<$T>() as u64 + )?; + if !$check_aligned { + Ok(unsafe { std::mem::transmute::(host_addr) }) + } else if !address_is_aligned::<$T>(host_addr) { + Err(SyscallError::UnalignedPointer.into()) + } else { + Ok(unsafe { &mut *(host_addr as *mut $T) }) + } + }}; +} +macro_rules! translate_slice_inner { + ($memory_mapping:expr, $access_type:expr, $vm_addr:expr, $len:expr, $T:ty, $check_aligned:expr $(,)?) => {{ + if $len == 0 { + return Ok(&mut []); + } + let total_size = $len.saturating_mul(size_of::<$T>() as u64); + if isize::try_from(total_size).is_err() { + return Err(SyscallError::InvalidLength.into()); + } + let host_addr = translate_inner!($memory_mapping, $access_type, $vm_addr, total_size)?; + if $check_aligned && !address_is_aligned::<$T>(host_addr) { + return Err(SyscallError::UnalignedPointer.into()); + } + Ok(unsafe { from_raw_parts_mut(host_addr as *mut $T, $len as usize) }) + }}; } + fn translate_type_mut<'a, T>( memory_mapping: &MemoryMapping, vm_addr: u64, check_aligned: bool, ) -> Result<&'a mut T, Error> { - translate_type_inner::(memory_mapping, AccessType::Store, vm_addr, check_aligned) + translate_type_inner!(memory_mapping, AccessType::Store, vm_addr, T, check_aligned) } fn translate_type<'a, T>( memory_mapping: &MemoryMapping, vm_addr: u64, check_aligned: bool, ) -> Result<&'a T, Error> { - translate_type_inner::(memory_mapping, AccessType::Load, vm_addr, check_aligned) + translate_type_inner!(memory_mapping, AccessType::Load, vm_addr, T, check_aligned) .map(|value| &*value) } -fn translate_slice_inner<'a, T>( - memory_mapping: &MemoryMapping, - access_type: AccessType, - vm_addr: u64, - len: u64, - check_aligned: bool, -) -> Result<&'a mut [T], Error> { - if len == 0 { - return Ok(&mut []); - } - - let total_size = len.saturating_mul(size_of::() as u64); - if isize::try_from(total_size).is_err() { - return Err(SyscallError::InvalidLength.into()); - } - - let host_addr = translate(memory_mapping, access_type, vm_addr, total_size)?; - - if check_aligned && !address_is_aligned::(host_addr) { - return Err(SyscallError::UnalignedPointer.into()); - } - Ok(unsafe { from_raw_parts_mut(host_addr as *mut T, len as usize) }) -} fn translate_slice_mut<'a, T>( memory_mapping: &MemoryMapping, vm_addr: u64, len: u64, check_aligned: bool, ) -> Result<&'a mut [T], Error> { - translate_slice_inner::( + translate_slice_inner!( memory_mapping, AccessType::Store, vm_addr, len, + T, check_aligned, ) } @@ -672,67 +666,12 @@ fn translate_slice<'a, T>( len: u64, check_aligned: bool, ) -> Result<&'a [T], Error> { - translate_slice_inner::( - memory_mapping, - AccessType::Load, - vm_addr, - len, - check_aligned, - ) - .map(|value| &*value) -} - -fn translate_slice_of_slices_inner<'a, T>( - memory_mapping: &MemoryMapping, - access_type: AccessType, - vm_addr: u64, - len: u64, - check_aligned: bool, -) -> Result<&'a mut [VmSlice], Error> { - if len == 0 { - return Ok(&mut []); - } - - let total_size = len.saturating_mul(size_of::>() as u64); - if isize::try_from(total_size).is_err() { - return Err(SyscallError::InvalidLength.into()); - } - - let host_addr = translate(memory_mapping, access_type, vm_addr, total_size)?; - - if check_aligned && !address_is_aligned::>(host_addr) { - return Err(SyscallError::UnalignedPointer.into()); - } - Ok(unsafe { from_raw_parts_mut(host_addr as *mut VmSlice, len as usize) }) -} - -#[allow(dead_code)] -fn translate_slice_of_slices_mut<'a, T>( - memory_mapping: &MemoryMapping, - vm_addr: u64, - len: u64, - check_aligned: bool, -) -> Result<&'a mut [VmSlice], Error> { - translate_slice_of_slices_inner::( - memory_mapping, - AccessType::Store, - vm_addr, - len, - check_aligned, - ) -} - -fn translate_slice_of_slices<'a, T>( - memory_mapping: &MemoryMapping, - vm_addr: u64, - len: u64, - check_aligned: bool, -) -> Result<&'a [VmSlice], Error> { - translate_slice_of_slices_inner::( + translate_slice_inner!( memory_mapping, AccessType::Load, vm_addr, len, + T, check_aligned, ) .map(|value| &*value) @@ -844,7 +783,7 @@ fn translate_and_check_program_address_inputs<'a>( check_aligned: bool, ) -> Result<(Vec<&'a [u8]>, &'a Pubkey), Error> { let untranslated_seeds = - translate_slice_of_slices::(memory_mapping, seeds_addr, seeds_len, check_aligned)?; + translate_slice::>(memory_mapping, seeds_addr, seeds_len, check_aligned)?; if untranslated_seeds.len() > MAX_SEEDS { return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into()); } @@ -980,6 +919,12 @@ declare_builtin_function!( let cost = invoke_context.get_execution_cost().secp256k1_recover_cost; consume_compute_meter(invoke_context, cost)?; + let secp256k1_recover_result = translate_slice_mut::( + memory_mapping, + result_addr, + SECP256K1_PUBLIC_KEY_LENGTH as u64, + invoke_context.get_check_aligned(), + )?; let hash = translate_slice::( memory_mapping, hash_addr, @@ -992,12 +937,6 @@ declare_builtin_function!( SECP256K1_SIGNATURE_LENGTH as u64, invoke_context.get_check_aligned(), )?; - let secp256k1_recover_result = translate_slice_mut::( - memory_mapping, - result_addr, - SECP256K1_PUBLIC_KEY_LENGTH as u64, - invoke_context.get_check_aligned(), - )?; let Ok(message) = libsecp256k1::Message::parse_slice(hash) else { return Ok(Secp256k1RecoverError::InvalidHash.into()); @@ -1493,6 +1432,11 @@ declare_builtin_function!( length, invoke_context.get_check_aligned(), )?; + let program_id_result = translate_type_mut::( + memory_mapping, + program_id_addr, + invoke_context.get_check_aligned(), + )?; let to_slice = return_data_result; let from_slice = return_data @@ -1503,12 +1447,6 @@ declare_builtin_function!( } to_slice.copy_from_slice(from_slice); - let program_id_result = translate_type_mut::( - memory_mapping, - program_id_addr, - invoke_context.get_check_aligned(), - )?; - if !is_nonoverlapping( to_slice.as_ptr() as usize, length as usize, @@ -1730,19 +1668,18 @@ declare_builtin_function!( consume_compute_meter(invoke_context, cost)?; - let input = translate_slice::( - memory_mapping, - input_addr, - input_size, - invoke_context.get_check_aligned(), - )?; - let call_result = translate_slice_mut::( memory_mapping, result_addr, output as u64, invoke_context.get_check_aligned(), )?; + let input = translate_slice::( + memory_mapping, + input_addr, + input_size, + invoke_context.get_check_aligned(), + )?; let calculation = match group_op { ALT_BN128_ADD => alt_bn128_addition, @@ -1904,7 +1841,7 @@ declare_builtin_function!( poseidon::HASH_BYTES as u64, invoke_context.get_check_aligned(), )?; - let inputs = translate_slice_of_slices::( + let inputs = translate_slice::>( memory_mapping, vals_addr, vals_len, @@ -1996,19 +1933,18 @@ declare_builtin_function!( consume_compute_meter(invoke_context, cost)?; - let input = translate_slice::( - memory_mapping, - input_addr, - input_size, - invoke_context.get_check_aligned(), - )?; - let call_result = translate_slice_mut::( memory_mapping, result_addr, output as u64, invoke_context.get_check_aligned(), )?; + let input = translate_slice::( + memory_mapping, + input_addr, + input_size, + invoke_context.get_check_aligned(), + )?; let simplify_alt_bn128_syscall_error_codes = invoke_context .get_feature_set() @@ -2114,7 +2050,7 @@ declare_builtin_function!( )?; let mut hasher = H::create_hasher(); if vals_len > 0 { - let vals = translate_slice_of_slices::( + let vals = translate_slice::>( memory_mapping, vals_addr, vals_len, @@ -2236,7 +2172,11 @@ mod tests { solana_slot_hashes::{self as slot_hashes, SlotHashes}, solana_stable_layout::stable_instruction::StableInstruction, solana_sysvar::stake_history::{self, StakeHistory, StakeHistoryEntry}, - std::{mem, str::FromStr}, + std::{ + hash::{DefaultHasher, Hash, Hasher}, + mem, + str::FromStr, + }, test_case::test_case, }; @@ -2312,11 +2252,11 @@ mod tests { for (ok, start, length, value) in cases { if ok { assert_eq!( - translate(&memory_mapping, AccessType::Load, start, length).unwrap(), + translate_inner!(&memory_mapping, AccessType::Load, start, length).unwrap(), value ) } else { - assert!(translate(&memory_mapping, AccessType::Load, start, length).is_err()) + assert!(translate_inner!(&memory_mapping, AccessType::Load, start, length).is_err()) } } } @@ -4590,7 +4530,7 @@ mod tests { #[test] fn test_create_program_address() { - // These tests duplicate the direct tests in solana_program::pubkey + // These tests duplicate the direct tests in solana_pubkey prepare_mockup!(invoke_context, program_id, bpf_loader::id()); let address = bpf_loader_upgradeable::id(); @@ -5094,4 +5034,185 @@ mod tests { assert_eq!(address_is_aligned::(address as u64), address == 0); } } + + #[test_case(0x100000004, 0x100000004, &[0x00, 0x00, 0x00, 0x00])] // Intra region match + #[test_case(0x100000003, 0x100000004, &[0xFF, 0xFF, 0xFF, 0xFF])] // Intra region down + #[test_case(0x100000005, 0x100000004, &[0x01, 0x00, 0x00, 0x00])] // Intra region up + #[test_case(0x100000004, 0x200000004, &[0x00, 0x00, 0x00, 0x00])] // Inter region match + #[test_case(0x100000003, 0x200000004, &[0xFF, 0xFF, 0xFF, 0xFF])] // Inter region down + #[test_case(0x100000005, 0x200000004, &[0x01, 0x00, 0x00, 0x00])] // Inter region up + fn test_memcmp_success(src_a: u64, src_b: u64, expected_result: &[u8; 4]) { + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); + let mem = (0..12).collect::>(); + let mut result_mem = vec![0; 4]; + let config = Config::default(); + let mut memory_mapping = MemoryMapping::new( + vec![ + MemoryRegion::new_readonly(&mem, 0x100000000), + MemoryRegion::new_readonly(&mem, 0x200000000), + MemoryRegion::new_writable(&mut result_mem, 0x300000000), + ], + &config, + SBPFVersion::V3, + ) + .unwrap(); + + let result = SyscallMemcmp::rust( + &mut invoke_context, + src_a, + src_b, + 4, + 0x300000000, + 0, + &mut memory_mapping, + ); + result.unwrap(); + assert_eq!(result_mem, expected_result); + } + + #[test_case(0x100000002, 0x100000004, 18245498089483734664)] // Down overlapping + #[test_case(0x100000004, 0x100000002, 6092969436446403628)] // Up overlapping + #[test_case(0x100000002, 0x100000006, 16598193894146733116)] // Down touching + #[test_case(0x100000006, 0x100000002, 8940776276357560353)] // Up touching + #[test_case(0x100000000, 0x100000008, 1288053912680171784)] // Down apart + #[test_case(0x100000008, 0x100000000, 4652742827052033592)] // Up apart + #[test_case(0x100000004, 0x200000004, 8833460765081683332)] // Down inter region + #[test_case(0x200000004, 0x100000004, 11837649335115988407)] // Up inter region + fn test_memmove_success(dst: u64, src: u64, expected_hash: u64) { + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); + let mut mem = (0..24).collect::>(); + let config = Config::default(); + let mut memory_mapping = MemoryMapping::new( + vec![ + MemoryRegion::new_writable(&mut mem[..12], 0x100000000), + MemoryRegion::new_writable(&mut mem[12..], 0x200000000), + ], + &config, + SBPFVersion::V3, + ) + .unwrap(); + + let result = + SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping); + result.unwrap(); + let mut hasher = DefaultHasher::new(); + mem.hash(&mut hasher); + assert_eq!(hasher.finish(), expected_hash); + } + + #[test_case(0x100000002, 0x00, 6070675560359421890)] + #[test_case(0x100000002, 0xFF, 3413209638111181029)] + fn test_memset_success(dst: u64, value: u64, expected_hash: u64) { + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); + let mut mem = (0..12).collect::>(); + let config = Config::default(); + let mut memory_mapping = MemoryMapping::new( + vec![MemoryRegion::new_writable(&mut mem, 0x100000000)], + &config, + SBPFVersion::V3, + ) + .unwrap(); + + let result = SyscallMemset::rust( + &mut invoke_context, + dst, + value, + 4, + 0, + 0, + &mut memory_mapping, + ); + result.unwrap(); + let mut hasher = DefaultHasher::new(); + mem.hash(&mut hasher); + assert_eq!(hasher.finish(), expected_hash); + } + + #[test_case(0x100000002, 0x100000004)] // Down overlapping + #[test_case(0x100000004, 0x100000002)] // Up overlapping + fn test_memcpy_overlapping(dst: u64, src: u64) { + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); + let mut mem = (0..12).collect::>(); + let config = Config::default(); + let mut memory_mapping = MemoryMapping::new( + vec![MemoryRegion::new_writable(&mut mem, 0x100000000)], + &config, + SBPFVersion::V3, + ) + .unwrap(); + + let result = + SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping); + assert_matches!( + result, + Result::Err(error) if error.downcast_ref::().unwrap() == &SyscallError::CopyOverlapping + ); + } + + #[test_case(0xFFFFFFFFF, 0x100000006, 0xFFFFFFFFF)] // Dst lower bound + #[test_case(0x100000010, 0x100000006, 0x100000010)] // Dst upper bound + #[test_case(0x100000002, 0xFFFFFFFFF, 0xFFFFFFFFF)] // Src lower bound + #[test_case(0x100000002, 0x100000010, 0x100000010)] // Src upper bound + fn test_memops_access_violation(dst: u64, src: u64, fault_address: u64) { + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); + let mut mem = (0..12).collect::>(); + let config = Config::default(); + let mut memory_mapping = MemoryMapping::new( + vec![MemoryRegion::new_writable(&mut mem, 0x100000000)], + &config, + SBPFVersion::V3, + ) + .unwrap(); + + let result = + SyscallMemcpy::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping); + assert_access_violation!(result, fault_address, 4); + let result = + SyscallMemmove::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping); + assert_access_violation!(result, fault_address, 4); + let result = + SyscallMemcmp::rust(&mut invoke_context, dst, src, 4, 0, 0, &mut memory_mapping); + assert_access_violation!(result, fault_address, 4); + } + + #[test_case(0xFFFFFFFFF)] // Dst lower bound + #[test_case(0x100000010)] // Dst upper bound + fn test_memset_access_violation(dst: u64) { + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); + let mut mem = (0..12).collect::>(); + let config = Config::default(); + let mut memory_mapping = MemoryMapping::new( + vec![MemoryRegion::new_writable(&mut mem, 0x100000000)], + &config, + SBPFVersion::V3, + ) + .unwrap(); + + let result = SyscallMemset::rust(&mut invoke_context, dst, 0, 4, 0, 0, &mut memory_mapping); + assert_access_violation!(result, dst, 4); + } + + #[test] + fn test_memcmp_result_access_violation() { + prepare_mockup!(invoke_context, program_id, bpf_loader::id()); + let mem = (0..12).collect::>(); + let config = Config::default(); + let mut memory_mapping = MemoryMapping::new( + vec![MemoryRegion::new_readonly(&mem, 0x100000000)], + &config, + SBPFVersion::V3, + ) + .unwrap(); + + let result = SyscallMemcmp::rust( + &mut invoke_context, + 0x100000000, + 0x100000000, + 4, + 0x100000000, + 0, + &mut memory_mapping, + ); + assert_access_violation!(result, 0x100000000, 4); + } } diff --git a/programs/bpf_loader/src/syscalls/sysvar.rs b/programs/bpf_loader/src/syscalls/sysvar.rs index d46cb504a59ab7..d7ce265debae15 100644 --- a/programs/bpf_loader/src/syscalls/sysvar.rs +++ b/programs/bpf_loader/src/syscalls/sysvar.rs @@ -196,12 +196,12 @@ declare_builtin_function!( .saturating_add(std::cmp::max(sysvar_buf_cost, mem_op_base_cost)), )?; - // Abort: "Not all bytes in VM memory range `[sysvar_id, sysvar_id + 32)` are readable." - let sysvar_id = translate_type::(memory_mapping, sysvar_id_addr, check_aligned)?; - // Abort: "Not all bytes in VM memory range `[var_addr, var_addr + length)` are writable." let var = translate_slice_mut::(memory_mapping, var_addr, length, check_aligned)?; + // Abort: "Not all bytes in VM memory range `[sysvar_id, sysvar_id + 32)` are readable." + let sysvar_id = translate_type::(memory_mapping, sysvar_id_addr, check_aligned)?; + // Abort: "`offset + length` is not in `[0, 2^64)`." let offset_length = offset .checked_add(length) diff --git a/programs/compute-budget-bench/Cargo.toml b/programs/compute-budget-bench/Cargo.toml index 49232a5627944a..e072e16e8306a6 100644 --- a/programs/compute-budget-bench/Cargo.toml +++ b/programs/compute-budget-bench/Cargo.toml @@ -8,6 +8,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] agave-feature-set = { workspace = true } criterion = { workspace = true } @@ -22,6 +25,3 @@ solana-svm-transaction = { workspace = true } [[bench]] name = "compute_budget" harness = false - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/compute-budget/Cargo.toml b/programs/compute-budget/Cargo.toml index 4a69c15a017a93..b8262283f40afd 100644 --- a/programs/compute-budget/Cargo.toml +++ b/programs/compute-budget/Cargo.toml @@ -9,12 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program-runtime = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [lib] crate-type = ["lib"] name = "solana_compute_budget_program" -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +[dependencies] +solana-program-runtime = { workspace = true } diff --git a/programs/ed25519-tests/Cargo.toml b/programs/ed25519-tests/Cargo.toml index 930ca7424ddbbc..07d5eebb592976 100644 --- a/programs/ed25519-tests/Cargo.toml +++ b/programs/ed25519-tests/Cargo.toml @@ -8,6 +8,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dev-dependencies] assert_matches = { workspace = true } ed25519-dalek = { workspace = true } @@ -19,6 +22,3 @@ solana-program-test = { workspace = true } solana-signer = { workspace = true } solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/ed25519-tests/tests/process_transaction.rs b/programs/ed25519-tests/tests/process_transaction.rs index acc790db02d67f..abe6e117d96d13 100644 --- a/programs/ed25519-tests/tests/process_transaction.rs +++ b/programs/ed25519-tests/tests/process_transaction.rs @@ -1,5 +1,6 @@ use { - assert_matches::assert_matches, solana_ed25519_program::new_ed25519_instruction, + assert_matches::assert_matches, ed25519_dalek::ed25519::signature::Signer as EdSigner, + solana_ed25519_program::new_ed25519_instruction_with_signature, solana_instruction::error::InstructionError, solana_precompile_error::PrecompileError, solana_program_test::*, solana_signer::Signer, solana_transaction::Transaction, solana_transaction_error::TransactionError, @@ -29,7 +30,9 @@ async fn test_success() { let privkey = generate_keypair(); let message_arr = b"hello"; - let instruction = new_ed25519_instruction(&privkey, message_arr); + let signature = privkey.sign(message_arr).to_bytes(); + let pubkey = privkey.public.to_bytes(); + let instruction = new_ed25519_instruction_with_signature(message_arr, &signature, &pubkey); let transaction = Transaction::new_signed_with_payer( &[instruction], @@ -51,7 +54,9 @@ async fn test_failure() { let privkey = generate_keypair(); let message_arr = b"hello"; - let mut instruction = new_ed25519_instruction(&privkey, message_arr); + let signature = privkey.sign(message_arr).to_bytes(); + let pubkey = privkey.public.to_bytes(); + let mut instruction = new_ed25519_instruction_with_signature(message_arr, &signature, &pubkey); instruction.data[0] += 1; diff --git a/programs/loader-v4/Cargo.toml b/programs/loader-v4/Cargo.toml index 8e1935e9bde57f..5aaaa6b012d567 100644 --- a/programs/loader-v4/Cargo.toml +++ b/programs/loader-v4/Cargo.toml @@ -8,6 +8,22 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_loader_v4_program" + +[features] +agave-unstable-api = [] +shuttle-test = [ + "solana-type-overrides/shuttle-test", + "solana-program-runtime/shuttle-test", + "solana-sbpf/shuttle-test", +] +svm-internal = [] + [dependencies] log = { workspace = true } qualifier_attr = { workspace = true } @@ -31,19 +47,3 @@ solana-type-overrides = { workspace = true } bincode = { workspace = true } solana-clock = { workspace = true } solana-sysvar = { workspace = true } - -[lib] -crate-type = ["lib"] -name = "solana_loader_v4_program" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -agave-unstable-api = [] -shuttle-test = [ - "solana-type-overrides/shuttle-test", - "solana-program-runtime/shuttle-test", - "solana-sbpf/shuttle-test" -] -svm-internal = [] diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 3a64bc31415203..dd5d7148fad732 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -65,7 +65,7 @@ dependencies = [ [[package]] name = "agave-banking-stage-ingress-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "solana-perf", @@ -73,7 +73,7 @@ dependencies = [ [[package]] name = "agave-feature-set" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "solana-epoch-schedule", @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "agave-geyser-plugin-interface" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-clock", @@ -97,7 +97,7 @@ dependencies = [ [[package]] name = "agave-precompiles" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -117,7 +117,7 @@ dependencies = [ [[package]] name = "agave-reserved-account-keys" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-pubkey", @@ -126,7 +126,7 @@ dependencies = [ [[package]] name = "agave-transaction-view" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-hash", "solana-message", @@ -140,7 +140,7 @@ dependencies = [ [[package]] name = "agave-validator" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-geyser-plugin-interface", "chrono", @@ -219,7 +219,7 @@ dependencies = [ [[package]] name = "agave-xdp" -version = "2.3.0" +version = "3.0.0" dependencies = [ "aya", "caps", @@ -770,7 +770,7 @@ dependencies = [ "bitflags 2.9.1", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "proc-macro2", @@ -844,7 +844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" dependencies = [ "borsh-derive 0.10.3", - "hashbrown 0.13.2", + "hashbrown 0.12.3", ] [[package]] @@ -2360,9 +2360,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hidapi" @@ -2471,9 +2471,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -2513,9 +2513,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -2570,7 +2570,7 @@ checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http 1.2.0", - "hyper 1.5.2", + "hyper 1.6.0", "hyper-util", "rustls 0.23.27", "rustls-pki-types", @@ -2607,16 +2607,21 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.2.0", "http-body 1.0.1", - "hyper 1.5.2", + "hyper 1.6.0", + "ipnet", + "libc", + "percent-encoding 2.3.1", "pin-project-lite", "socket2", "tokio", @@ -2888,9 +2893,19 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.0" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "itertools" @@ -3699,11 +3714,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.1", "libc", ] @@ -4607,7 +4622,7 @@ dependencies = [ "percent-encoding 2.3.1", "pin-project-lite", "rustls 0.21.12", - "rustls-pemfile 1.0.0", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -4628,9 +4643,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" dependencies = [ "async-compression", "base64 0.22.1", @@ -4641,7 +4656,7 @@ dependencies = [ "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.2", + "hyper 1.6.0", "hyper-rustls 0.27.5", "hyper-util", "ipnet", @@ -4653,7 +4668,6 @@ dependencies = [ "pin-project-lite", "quinn", "rustls 0.23.27", - "rustls-pemfile 2.1.3", "rustls-pki-types", "serde", "serde_json", @@ -4663,13 +4677,13 @@ dependencies = [ "tokio-rustls 0.26.2", "tokio-util 0.7.15", "tower 0.5.2", + "tower-http", "tower-service", "url 2.5.4", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.8", - "windows-registry", + "webpki-roots 1.0.0", ] [[package]] @@ -4681,7 +4695,7 @@ dependencies = [ "anyhow", "async-trait", "http 1.2.0", - "reqwest 0.12.15", + "reqwest 0.12.19", "serde", "thiserror 1.0.69", "tower-service", @@ -4850,16 +4864,6 @@ dependencies = [ "base64 0.13.1", ] -[[package]] -name = "rustls-pemfile" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.11.0" @@ -5286,9 +5290,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -5330,7 +5334,7 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "base64 0.22.1", @@ -5371,7 +5375,7 @@ dependencies = [ [[package]] name = "solana-account-decoder-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bs58", @@ -5385,9 +5389,9 @@ dependencies = [ [[package]] name = "solana-account-info" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c17d606a298a205fae325489fbed88ee6dc4463c111672172327e741c8905d" +checksum = "c8f5152a288ef1912300fc6efa6c2d1f9bb55d9398eb6c72326360b8063987da" dependencies = [ "bincode", "serde", @@ -5398,7 +5402,7 @@ dependencies = [ [[package]] name = "solana-accounts-db" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "bincode", @@ -5447,7 +5451,7 @@ dependencies = [ "solana-sysvar", "solana-time-utils", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "spl-generic-token", "static_assertions", @@ -5484,18 +5488,23 @@ dependencies = [ [[package]] name = "solana-banks-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "borsh 1.5.7", "futures 0.3.31", "solana-account", "solana-banks-interface", + "solana-clock", "solana-commitment-config", + "solana-hash", "solana-message", - "solana-program", + "solana-program-pack", + "solana-pubkey", + "solana-rent", "solana-signature", + "solana-sysvar", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "tarpc", "thiserror 2.0.12", @@ -5505,7 +5514,7 @@ dependencies = [ [[package]] name = "solana-banks-interface" -version = "2.3.0" +version = "3.0.0" dependencies = [ "serde", "serde_derive", @@ -5517,14 +5526,14 @@ dependencies = [ "solana-pubkey", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "tarpc", ] [[package]] name = "solana-banks-server" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -5586,7 +5595,7 @@ dependencies = [ [[package]] name = "solana-bloom" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bv", "fnv", @@ -5624,7 +5633,7 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "libsecp256k1 0.6.0", @@ -5639,7 +5648,7 @@ dependencies = [ "solana-bn254", "solana-clock", "solana-cpi", - "solana-curve25519", + "solana-curve25519 3.0.0", "solana-hash", "solana-instruction", "solana-keccak-hasher", @@ -5662,14 +5671,14 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "thiserror 2.0.12", ] [[package]] name = "solana-bucket-map" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bv", "bytemuck", @@ -5686,7 +5695,7 @@ dependencies = [ [[package]] name = "solana-builtins" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-bpf-loader-program", @@ -5705,7 +5714,7 @@ dependencies = [ [[package]] name = "solana-builtins-default-costs" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "ahash 0.8.11", @@ -5722,7 +5731,7 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "chrono", "clap", @@ -5749,7 +5758,7 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "2.3.0" +version = "3.0.0" dependencies = [ "dirs-next", "serde", @@ -5762,7 +5771,7 @@ dependencies = [ [[package]] name = "solana-cli-output" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "agave-reserved-account-keys", @@ -5787,11 +5796,11 @@ dependencies = [ "solana-message", "solana-native-token", "solana-packet", - "solana-program", "solana-pubkey", "solana-rpc-client-api", "solana-sdk-ids", "solana-signature", + "solana-stake-interface", "solana-system-interface", "solana-sysvar", "solana-transaction", @@ -5803,7 +5812,7 @@ dependencies = [ [[package]] name = "solana-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -5902,7 +5911,7 @@ dependencies = [ [[package]] name = "solana-compute-budget" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-fee-structure", "solana-program-runtime", @@ -5910,7 +5919,7 @@ dependencies = [ [[package]] name = "solana-compute-budget-instruction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "log", @@ -5934,35 +5943,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8432d2c4c22d0499aa06d62e4f7e333f81777b3d7c96050ae9e5cb71a8c3aee4" dependencies = [ "borsh 1.5.7", - "serde", - "serde_derive", "solana-instruction", "solana-sdk-ids", ] [[package]] name = "solana-compute-budget-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-program-runtime", ] +[[package]] +name = "solana-config-interface" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbdbcfedb467322ac9686ca61da0a1fdede2fd99a01fb2ed52b49452abd22e0" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-short-vec", + "solana-system-interface", +] + [[package]] name = "solana-config-program-client" -version = "0.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53aceac36f105fd4922e29b4f0c1f785b69d7b3e7e387e384b8985c8e0c3595e" +checksum = "ef9867b9ffae6e48a97ce6349e7796fcb34084298e909a8fa1fe427f41b52fd4" dependencies = [ "bincode", "borsh 0.10.3", "kaigan", "serde", + "solana-config-interface", "solana-program", ] [[package]] name = "solana-connection-cache" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -5983,7 +6008,7 @@ dependencies = [ [[package]] name = "solana-core" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "agave-feature-set", @@ -6001,6 +6026,7 @@ dependencies = [ "conditional-mod", "crossbeam-channel", "dashmap", + "derive_more 1.0.0", "etcd-client", "futures 0.3.31", "histogram", @@ -6115,7 +6141,7 @@ dependencies = [ [[package]] name = "solana-cost-model" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "ahash 0.8.11", @@ -6155,7 +6181,21 @@ dependencies = [ [[package]] name = "solana-curve25519" -version = "2.3.0" +version = "2.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def3cfe5279edb64fc39111cff6dcf77b01fbfba2c02c13ced41e6a48baf4cbe" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-define-syscall", + "subtle", + "thiserror 2.0.12", +] + +[[package]] +name = "solana-curve25519" +version = "3.0.0" dependencies = [ "bytemuck", "bytemuck_derive", @@ -6193,7 +6233,7 @@ dependencies = [ [[package]] name = "solana-download-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-clock", @@ -6204,9 +6244,9 @@ dependencies = [ [[package]] name = "solana-ed25519-program" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0fc717048fdbe5d2ee7d673d73e6a30a094002f4a29ca7630ac01b6bddec04" +checksum = "a1feafa1691ea3ae588f99056f4bdd1293212c7ece28243d7da257c443e84753" dependencies = [ "bytemuck", "bytemuck_derive", @@ -6219,7 +6259,7 @@ dependencies = [ [[package]] name = "solana-entry" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "crossbeam-channel", @@ -6312,7 +6352,7 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "clap", @@ -6376,7 +6416,7 @@ dependencies = [ [[package]] name = "solana-fee" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-fee-structure", @@ -6396,9 +6436,9 @@ dependencies = [ [[package]] name = "solana-fee-structure" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f45f94a88efdb512805563181dfa1c85c60a21b6e6d602bf24a2ea88f9399d6e" +checksum = "33adf673581c38e810bf618f745bf31b683a0a4a4377682e6aaac5d9a058dd4e" dependencies = [ "serde", "serde_derive", @@ -6451,7 +6491,7 @@ dependencies = [ [[package]] name = "solana-genesis-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-accounts-db", @@ -6463,7 +6503,7 @@ dependencies = [ [[package]] name = "solana-geyser-plugin-manager" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-geyser-plugin-interface", "bs58", @@ -6492,7 +6532,7 @@ dependencies = [ [[package]] name = "solana-gossip" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "arrayvec", @@ -6594,9 +6634,9 @@ dependencies = [ [[package]] name = "solana-instruction" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce496a475e5062ba5de97215ab39d9c358f9c9df4bb7f3a45a1f1a8bd9065ed" +checksum = "47298e2ce82876b64f71e9d13a46bc4b9056194e7f9937ad3084385befa50885" dependencies = [ "bincode", "borsh 1.5.7", @@ -6673,7 +6713,7 @@ dependencies = [ [[package]] name = "solana-lattice-hash" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "blake3", @@ -6683,7 +6723,7 @@ dependencies = [ [[package]] name = "solana-ledger" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -6760,7 +6800,7 @@ dependencies = [ "solana-time-utils", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-vote", @@ -6837,7 +6877,7 @@ dependencies = [ [[package]] name = "solana-loader-v4-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "qualifier_attr", @@ -6854,13 +6894,13 @@ dependencies = [ "solana-pubkey", "solana-sbpf", "solana-sdk-ids", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", ] [[package]] name = "solana-log-collector" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", ] @@ -6880,11 +6920,11 @@ dependencies = [ [[package]] name = "solana-measure" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-merkle-tree" -version = "2.3.0" +version = "3.0.0" dependencies = [ "fast-math", "solana-hash", @@ -6893,9 +6933,9 @@ dependencies = [ [[package]] name = "solana-message" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6bf99c4570173710107a1f233f3bee226feea5fc817308707d4f7cb100a72d" +checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b" dependencies = [ "bincode", "blake3", @@ -6916,12 +6956,12 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "gethostname", "log", - "reqwest 0.12.15", + "reqwest 0.12.19", "solana-cluster-type", "solana-sha256-hasher", "solana-time-utils", @@ -6945,7 +6985,7 @@ checksum = "307fb2f78060995979e9b4f68f833623565ed4e55d3725f100454ce78a99a1a3" [[package]] name = "solana-net-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "bincode", @@ -7003,7 +7043,6 @@ dependencies = [ "num_enum", "solana-hash", "solana-packet", - "solana-pubkey", "solana-sanitize", "solana-sha256-hasher", "solana-signature", @@ -7026,7 +7065,7 @@ dependencies = [ [[package]] name = "solana-perf" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "bincode", @@ -7056,7 +7095,7 @@ dependencies = [ [[package]] name = "solana-poh" -version = "2.3.0" +version = "3.0.0" dependencies = [ "core_affinity", "crossbeam-channel", @@ -7088,7 +7127,7 @@ dependencies = [ [[package]] name = "solana-poseidon" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ark-bn254", "light-poseidon", @@ -7098,31 +7137,14 @@ dependencies = [ [[package]] name = "solana-precompile-error" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff64daa2933c22982b323d88d0cdf693201ef56ac381ae16737fd5f579e07d6" +checksum = "4d87b2c1f5de77dfe2b175ee8dd318d196aaca4d0f66f02842f80c852811f9f8" dependencies = [ "num-traits", "solana-decode-error", ] -[[package]] -name = "solana-precompiles" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a460ab805ec063802105b463ecb5eb02c3ffe469e67a967eea8a6e778e0bc06" -dependencies = [ - "lazy_static", - "solana-ed25519-program", - "solana-feature-set", - "solana-message", - "solana-precompile-error", - "solana-pubkey", - "solana-sdk-ids", - "solana-secp256k1-program", - "solana-secp256r1-program", -] - [[package]] name = "solana-presigner" version = "2.2.1" @@ -7228,9 +7250,9 @@ dependencies = [ [[package]] name = "solana-program-error" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8ae2c1a8d0d4ae865882d5770a7ebca92bab9c685e43f0461682c6c05a35bfa" +checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" dependencies = [ "borsh 1.5.7", "num-traits", @@ -7269,7 +7291,7 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -7303,14 +7325,14 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "thiserror 2.0.12", ] [[package]] name = "solana-program-test" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -7330,7 +7352,6 @@ dependencies = [ "solana-clock", "solana-commitment-config", "solana-compute-budget", - "solana-cpi", "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", @@ -7352,9 +7373,7 @@ dependencies = [ "solana-rent", "solana-runtime", "solana-sbpf", - "solana-sdk", "solana-sdk-ids", - "solana-sdk-macro", "solana-signer", "solana-stable-layout", "solana-stake-interface", @@ -7364,7 +7383,7 @@ dependencies = [ "solana-sysvar-id", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-vote-program", "spl-generic-token", @@ -7401,7 +7420,7 @@ dependencies = [ [[package]] name = "solana-pubsub-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "futures-util", @@ -7426,7 +7445,7 @@ dependencies = [ [[package]] name = "solana-quic-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-lock", "async-trait", @@ -7463,14 +7482,14 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "2.3.0" +version = "3.0.0" dependencies = [ "num_cpus", ] [[package]] name = "solana-remote-wallet" -version = "2.3.0" +version = "3.0.0" dependencies = [ "console", "dialoguer", @@ -7530,18 +7549,6 @@ dependencies = [ "solana-reward-info", ] -[[package]] -name = "solana-reserved-account-keys" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b293f4246626c0e0a991531f08848a713ada965612e99dc510963f04d12cae7" -dependencies = [ - "lazy_static", - "solana-feature-set", - "solana-pubkey", - "solana-sdk-ids", -] - [[package]] name = "solana-reward-info" version = "2.2.1" @@ -7554,7 +7561,7 @@ dependencies = [ [[package]] name = "solana-rpc" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "base64 0.22.1", @@ -7620,7 +7627,7 @@ dependencies = [ "solana-time-utils", "solana-tpu-client", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-validator-exit", @@ -7638,7 +7645,7 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "base64 0.22.1", @@ -7647,7 +7654,7 @@ dependencies = [ "futures 0.3.31", "indicatif", "log", - "reqwest 0.12.15", + "reqwest 0.12.19", "reqwest-middleware", "semver", "serde", @@ -7670,16 +7677,17 @@ dependencies = [ "solana-transaction-error", "solana-transaction-status-client-types", "solana-version", + "solana-vote-interface", "tokio", ] [[package]] name = "solana-rpc-client-api" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "jsonrpc-core", - "reqwest 0.12.15", + "reqwest 0.12.19", "reqwest-middleware", "serde", "serde_derive", @@ -7695,7 +7703,7 @@ dependencies = [ [[package]] name = "solana-rpc-client-nonce-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-commitment-config", @@ -7710,7 +7718,7 @@ dependencies = [ [[package]] name = "solana-rpc-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bs58", @@ -7734,7 +7742,7 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-precompiles", @@ -7818,7 +7826,6 @@ dependencies = [ "solana-perf", "solana-poh-config", "solana-precompile-error", - "solana-program", "solana-program-runtime", "solana-pubkey", "solana-rayon-threadlimit", @@ -7827,9 +7834,7 @@ dependencies = [ "solana-rent-debits", "solana-reward-info", "solana-runtime-transaction", - "solana-sdk", "solana-sdk-ids", - "solana-sdk-macro", "solana-secp256k1-program", "solana-seed-derivable", "solana-serde", @@ -7852,7 +7857,7 @@ dependencies = [ "solana-time-utils", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status-client-types", "solana-unified-scheduler-logic", @@ -7873,7 +7878,7 @@ dependencies = [ [[package]] name = "solana-runtime-transaction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-transaction-view", "log", @@ -7898,7 +7903,7 @@ checksum = "61f1bc1357b8188d9c4a3af3fc55276e56987265eb7ad073ae6f8180ee54cecf" [[package]] name = "solana-sbf-programs" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -7958,7 +7963,7 @@ dependencies = [ "solana-sysvar", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-type-overrides", @@ -7968,548 +7973,696 @@ dependencies = [ [[package]] name = "solana-sbf-rust-128bit" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-program-entrypoint", "solana-sbf-rust-128bit-dep", ] [[package]] name = "solana-sbf-rust-128bit-dep" -version = "2.3.0" -dependencies = [ - "solana-program", -] +version = "3.0.0" [[package]] name = "solana-sbf-rust-account-mem" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", -] + "solana-account-info", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-pubkey", +] [[package]] name = "solana-sbf-rust-account-mem-deprecated" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", "solana-program", + "solana-program-error", + "solana-program-memory", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-alloc" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-alt-bn128" -version = "2.3.0" +version = "3.0.0" dependencies = [ "array-bytes", "solana-bn254", - "solana-program", + "solana-msg", + "solana-program-entrypoint", ] [[package]] name = "solana-sbf-rust-alt-bn128-compression" -version = "2.3.0" +version = "3.0.0" dependencies = [ "array-bytes", "solana-bn254", - "solana-program", + "solana-msg", + "solana-program-entrypoint", ] [[package]] name = "solana-sbf-rust-big-mod-exp" -version = "2.3.0" +version = "3.0.0" dependencies = [ "array-bytes", "serde", "serde_derive", "serde_json", - "solana-program", + "solana-big-mod-exp", + "solana-msg", + "solana-program-entrypoint", ] [[package]] name = "solana-sbf-rust-call-args" -version = "2.3.0" +version = "3.0.0" dependencies = [ "borsh 1.5.7", + "solana-account-info", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-call-depth" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-caller-access" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-curve25519" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-curve25519", - "solana-program", + "solana-curve25519 3.0.0", + "solana-msg", + "solana-program-entrypoint", ] [[package]] name = "solana-sbf-rust-custom-heap" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-dep-crate" -version = "2.3.0" +version = "3.0.0" dependencies = [ "byteorder 1.5.0", - "solana-program", + "solana-program-entrypoint", ] [[package]] name = "solana-sbf-rust-deprecated-loader" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", "solana-sbf-rust-invoke-dep", "solana-sbf-rust-realloc-dep", + "solana-sdk-ids", ] [[package]] name = "solana-sbf-rust-divide-by-zero" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-dup-accounts" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-error-handling" -version = "2.3.0" +version = "3.0.0" dependencies = [ "num-derive", "num-traits", + "solana-account-info", "solana-decode-error", - "solana-program", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", "thiserror 1.0.69", ] [[package]] name = "solana-sbf-rust-external-spend" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-get-minimum-delegation" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-stake-interface", ] [[package]] name = "solana-sbf-rust-inner_instruction_alignment_check" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-instruction-introspection" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-instructions-sysvar", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-invoke" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-pubkey", "solana-sbf-rust-invoke-dep", "solana-sbf-rust-invoked-dep", "solana-sbf-rust-realloc-dep", + "solana-sdk-ids", + "solana-system-interface", ] [[package]] name = "solana-sbf-rust-invoke-and-error" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-invoke-and-ok" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-invoke-and-return" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-invoke-dep" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-sbf-rust-invoked" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", "solana-sbf-rust-invoked-dep", + "solana-sdk-ids", + "solana-system-interface", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-invoked-dep" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-instruction", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-iter" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-program", + "solana-program-entrypoint", ] [[package]] name = "solana-sbf-rust-log-data" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-many-args" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-msg", "solana-program", + "solana-program-entrypoint", "solana-sbf-rust-many-args-dep", ] [[package]] name = "solana-sbf-rust-many-args-dep" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-msg", "solana-program", ] [[package]] name = "solana-sbf-rust-mem" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-pubkey", "solana-sbf-rust-mem-dep", ] [[package]] name = "solana-sbf-rust-mem-dep" -version = "2.3.0" -dependencies = [ - "solana-program", -] +version = "3.0.0" [[package]] name = "solana-sbf-rust-membuiltins" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-program-entrypoint", "solana-sbf-rust-mem-dep", ] [[package]] name = "solana-sbf-rust-noop" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-panic" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-param-passing" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-program", + "solana-program-entrypoint", "solana-sbf-rust-param-passing-dep", ] [[package]] name = "solana-sbf-rust-param-passing-dep" -version = "2.3.0" -dependencies = [ - "solana-program", -] +version = "3.0.0" [[package]] name = "solana-sbf-rust-poseidon" -version = "2.3.0" +version = "3.0.0" dependencies = [ "array-bytes", + "solana-msg", "solana-poseidon", - "solana-program", + "solana-program-entrypoint", ] [[package]] name = "solana-sbf-rust-rand" -version = "2.3.0" +version = "3.0.0" dependencies = [ "getrandom 0.2.10", "rand 0.8.5", - "solana-program", + "solana-account-info", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-realloc" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", "solana-sbf-rust-realloc-dep", + "solana-system-interface", ] [[package]] name = "solana-sbf-rust-realloc-dep" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-instruction", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-realloc-invoke" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", "solana-sbf-rust-realloc-dep", "solana-sbf-rust-realloc-invoke-dep", + "solana-system-interface", ] [[package]] name = "solana-sbf-rust-realloc-invoke-dep" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-sbf-rust-remaining-compute-units" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-ro-account_modify" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-ro-modify" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-system-interface", ] [[package]] name = "solana-sbf-rust-sanity" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-sdk-ids", ] [[package]] name = "solana-sbf-rust-secp256k1-recover" -version = "2.3.0" +version = "3.0.0" dependencies = [ "libsecp256k1 0.7.0", - "solana-program", + "solana-keccak-hasher", + "solana-msg", + "solana-program-entrypoint", "solana-secp256k1-recover", ] [[package]] name = "solana-sbf-rust-sha" -version = "2.3.0" +version = "3.0.0" dependencies = [ "blake3", - "solana-program", + "solana-blake3-hasher", + "solana-keccak-hasher", + "solana-msg", + "solana-program-entrypoint", + "solana-sha256-hasher", ] [[package]] name = "solana-sbf-rust-sibling-inner-instructions" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-sibling-instructions" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-simulation" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-clock", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-spoof1" -version = "2.3.0" +version = "3.0.0" dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", "solana-program", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-system-interface", ] [[package]] name = "solana-sbf-rust-spoof1-system" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "solana-sbf-rust-sysvar" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", - "solana-program", + "solana-account-info", + "solana-define-syscall", + "solana-instruction", + "solana-instructions-sysvar", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-sdk-ids", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-upgradeable" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-sysvar", ] [[package]] name = "solana-sbf-rust-upgraded" -version = "2.3.0" +version = "3.0.0" dependencies = [ - "solana-program", + "solana-account-info", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-sysvar", ] [[package]] name = "solana-sbf-syscall-get-epoch-stake" -version = "2.3.0" -dependencies = [ - "solana-program", -] - -[[package]] -name = "solana-sbpf" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474a2d95dc819898ded08d24f29642d02189d3e1497bbb442a92a3997b7eb55f" -dependencies = [ - "byteorder 1.5.0", - "combine 3.8.1", - "hash32", - "libc", - "log", - "rand 0.8.5", - "rustc-demangle", - "thiserror 2.0.12", - "winapi 0.3.9", -] - -[[package]] -name = "solana-sdk" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8af90d2ce445440e0548fa4a5f96fe8b265c22041a68c942012ffadd029667d" -dependencies = [ - "bincode", - "bs58", - "getrandom 0.1.14", - "js-sys", - "serde", - "serde_json", - "solana-account", - "solana-bn254", - "solana-client-traits", - "solana-cluster-type", - "solana-commitment-config", - "solana-compute-budget-interface", - "solana-decode-error", - "solana-derivation-path", - "solana-ed25519-program", - "solana-epoch-info", - "solana-epoch-rewards-hasher", - "solana-feature-set", - "solana-fee-structure", - "solana-genesis-config", - "solana-hard-forks", - "solana-inflation", - "solana-instruction", - "solana-keypair", - "solana-message", - "solana-native-token", - "solana-nonce-account", - "solana-offchain-message", - "solana-packet", - "solana-poh-config", - "solana-precompile-error", - "solana-precompiles", - "solana-presigner", +version = "3.0.0" +dependencies = [ + "solana-account-info", + "solana-msg", "solana-program", - "solana-program-memory", + "solana-program-entrypoint", + "solana-program-error", "solana-pubkey", - "solana-quic-definitions", - "solana-rent-collector", - "solana-rent-debits", - "solana-reserved-account-keys", - "solana-reward-info", - "solana-sanitize", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-secp256k1-program", - "solana-secp256k1-recover", - "solana-secp256r1-program", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-serde", - "solana-serde-varint", - "solana-short-vec", - "solana-shred-version", - "solana-signature", - "solana-signer", - "solana-system-transaction", - "solana-time-utils", - "solana-transaction", - "solana-transaction-context 2.2.1", - "solana-transaction-error", - "solana-validator-exit", +] + +[[package]] +name = "solana-sbpf" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "474a2d95dc819898ded08d24f29642d02189d3e1497bbb442a92a3997b7eb55f" +dependencies = [ + "byteorder 1.5.0", + "combine 3.8.1", + "hash32", + "libc", + "log", + "rand 0.8.5", + "rustc-demangle", "thiserror 2.0.12", - "wasm-bindgen", + "winapi 0.3.9", ] [[package]] @@ -8539,16 +8692,11 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0a1caa972414cc78122c32bdae65ac5fe89df7db598585a5cde19d16a20280a" dependencies = [ - "bincode", "digest 0.10.7", "libsecp256k1 0.6.0", "serde", "serde_derive", "sha3", - "solana-feature-set", - "solana-instruction", - "solana-precompile-error", - "solana-sdk-ids", ] [[package]] @@ -8564,9 +8712,9 @@ dependencies = [ [[package]] name = "solana-secp256r1-program" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cda2aa1bbaceda14763c4f142a00b486f2f262cfd901bd0410649ad0404d5f7" +checksum = "cf903cbdc36a161533812f90acfccdb434ed48982bd5dd71f3217930572c4a80" dependencies = [ "bytemuck", "openssl", @@ -8604,7 +8752,7 @@ dependencies = [ [[package]] name = "solana-send-transaction-service" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "crossbeam-channel", @@ -8696,7 +8844,6 @@ checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c" dependencies = [ "ed25519-dalek", "five8", - "rand 0.8.5", "serde", "serde-big-array", "serde_derive", @@ -8773,7 +8920,7 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -8793,14 +8940,14 @@ dependencies = [ "solana-sdk-ids", "solana-stake-interface", "solana-sysvar", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "solana-vote-interface", ] [[package]] name = "solana-storage-bigtable" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-reserved-account-keys", "backoff", @@ -8840,7 +8987,7 @@ dependencies = [ [[package]] name = "solana-storage-proto" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "bs58", @@ -8855,7 +9002,7 @@ dependencies = [ "solana-serde", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "tonic-build", @@ -8863,7 +9010,7 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-channel", "bytes", @@ -8908,7 +9055,7 @@ dependencies = [ [[package]] name = "solana-svm" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "itertools 0.12.1", @@ -8947,7 +9094,7 @@ dependencies = [ "solana-system-interface", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-type-overrides", "spl-generic-token", @@ -8956,7 +9103,7 @@ dependencies = [ [[package]] name = "solana-svm-callback" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-precompile-error", @@ -8965,11 +9112,11 @@ dependencies = [ [[package]] name = "solana-svm-feature-set" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-svm-rent-collector" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-clock", @@ -8977,13 +9124,13 @@ dependencies = [ "solana-rent", "solana-rent-collector", "solana-sdk-ids", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", ] [[package]] name = "solana-svm-transaction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-hash", "solana-message", @@ -9011,7 +9158,7 @@ dependencies = [ [[package]] name = "solana-system-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "log", @@ -9030,7 +9177,7 @@ dependencies = [ "solana-sdk-ids", "solana-system-interface", "solana-sysvar", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", ] @@ -9098,7 +9245,7 @@ dependencies = [ [[package]] name = "solana-test-validator" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "base64 0.22.1", @@ -9145,7 +9292,7 @@ dependencies = [ [[package]] name = "solana-thin-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "log", @@ -9178,7 +9325,7 @@ checksum = "6af261afb0e8c39252a04d026e3ea9c405342b08c871a2ad8aa5448e068c784c" [[package]] name = "solana-timings" -version = "2.3.0" +version = "3.0.0" dependencies = [ "eager", "enum-iterator", @@ -9187,7 +9334,7 @@ dependencies = [ [[package]] name = "solana-tls-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "rustls 0.23.27", "solana-keypair", @@ -9198,7 +9345,7 @@ dependencies = [ [[package]] name = "solana-tpu-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -9230,7 +9377,7 @@ dependencies = [ [[package]] name = "solana-tpu-client-next" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "log", @@ -9263,12 +9410,10 @@ dependencies = [ "serde", "serde_derive", "solana-bincode", - "solana-feature-set", "solana-hash", "solana-instruction", "solana-keypair", "solana-message", - "solana-precompiles", "solana-pubkey", "solana-sanitize", "solana-sdk-ids", @@ -9282,23 +9427,7 @@ dependencies = [ [[package]] name = "solana-transaction-context" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5022de04cbba05377f68bf848c8c1322ead733f88a657bf792bb40f3257b8218" -dependencies = [ - "bincode", - "serde", - "serde_derive", - "solana-account", - "solana-instruction", - "solana-pubkey", - "solana-rent", - "solana-signature", -] - -[[package]] -name = "solana-transaction-context" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "serde", @@ -9326,7 +9455,7 @@ dependencies = [ [[package]] name = "solana-transaction-metrics-tracker" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -9340,7 +9469,7 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "agave-reserved-account-keys", @@ -9382,7 +9511,7 @@ dependencies = [ [[package]] name = "solana-transaction-status-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -9396,14 +9525,14 @@ dependencies = [ "solana-reward-info", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "thiserror 2.0.12", ] [[package]] name = "solana-turbine" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-xdp", @@ -9454,14 +9583,14 @@ dependencies = [ [[package]] name = "solana-type-overrides" -version = "2.3.0" +version = "3.0.0" dependencies = [ "rand 0.8.5", ] [[package]] name = "solana-udp-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "solana-connection-cache", @@ -9475,7 +9604,7 @@ dependencies = [ [[package]] name = "solana-unified-scheduler-logic" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "solana-pubkey", @@ -9487,7 +9616,7 @@ dependencies = [ [[package]] name = "solana-unified-scheduler-pool" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "aquamarine", @@ -9526,7 +9655,7 @@ checksum = "7bbf6d7a3c0b28dd5335c52c0e9eae49d0ae489a8f324917faf0ded65a812c1d" [[package]] name = "solana-version" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "rand 0.8.5", @@ -9539,7 +9668,7 @@ dependencies = [ [[package]] name = "solana-vortexor-receiver" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-perf", "solana-streamer", @@ -9547,7 +9676,7 @@ dependencies = [ [[package]] name = "solana-vote" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "itertools 0.12.1", @@ -9599,7 +9728,7 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -9624,14 +9753,14 @@ dependencies = [ "solana-signer", "solana-slot-hashes", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-vote-interface", "thiserror 2.0.12", ] [[package]] name = "solana-wen-restart" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "log", @@ -9645,19 +9774,19 @@ dependencies = [ "solana-gossip", "solana-hash", "solana-ledger", - "solana-program", "solana-pubkey", "solana-runtime", "solana-shred-version", "solana-time-utils", "solana-timings", "solana-vote", + "solana-vote-interface", "solana-vote-program", ] [[package]] name = "solana-zk-elgamal-proof-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bytemuck", "num-derive", @@ -9666,12 +9795,49 @@ dependencies = [ "solana-log-collector", "solana-program-runtime", "solana-sdk-ids", - "solana-zk-sdk", + "solana-zk-sdk 3.0.0", ] [[package]] name = "solana-zk-sdk" -version = "2.3.0" +version = "2.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15045540c315a9b8ea056323e73320e76098dfdaac9e65b1b33fe9c2f3c9b9e1" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "js-sys", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-derivation-path", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", + "subtle", + "thiserror 2.0.12", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-zk-sdk" +version = "3.0.0" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -9705,7 +9871,7 @@ dependencies = [ [[package]] name = "solana-zk-token-proof-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bytemuck", @@ -9720,7 +9886,7 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "2.3.0" +version = "3.0.0" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -9737,7 +9903,7 @@ dependencies = [ "serde_derive", "serde_json", "sha3", - "solana-curve25519", + "solana-curve25519 3.0.0", "solana-derivation-path", "solana-instruction", "solana-pubkey", @@ -9846,7 +10012,7 @@ dependencies = [ "solana-sdk-ids", "solana-system-interface", "solana-sysvar", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-pod", "spl-token-confidential-transfer-proof-extraction", ] @@ -9891,7 +10057,7 @@ dependencies = [ "solana-program-error", "solana-program-option", "solana-pubkey", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "thiserror 2.0.12", ] @@ -10001,7 +10167,7 @@ dependencies = [ "solana-security-txt", "solana-system-interface", "solana-sysvar", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-elgamal-registry", "spl-memo", "spl-pod", @@ -10024,8 +10190,8 @@ checksum = "94ab20faf7b5edaa79acd240e0f21d5a2ef936aa99ed98f698573a2825b299c4" dependencies = [ "base64 0.22.1", "bytemuck", - "solana-curve25519", - "solana-zk-sdk", + "solana-curve25519 2.2.15", + "solana-zk-sdk 2.2.15", ] [[package]] @@ -10036,14 +10202,14 @@ checksum = "fe2629860ff04c17bafa9ba4bed8850a404ecac81074113e1f840dbd0ebb7bd6" dependencies = [ "bytemuck", "solana-account-info", - "solana-curve25519", + "solana-curve25519 2.2.15", "solana-instruction", "solana-instructions-sysvar", "solana-msg", "solana-program-error", "solana-pubkey", "solana-sdk-ids", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-pod", "thiserror 2.0.12", ] @@ -10055,7 +10221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae5b124840d4aed474cef101d946a798b806b46a509ee4df91021e1ab1cef3ef" dependencies = [ "curve25519-dalek 4.1.3", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "thiserror 2.0.12", ] @@ -10730,7 +10896,7 @@ dependencies = [ "percent-encoding 2.3.1", "pin-project", "prost", - "rustls-pemfile 1.0.0", + "rustls-pemfile", "tokio", "tokio-rustls 0.24.1", "tokio-stream", @@ -10788,6 +10954,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.1", + "bytes", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -11256,6 +11440,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.2.5" @@ -11326,35 +11519,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.53.0", -] - -[[package]] -name = "windows-result" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -11430,29 +11594,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -11471,12 +11619,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -11495,12 +11637,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -11519,24 +11655,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -11555,12 +11679,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -11579,12 +11697,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -11603,12 +11715,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -11627,12 +11733,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" version = "0.5.25" diff --git a/programs/sbf/Cargo.toml b/programs/sbf/Cargo.toml index 945ca12ae9667a..aaf72ca7ea5f70 100644 --- a/programs/sbf/Cargo.toml +++ b/programs/sbf/Cargo.toml @@ -1,5 +1,79 @@ + +[package] +name = "solana-sbf-programs" +description = "Blockchain, Rebuilt for Scale" +documentation = "https://docs.rs/solana" +readme = "README.md" +publish = false +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[workspace] +members = [ + "rust/128bit", + "rust/128bit_dep", + "rust/account_mem", + "rust/account_mem_deprecated", + "rust/alloc", + "rust/alt_bn128", + "rust/alt_bn128_compression", + "rust/big_mod_exp", + "rust/call_args", + "rust/call_depth", + "rust/caller_access", + "rust/curve25519", + "rust/custom_heap", + "rust/dep_crate", + "rust/deprecated_loader", + "rust/divide_by_zero", + "rust/dup_accounts", + "rust/error_handling", + "rust/external_spend", + "rust/get_minimum_delegation", + "rust/inner_instruction_alignment_check", + "rust/instruction_introspection", + "rust/invoke", + "rust/invoke_and_error", + "rust/invoke_and_ok", + "rust/invoke_and_return", + "rust/invoked", + "rust/iter", + "rust/log_data", + "rust/many_args", + "rust/many_args_dep", + "rust/mem", + "rust/mem_dep", + "rust/membuiltins", + "rust/noop", + "rust/panic", + "rust/param_passing", + "rust/param_passing_dep", + "rust/poseidon", + "rust/rand", + "rust/realloc", + "rust/realloc_invoke", + "rust/remaining_compute_units", + "rust/ro_account_modify", + "rust/ro_modify", + "rust/sanity", + "rust/secp256k1_recover", + "rust/sha", + "rust/sibling_inner_instructions", + "rust/sibling_instructions", + "rust/simulation", + "rust/spoof1", + "rust/spoof1_system", + "rust/syscall-get-epoch-stake", + "rust/sysvar", + "rust/upgradeable", + "rust/upgraded", +] [workspace.package] -version = "2.3.0" +version = "3.0.0" description = "Solana SBF test program written in Rust" authors = ["Anza Maintainers "] repository = "https://github.com/anza-xyz/agave" @@ -12,12 +86,13 @@ level = "warn" check-cfg = [ 'cfg(target_os, values("solana"))', 'cfg(feature, values("custom-panic", "custom-heap"))', - 'cfg(target_feature, values("dynamic-frames"))' + 'cfg(target_feature, values("dynamic-frames"))', ] [workspace.dependencies] -agave-feature-set = { path = "../../feature-set", version = "=2.3.0" } -agave-reserved-account-keys = { path = "../../reserved-account-keys", version = "=2.3.0" } +agave-feature-set = { path = "../../feature-set", version = "=3.0.0" } +agave-reserved-account-keys = { path = "../../reserved-account-keys", version = "=3.0.0" } +agave-validator = { path = "../../validator", version = "=3.0.0" } array-bytes = "=1.4.1" bincode = { version = "1.1.4", default-features = false } blake3 = "1.0.0" @@ -36,67 +111,67 @@ rand = "0.8" serde = "1.0.112" # must match the serde_derive version, see https://github.com/serde-rs/serde/issues/2584#issuecomment-1685252251 serde_derive = "1.0.112" # must match the serde version, see https://github.com/serde-rs/serde/issues/2584#issuecomment-1685252251 serde_json = "1.0.56" -solana-account-decoder = { path = "../../account-decoder", version = "=2.3.0" } -solana-accounts-db = { path = "../../accounts-db", version = "=2.3.0" } +solana-account-decoder = { path = "../../account-decoder", version = "=3.0.0" } +solana-account-info = "=2.3.0" +solana-accounts-db = { path = "../../accounts-db", version = "=3.0.0" } +solana-big-mod-exp = "=2.2.1" +solana-blake3-hasher = { version = "=2.2.1", features = ["blake3"] } solana-bn254 = "=2.2.2" -solana-bpf-loader-program = { path = "../bpf_loader", version = "=2.3.0" } -solana-cli-output = { path = "../../cli-output", version = "=2.3.0" } -solana-compute-budget = { path = "../../compute-budget", version = "=2.3.0" } -solana-compute-budget-instruction = { path = "../../compute-budget-instruction", version = "=2.3.0" } -solana-curve25519 = { path = "../../curves/curve25519", version = "=2.3.0" } +solana-bpf-loader-program = { path = "../bpf_loader", version = "=3.0.0" } +solana-cli-output = { path = "../../cli-output", version = "=3.0.0" } +solana-clock = { version = "=2.2.2", features = ["serde", "sysvar"] } +solana-compute-budget = { path = "../../compute-budget", version = "=3.0.0" } +solana-compute-budget-instruction = { path = "../../compute-budget-instruction", version = "=3.0.0" } +solana-curve25519 = { path = "../../curves/curve25519", version = "=3.0.0" } solana-decode-error = "=2.2.1" -solana-fee = { path = "../../fee", version = "=2.3.0" } -solana-ledger = { path = "../../ledger", version = "=2.3.0" } -solana-log-collector = { path = "../../log-collector", version = "=2.3.0" } +solana-define-syscall = "=2.3.0" +solana-fee = { path = "../../fee", version = "=3.0.0" } +solana-hash = { version = "=2.3.0", features = ["bytemuck", "serde", "std"] } +solana-instruction = "=2.3.0" +solana-instructions-sysvar = "=2.2.2" +solana-keccak-hasher = { version = "=2.2.1", features = ["sha3"] } +solana-ledger = { path = "../../ledger", version = "=3.0.0" } +solana-log-collector = { path = "../../log-collector", version = "=3.0.0" } solana-logger = "=2.3.1" -solana-measure = { path = "../../measure", version = "=2.3.0" } -solana-poseidon = { path = "../../poseidon/", version = "=2.3.0" } +solana-measure = { path = "../../measure", version = "=3.0.0" } +solana-msg = "=2.2.1" +solana-poseidon = { path = "../../poseidon/", version = "=3.0.0" } solana-program = "=2.2.1" -solana-program-runtime = { path = "../../program-runtime", version = "=2.3.0" } -solana-runtime = { path = "../../runtime", version = "=2.3.0" } -solana-runtime-transaction = { path = "../../runtime-transaction", version = "=2.3.0" } -solana-sbf-rust-128bit-dep = { path = "rust/128bit_dep", version = "=2.3.0" } -solana-sbf-rust-invoke-dep = { path = "rust/invoke_dep", version = "=2.3.0" } -solana-sbf-rust-invoked-dep = { path = "rust/invoked_dep", version = "=2.3.0" } -solana-sbf-rust-many-args-dep = { path = "rust/many_args_dep", version = "=2.3.0" } -solana-sbf-rust-mem-dep = { path = "rust/mem_dep", version = "=2.3.0" } -solana-sbf-rust-param-passing-dep = { path = "rust/param_passing_dep", version = "=2.3.0" } -solana-sbf-rust-realloc-dep = { path = "rust/realloc_dep", version = "=2.3.0" } -solana-sbf-rust-realloc-invoke-dep = { path = "rust/realloc_invoke_dep", version = "=2.3.0" } +solana-program-entrypoint = "=2.2.1" +solana-program-error = "=2.2.2" +solana-program-memory = "=2.2.1" +solana-program-runtime = { path = "../../program-runtime", version = "=3.0.0" } +solana-pubkey = { version = "=2.4.0", default-features = false } +solana-runtime = { path = "../../runtime", version = "=3.0.0" } +solana-runtime-transaction = { path = "../../runtime-transaction", version = "=3.0.0" } +solana-sbf-rust-128bit-dep = { path = "rust/128bit_dep", version = "=3.0.0" } +solana-sbf-rust-invoke-dep = { path = "rust/invoke_dep", version = "=3.0.0" } +solana-sbf-rust-invoked-dep = { path = "rust/invoked_dep", version = "=3.0.0" } +solana-sbf-rust-many-args-dep = { path = "rust/many_args_dep", version = "=3.0.0" } +solana-sbf-rust-mem-dep = { path = "rust/mem_dep", version = "=3.0.0" } +solana-sbf-rust-param-passing-dep = { path = "rust/param_passing_dep", version = "=3.0.0" } +solana-sbf-rust-realloc-dep = { path = "rust/realloc_dep", version = "=3.0.0" } +solana-sbf-rust-realloc-invoke-dep = { path = "rust/realloc_invoke_dep", version = "=3.0.0" } solana-sbpf = "=0.11.1" +solana-sdk-ids = "=2.2.1" solana-secp256k1-recover = "=2.2.1" -solana-svm = { path = "../../svm", version = "=2.3.0" } -solana-svm-callback = { path = "../../svm-callback", version = "=2.3.0" } -solana-svm-feature-set = { path = "../../svm-feature-set", version = "=2.3.0" } -solana-svm-transaction = { path = "../../svm-transaction", version = "=2.3.0" } -solana-timings = { path = "../../timings", version = "=2.3.0" } -solana-transaction-context = { path = "../../transaction-context", version = "=2.3.0" } -solana-transaction-status = { path = "../../transaction-status", version = "=2.3.0" } -solana-type-overrides = { path = "../../type-overrides", version = "=2.3.0" } -solana-vote = { path = "../../vote", version = "=2.3.0" } -solana-vote-program = { path = "../../programs/vote", version = "=2.3.0" } -agave-validator = { path = "../../validator", version = "=2.3.0" } +solana-sha256-hasher = { version = "=2.2.1", features = ["sha2"] } +solana-stake-interface = { version = "=1.2.1", features = ["bincode"] } +solana-svm = { path = "../../svm", version = "=3.0.0" } +solana-svm-callback = { path = "../../svm-callback", version = "=3.0.0" } +solana-svm-feature-set = { path = "../../svm-feature-set", version = "=3.0.0" } +solana-svm-transaction = { path = "../../svm-transaction", version = "=3.0.0" } +solana-system-interface = { version = "=1.0", features = ["bincode"] } +solana-sysvar = "=2.2.2" +solana-timings = { path = "../../timings", version = "=3.0.0" } +solana-transaction-context = { path = "../../transaction-context", version = "=3.0.0" } +solana-transaction-status = { path = "../../transaction-status", version = "=3.0.0" } +solana-type-overrides = { path = "../../type-overrides", version = "=3.0.0" } +solana-vote = { path = "../../vote", version = "=3.0.0" } +solana-vote-program = { path = "../../programs/vote", version = "=3.0.0" } solana-zk-sdk = "=2.2.1" thiserror = "1.0" -[package] -name = "solana-sbf-programs" -description = "Blockchain, Rebuilt for Scale" -documentation = "https://docs.rs/solana" -readme = "README.md" -publish = false -version = { workspace = true } -authors = { workspace = true } -repository = { workspace = true } -homepage = { workspace = true } -license = { workspace = true } -edition = { workspace = true } - -[profile.release] -# The test programs are build in release mode -# Minimize their file size so that they fit into the account size limit -strip = true - [features] sbf_c = [] sbf_rust = [] @@ -119,7 +194,7 @@ miow = { workspace = true } net2 = { workspace = true } solana-account = "2.2.1" solana-account-decoder = { workspace = true } -solana-account-info = "2.2.1" +solana-account-info = "2.3.0" solana-accounts-db = { workspace = true } solana-bpf-loader-program = { workspace = true } solana-cli-output = { workspace = true } @@ -132,7 +207,7 @@ solana-compute-budget-instruction = { workspace = true, features = [ solana-compute-budget-interface = "2.2.2" solana-fee = { workspace = true } solana-fee-calculator = "2.2.1" -solana-fee-structure = "2.2.1" +solana-fee-structure = "2.3.0" solana-genesis-config = "2.2.1" solana-hash = "2.2.1" solana-instruction = "2.2.1" @@ -147,7 +222,7 @@ solana-message = "2.3.0" solana-program = { workspace = true } solana-program-entrypoint = "2.2.1" solana-program-runtime = { workspace = true } -solana-pubkey = "2.3.0" +solana-pubkey = "2.4.0" solana-rent = "2.2.1" solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-runtime-transaction = { workspace = true, features = [ @@ -175,70 +250,14 @@ solana-type-overrides = { workspace = true } solana-vote = { workspace = true } solana-vote-program = { workspace = true } +[profile.release] +# The test programs are build in release mode +# Minimize their file size so that they fit into the account size limit +strip = true + [[bench]] name = "bpf_loader" -[workspace] -members = [ - "rust/128bit", - "rust/128bit_dep", - "rust/account_mem", - "rust/account_mem_deprecated", - "rust/alloc", - "rust/alt_bn128", - "rust/alt_bn128_compression", - "rust/big_mod_exp", - "rust/call_args", - "rust/call_depth", - "rust/caller_access", - "rust/curve25519", - "rust/custom_heap", - "rust/dep_crate", - "rust/deprecated_loader", - "rust/divide_by_zero", - "rust/dup_accounts", - "rust/error_handling", - "rust/external_spend", - "rust/get_minimum_delegation", - "rust/inner_instruction_alignment_check", - "rust/instruction_introspection", - "rust/invoke", - "rust/invoke_and_error", - "rust/invoke_and_ok", - "rust/invoke_and_return", - "rust/invoked", - "rust/iter", - "rust/log_data", - "rust/many_args", - "rust/many_args_dep", - "rust/mem", - "rust/mem_dep", - "rust/membuiltins", - "rust/noop", - "rust/panic", - "rust/param_passing", - "rust/param_passing_dep", - "rust/poseidon", - "rust/rand", - "rust/realloc", - "rust/realloc_invoke", - "rust/remaining_compute_units", - "rust/ro_account_modify", - "rust/ro_modify", - "rust/sanity", - "rust/secp256k1_recover", - "rust/sha", - "rust/sibling_inner_instructions", - "rust/sibling_instructions", - "rust/simulation", - "rust/spoof1", - "rust/spoof1_system", - "rust/syscall-get-epoch-stake", - "rust/sysvar", - "rust/upgradeable", - "rust/upgraded", -] - [patch.crates-io] # We include the following crates as our dependencies from crates.io: # diff --git a/programs/sbf/rust/128bit/Cargo.toml b/programs/sbf/rust/128bit/Cargo.toml index c9b401344ae4d1..1540bc8fb94265 100644 --- a/programs/sbf/rust/128bit/Cargo.toml +++ b/programs/sbf/rust/128bit/Cargo.toml @@ -8,12 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } -solana-sbf-rust-128bit-dep = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-program-entrypoint = { workspace = true } +solana-sbf-rust-128bit-dep = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/128bit/src/lib.rs b/programs/sbf/rust/128bit/src/lib.rs index 55095c73977acc..a77e8e5e2e8a5b 100644 --- a/programs/sbf/rust/128bit/src/lib.rs +++ b/programs/sbf/rust/128bit/src/lib.rs @@ -2,8 +2,7 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; -use solana_program::{custom_heap_default, custom_panic_default, entrypoint::SUCCESS}; +use solana_program_entrypoint::{custom_heap_default, custom_panic_default, SUCCESS}; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { diff --git a/programs/sbf/rust/128bit_dep/Cargo.toml b/programs/sbf/rust/128bit_dep/Cargo.toml index 9fe86cf605f588..6015395f67b436 100644 --- a/programs/sbf/rust/128bit_dep/Cargo.toml +++ b/programs/sbf/rust/128bit_dep/Cargo.toml @@ -9,4 +9,3 @@ license = { workspace = true } edition = { workspace = true } [dependencies] -solana-program = { workspace = true } diff --git a/programs/sbf/rust/128bit_dep/src/lib.rs b/programs/sbf/rust/128bit_dep/src/lib.rs index c78c13a357358a..ccb6942a858459 100644 --- a/programs/sbf/rust/128bit_dep/src/lib.rs +++ b/programs/sbf/rust/128bit_dep/src/lib.rs @@ -2,8 +2,6 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; - pub fn uadd(x: u128, y: u128) -> u128 { x + y } diff --git a/programs/sbf/rust/account_mem/Cargo.toml b/programs/sbf/rust/account_mem/Cargo.toml index 39f72a5ff71d66..606647aafd8e71 100644 --- a/programs/sbf/rust/account_mem/Cargo.toml +++ b/programs/sbf/rust/account_mem/Cargo.toml @@ -8,11 +8,15 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-program-memory = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/account_mem/src/lib.rs b/programs/sbf/rust/account_mem/src/lib.rs index 989a4a7ee9635e..7d20446b9f0101 100644 --- a/programs/sbf/rust/account_mem/src/lib.rs +++ b/programs/sbf/rust/account_mem/src/lib.rs @@ -1,14 +1,13 @@ //! Test mem functions -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - program_error::ProgramError, - program_memory::{sol_memcmp, sol_memcpy, sol_memmove, sol_memset}, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_program_error::{ProgramError, ProgramResult}, + solana_program_memory::{sol_memcmp, sol_memcpy, sol_memmove, sol_memset}, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], @@ -30,14 +29,6 @@ pub fn process_instruction( match instruction_data[0] { 0 => { - // memcmp overlaps end - sol_memcmp(&buf, &data[data_len.saturating_sub(8)..], 16); - } - 1 => { - // memcmp overlaps end - sol_memcmp(&data[data_len.saturating_sub(7)..], &buf, 15); - } - 2 => { // memcmp overlaps begining #[allow(clippy::manual_memcpy)] for i in 0..500 { @@ -46,7 +37,7 @@ pub fn process_instruction( sol_memcmp(too_early(8), &buf, 500); } - 3 => { + 1 => { // memcmp overlaps begining #[allow(clippy::manual_memcpy)] for i in 0..12 { @@ -55,11 +46,7 @@ pub fn process_instruction( sol_memcmp(&buf, too_early(9), 12); } - 4 => { - // memset overlaps end of account - sol_memset(&mut data[data_len.saturating_sub(2)..], 0, 3); - } - 5 => { + 2 => { // memcmp overlaps begining #[allow(clippy::manual_memcpy)] for i in 0..3 { @@ -70,11 +57,43 @@ pub fn process_instruction( sol_memset(too_early(2), 3, 3); sol_memcpy(too_early(2), &buf, 3); } + 3 => { + // memcpy src overlaps begin of account + sol_memcpy(&mut buf, too_early(3), 10); + } + 4 => { + // memmov src overlaps begin of account + unsafe { sol_memmove(buf.as_mut_ptr(), too_early(3).as_ptr(), 10) }; + } + 5 => { + // memcpy dst overlaps begin of account + sol_memcpy(too_early(3), &buf, 10); + } 6 => { + // memmov dst overlaps begin of account + unsafe { sol_memmove(too_early(3).as_mut_ptr(), buf.as_ptr(), 10) }; + } + 7 => { + // memmove dst overlaps begin of account, reverse order + unsafe { sol_memmove(too_early(0).as_mut_ptr(), too_early(3).as_ptr(), 10) }; + } + 8 => { + // memcmp overlaps end + sol_memcmp(&buf, &data[data_len.saturating_sub(8)..], 16); + } + 9 => { + // memcmp overlaps end + sol_memcmp(&data[data_len.saturating_sub(7)..], &buf, 15); + } + 10 => { + // memset overlaps end of account + sol_memset(&mut data[data_len.saturating_sub(2)..], 0, 3); + } + 11 => { // memcpy src overlaps end of account sol_memcpy(&mut buf, &data[data_len.saturating_sub(3)..], 10); } - 7 => { + 12 => { // memmov src overlaps end of account unsafe { sol_memmove( @@ -84,20 +103,11 @@ pub fn process_instruction( ) }; } - 8 => { - // memcpy src overlaps begin of account - sol_memcpy(&mut buf, too_early(3), 10); - } - 9 => { - // memmov src overlaps begin of account - unsafe { sol_memmove(buf.as_mut_ptr(), too_early(3).as_ptr(), 10) }; - } - - 10 => { + 13 => { // memcpy dst overlaps end of account sol_memcpy(&mut data[data_len.saturating_sub(3)..], &buf, 10); } - 11 => { + 14 => { // memmov dst overlaps end of account unsafe { sol_memmove( @@ -107,18 +117,6 @@ pub fn process_instruction( ) }; } - 12 => { - // memcpy dst overlaps begin of account - sol_memcpy(too_early(3), &buf, 10); - } - 13 => { - // memmov dst overlaps begin of account - unsafe { sol_memmove(too_early(3).as_mut_ptr(), buf.as_ptr(), 10) }; - } - 14 => { - // memmove dst overlaps begin of account, reverse order - unsafe { sol_memmove(too_early(0).as_mut_ptr(), too_early(3).as_ptr(), 10) }; - } 15 => { // memmove dst overlaps end of account, reverse order unsafe { diff --git a/programs/sbf/rust/account_mem_deprecated/Cargo.toml b/programs/sbf/rust/account_mem_deprecated/Cargo.toml index 4ca338cde26e2f..ad85d55141a723 100644 --- a/programs/sbf/rust/account_mem_deprecated/Cargo.toml +++ b/programs/sbf/rust/account_mem_deprecated/Cargo.toml @@ -8,11 +8,15 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program = { workspace = true } +solana-program-error = { workspace = true } +solana-program-memory = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/account_mem_deprecated/src/lib.rs b/programs/sbf/rust/account_mem_deprecated/src/lib.rs index 59ac880a4cb465..4a95e6b8202618 100644 --- a/programs/sbf/rust/account_mem_deprecated/src/lib.rs +++ b/programs/sbf/rust/account_mem_deprecated/src/lib.rs @@ -1,11 +1,10 @@ //! Test mem functions -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - program_error::ProgramError, - program_memory::{sol_memcmp, sol_memcpy, sol_memmove, sol_memset}, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_program_error::{ProgramError, ProgramResult}, + solana_program_memory::{sol_memcmp, sol_memcpy, sol_memmove, sol_memset}, + solana_pubkey::Pubkey, }; solana_program::entrypoint_deprecated!(process_instruction); @@ -30,14 +29,6 @@ pub fn process_instruction( match instruction_data[0] { 0 => { - // memcmp overlaps end - sol_memcmp(&buf, &data[data_len.saturating_sub(8)..], 16); - } - 1 => { - // memcmp overlaps end - sol_memcmp(&data[data_len.saturating_sub(7)..], &buf, 15); - } - 2 => { // memcmp overlaps begining #[allow(clippy::manual_memcpy)] for i in 0..90 { @@ -46,7 +37,7 @@ pub fn process_instruction( sol_memcmp(too_early(8), &buf, 90); } - 3 => { + 1 => { // memcmp overlaps begining #[allow(clippy::manual_memcpy)] for i in 0..12 { @@ -55,19 +46,47 @@ pub fn process_instruction( sol_memcmp(&buf, too_early(9), 12); } + 2 => { + // memset overlaps begin of account area + sol_memset(too_early(2), 3, 3); + } + 3 => { + // memcpy src overlaps begin of account + sol_memcpy(&mut buf, too_early(3), 10); + } 4 => { - // memset overlaps end of account - sol_memset(&mut data[data_len.saturating_sub(2)..], 0, 3); + // memmov src overlaps begin of account + unsafe { sol_memmove(buf.as_mut_ptr(), too_early(3).as_ptr(), 10) }; } 5 => { - // memset overlaps begin of account area - sol_memset(too_early(2), 3, 3); + // memcpy dst overlaps begin of account + sol_memcpy(too_early(3), &buf, 10); } 6 => { + // memmov dst overlaps begin of account + unsafe { sol_memmove(too_early(3).as_mut_ptr(), buf.as_ptr(), 10) }; + } + 7 => { + // memmove dst overlaps begin of account, reverse order + unsafe { sol_memmove(too_early(0).as_mut_ptr(), too_early(3).as_ptr(), 10) }; + } + 8 => { + // memcmp overlaps end + sol_memcmp(&buf, &data[data_len.saturating_sub(8)..], 16); + } + 9 => { + // memcmp overlaps end + sol_memcmp(&data[data_len.saturating_sub(7)..], &buf, 15); + } + 10 => { + // memset overlaps end of account + sol_memset(&mut data[data_len.saturating_sub(2)..], 0, 3); + } + 11 => { // memcpy src overlaps end of account sol_memcpy(&mut buf, &data[data_len.saturating_sub(3)..], 10); } - 7 => { + 12 => { // memmov src overlaps end of account unsafe { sol_memmove( @@ -77,20 +96,11 @@ pub fn process_instruction( ) }; } - 8 => { - // memcpy src overlaps begin of account - sol_memcpy(&mut buf, too_early(3), 10); - } - 9 => { - // memmov src overlaps begin of account - unsafe { sol_memmove(buf.as_mut_ptr(), too_early(3).as_ptr(), 10) }; - } - - 10 => { + 13 => { // memcpy dst overlaps end of account sol_memcpy(&mut data[data_len.saturating_sub(3)..], &buf, 10); } - 11 => { + 14 => { // memmov dst overlaps end of account unsafe { sol_memmove( @@ -100,18 +110,6 @@ pub fn process_instruction( ) }; } - 12 => { - // memcpy dst overlaps begin of account - sol_memcpy(too_early(3), &buf, 10); - } - 13 => { - // memmov dst overlaps begin of account - unsafe { sol_memmove(too_early(3).as_mut_ptr(), buf.as_ptr(), 10) }; - } - 14 => { - // memmove dst overlaps begin of account, reverse order - unsafe { sol_memmove(too_early(0).as_mut_ptr(), too_early(3).as_ptr(), 10) }; - } 15 => { // memmove dst overlaps end of account, reverse order unsafe { diff --git a/programs/sbf/rust/alloc/Cargo.toml b/programs/sbf/rust/alloc/Cargo.toml index cddf373c236cea..ef99134990530e 100644 --- a/programs/sbf/rust/alloc/Cargo.toml +++ b/programs/sbf/rust/alloc/Cargo.toml @@ -8,11 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/alloc/src/lib.rs b/programs/sbf/rust/alloc/src/lib.rs index 2ee3e72f8b5f62..5993eeedf77f98 100644 --- a/programs/sbf/rust/alloc/src/lib.rs +++ b/programs/sbf/rust/alloc/src/lib.rs @@ -5,9 +5,9 @@ #[macro_use] extern crate alloc; use { - solana_program::{ - custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, msg, - }, + solana_msg::msg, + solana_program::log::sol_log_64, + solana_program_entrypoint::{custom_heap_default, custom_panic_default, SUCCESS}, std::{alloc::Layout, mem}, }; diff --git a/programs/sbf/rust/alt_bn128/Cargo.toml b/programs/sbf/rust/alt_bn128/Cargo.toml index f283ce759342bf..eb41b8ca8ea296 100644 --- a/programs/sbf/rust/alt_bn128/Cargo.toml +++ b/programs/sbf/rust/alt_bn128/Cargo.toml @@ -8,13 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] array-bytes = { workspace = true } solana-bn254 = { workspace = true } -solana-program = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/alt_bn128/src/lib.rs b/programs/sbf/rust/alt_bn128/src/lib.rs index 7a546dc248fba3..ed0e90d1f2fa93 100644 --- a/programs/sbf/rust/alt_bn128/src/lib.rs +++ b/programs/sbf/rust/alt_bn128/src/lib.rs @@ -1,9 +1,9 @@ //! Alt_bn128 Syscalls tests -extern crate solana_program; use { solana_bn254::prelude::{alt_bn128_addition, alt_bn128_multiplication, alt_bn128_pairing}, - solana_program::{custom_heap_default, custom_panic_default, msg}, + solana_msg::msg, + solana_program_entrypoint::{custom_heap_default, custom_panic_default}, }; fn alt_bn128_addition_test() { diff --git a/programs/sbf/rust/alt_bn128_compression/Cargo.toml b/programs/sbf/rust/alt_bn128_compression/Cargo.toml index 7f52a923a1f53d..1f1bd6166633a9 100644 --- a/programs/sbf/rust/alt_bn128_compression/Cargo.toml +++ b/programs/sbf/rust/alt_bn128_compression/Cargo.toml @@ -8,13 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] array-bytes = { workspace = true } solana-bn254 = { workspace = true } -solana-program = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/alt_bn128_compression/src/lib.rs b/programs/sbf/rust/alt_bn128_compression/src/lib.rs index a5ca6645142ec3..99e3e5ffe217b5 100644 --- a/programs/sbf/rust/alt_bn128_compression/src/lib.rs +++ b/programs/sbf/rust/alt_bn128_compression/src/lib.rs @@ -1,12 +1,12 @@ //! Alt_bn128 compression Syscalls tests -extern crate solana_program; use { solana_bn254::compression::prelude::{ alt_bn128_g1_compress, alt_bn128_g1_decompress, alt_bn128_g2_compress, alt_bn128_g2_decompress, }, - solana_program::{custom_heap_default, custom_panic_default, msg}, + solana_msg::msg, + solana_program_entrypoint::{custom_heap_default, custom_panic_default}, }; fn alt_bn128_compression_g1() { diff --git a/programs/sbf/rust/big_mod_exp/Cargo.toml b/programs/sbf/rust/big_mod_exp/Cargo.toml index a0567b3b7b18e2..20a6c1b01ad7e9 100644 --- a/programs/sbf/rust/big_mod_exp/Cargo.toml +++ b/programs/sbf/rust/big_mod_exp/Cargo.toml @@ -8,15 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] array-bytes = { workspace = true } serde = { workspace = true } serde_derive = { workspace = true } serde_json = { workspace = true } -solana-program = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-big-mod-exp = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/big_mod_exp/src/lib.rs b/programs/sbf/rust/big_mod_exp/src/lib.rs index 11a56d7ff17bbf..7f97a0e8335245 100644 --- a/programs/sbf/rust/big_mod_exp/src/lib.rs +++ b/programs/sbf/rust/big_mod_exp/src/lib.rs @@ -1,7 +1,9 @@ //! Big_mod_exp Syscall tests -extern crate solana_program; -use solana_program::{big_mod_exp::big_mod_exp, custom_panic_default, msg}; +use { + solana_big_mod_exp::big_mod_exp, solana_msg::msg, + solana_program_entrypoint::custom_panic_default, +}; fn big_mod_exp_test() { #[derive(serde_derive::Deserialize)] diff --git a/programs/sbf/rust/call_args/Cargo.toml b/programs/sbf/rust/call_args/Cargo.toml index 2d4a4ecd84db9d..b2241b24058544 100644 --- a/programs/sbf/rust/call_args/Cargo.toml +++ b/programs/sbf/rust/call_args/Cargo.toml @@ -8,12 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] borsh = { workspace = true } +solana-account-info = { workspace = true } solana-program = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/call_args/src/lib.rs b/programs/sbf/rust/call_args/src/lib.rs index 43d61187110bce..8a9c50fa29fea3 100644 --- a/programs/sbf/rust/call_args/src/lib.rs +++ b/programs/sbf/rust/call_args/src/lib.rs @@ -1,9 +1,9 @@ use { borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize}, - solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, program::set_return_data, - pubkey::Pubkey, - }, + solana_account_info::AccountInfo, + solana_program::program::set_return_data, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; #[derive(BorshSerialize, BorshDeserialize, Clone, Copy)] @@ -33,7 +33,7 @@ struct OutputData { many_args_2: i64, } -solana_program::entrypoint_no_alloc!(entry); +solana_program_entrypoint::entrypoint_no_alloc!(entry); pub fn entry(_program_id: &Pubkey, _accounts: &[AccountInfo], data: &[u8]) -> ProgramResult { // This code is supposed to occupy stack space. The purpose of this test is to make sure diff --git a/programs/sbf/rust/call_depth/Cargo.toml b/programs/sbf/rust/call_depth/Cargo.toml index 5d2f503234c026..7f755402e2b513 100644 --- a/programs/sbf/rust/call_depth/Cargo.toml +++ b/programs/sbf/rust/call_depth/Cargo.toml @@ -8,11 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/call_depth/src/lib.rs b/programs/sbf/rust/call_depth/src/lib.rs index 6f0052dbd34cf3..a97f34f2af7e5e 100644 --- a/programs/sbf/rust/call_depth/src/lib.rs +++ b/programs/sbf/rust/call_depth/src/lib.rs @@ -1,7 +1,9 @@ //! Example Rust-based SBF program that tests call depth and stack usage -use solana_program::{ - custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, msg, +use { + solana_msg::msg, + solana_program::log::sol_log_64, + solana_program_entrypoint::{custom_heap_default, custom_panic_default, SUCCESS}, }; #[inline(never)] diff --git a/programs/sbf/rust/caller_access/Cargo.toml b/programs/sbf/rust/caller_access/Cargo.toml index e0b717927e5d7f..f871a2be728cd5 100644 --- a/programs/sbf/rust/caller_access/Cargo.toml +++ b/programs/sbf/rust/caller_access/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/caller_access/src/lib.rs b/programs/sbf/rust/caller_access/src/lib.rs index b1c41ad6e1a9bb..69cee1fd8c570d 100644 --- a/programs/sbf/rust/caller_access/src/lib.rs +++ b/programs/sbf/rust/caller_access/src/lib.rs @@ -1,16 +1,14 @@ use { - solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - msg, - program::invoke, - pubkey::Pubkey, - }, + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_msg::msg, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, std::convert::TryInto, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/curve25519/Cargo.toml b/programs/sbf/rust/curve25519/Cargo.toml index 936f30a645fa90..85523ead8e7f98 100644 --- a/programs/sbf/rust/curve25519/Cargo.toml +++ b/programs/sbf/rust/curve25519/Cargo.toml @@ -8,12 +8,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-curve25519 = { workspace = true } -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-curve25519 = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/curve25519/src/lib.rs b/programs/sbf/rust/curve25519/src/lib.rs index 42718278c2c685..a5ba54cd8a35e4 100644 --- a/programs/sbf/rust/curve25519/src/lib.rs +++ b/programs/sbf/rust/curve25519/src/lib.rs @@ -1,9 +1,9 @@ //! @brief curve25519 syscall tests -extern crate solana_program; use { solana_curve25519::{edwards, ristretto, scalar}, - solana_program::{custom_heap_default, custom_panic_default, msg}, + solana_msg::msg, + solana_program_entrypoint::{custom_heap_default, custom_panic_default}, }; #[no_mangle] diff --git a/programs/sbf/rust/custom_heap/Cargo.toml b/programs/sbf/rust/custom_heap/Cargo.toml index 3386d32547b31f..7c0363db70821b 100644 --- a/programs/sbf/rust/custom_heap/Cargo.toml +++ b/programs/sbf/rust/custom_heap/Cargo.toml @@ -8,15 +8,19 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } +[lib] +crate-type = ["cdylib"] [features] default = ["custom-heap"] custom-heap = [] -[lib] -crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/custom_heap/src/lib.rs b/programs/sbf/rust/custom_heap/src/lib.rs index 9738db15226335..ce648e6baffba7 100644 --- a/programs/sbf/rust/custom_heap/src/lib.rs +++ b/programs/sbf/rust/custom_heap/src/lib.rs @@ -2,18 +2,21 @@ #![allow(clippy::arithmetic_side_effects)] -#[cfg(target_os = "solana")] -use { - solana_program::entrypoint::{HEAP_LENGTH, HEAP_START_ADDRESS}, - std::{mem::size_of, ptr::null_mut}, -}; use { - solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey}, + solana_account_info::AccountInfo, + solana_msg::msg, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, std::{ alloc::{alloc, Layout}, mem::align_of, }, }; +#[cfg(target_os = "solana")] +use { + solana_program_entrypoint::{HEAP_LENGTH, HEAP_START_ADDRESS}, + std::{mem::size_of, ptr::null_mut}, +}; /// Developers can implement their own heap by defining their own /// `#[global_allocator]`. The following implements a dummy for test purposes @@ -55,7 +58,7 @@ unsafe impl std::alloc::GlobalAlloc for BumpAllocator { #[global_allocator] static A: BumpAllocator = BumpAllocator; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/dep_crate/Cargo.toml b/programs/sbf/rust/dep_crate/Cargo.toml index f583014cbac633..6902b2fd5ee802 100644 --- a/programs/sbf/rust/dep_crate/Cargo.toml +++ b/programs/sbf/rust/dep_crate/Cargo.toml @@ -8,9 +8,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -byteorder = { workspace = true } -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] + +[dependencies] +byteorder = { workspace = true } +solana-program-entrypoint = { workspace = true } diff --git a/programs/sbf/rust/dep_crate/src/lib.rs b/programs/sbf/rust/dep_crate/src/lib.rs index 9cdf32e2fcf991..e8b8365e1eaae6 100644 --- a/programs/sbf/rust/dep_crate/src/lib.rs +++ b/programs/sbf/rust/dep_crate/src/lib.rs @@ -1,9 +1,8 @@ //! Example Rust-based SBF program tests dependent crates -extern crate solana_program; use { byteorder::{ByteOrder, LittleEndian}, - solana_program::entrypoint::SUCCESS, + solana_program_entrypoint::SUCCESS, }; #[no_mangle] diff --git a/programs/sbf/rust/deprecated_loader/Cargo.toml b/programs/sbf/rust/deprecated_loader/Cargo.toml index a3dff0c68ed64f..2b13a127bcfa35 100644 --- a/programs/sbf/rust/deprecated_loader/Cargo.toml +++ b/programs/sbf/rust/deprecated_loader/Cargo.toml @@ -8,13 +8,20 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } solana-sbf-rust-invoke-dep = { workspace = true } solana-sbf-rust-realloc-dep = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-sdk-ids = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/deprecated_loader/src/lib.rs b/programs/sbf/rust/deprecated_loader/src/lib.rs index d0cb9b009ef3ec..38a5950614ab30 100644 --- a/programs/sbf/rust/deprecated_loader/src/lib.rs +++ b/programs/sbf/rust/deprecated_loader/src/lib.rs @@ -3,20 +3,16 @@ #![allow(unreachable_code)] #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; use { - solana_program::{ - account_info::AccountInfo, - bpf_loader, - entrypoint_deprecated::ProgramResult, - instruction::{AccountMeta, Instruction}, - log::*, - msg, - program::invoke, - pubkey::Pubkey, - }, + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_msg::msg, + solana_program::{log::sol_log_params, program::invoke}, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, solana_sbf_rust_invoke_dep::*, solana_sbf_rust_realloc_dep::*, + solana_sdk_ids::bpf_loader, }; #[derive(Debug, PartialEq)] @@ -57,7 +53,7 @@ fn process_instruction( let new_len = usize::from_le_bytes(bytes.try_into().unwrap()); msg!("realloc to {}", new_len); let account = &accounts[0]; - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(new_len, account.data_len()); } Some(&REALLOC_EXTEND_FROM_SLICE) => { @@ -65,7 +61,7 @@ fn process_instruction( let data = &instruction_data[1..]; let account = &accounts[0]; let prev_len = account.data_len(); - account.realloc(prev_len + data.len(), false)?; + account.resize(prev_len + data.len())?; account.data.borrow_mut()[prev_len..].copy_from_slice(data); } Some(&TEST_CPI_ACCOUNT_UPDATE_CALLER_GROWS) => { @@ -82,7 +78,7 @@ fn process_instruction( // whatever comes after the data slice (owner, executable, rent // epoch etc). When direct mapping is on, you get an // InvalidRealloc error. - account.realloc(prev_len + data.len(), false)?; + account.resize(prev_len + data.len())?; account.data.borrow_mut()[prev_len..].copy_from_slice(data); account.data.borrow().to_vec() }; @@ -135,7 +131,7 @@ fn process_instruction( ) .unwrap(); - if !solana_program::bpf_loader_deprecated::check_id(realloc_program_owner) { + if !solana_sdk_ids::bpf_loader_deprecated::check_id(realloc_program_owner) { assert_eq!(&*account.data.borrow(), &expected); } } @@ -169,7 +165,7 @@ fn process_instruction( // deserialize_parameters_unaligned predates realloc support, and // hardcodes the account data length to the original length. - if !solana_program::bpf_loader_deprecated::check_id(realloc_program_owner) { + if !solana_sdk_ids::bpf_loader_deprecated::check_id(realloc_program_owner) { assert_eq!(&*account.data.borrow(), &expected); assert_eq!( unsafe { @@ -193,7 +189,7 @@ fn process_instruction( let prev_data = { let data = &instruction_data[9..]; let prev_len = account.data_len(); - account.realloc(prev_len + data.len(), false)?; + account.resize(prev_len + data.len())?; account.data.borrow_mut()[prev_len..].copy_from_slice(data); unsafe { // write a sentinel value just outside the account data to @@ -247,7 +243,7 @@ fn process_instruction( const ARGUMENT_INDEX: usize = 0; let account = &accounts[ARGUMENT_INDEX]; let new_len = usize::from_le_bytes(instruction_data[1..9].try_into().unwrap()); - account.realloc(new_len, false).unwrap(); + account.resize(new_len).unwrap(); } _ => { { diff --git a/programs/sbf/rust/divide_by_zero/Cargo.toml b/programs/sbf/rust/divide_by_zero/Cargo.toml index eb4bf4e9f93f29..88ec81dce4c2cb 100644 --- a/programs/sbf/rust/divide_by_zero/Cargo.toml +++ b/programs/sbf/rust/divide_by_zero/Cargo.toml @@ -8,11 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/divide_by_zero/src/lib.rs b/programs/sbf/rust/divide_by_zero/src/lib.rs index 446faa0730dd2c..ad0f9f6e4f9c27 100644 --- a/programs/sbf/rust/divide_by_zero/src/lib.rs +++ b/programs/sbf/rust/divide_by_zero/src/lib.rs @@ -2,13 +2,12 @@ #![feature(asm_experimental_arch)] -extern crate solana_program; use { - solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey}, + solana_account_info::AccountInfo, solana_program_error::ProgramResult, solana_pubkey::Pubkey, std::arch::asm, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/dup_accounts/Cargo.toml b/programs/sbf/rust/dup_accounts/Cargo.toml index 03c1c57264afcc..514767f1e5192d 100644 --- a/programs/sbf/rust/dup_accounts/Cargo.toml +++ b/programs/sbf/rust/dup_accounts/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/dup_accounts/src/lib.rs b/programs/sbf/rust/dup_accounts/src/lib.rs index fb49994a79abf2..d12f8f797ef1eb 100644 --- a/programs/sbf/rust/dup_accounts/src/lib.rs +++ b/programs/sbf/rust/dup_accounts/src/lib.rs @@ -2,18 +2,16 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - msg, - program::invoke, - program_error::ProgramError, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_msg::msg, + solana_program::program::invoke, + solana_program_error::{ProgramError, ProgramResult}, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/error_handling/Cargo.toml b/programs/sbf/rust/error_handling/Cargo.toml index f07ca571dbe37d..885639dc5481f7 100644 --- a/programs/sbf/rust/error_handling/Cargo.toml +++ b/programs/sbf/rust/error_handling/Cargo.toml @@ -8,15 +8,19 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] num-derive = { workspace = true } num-traits = { workspace = true } +solana-account-info = { workspace = true } solana-decode-error = { workspace = true } -solana-program = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } thiserror = { workspace = true } -[lib] -crate-type = ["cdylib"] - [lints] workspace = true diff --git a/programs/sbf/rust/error_handling/src/lib.rs b/programs/sbf/rust/error_handling/src/lib.rs index b2c1a4d577e1dc..a24bc9704bdb33 100644 --- a/programs/sbf/rust/error_handling/src/lib.rs +++ b/programs/sbf/rust/error_handling/src/lib.rs @@ -1,17 +1,12 @@ //! Example Rust-based SBF program that exercises error handling -extern crate solana_program; use { num_derive::FromPrimitive, - num_traits::FromPrimitive, + solana_account_info::AccountInfo, solana_decode_error::DecodeError, - solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - msg, - program_error::{PrintProgramError, ProgramError}, - pubkey::{Pubkey, PubkeyError}, - }, + solana_msg::msg, + solana_program_error::{ProgramError, ProgramResult, ToStr}, + solana_pubkey::{Pubkey, PubkeyError}, thiserror::Error, }; @@ -33,19 +28,19 @@ impl DecodeError for MyError { "MyError" } } -impl PrintProgramError for MyError { - fn print(&self) +impl ToStr for MyError { + fn to_str(&self) -> &'static str where - E: 'static + std::error::Error + DecodeError + PrintProgramError + FromPrimitive, + E: 'static + ToStr + TryFrom, { match self { - MyError::DefaultEnumStart => msg!("Error: Default enum start"), - MyError::TheAnswer => msg!("Error: The Answer"), + MyError::DefaultEnumStart => "Error: Default enum start", + MyError::TheAnswer => "Error: The Answer", } } } -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/external_spend/Cargo.toml b/programs/sbf/rust/external_spend/Cargo.toml index 37401ff9e4b6ff..893ea8944ab45d 100644 --- a/programs/sbf/rust/external_spend/Cargo.toml +++ b/programs/sbf/rust/external_spend/Cargo.toml @@ -8,11 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/external_spend/src/lib.rs b/programs/sbf/rust/external_spend/src/lib.rs index ed5abce617f93c..b825ed21783760 100644 --- a/programs/sbf/rust/external_spend/src/lib.rs +++ b/programs/sbf/rust/external_spend/src/lib.rs @@ -2,10 +2,11 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; -use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey}; +use { + solana_account_info::AccountInfo, solana_program_error::ProgramResult, solana_pubkey::Pubkey, +}; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/get_minimum_delegation/Cargo.toml b/programs/sbf/rust/get_minimum_delegation/Cargo.toml index 3856d2294283f9..bfac975625cf53 100644 --- a/programs/sbf/rust/get_minimum_delegation/Cargo.toml +++ b/programs/sbf/rust/get_minimum_delegation/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-stake-interface = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/get_minimum_delegation/src/lib.rs b/programs/sbf/rust/get_minimum_delegation/src/lib.rs index d5df8448a37a3d..7dd0cb88a632b7 100644 --- a/programs/sbf/rust/get_minimum_delegation/src/lib.rs +++ b/programs/sbf/rust/get_minimum_delegation/src/lib.rs @@ -2,12 +2,12 @@ #![allow(unreachable_code)] -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey, stake, +use { + solana_account_info::AccountInfo, solana_msg::msg, solana_program_error::ProgramResult, + solana_pubkey::Pubkey, solana_stake_interface as stake, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/inner_instruction_alignment_check/Cargo.toml b/programs/sbf/rust/inner_instruction_alignment_check/Cargo.toml index 724f5503bb358f..2f8c0cad3705ac 100644 --- a/programs/sbf/rust/inner_instruction_alignment_check/Cargo.toml +++ b/programs/sbf/rust/inner_instruction_alignment_check/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/inner_instruction_alignment_check/src/lib.rs b/programs/sbf/rust/inner_instruction_alignment_check/src/lib.rs index 26632e9d2677dc..9946c3ab0c6638 100644 --- a/programs/sbf/rust/inner_instruction_alignment_check/src/lib.rs +++ b/programs/sbf/rust/inner_instruction_alignment_check/src/lib.rs @@ -1,13 +1,13 @@ //! Example Rust-based SBF noop program -use solana_program::{ - account_info::AccountInfo, - custom_heap_default, - entrypoint_deprecated::ProgramResult, - instruction::{AccountMeta, Instruction}, - msg, - program::invoke, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_msg::msg, + solana_program::program::invoke, + solana_program_entrypoint::custom_heap_default, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; solana_program::entrypoint_deprecated!(process_instruction); diff --git a/programs/sbf/rust/instruction_introspection/Cargo.toml b/programs/sbf/rust/instruction_introspection/Cargo.toml index 42c87a6acc3326..df3ad3d576da3e 100644 --- a/programs/sbf/rust/instruction_introspection/Cargo.toml +++ b/programs/sbf/rust/instruction_introspection/Cargo.toml @@ -8,11 +8,19 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-instructions-sysvar = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/instruction_introspection/src/lib.rs b/programs/sbf/rust/instruction_introspection/src/lib.rs index ef0763c663aeff..94632bc543deba 100644 --- a/programs/sbf/rust/instruction_introspection/src/lib.rs +++ b/programs/sbf/rust/instruction_introspection/src/lib.rs @@ -1,18 +1,16 @@ //! Example Rust-based SBF program that exercises instruction introspection -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - msg, - program::invoke, - program_error::ProgramError, - pubkey::Pubkey, - sysvar::instructions, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_instructions_sysvar as instructions, + solana_msg::msg, + solana_program::program::invoke, + solana_program_error::{ProgramError, ProgramResult}, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/invoke/Cargo.toml b/programs/sbf/rust/invoke/Cargo.toml index 94aaf9a851dec2..6fde6cec5bab6c 100644 --- a/programs/sbf/rust/invoke/Cargo.toml +++ b/programs/sbf/rust/invoke/Cargo.toml @@ -8,14 +8,23 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-program-memory = { workspace = true } +solana-pubkey = { workspace = true } solana-sbf-rust-invoke-dep = { workspace = true } solana-sbf-rust-invoked-dep = { workspace = true } solana-sbf-rust-realloc-dep = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-sdk-ids = { workspace = true } +solana-system-interface = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/invoke/src/lib.rs b/programs/sbf/rust/invoke/src/lib.rs index 88c420d1cbde2d..86a18c610c3888 100644 --- a/programs/sbf/rust/invoke/src/lib.rs +++ b/programs/sbf/rust/invoke/src/lib.rs @@ -4,25 +4,25 @@ #![allow(clippy::arithmetic_side_effects)] #[cfg(target_feature = "dynamic-frames")] -use solana_program::program_memory::sol_memcmp; +use solana_program_memory::sol_memcmp; use { + solana_account_info::AccountInfo, + solana_instruction::Instruction, + solana_msg::msg, solana_program::{ - account_info::AccountInfo, - bpf_loader_deprecated, - entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE}, - instruction::Instruction, - msg, program::{get_return_data, invoke, invoke_signed, set_return_data}, - program_error::ProgramError, - pubkey::{Pubkey, PubkeyError}, syscalls::{ MAX_CPI_ACCOUNT_INFOS, MAX_CPI_INSTRUCTION_ACCOUNTS, MAX_CPI_INSTRUCTION_DATA_LEN, }, - system_instruction, system_program, }, + solana_program_entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE}, + solana_program_error::ProgramError, + solana_pubkey::{Pubkey, PubkeyError}, solana_sbf_rust_invoke_dep::*, solana_sbf_rust_invoked_dep::*, solana_sbf_rust_realloc_dep::*, + solana_sdk_ids::bpf_loader_deprecated, + solana_system_interface::{instruction as system_instruction, program as system_program}, std::{cell::RefCell, mem, rc::Rc, slice}, }; @@ -67,7 +67,7 @@ fn do_nested_invokes(num_nested_invokes: u64, accounts: &[AccountInfo]) -> Progr Ok(()) } -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction<'a>( program_id: &Pubkey, accounts: &[AccountInfo<'a>], @@ -86,7 +86,7 @@ fn process_instruction<'a>( let from_lamports = accounts[FROM_INDEX].lamports(); let to_lamports = accounts[DERIVED_KEY1_INDEX].lamports(); assert_eq!(accounts[DERIVED_KEY1_INDEX].data_len(), 0); - assert!(solana_program::system_program::check_id( + assert!(solana_system_interface::program::check_id( accounts[DERIVED_KEY1_INDEX].owner )); @@ -770,7 +770,7 @@ fn process_instruction<'a>( let account = &accounts[ARGUMENT_INDEX]; let realloc_program_id = accounts[REALLOC_PROGRAM_INDEX].key; let invoke_program_id = accounts[INVOKE_PROGRAM_INDEX].key; - account.realloc(0, false).unwrap(); + account.resize(0).unwrap(); account.assign(realloc_program_id); // Place a RcBox> in the account data. This @@ -859,9 +859,9 @@ fn process_instruction<'a>( let target_account = &accounts[target_account_index]; let realloc_program_id = accounts[REALLOC_PROGRAM_INDEX].key; let invoke_program_id = accounts[INVOKE_PROGRAM_INDEX].key; - account.realloc(0, false).unwrap(); + account.resize(0).unwrap(); account.assign(realloc_program_id); - target_account.realloc(0, false).unwrap(); + target_account.resize(0).unwrap(); target_account.assign(realloc_program_id); let rc_box_addr = @@ -968,7 +968,7 @@ fn process_instruction<'a>( let expected = { let data = &instruction_data[1..]; let prev_len = account.data_len(); - account.realloc(prev_len + data.len(), false)?; + account.resize(prev_len + data.len())?; account.data.borrow_mut()[prev_len..].copy_from_slice(data); account.data.borrow().to_vec() }; @@ -1076,7 +1076,7 @@ fn process_instruction<'a>( let prev_data = { let data = &instruction_data[9..]; let prev_len = account.data_len(); - account.realloc(prev_len + data.len(), false)?; + account.resize(prev_len + data.len())?; account.data.borrow_mut()[prev_len..].copy_from_slice(data); unsafe { // write a sentinel value just outside the account data to @@ -1130,7 +1130,7 @@ fn process_instruction<'a>( const ARGUMENT_INDEX: usize = 0; let account = &accounts[ARGUMENT_INDEX]; let new_len = usize::from_le_bytes(instruction_data[1..9].try_into().unwrap()); - account.realloc(new_len, false).unwrap(); + account.resize(new_len).unwrap(); } TEST_CPI_INVALID_KEY_POINTER => { msg!("TEST_CPI_INVALID_KEY_POINTER"); @@ -1398,7 +1398,7 @@ fn process_instruction<'a>( let account = &accounts[ARGUMENT_INDEX]; if resize != 0 { - account.realloc(resize, false).unwrap(); + account.resize(resize).unwrap(); } if pre_write_offset != 0 { diff --git a/programs/sbf/rust/invoke_and_error/Cargo.toml b/programs/sbf/rust/invoke_and_error/Cargo.toml index 6427bc82629bbd..a7938fc328c65f 100644 --- a/programs/sbf/rust/invoke_and_error/Cargo.toml +++ b/programs/sbf/rust/invoke_and_error/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/invoke_and_error/src/lib.rs b/programs/sbf/rust/invoke_and_error/src/lib.rs index 86d6114827567d..29845940e5aba8 100644 --- a/programs/sbf/rust/invoke_and_error/src/lib.rs +++ b/programs/sbf/rust/invoke_and_error/src/lib.rs @@ -1,15 +1,15 @@ //! Invokes an instruction and returns an error, the instruction invoked //! uses the instruction data provided and all the accounts -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - program::invoke, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/invoke_and_ok/Cargo.toml b/programs/sbf/rust/invoke_and_ok/Cargo.toml index 9fbdda726c55b9..5b3f076e3c5ab6 100644 --- a/programs/sbf/rust/invoke_and_ok/Cargo.toml +++ b/programs/sbf/rust/invoke_and_ok/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/invoke_and_ok/src/lib.rs b/programs/sbf/rust/invoke_and_ok/src/lib.rs index fe624f7f98c3f7..e2ccad2bce545f 100644 --- a/programs/sbf/rust/invoke_and_ok/src/lib.rs +++ b/programs/sbf/rust/invoke_and_ok/src/lib.rs @@ -1,15 +1,15 @@ //! Invokes an instruction and return ok no matter what, the instruction invoked //! uses the instruction data provided and all the accounts -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - program::invoke, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/invoke_and_return/Cargo.toml b/programs/sbf/rust/invoke_and_return/Cargo.toml index b7cc9c5d7d00ea..d0fb4bc66db0f3 100644 --- a/programs/sbf/rust/invoke_and_return/Cargo.toml +++ b/programs/sbf/rust/invoke_and_return/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/invoke_and_return/src/lib.rs b/programs/sbf/rust/invoke_and_return/src/lib.rs index cdec1102e7c0e3..09bfc2ecefd565 100644 --- a/programs/sbf/rust/invoke_and_return/src/lib.rs +++ b/programs/sbf/rust/invoke_and_return/src/lib.rs @@ -1,15 +1,15 @@ //! Invokes an instruction and returns the invoke result, the instruction invoked //! uses the instruction data provided and all the accounts -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - program::invoke, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/invoked/Cargo.toml b/programs/sbf/rust/invoked/Cargo.toml index dcb0078d05e20e..3209c02d29b80a 100644 --- a/programs/sbf/rust/invoked/Cargo.toml +++ b/programs/sbf/rust/invoked/Cargo.toml @@ -8,12 +8,20 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } solana-sbf-rust-invoked-dep = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-sdk-ids = { workspace = true } +solana-system-interface = { workspace = true } +solana-sysvar = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/invoked/src/lib.rs b/programs/sbf/rust/invoked/src/lib.rs index ab92368a87a875..6531c56798ced6 100644 --- a/programs/sbf/rust/invoked/src/lib.rs +++ b/programs/sbf/rust/invoked/src/lib.rs @@ -3,21 +3,20 @@ #![allow(clippy::arithmetic_side_effects)] use { + solana_account_info::{AccountInfo, MAX_PERMITTED_DATA_INCREASE}, + solana_msg::msg, solana_program::{ - account_info::AccountInfo, - entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE}, - loader_v4, log::sol_log_64, - msg, program::{get_return_data, invoke, invoke_signed, set_return_data}, - program_error::ProgramError, - pubkey::Pubkey, - system_instruction, }, + solana_program_error::{ProgramError, ProgramResult}, + solana_pubkey::Pubkey, solana_sbf_rust_invoked_dep::*, + solana_sdk_ids::loader_v4, + solana_system_interface::instruction as system_instruction, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); #[allow(clippy::cognitive_complexity)] fn process_instruction( program_id: &Pubkey, @@ -254,7 +253,7 @@ fn process_instruction( let from_lamports = accounts[FROM_INDEX].lamports(); let to_lamports = accounts[DERIVED_KEY2_INDEX].lamports(); assert_eq!(accounts[DERIVED_KEY2_INDEX].data_len(), 0); - assert!(solana_program::system_program::check_id( + assert!(solana_system_interface::program::check_id( accounts[DERIVED_KEY2_INDEX].owner )); diff --git a/programs/sbf/rust/invoked_dep/Cargo.toml b/programs/sbf/rust/invoked_dep/Cargo.toml index 52cebbba70f172..a70b7d87bfd2d5 100644 --- a/programs/sbf/rust/invoked_dep/Cargo.toml +++ b/programs/sbf/rust/invoked_dep/Cargo.toml @@ -9,7 +9,8 @@ license = { workspace = true } edition = { workspace = true } [dependencies] -solana-program = { workspace = true } +solana-instruction = { workspace = true } +solana-pubkey = { workspace = true } [lib] crate-type = ["lib"] diff --git a/programs/sbf/rust/invoked_dep/src/lib.rs b/programs/sbf/rust/invoked_dep/src/lib.rs index 46a4f1d9f2f45c..89fcc4a291e011 100644 --- a/programs/sbf/rust/invoked_dep/src/lib.rs +++ b/programs/sbf/rust/invoked_dep/src/lib.rs @@ -1,8 +1,8 @@ //! Example Rust-based SBF program that issues a cross-program-invocation -use solana_program::{ - instruction::{AccountMeta, Instruction}, - pubkey::Pubkey, +use { + solana_instruction::{AccountMeta, Instruction}, + solana_pubkey::Pubkey, }; pub const VERIFY_TRANSLATIONS: u8 = 0; diff --git a/programs/sbf/rust/iter/Cargo.toml b/programs/sbf/rust/iter/Cargo.toml index f859f4fb44fd00..3b47da1d7e8fec 100644 --- a/programs/sbf/rust/iter/Cargo.toml +++ b/programs/sbf/rust/iter/Cargo.toml @@ -8,11 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/iter/src/lib.rs b/programs/sbf/rust/iter/src/lib.rs index 2128765e1349de..fa12bf5a9975c5 100644 --- a/programs/sbf/rust/iter/src/lib.rs +++ b/programs/sbf/rust/iter/src/lib.rs @@ -2,9 +2,9 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; -use solana_program::{ - custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, +use { + solana_program::log::sol_log_64, + solana_program_entrypoint::{custom_heap_default, custom_panic_default, SUCCESS}, }; #[no_mangle] diff --git a/programs/sbf/rust/log_data/Cargo.toml b/programs/sbf/rust/log_data/Cargo.toml index fc9a6ced55d488..0b909621d0e3df 100644 --- a/programs/sbf/rust/log_data/Cargo.toml +++ b/programs/sbf/rust/log_data/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/log_data/src/lib.rs b/programs/sbf/rust/log_data/src/lib.rs index b4c67634e22c87..f8e78f0886d25a 100644 --- a/programs/sbf/rust/log_data/src/lib.rs +++ b/programs/sbf/rust/log_data/src/lib.rs @@ -1,11 +1,13 @@ //! Example Rust-based SBF program that uses sol_log_data syscall -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, log::sol_log_data, - program::set_return_data, pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_program::{log::sol_log_data, program::set_return_data}, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); #[allow(clippy::cognitive_complexity)] fn process_instruction( _program_id: &Pubkey, diff --git a/programs/sbf/rust/many_args/Cargo.toml b/programs/sbf/rust/many_args/Cargo.toml index 2ec3671be62d38..539eb64b5ab36e 100644 --- a/programs/sbf/rust/many_args/Cargo.toml +++ b/programs/sbf/rust/many_args/Cargo.toml @@ -8,12 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] +solana-msg = { workspace = true } solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } solana-sbf-rust-many-args-dep = { workspace = true } -[lib] -crate-type = ["cdylib"] - [lints] workspace = true diff --git a/programs/sbf/rust/many_args/src/helper.rs b/programs/sbf/rust/many_args/src/helper.rs index 72c89fc060a6b3..95872c086e08b2 100644 --- a/programs/sbf/rust/many_args/src/helper.rs +++ b/programs/sbf/rust/many_args/src/helper.rs @@ -2,8 +2,7 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; -use solana_program::log::*; +use solana_program::log::{sol_log, sol_log_64}; pub fn many_args( arg1: u64, diff --git a/programs/sbf/rust/many_args/src/lib.rs b/programs/sbf/rust/many_args/src/lib.rs index e90fd54e129a96..72b4f5ad7efd8a 100644 --- a/programs/sbf/rust/many_args/src/lib.rs +++ b/programs/sbf/rust/many_args/src/lib.rs @@ -1,8 +1,10 @@ //! Example Rust-based SBF program tests loop iteration mod helper; -extern crate solana_program; -use solana_program::{custom_heap_default, custom_panic_default, entrypoint::SUCCESS, msg}; +use { + solana_msg::msg, + solana_program_entrypoint::{custom_heap_default, custom_panic_default, SUCCESS}, +}; #[no_mangle] pub extern "C" fn entrypoint(_input: *mut u8) -> u64 { diff --git a/programs/sbf/rust/many_args_dep/Cargo.toml b/programs/sbf/rust/many_args_dep/Cargo.toml index d1c14406b7ccde..0dde7fc44ccea0 100644 --- a/programs/sbf/rust/many_args_dep/Cargo.toml +++ b/programs/sbf/rust/many_args_dep/Cargo.toml @@ -9,4 +9,5 @@ license = { workspace = true } edition = { workspace = true } [dependencies] +solana-msg = { workspace = true } solana-program = { workspace = true } diff --git a/programs/sbf/rust/many_args_dep/src/lib.rs b/programs/sbf/rust/many_args_dep/src/lib.rs index 263b0e1ce01c65..af1eb00d46c21a 100644 --- a/programs/sbf/rust/many_args_dep/src/lib.rs +++ b/programs/sbf/rust/many_args_dep/src/lib.rs @@ -2,8 +2,7 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; -use solana_program::{log::sol_log_64, msg}; +use {solana_msg::msg, solana_program::log::sol_log_64}; pub fn many_args( arg1: u64, diff --git a/programs/sbf/rust/mem/Cargo.toml b/programs/sbf/rust/mem/Cargo.toml index ed5668bbdc6c6f..35dc8a90b74cf7 100644 --- a/programs/sbf/rust/mem/Cargo.toml +++ b/programs/sbf/rust/mem/Cargo.toml @@ -8,12 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } -solana-sbf-rust-mem-dep = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-program-memory = { workspace = true } +solana-pubkey = { workspace = true } +solana-sbf-rust-mem-dep = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/mem/src/lib.rs b/programs/sbf/rust/mem/src/lib.rs index 52da6609c88723..0fb4aac820bd34 100644 --- a/programs/sbf/rust/mem/src/lib.rs +++ b/programs/sbf/rust/mem/src/lib.rs @@ -1,16 +1,14 @@ //! Test mem functions use { - solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - program_memory::{sol_memcmp, sol_memcpy, sol_memmove, sol_memset}, - pubkey::Pubkey, - }, + solana_account_info::AccountInfo, + solana_program_error::ProgramResult, + solana_program_memory::{sol_memcmp, sol_memcpy, sol_memmove, sol_memset}, + solana_pubkey::Pubkey, solana_sbf_rust_mem_dep::{run_mem_tests, MemOps}, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/mem_dep/Cargo.toml b/programs/sbf/rust/mem_dep/Cargo.toml index def7109a05317a..8b0ef1caed90a4 100644 --- a/programs/sbf/rust/mem_dep/Cargo.toml +++ b/programs/sbf/rust/mem_dep/Cargo.toml @@ -8,8 +8,7 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["lib"] + +[dependencies] diff --git a/programs/sbf/rust/membuiltins/Cargo.toml b/programs/sbf/rust/membuiltins/Cargo.toml index 405feffd4effb9..5d45b7c61f06f3 100644 --- a/programs/sbf/rust/membuiltins/Cargo.toml +++ b/programs/sbf/rust/membuiltins/Cargo.toml @@ -8,12 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } -solana-sbf-rust-mem-dep = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-program-entrypoint = { workspace = true } +solana-sbf-rust-mem-dep = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/membuiltins/src/lib.rs b/programs/sbf/rust/membuiltins/src/lib.rs index 155a90a98c95f7..da41a6634673a4 100644 --- a/programs/sbf/rust/membuiltins/src/lib.rs +++ b/programs/sbf/rust/membuiltins/src/lib.rs @@ -5,7 +5,7 @@ extern crate compiler_builtins; use { - solana_program::{custom_heap_default, custom_panic_default, entrypoint::SUCCESS}, + solana_program_entrypoint::{custom_heap_default, custom_panic_default, SUCCESS}, solana_sbf_rust_mem_dep::{run_mem_tests, MemOps}, }; diff --git a/programs/sbf/rust/noop/Cargo.toml b/programs/sbf/rust/noop/Cargo.toml index f2cdff7f18e5f8..81c9864775efe8 100644 --- a/programs/sbf/rust/noop/Cargo.toml +++ b/programs/sbf/rust/noop/Cargo.toml @@ -8,11 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/noop/src/lib.rs b/programs/sbf/rust/noop/src/lib.rs index c3b8f7962bc862..92d4774e5f81d7 100644 --- a/programs/sbf/rust/noop/src/lib.rs +++ b/programs/sbf/rust/noop/src/lib.rs @@ -1,11 +1,12 @@ //! Example Rust-based SBF noop program -extern crate solana_program; -use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey}; +use { + solana_account_info::AccountInfo, solana_program_error::ProgramResult, solana_pubkey::Pubkey, +}; // This program intentionally uses `entrypoint!` instead of `entrypoint_no_alloc!` // to handle any number of accounts. -solana_program::entrypoint!(process_instruction); +solana_program_entrypoint::entrypoint!(process_instruction); fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/panic/Cargo.toml b/programs/sbf/rust/panic/Cargo.toml index 46f99056ac901e..abebc7e317bdbd 100644 --- a/programs/sbf/rust/panic/Cargo.toml +++ b/programs/sbf/rust/panic/Cargo.toml @@ -8,15 +8,19 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } +[lib] +crate-type = ["cdylib"] [features] default = ["custom-panic"] custom-panic = [] -[lib] -crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/panic/src/lib.rs b/programs/sbf/rust/panic/src/lib.rs index d7b5f99d14ff68..82f6f718e438be 100644 --- a/programs/sbf/rust/panic/src/lib.rs +++ b/programs/sbf/rust/panic/src/lib.rs @@ -4,14 +4,15 @@ #[no_mangle] fn custom_panic(info: &core::panic::PanicInfo<'_>) { // Note: Full panic reporting is included here for testing purposes - solana_program::msg!("program custom panic enabled"); - solana_program::msg!(&format!("{info}")); + solana_msg::msg!("program custom panic enabled"); + solana_msg::msg!(&format!("{info}")); } -extern crate solana_program; -use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey}; +use { + solana_account_info::AccountInfo, solana_program_error::ProgramResult, solana_pubkey::Pubkey, +}; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/param_passing/Cargo.toml b/programs/sbf/rust/param_passing/Cargo.toml index 43bb48c4fcdee0..7a77418e2bbd16 100644 --- a/programs/sbf/rust/param_passing/Cargo.toml +++ b/programs/sbf/rust/param_passing/Cargo.toml @@ -8,12 +8,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } solana-sbf-rust-param-passing-dep = { workspace = true } -[lib] -crate-type = ["cdylib"] - [lints] workspace = true diff --git a/programs/sbf/rust/param_passing/src/lib.rs b/programs/sbf/rust/param_passing/src/lib.rs index 263bce70f4e08b..b7505edecefe5f 100644 --- a/programs/sbf/rust/param_passing/src/lib.rs +++ b/programs/sbf/rust/param_passing/src/lib.rs @@ -1,10 +1,8 @@ //! Example Rust-based SBF program tests loop iteration -extern crate solana_program; use { - solana_program::{ - custom_heap_default, custom_panic_default, entrypoint::SUCCESS, log::sol_log_64, - }, + solana_program::log::sol_log_64, + solana_program_entrypoint::{custom_heap_default, custom_panic_default, SUCCESS}, solana_sbf_rust_param_passing_dep::{Data, TestDep}, }; diff --git a/programs/sbf/rust/param_passing_dep/Cargo.toml b/programs/sbf/rust/param_passing_dep/Cargo.toml index 930ece46ac989d..7c85e0cf5cf033 100644 --- a/programs/sbf/rust/param_passing_dep/Cargo.toml +++ b/programs/sbf/rust/param_passing_dep/Cargo.toml @@ -9,4 +9,3 @@ license = { workspace = true } edition = { workspace = true } [dependencies] -solana-program = { workspace = true } diff --git a/programs/sbf/rust/param_passing_dep/src/lib.rs b/programs/sbf/rust/param_passing_dep/src/lib.rs index 9407327eeb8481..d4965295f05932 100644 --- a/programs/sbf/rust/param_passing_dep/src/lib.rs +++ b/programs/sbf/rust/param_passing_dep/src/lib.rs @@ -2,8 +2,6 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; - #[derive(Debug)] pub struct Data<'a> { pub twentyone: u64, diff --git a/programs/sbf/rust/poseidon/Cargo.toml b/programs/sbf/rust/poseidon/Cargo.toml index 4c70ea83242e44..d84a9572ee8144 100644 --- a/programs/sbf/rust/poseidon/Cargo.toml +++ b/programs/sbf/rust/poseidon/Cargo.toml @@ -8,13 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] array-bytes = { workspace = true } +solana-msg = { workspace = true } solana-poseidon = { workspace = true } -solana-program = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-program-entrypoint = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/poseidon/src/lib.rs b/programs/sbf/rust/poseidon/src/lib.rs index 823bfaed8ea204..dc5d161c317d75 100644 --- a/programs/sbf/rust/poseidon/src/lib.rs +++ b/programs/sbf/rust/poseidon/src/lib.rs @@ -1,8 +1,9 @@ //! Example SBF program using Poseidon syscall use { + solana_msg::msg, solana_poseidon::{hashv, Endianness, Parameters, PoseidonSyscallError}, - solana_program::{custom_heap_default, custom_panic_default, msg}, + solana_program_entrypoint::{custom_heap_default, custom_panic_default}, }; fn test_poseidon_input_ones_twos() -> Result<(), PoseidonSyscallError> { diff --git a/programs/sbf/rust/rand/Cargo.toml b/programs/sbf/rust/rand/Cargo.toml index 4a8087f8229c56..ffc21817f422fe 100644 --- a/programs/sbf/rust/rand/Cargo.toml +++ b/programs/sbf/rust/rand/Cargo.toml @@ -8,13 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] getrandom = { workspace = true, features = ["custom"] } rand = { workspace = true } -solana-program = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/rand/src/lib.rs b/programs/sbf/rust/rand/src/lib.rs index e4241b67ecaa81..311db9565c0738 100644 --- a/programs/sbf/rust/rand/src/lib.rs +++ b/programs/sbf/rust/rand/src/lib.rs @@ -2,10 +2,12 @@ #![allow(unreachable_code)] -extern crate solana_program; -use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey}; +use { + solana_account_info::AccountInfo, solana_msg::msg, solana_program_error::ProgramResult, + solana_pubkey::Pubkey, +}; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/realloc/Cargo.toml b/programs/sbf/rust/realloc/Cargo.toml index 8d61550795393b..c493bc806505ca 100644 --- a/programs/sbf/rust/realloc/Cargo.toml +++ b/programs/sbf/rust/realloc/Cargo.toml @@ -8,12 +8,18 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } solana-sbf-rust-realloc-dep = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-system-interface = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/realloc/src/lib.rs b/programs/sbf/rust/realloc/src/lib.rs index 8e2bf3f211d6da..e57030de8ab835 100644 --- a/programs/sbf/rust/realloc/src/lib.rs +++ b/programs/sbf/rust/realloc/src/lib.rs @@ -2,21 +2,18 @@ #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; use { - solana_program::{ - account_info::AccountInfo, - entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE}, - msg, - program::invoke, - pubkey::Pubkey, - system_instruction, system_program, - }, + solana_account_info::{AccountInfo, MAX_PERMITTED_DATA_INCREASE}, + solana_msg::msg, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, solana_sbf_rust_realloc_dep::*, + solana_system_interface::{instruction as system_instruction, program as system_program}, std::{convert::TryInto, mem}, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], @@ -29,7 +26,7 @@ fn process_instruction( let (bytes, _) = instruction_data[2..].split_at(std::mem::size_of::()); let new_len = usize::from_le_bytes(bytes.try_into().unwrap()); msg!("realloc to {}", new_len); - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(new_len, account.data_len()); } REALLOC_EXTEND => { @@ -37,7 +34,7 @@ fn process_instruction( let (bytes, _) = instruction_data[2..].split_at(std::mem::size_of::()); let new_len = pre_len.saturating_add(usize::from_le_bytes(bytes.try_into().unwrap())); msg!("realloc extend by {}", new_len); - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(new_len, account.data_len()); } REALLOC_EXTEND_AND_UNDO => { @@ -45,9 +42,9 @@ fn process_instruction( let (bytes, _) = instruction_data[2..].split_at(std::mem::size_of::()); let new_len = pre_len.saturating_add(usize::from_le_bytes(bytes.try_into().unwrap())); msg!("realloc extend by {}", new_len); - account.realloc(new_len, false)?; + account.resize(new_len)?; msg!("undo realloc"); - account.realloc(pre_len, false)?; + account.resize(pre_len)?; assert_eq!(pre_len, account.data_len()); } REALLOC_EXTEND_AND_FILL => { @@ -56,7 +53,7 @@ fn process_instruction( let (bytes, _) = instruction_data[4..].split_at(std::mem::size_of::()); let new_len = pre_len.saturating_add(usize::from_le_bytes(bytes.try_into().unwrap())); msg!("realloc extend by {}", new_len); - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(new_len, account.data_len()); account.try_borrow_mut_data()?[pre_len..].fill(fill); } @@ -66,7 +63,7 @@ fn process_instruction( let pre_len = account.data_len(); let new_len = mem::size_of::(); assert!(pre_len < new_len); - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(new_len, account.data_len()); let (bytes, _) = instruction_data[1..].split_at(new_len); @@ -98,7 +95,7 @@ fn process_instruction( } REALLOC_AND_ASSIGN => { msg!("realloc and assign"); - account.realloc(MAX_PERMITTED_DATA_INCREASE, false)?; + account.resize(MAX_PERMITTED_DATA_INCREASE)?; assert_eq!(MAX_PERMITTED_DATA_INCREASE, account.data_len()); account.assign(&system_program::id()); assert_eq!(*account.owner, system_program::id()); @@ -106,7 +103,15 @@ fn process_instruction( REALLOC_AND_ASSIGN_TO_SELF_VIA_SYSTEM_PROGRAM => { msg!("realloc and assign to self via system program"); let pre_len = account.data_len(); - account.realloc(pre_len.saturating_add(MAX_PERMITTED_DATA_INCREASE), false)?; + let new_len = pre_len.saturating_add(MAX_PERMITTED_DATA_INCREASE); + unsafe { + let mut data = account.data.borrow_mut(); + let data_ptr = data.as_mut_ptr(); + // First set new length in the serialized data + *(data_ptr.offset(-8) as *mut u64) = new_len as u64; + // Then recreate the local slice with the new length + *data = std::slice::from_raw_parts_mut(data_ptr, new_len) + } assert_eq!( pre_len.saturating_add(MAX_PERMITTED_DATA_INCREASE), account.data_len() @@ -125,7 +130,7 @@ fn process_instruction( accounts, )?; assert_eq!(account.owner, program_id); - account.realloc(pre_len.saturating_add(MAX_PERMITTED_DATA_INCREASE), false)?; + account.resize(pre_len.saturating_add(MAX_PERMITTED_DATA_INCREASE))?; assert_eq!( account.data_len(), pre_len.saturating_add(MAX_PERMITTED_DATA_INCREASE) @@ -133,7 +138,7 @@ fn process_instruction( } DEALLOC_AND_ASSIGN_TO_CALLER => { msg!("dealloc and assign to caller"); - account.realloc(0, false)?; + account.resize(0)?; assert_eq!(account.data_len(), 0); account.assign(accounts[1].key); assert_eq!(account.owner, accounts[1].key); @@ -150,7 +155,7 @@ fn process_instruction( } } ZERO_INIT => { - account.realloc(10, false)?; + account.resize(10)?; { let mut data = account.try_borrow_mut_data()?; for i in 0..10 { @@ -162,17 +167,8 @@ fn process_instruction( } } - account.realloc(5, false)?; - account.realloc(10, false)?; - { - let data = account.try_borrow_data()?; - for i in 0..10 { - assert_eq!(1, data[i]); - } - } - - account.realloc(5, false)?; - account.realloc(10, true)?; + account.resize(5)?; + account.resize(10)?; { let data = account.try_borrow_data()?; for i in 0..5 { @@ -187,7 +183,7 @@ fn process_instruction( msg!("realloc extend from slice"); let data = &instruction_data[1..]; let prev_len = account.data_len(); - account.realloc(prev_len.saturating_add(data.len()), false)?; + account.resize(prev_len.saturating_add(data.len()))?; account.data.borrow_mut()[prev_len..].copy_from_slice(data); } _ => panic!(), diff --git a/programs/sbf/rust/realloc_dep/Cargo.toml b/programs/sbf/rust/realloc_dep/Cargo.toml index 40b01115e09c64..c2b90bb6f4aa4f 100644 --- a/programs/sbf/rust/realloc_dep/Cargo.toml +++ b/programs/sbf/rust/realloc_dep/Cargo.toml @@ -9,7 +9,8 @@ license = { workspace = true } edition = { workspace = true } [dependencies] -solana-program = { workspace = true } +solana-instruction = { workspace = true } +solana-pubkey = { workspace = true } [lib] crate-type = ["lib"] diff --git a/programs/sbf/rust/realloc_dep/src/lib.rs b/programs/sbf/rust/realloc_dep/src/lib.rs index e15ba5d48c5e21..4ff808f6ccfe53 100644 --- a/programs/sbf/rust/realloc_dep/src/lib.rs +++ b/programs/sbf/rust/realloc_dep/src/lib.rs @@ -1,8 +1,8 @@ //! Example Rust-based SBF realloc test program -use solana_program::{ - instruction::{AccountMeta, Instruction}, - pubkey::Pubkey, +use { + solana_instruction::{AccountMeta, Instruction}, + solana_pubkey::Pubkey, }; pub const REALLOC: u8 = 1; diff --git a/programs/sbf/rust/realloc_invoke/Cargo.toml b/programs/sbf/rust/realloc_invoke/Cargo.toml index 010fd1550f66ea..61342677b4734e 100644 --- a/programs/sbf/rust/realloc_invoke/Cargo.toml +++ b/programs/sbf/rust/realloc_invoke/Cargo.toml @@ -8,13 +8,20 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } solana-sbf-rust-realloc-dep = { workspace = true } solana-sbf-rust-realloc-invoke-dep = { workspace = true } - -[lib] -crate-type = ["cdylib"] +solana-system-interface = { workspace = true } [lints] workspace = true diff --git a/programs/sbf/rust/realloc_invoke/src/lib.rs b/programs/sbf/rust/realloc_invoke/src/lib.rs index 7ccda1b2395c05..41ad6eaf07415e 100644 --- a/programs/sbf/rust/realloc_invoke/src/lib.rs +++ b/programs/sbf/rust/realloc_invoke/src/lib.rs @@ -1,22 +1,19 @@ //! Example Rust-based SBF realloc test program -extern crate solana_program; use { - solana_program::{ - account_info::AccountInfo, - entrypoint::{ProgramResult, MAX_PERMITTED_DATA_INCREASE}, - instruction::{AccountMeta, Instruction}, - msg, - program::invoke, - pubkey::Pubkey, - system_instruction, system_program, - }, + solana_account_info::{AccountInfo, MAX_PERMITTED_DATA_INCREASE}, + solana_instruction::{AccountMeta, Instruction}, + solana_msg::msg, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, solana_sbf_rust_realloc_dep::*, solana_sbf_rust_realloc_invoke_dep::*, + solana_system_interface::{instruction as system_instruction, program as system_program}, std::convert::TryInto, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], @@ -94,7 +91,7 @@ fn process_instruction( let (bytes, _) = remaining_data.split_at(std::mem::size_of::()); let extend_len = usize::from_le_bytes(bytes.try_into().unwrap()); msg!("realloc extend {} byte(s)", extend_len); - account.realloc(new_len.saturating_add(extend_len), false)?; + account.resize(new_len.saturating_add(extend_len))?; assert_eq!(new_len.saturating_add(extend_len), account.data_len()); } INVOKE_REALLOC_MAX_TWICE => { @@ -110,7 +107,7 @@ fn process_instruction( )?; let new_len = pre_len.saturating_add(MAX_PERMITTED_DATA_INCREASE); assert_eq!(new_len, account.data_len()); - account.realloc(new_len.saturating_add(MAX_PERMITTED_DATA_INCREASE), false)?; + account.resize(new_len.saturating_add(MAX_PERMITTED_DATA_INCREASE))?; assert_eq!( new_len.saturating_add(MAX_PERMITTED_DATA_INCREASE), account.data_len() @@ -162,7 +159,7 @@ fn process_instruction( } INVOKE_REALLOC_INVOKE_CHECK => { msg!("realloc invoke check size"); - account.realloc(100, false)?; + account.resize(100)?; assert_eq!(100, account.data_len()); account.try_borrow_mut_data()?[pre_len..].fill(2); invoke( @@ -178,7 +175,7 @@ fn process_instruction( let (bytes, _) = instruction_data[2..].split_at(std::mem::size_of::()); let new_len = usize::from_le_bytes(bytes.try_into().unwrap()); msg!("realloc to {}", new_len); - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(new_len, account.data_len()); if pre_len < new_len { account.try_borrow_mut_data()?[pre_len..].fill(instruction_data[1]); @@ -188,7 +185,7 @@ fn process_instruction( msg!("realloc invoke recursive"); let (bytes, _) = instruction_data[2..].split_at(std::mem::size_of::()); let new_len = usize::from_le_bytes(bytes.try_into().unwrap()); - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(new_len, account.data_len()); account.try_borrow_mut_data()?[pre_len..].fill(instruction_data[1]); let final_len: usize = 200; @@ -229,7 +226,7 @@ fn process_instruction( accounts, )?; assert_eq!(pre_len, accounts[1].data_len()); - accounts[1].realloc(pre_len.saturating_add(1), false)?; + accounts[1].resize(pre_len.saturating_add(1))?; assert_eq!(pre_len.saturating_add(1), accounts[1].data_len()); assert_eq!(accounts[1].owner, program_id); let final_len: usize = 200; @@ -275,7 +272,7 @@ fn process_instruction( )?; assert_eq!(account.owner, program_id); assert_eq!(account.data_len(), 0); - account.realloc(new_len, false)?; + account.resize(new_len)?; assert_eq!(account.data_len(), new_len); { let data = account.try_borrow_mut_data()?; @@ -287,7 +284,7 @@ fn process_instruction( INVOKE_REALLOC_MAX_INVOKE_MAX => { msg!("invoke realloc max invoke max"); assert_eq!(0, account.data_len()); - account.realloc(MAX_PERMITTED_DATA_INCREASE, false)?; + account.resize(MAX_PERMITTED_DATA_INCREASE)?; assert_eq!(MAX_PERMITTED_DATA_INCREASE, account.data_len()); account.assign(invoke_program_id); assert_eq!(account.owner, invoke_program_id); diff --git a/programs/sbf/rust/remaining_compute_units/Cargo.toml b/programs/sbf/rust/remaining_compute_units/Cargo.toml index 3dceb27455ee23..7cc32b4a8e5769 100644 --- a/programs/sbf/rust/remaining_compute_units/Cargo.toml +++ b/programs/sbf/rust/remaining_compute_units/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/remaining_compute_units/src/lib.rs b/programs/sbf/rust/remaining_compute_units/src/lib.rs index 4259799e0add1a..91d9dd15e27424 100644 --- a/programs/sbf/rust/remaining_compute_units/src/lib.rs +++ b/programs/sbf/rust/remaining_compute_units/src/lib.rs @@ -1,11 +1,11 @@ //! @brief Example Rust-based BPF program that exercises the sol_remaining_compute_units syscall -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, compute_units::sol_remaining_compute_units, - entrypoint::ProgramResult, msg, pubkey::Pubkey, +use { + solana_account_info::AccountInfo, solana_msg::msg, + solana_program::compute_units::sol_remaining_compute_units, + solana_program_error::ProgramResult, solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( _program_id: &Pubkey, _accounts: &[AccountInfo], diff --git a/programs/sbf/rust/ro_account_modify/Cargo.toml b/programs/sbf/rust/ro_account_modify/Cargo.toml index c9f6b94e4ece4b..a22e0bde5adc6f 100644 --- a/programs/sbf/rust/ro_account_modify/Cargo.toml +++ b/programs/sbf/rust/ro_account_modify/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/ro_account_modify/src/lib.rs b/programs/sbf/rust/ro_account_modify/src/lib.rs index 3fca230c183915..485e88f7128f6a 100644 --- a/programs/sbf/rust/ro_account_modify/src/lib.rs +++ b/programs/sbf/rust/ro_account_modify/src/lib.rs @@ -1,10 +1,10 @@ -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - msg, - program::invoke, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_msg::msg, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; const ARGUMENT_INDEX: usize = 0; @@ -14,7 +14,7 @@ const INSTRUCTION_INVOKE_MODIFY: u8 = 1; const INSTRUCTION_MODIFY_INVOKE: u8 = 2; const INSTRUCTION_VERIFY_MODIFIED: u8 = 3; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/ro_modify/Cargo.toml b/programs/sbf/rust/ro_modify/Cargo.toml index 566734108df255..ac66c703881c1c 100644 --- a/programs/sbf/rust/ro_modify/Cargo.toml +++ b/programs/sbf/rust/ro_modify/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-system-interface = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/ro_modify/src/lib.rs b/programs/sbf/rust/ro_modify/src/lib.rs index de005569efafcd..80ecf1325563cc 100644 --- a/programs/sbf/rust/ro_modify/src/lib.rs +++ b/programs/sbf/rust/ro_modify/src/lib.rs @@ -1,8 +1,12 @@ #![cfg(target_os = "solana")] -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, msg, program::invoke, - program_error::ProgramError, pubkey::Pubkey, syscalls::sol_invoke_signed_c, system_instruction, +use { + solana_account_info::AccountInfo, + solana_msg::msg, + solana_program::{program::invoke, syscalls::sol_invoke_signed_c}, + solana_program_error::{ProgramError, ProgramResult}, + solana_pubkey::Pubkey, + solana_system_interface::instruction as system_instruction, }; #[derive(Debug)] @@ -92,7 +96,7 @@ fn check_preconditions( Ok(()) } -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/sanity/Cargo.toml b/programs/sbf/rust/sanity/Cargo.toml index d5c47f9deb46b2..5c99b006e46317 100644 --- a/programs/sbf/rust/sanity/Cargo.toml +++ b/programs/sbf/rust/sanity/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-sdk-ids = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/sanity/src/lib.rs b/programs/sbf/rust/sanity/src/lib.rs index cb4cbc6353624c..b8cacf22795435 100644 --- a/programs/sbf/rust/sanity/src/lib.rs +++ b/programs/sbf/rust/sanity/src/lib.rs @@ -3,10 +3,16 @@ #![allow(unreachable_code)] #![allow(clippy::arithmetic_side_effects)] -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, bpf_loader, entrypoint::ProgramResult, log::*, msg, - program::check_type_assumptions, pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_msg::msg, + solana_program::{ + log::{sol_log_compute_units, sol_log_params}, + program::check_type_assumptions, + }, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, + solana_sdk_ids::bpf_loader, }; #[derive(Debug, PartialEq)] @@ -36,7 +42,7 @@ fn return_sstruct() -> SStruct { SStruct { x: 1, y: 2, z: 3 } } -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/secp256k1_recover/Cargo.toml b/programs/sbf/rust/secp256k1_recover/Cargo.toml index 357bf03e14e591..6615cfb4b290cb 100644 --- a/programs/sbf/rust/secp256k1_recover/Cargo.toml +++ b/programs/sbf/rust/secp256k1_recover/Cargo.toml @@ -8,13 +8,15 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib"] + [dependencies] libsecp256k1 = { workspace = true } -solana-program = { workspace = true } +solana-keccak-hasher = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } solana-secp256k1-recover = { workspace = true } -[lib] -crate-type = ["cdylib"] - [lints] workspace = true diff --git a/programs/sbf/rust/secp256k1_recover/src/lib.rs b/programs/sbf/rust/secp256k1_recover/src/lib.rs index 09b239e090a147..1b749d5aef1565 100644 --- a/programs/sbf/rust/secp256k1_recover/src/lib.rs +++ b/programs/sbf/rust/secp256k1_recover/src/lib.rs @@ -1,9 +1,9 @@ #![allow(clippy::arithmetic_side_effects)] //! Secp256k1Recover Syscall test -extern crate solana_program; use { - solana_program::{custom_heap_default, custom_panic_default, msg}, + solana_msg::msg, + solana_program_entrypoint::{custom_heap_default, custom_panic_default}, solana_secp256k1_recover::secp256k1_recover, }; @@ -38,7 +38,7 @@ fn test_secp256k1_recover() { fn test_secp256k1_recover_malleability() { let message = b"hello world"; let message_hash = { - let mut hasher = solana_program::keccak::Hasher::default(); + let mut hasher = solana_keccak_hasher::Hasher::default(); hasher.hash(message); hasher.result() }; diff --git a/programs/sbf/rust/sha/Cargo.toml b/programs/sbf/rust/sha/Cargo.toml index d5f13a040537b9..16fd6658852c2f 100644 --- a/programs/sbf/rust/sha/Cargo.toml +++ b/programs/sbf/rust/sha/Cargo.toml @@ -8,12 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -blake3 = { workspace = true } -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +blake3 = { workspace = true } +solana-blake3-hasher = { workspace = true } +solana-keccak-hasher = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-sha256-hasher = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/sha/src/lib.rs b/programs/sbf/rust/sha/src/lib.rs index bc1579b22bd744..3763969a13aa06 100644 --- a/programs/sbf/rust/sha/src/lib.rs +++ b/programs/sbf/rust/sha/src/lib.rs @@ -1,10 +1,12 @@ //! SHA Syscall test -extern crate solana_program; -use solana_program::{custom_heap_default, custom_panic_default, msg}; +use { + solana_msg::msg, + solana_program_entrypoint::{custom_heap_default, custom_panic_default}, +}; fn test_sha256_hasher() { - use solana_program::hash::{hashv, Hasher}; + use solana_sha256_hasher::{hashv, Hasher}; let vals = &["Gaggablaghblagh!".as_ref(), "flurbos".as_ref()]; let mut hasher = Hasher::default(); hasher.hashv(vals); @@ -12,7 +14,7 @@ fn test_sha256_hasher() { } fn test_keccak256_hasher() { - use solana_program::keccak::{hashv, Hasher}; + use solana_keccak_hasher::{hashv, Hasher}; let vals = &["Gaggablaghblagh!".as_ref(), "flurbos".as_ref()]; let mut hasher = Hasher::default(); hasher.hashv(vals); @@ -20,7 +22,7 @@ fn test_keccak256_hasher() { } fn test_blake3_hasher() { - use solana_program::blake3::hashv; + use solana_blake3_hasher::hashv; let v0: &[u8] = b"Gaggablaghblagh!"; let v1: &[u8] = b"flurbos!"; let vals: &[&[u8]] = &[v0, v1]; diff --git a/programs/sbf/rust/sibling_inner_instructions/Cargo.toml b/programs/sbf/rust/sibling_inner_instructions/Cargo.toml index f77323954bbfd8..de135369ba4c18 100644 --- a/programs/sbf/rust/sibling_inner_instructions/Cargo.toml +++ b/programs/sbf/rust/sibling_inner_instructions/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true, features = ["syscalls"] } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/sibling_inner_instructions/src/lib.rs b/programs/sbf/rust/sibling_inner_instructions/src/lib.rs index 1aa6e85e80fe90..5d4f1bb1ff1997 100644 --- a/programs/sbf/rust/sibling_inner_instructions/src/lib.rs +++ b/programs/sbf/rust/sibling_inner_instructions/src/lib.rs @@ -2,18 +2,18 @@ #![allow(clippy::arithmetic_side_effects)] -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{ - get_processed_sibling_instruction, get_stack_height, AccountMeta, Instruction, - TRANSACTION_LEVEL_STACK_HEIGHT, +use { + solana_account_info::AccountInfo, + solana_instruction::{ + syscalls::{get_processed_sibling_instruction, get_stack_height}, + AccountMeta, Instruction, TRANSACTION_LEVEL_STACK_HEIGHT, }, - msg, - pubkey::Pubkey, + solana_msg::msg, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/sibling_instructions/Cargo.toml b/programs/sbf/rust/sibling_instructions/Cargo.toml index a23ab923f7b5c8..78cdfd15d61912 100644 --- a/programs/sbf/rust/sibling_instructions/Cargo.toml +++ b/programs/sbf/rust/sibling_instructions/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/sibling_instructions/src/lib.rs b/programs/sbf/rust/sibling_instructions/src/lib.rs index a1406a9eb65209..246829704d7770 100644 --- a/programs/sbf/rust/sibling_instructions/src/lib.rs +++ b/programs/sbf/rust/sibling_instructions/src/lib.rs @@ -1,18 +1,18 @@ //! Example Rust-based SBF program that queries sibling instructions -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{ - get_processed_sibling_instruction, get_stack_height, AccountMeta, Instruction, - TRANSACTION_LEVEL_STACK_HEIGHT, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction, TRANSACTION_LEVEL_STACK_HEIGHT}, + solana_msg::msg, + solana_program::{ + instruction::{get_processed_sibling_instruction, get_stack_height}, + program::invoke, }, - msg, - program::invoke, - pubkey::Pubkey, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/simulation/Cargo.toml b/programs/sbf/rust/simulation/Cargo.toml index 7928cc7df43cce..70cc990023d17e 100644 --- a/programs/sbf/rust/simulation/Cargo.toml +++ b/programs/sbf/rust/simulation/Cargo.toml @@ -8,11 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-clock = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/simulation/src/lib.rs b/programs/sbf/rust/simulation/src/lib.rs index 8decae36b58811..8af47ee069d510 100644 --- a/programs/sbf/rust/simulation/src/lib.rs +++ b/programs/sbf/rust/simulation/src/lib.rs @@ -1,21 +1,18 @@ #![allow(clippy::arithmetic_side_effects)] use { - solana_program::{ - account_info::{next_account_info, AccountInfo}, - clock::Clock, - declare_id, - entrypoint::ProgramResult, - msg, - pubkey::Pubkey, - sysvar::Sysvar, - }, + solana_account_info::{next_account_info, AccountInfo}, + solana_clock::Clock, + solana_msg::msg, + solana_program_error::ProgramResult, + solana_pubkey::{declare_id, Pubkey}, + solana_sysvar::Sysvar, std::convert::TryInto, }; declare_id!("Sim1jD5C35odT8mzctm8BWnjic8xW5xgeb5MbcbErTo"); -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( _program_id: &Pubkey, diff --git a/programs/sbf/rust/spoof1/Cargo.toml b/programs/sbf/rust/spoof1/Cargo.toml index 59298bdc7105f1..b0e984824c1c8e 100644 --- a/programs/sbf/rust/spoof1/Cargo.toml +++ b/programs/sbf/rust/spoof1/Cargo.toml @@ -8,11 +8,18 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-instruction = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-system-interface = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/spoof1/src/lib.rs b/programs/sbf/rust/spoof1/src/lib.rs index c6efd612ef50fc..da51f7d9e46676 100644 --- a/programs/sbf/rust/spoof1/src/lib.rs +++ b/programs/sbf/rust/spoof1/src/lib.rs @@ -1,15 +1,14 @@ -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - msg, - program::invoke, - pubkey::Pubkey, - system_instruction::SystemInstruction, - system_program, +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_msg::msg, + solana_program::program::invoke, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, + solana_system_interface::{instruction::SystemInstruction, program as system_program}, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/spoof1_system/Cargo.toml b/programs/sbf/rust/spoof1_system/Cargo.toml index 5c6ab906805d09..3b1d4fbe763035 100644 --- a/programs/sbf/rust/spoof1_system/Cargo.toml +++ b/programs/sbf/rust/spoof1_system/Cargo.toml @@ -8,11 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/spoof1_system/src/lib.rs b/programs/sbf/rust/spoof1_system/src/lib.rs index b4956414077b56..d0471cef681480 100644 --- a/programs/sbf/rust/spoof1_system/src/lib.rs +++ b/programs/sbf/rust/spoof1_system/src/lib.rs @@ -1,8 +1,10 @@ #![allow(clippy::arithmetic_side_effects)] -use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey}; +use { + solana_account_info::AccountInfo, solana_program_error::ProgramResult, solana_pubkey::Pubkey, +}; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/syscall-get-epoch-stake/Cargo.toml b/programs/sbf/rust/syscall-get-epoch-stake/Cargo.toml index 006c3bf07aa48f..0ad802cf2b8715 100644 --- a/programs/sbf/rust/syscall-get-epoch-stake/Cargo.toml +++ b/programs/sbf/rust/syscall-get-epoch-stake/Cargo.toml @@ -8,11 +8,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/syscall-get-epoch-stake/src/lib.rs b/programs/sbf/rust/syscall-get-epoch-stake/src/lib.rs index 986ed681409a2a..c416c370ac9736 100644 --- a/programs/sbf/rust/syscall-get-epoch-stake/src/lib.rs +++ b/programs/sbf/rust/syscall-get-epoch-stake/src/lib.rs @@ -1,17 +1,18 @@ //! Example Rust-based SBF program that tests the `sol_get_epoch_stake` //! syscall. -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - epoch_stake::{get_epoch_stake_for_vote_account, get_epoch_total_stake}, - msg, - program::set_return_data, - pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_msg::msg, + solana_program::{ + epoch_stake::{get_epoch_stake_for_vote_account, get_epoch_total_stake}, + program::set_return_data, + }, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/sysvar/Cargo.toml b/programs/sbf/rust/sysvar/Cargo.toml index 0a4b9c222c642c..f7c9b9cd384a6e 100644 --- a/programs/sbf/rust/sysvar/Cargo.toml +++ b/programs/sbf/rust/sysvar/Cargo.toml @@ -8,12 +8,21 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -bincode = { workspace = true } -solana-program = { workspace = true } - [lib] crate-type = ["cdylib"] +[dependencies] +bincode = { workspace = true } +solana-account-info = { workspace = true } +solana-define-syscall = { workspace = true } +solana-instruction = { workspace = true } +solana-instructions-sysvar = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-sdk-ids = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/sysvar/src/lib.rs b/programs/sbf/rust/sysvar/src/lib.rs index 2556e404360b4d..9ed258ff7968e6 100644 --- a/programs/sbf/rust/sysvar/src/lib.rs +++ b/programs/sbf/rust/sysvar/src/lib.rs @@ -1,31 +1,28 @@ //! Example Rust-based SBF program that tests sysvar use -extern crate solana_program; #[allow(deprecated)] -use solana_program::sysvar::recent_blockhashes::RecentBlockhashes; -use solana_program::{ - account_info::AccountInfo, - entrypoint::ProgramResult, - instruction::{AccountMeta, Instruction}, - msg, - program_error::ProgramError, - pubkey::Pubkey, - stake_history::StakeHistoryGetEntry, - sysvar::{ - self, +use solana_sysvar::recent_blockhashes::RecentBlockhashes; +use { + solana_account_info::AccountInfo, + solana_instruction::{AccountMeta, Instruction}, + solana_instructions_sysvar as instructions, + solana_msg::msg, + solana_program_error::{ProgramError, ProgramResult}, + solana_pubkey::Pubkey, + solana_sdk_ids::sysvar, + solana_sysvar::{ clock::Clock, epoch_rewards::EpochRewards, epoch_schedule::EpochSchedule, - instructions, rent::Rent, slot_hashes::{PodSlotHashes, SlotHashes}, slot_history::SlotHistory, - stake_history::{StakeHistory, StakeHistorySysvar}, + stake_history::{StakeHistory, StakeHistoryGetEntry, StakeHistorySysvar}, Sysvar, }, }; -// Adapted from `solana_program::sysvar::get_sysvar` (private). +// Adapted from `solana_sysvar::get_sysvar` (private). #[cfg(target_os = "solana")] fn sol_get_sysvar_handler(dst: &mut [u8], offset: u64, length: u64) -> Result<(), ProgramError> where @@ -34,11 +31,12 @@ where let sysvar_id = &T::id() as *const _ as *const u8; let var_addr = dst as *mut _ as *mut u8; - let result = - unsafe { solana_program::syscalls::sol_get_sysvar(sysvar_id, var_addr, offset, length) }; + let result = unsafe { + solana_define_syscall::definitions::sol_get_sysvar(sysvar_id, var_addr, offset, length) + }; match result { - solana_program::entrypoint::SUCCESS => Ok(()), + solana_program_entrypoint::SUCCESS => Ok(()), e => Err(e.into()), } } @@ -61,7 +59,7 @@ where Err(ProgramError::UnsupportedSysvar) } -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); pub fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], @@ -150,7 +148,7 @@ pub fn process_instruction( Some(&1) => { // Instructions msg!("Instructions identifier:"); - sysvar::instructions::id().log(); + instructions::id().log(); assert_eq!(*accounts[4].owner, sysvar::id()); let index = instructions::load_current_index_checked(&accounts[4])?; let instruction = diff --git a/programs/sbf/rust/upgradeable/Cargo.toml b/programs/sbf/rust/upgradeable/Cargo.toml index 57ebcd4b0ca909..ba8624ce90c8cf 100644 --- a/programs/sbf/rust/upgradeable/Cargo.toml +++ b/programs/sbf/rust/upgradeable/Cargo.toml @@ -8,12 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] name = "solana_sbf_rust_upgradeable" crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/upgradeable/src/lib.rs b/programs/sbf/rust/upgradeable/src/lib.rs index cc1160f0e277da..1f2702936075d3 100644 --- a/programs/sbf/rust/upgradeable/src/lib.rs +++ b/programs/sbf/rust/upgradeable/src/lib.rs @@ -1,11 +1,11 @@ //! Example Rust-based SBF upgradeable program -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey, sysvar::clock, +use { + solana_account_info::AccountInfo, solana_msg::msg, solana_program_error::ProgramResult, + solana_pubkey::Pubkey, solana_sysvar::clock, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/rust/upgraded/Cargo.toml b/programs/sbf/rust/upgraded/Cargo.toml index 1214467993b0e9..f1d1e7fd0c3528 100644 --- a/programs/sbf/rust/upgraded/Cargo.toml +++ b/programs/sbf/rust/upgraded/Cargo.toml @@ -8,12 +8,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -solana-program = { workspace = true } - [lib] name = "solana_sbf_rust_upgraded" crate-type = ["cdylib"] +[dependencies] +solana-account-info = { workspace = true } +solana-msg = { workspace = true } +solana-program-entrypoint = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-sysvar = { workspace = true } + [lints] workspace = true diff --git a/programs/sbf/rust/upgraded/src/lib.rs b/programs/sbf/rust/upgraded/src/lib.rs index 085f532f28923a..1a861b86af5a01 100644 --- a/programs/sbf/rust/upgraded/src/lib.rs +++ b/programs/sbf/rust/upgraded/src/lib.rs @@ -1,11 +1,11 @@ //! Example Rust-based SBF upgraded program -extern crate solana_program; -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey, sysvar::clock, +use { + solana_account_info::AccountInfo, solana_msg::msg, solana_program_error::ProgramResult, + solana_pubkey::Pubkey, solana_sysvar::clock, }; -solana_program::entrypoint_no_alloc!(process_instruction); +solana_program_entrypoint::entrypoint_no_alloc!(process_instruction); fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index 78d50edb3c2748..beea5ec59dc46b 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -20,7 +20,7 @@ use { solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions, solana_compute_budget_interface::ComputeBudgetInstruction, solana_fee_calculator::FeeRateGovernor, - solana_fee_structure::{FeeBudgetLimits, FeeStructure}, + solana_fee_structure::{FeeBin, FeeBudgetLimits, FeeStructure}, solana_genesis_config::ClusterType, solana_hash::Hash, solana_instruction::{error::InstructionError, AccountMeta, Instruction}, @@ -3428,8 +3428,20 @@ fn test_program_fees() { genesis_config.fee_rate_governor = FeeRateGovernor::new(congestion_multiplier, 0); let mut bank = Bank::new_for_tests(&genesis_config); - let fee_structure = - FeeStructure::new(0.000005, 0.0, vec![(200, 0.0000005), (1400000, 0.000005)]); + let fee_structure = FeeStructure { + lamports_per_signature: 5000, + lamports_per_write_lock: 0, + compute_fee_bins: vec![ + FeeBin { + limit: 200, + fee: 500, + }, + FeeBin { + limit: 1400000, + fee: 5000, + }, + ], + }; bank.set_fee_structure(&fee_structure); let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests(); let feature_set = bank.feature_set.clone(); diff --git a/programs/stake-tests/Cargo.toml b/programs/stake-tests/Cargo.toml index 1b16150cff1ffc..a37e91f80a0a7c 100644 --- a/programs/stake-tests/Cargo.toml +++ b/programs/stake-tests/Cargo.toml @@ -11,6 +11,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dev-dependencies] agave-feature-set = { workspace = true } assert_matches = { workspace = true } @@ -29,6 +32,3 @@ solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } solana-vote-program = { workspace = true } test-case = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/stake/Cargo.toml b/programs/stake/Cargo.toml index 061409476c0fcd..0fdbff3e923b68 100644 --- a/programs/stake/Cargo.toml +++ b/programs/stake/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_stake_program" + [dependencies] agave-feature-set = { workspace = true } bincode = { workspace = true } @@ -47,13 +54,6 @@ solana-sysvar-id = { workspace = true } solana-vote-program = { workspace = true, default-features = false } test-case = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_stake_program" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [[bench]] name = "stake" harness = false diff --git a/programs/stake/src/config.rs b/programs/stake/src/config.rs index 5042aa82eebcbd..b6b4e6d43d53cd 100644 --- a/programs/stake/src/config.rs +++ b/programs/stake/src/config.rs @@ -45,9 +45,9 @@ pub fn create_account(lamports: u64, config: &Config) -> AccountSharedData { #[allow(deprecated)] pub fn add_genesis_account(genesis_config: &mut GenesisConfig) -> u64 { let mut account = create_config_account(vec![], &Config::default(), 0); - let lamports = genesis_config.rent.minimum_balance(account.data().len()); + let lamports = std::cmp::max(genesis_config.rent.minimum_balance(account.data().len()), 1); - account.set_lamports(lamports.max(1)); + account.set_lamports(lamports); genesis_config.add_account(solana_stake_interface::config::id(), account); diff --git a/programs/stake/src/epoch_rewards.rs b/programs/stake/src/epoch_rewards.rs new file mode 100644 index 00000000000000..958a59da350455 --- /dev/null +++ b/programs/stake/src/epoch_rewards.rs @@ -0,0 +1,21 @@ +//! Creates the initial empty EpochRewards sysvar +use { + solana_account::{AccountSharedData, WritableAccount}, + solana_genesis_config::GenesisConfig, + solana_sdk_ids::sysvar, + solana_sysvar::{ + epoch_rewards::{self, EpochRewards}, + Sysvar, + }, +}; + +pub fn add_genesis_account(genesis_config: &mut GenesisConfig) -> u64 { + let data = vec![0; EpochRewards::size_of()]; + let lamports = std::cmp::max(genesis_config.rent.minimum_balance(data.len()), 1); + + let account = AccountSharedData::create(lamports, data, sysvar::id(), false, u64::MAX); + + genesis_config.add_account(epoch_rewards::id(), account); + + lamports +} diff --git a/programs/stake/src/lib.rs b/programs/stake/src/lib.rs index 218d993029a92a..fd68f1771609d8 100644 --- a/programs/stake/src/lib.rs +++ b/programs/stake/src/lib.rs @@ -8,13 +8,16 @@ pub use solana_sdk_ids::stake::{check_id, id}; use {solana_genesis_config::GenesisConfig, solana_native_token::LAMPORTS_PER_SOL}; pub mod config; +pub mod epoch_rewards; #[deprecated(since = "2.2.0")] pub mod points; pub mod stake_instruction; pub mod stake_state; pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig) -> u64 { - config::add_genesis_account(genesis_config) + let config_lamports = config::add_genesis_account(genesis_config); + let rewards_lamports = epoch_rewards::add_genesis_account(genesis_config); + config_lamports.saturating_add(rewards_lamports) } /// The minimum stake amount that can be delegated, in lamports. diff --git a/programs/system/Cargo.toml b/programs/system/Cargo.toml index 0095b1a07d8a4f..efdbb17443c831 100644 --- a/programs/system/Cargo.toml +++ b/programs/system/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_system_program" + [dependencies] bincode = { workspace = true } log = { workspace = true } @@ -42,13 +49,6 @@ solana-sha256-hasher = { workspace = true } solana-svm-callback = { workspace = true } solana-svm-feature-set = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_system_program" - [[bench]] name = "system" harness = false - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/programs/vote/Cargo.toml b/programs/vote/Cargo.toml index 7a506f33bea306..cbacb867fc1087 100644 --- a/programs/vote/Cargo.toml +++ b/programs/vote/Cargo.toml @@ -9,6 +9,23 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_vote_program" + +[features] +default = ["metrics"] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-program-runtime/frozen-abi", + "solana-vote-interface/frozen-abi", +] +metrics = ["dep:solana-metrics"] + [dependencies] agave-feature-set = { workspace = true } bincode = { workspace = true } @@ -62,22 +79,5 @@ test-case = { workspace = true } name = "vote_instructions" harness = false -[lib] -crate-type = ["lib"] -name = "solana_vote_program" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -default = ["metrics"] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-program-runtime/frozen-abi", - "solana-vote-interface/frozen-abi" -] -metrics = ["dep:solana-metrics"] - [lints] workspace = true diff --git a/pubsub-client/Cargo.toml b/pubsub-client/Cargo.toml index 769268dbcb4429..3d82b5440ee75b 100644 --- a/pubsub-client/Cargo.toml +++ b/pubsub-client/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] crossbeam-channel = { workspace = true } futures-util = { workspace = true } @@ -34,6 +37,3 @@ url = { workspace = true } anyhow = { workspace = true } solana-commitment-config = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/rayon-threadlimit/Cargo.toml b/rayon-threadlimit/Cargo.toml index 375b43e1142845..b2f433492e5679 100644 --- a/rayon-threadlimit/Cargo.toml +++ b/rayon-threadlimit/Cargo.toml @@ -10,8 +10,8 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -num_cpus = { workspace = true } - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +num_cpus = { workspace = true } diff --git a/remote-wallet/Cargo.toml b/remote-wallet/Cargo.toml index 75a8691f3cad10..01698749762f57 100644 --- a/remote-wallet/Cargo.toml +++ b/remote-wallet/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +default = ["linux-static-hidraw", "hidapi"] +linux-shared-hidraw = ["hidapi/linux-shared-hidraw"] +linux-shared-libusb = ["hidapi/linux-shared-libusb"] +linux-static-hidraw = ["hidapi/linux-static-hidraw"] +linux-static-libusb = ["hidapi/linux-static-libusb"] + [dependencies] console = { workspace = true } dialoguer = { workspace = true } @@ -30,13 +40,3 @@ uriparse = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } - -[features] -default = ["linux-static-hidraw", "hidapi"] -linux-shared-hidraw = ["hidapi/linux-shared-hidraw"] -linux-shared-libusb = ["hidapi/linux-shared-libusb"] -linux-static-hidraw = ["hidapi/linux-static-hidraw"] -linux-static-libusb = ["hidapi/linux-static-libusb"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/reserved-account-keys/Cargo.toml b/reserved-account-keys/Cargo.toml index 0fb5d92b36e9b7..ac1ad6f443d9d7 100644 --- a/reserved-account-keys/Cargo.toml +++ b/reserved-account-keys/Cargo.toml @@ -9,6 +9,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + +[features] +frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] + [dependencies] agave-feature-set = { workspace = true } solana-frozen-abi = { workspace = true, optional = true, features = [ @@ -24,13 +32,5 @@ solana-sdk-ids = { workspace = true } solana-message = { workspace = true } solana-sysvar = { workspace = true } -[features] -frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] -all-features = true -rustdoc-args = ["--cfg=docsrs"] - [lints] workspace = true diff --git a/reserved-account-keys/src/lib.rs b/reserved-account-keys/src/lib.rs index 383d141a34e72e..f4a22835112d74 100644 --- a/reserved-account-keys/src/lib.rs +++ b/reserved-account-keys/src/lib.rs @@ -49,7 +49,7 @@ impl ReservedAccountKeys { /// designate a feature id, it's already activated and should be inserted /// into the active set. If it does have a feature id, insert the key and /// its feature id into the inactive map. - fn new(reserved_accounts: &[ReservedAccount]) -> Self { + pub fn new(reserved_accounts: &[ReservedAccount]) -> Self { Self { active: reserved_accounts .iter() @@ -113,20 +113,20 @@ impl ReservedAccountKeys { /// write-lockable by transactions. If a feature id is set, the account will /// become read-only only after the feature has been activated. #[derive(Debug, Clone, Copy, Eq, PartialEq)] -struct ReservedAccount { +pub struct ReservedAccount { key: Pubkey, feature_id: Option, } impl ReservedAccount { - fn new_pending(key: Pubkey, feature_id: Pubkey) -> Self { + pub fn new_pending(key: Pubkey, feature_id: Pubkey) -> Self { Self { key, feature_id: Some(feature_id), } } - fn new_active(key: Pubkey) -> Self { + pub fn new_active(key: Pubkey) -> Self { Self { key, feature_id: None, @@ -141,31 +141,16 @@ static RESERVED_ACCOUNTS: std::sync::LazyLock> = std::sync::LazyLock::new(|| { vec![ // builtin programs - ReservedAccount::new_pending( - address_lookup_table::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(address_lookup_table::id()), ReservedAccount::new_active(bpf_loader::id()), ReservedAccount::new_active(bpf_loader_deprecated::id()), ReservedAccount::new_active(bpf_loader_upgradeable::id()), - ReservedAccount::new_pending( - compute_budget::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(compute_budget::id()), ReservedAccount::new_active(config::id()), - ReservedAccount::new_pending( - ed25519_program::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(ed25519_program::id()), ReservedAccount::new_active(feature::id()), - ReservedAccount::new_pending( - loader_v4::id(), - feature_set::add_new_reserved_account_keys::id(), - ), - ReservedAccount::new_pending( - secp256k1_program::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(loader_v4::id()), + ReservedAccount::new_active(secp256k1_program::id()), ReservedAccount::new_pending( secp256r1_program::id(), feature_set::enable_secp256r1_precompile::id(), @@ -175,28 +160,16 @@ static RESERVED_ACCOUNTS: std::sync::LazyLock> = ReservedAccount::new_active(stake::id()), ReservedAccount::new_active(system_program::id()), ReservedAccount::new_active(vote::id()), - ReservedAccount::new_pending( - zk_elgamal_proof_program::id(), - feature_set::add_new_reserved_account_keys::id(), - ), - ReservedAccount::new_pending( - zk_token_proof_program::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(zk_elgamal_proof_program::id()), + ReservedAccount::new_active(zk_token_proof_program::id()), // sysvars ReservedAccount::new_active(sysvar::clock::id()), - ReservedAccount::new_pending( - sysvar::epoch_rewards::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(sysvar::epoch_rewards::id()), ReservedAccount::new_active(sysvar::epoch_schedule::id()), #[allow(deprecated)] ReservedAccount::new_active(sysvar::fees::id()), ReservedAccount::new_active(sysvar::instructions::id()), - ReservedAccount::new_pending( - sysvar::last_restart_slot::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(sysvar::last_restart_slot::id()), #[allow(deprecated)] ReservedAccount::new_active(sysvar::recent_blockhashes::id()), ReservedAccount::new_active(sysvar::rent::id()), @@ -206,17 +179,13 @@ static RESERVED_ACCOUNTS: std::sync::LazyLock> = ReservedAccount::new_active(sysvar::stake_history::id()), // other ReservedAccount::new_active(native_loader::id()), - ReservedAccount::new_pending( - sysvar::id(), - feature_set::add_new_reserved_account_keys::id(), - ), + ReservedAccount::new_active(sysvar::id()), ] }); #[cfg(test)] mod tests { - #![allow(deprecated)] - use {super::*, solana_message::legacy::BUILTIN_PROGRAMS_KEYS, solana_sysvar::ALL_IDS}; + use super::*; #[test] fn test_is_reserved() { @@ -277,15 +246,4 @@ mod tests { assert!(reserved_account_keys.is_reserved(&pending_reserved_keys[0])); assert!(reserved_account_keys.is_reserved(&pending_reserved_keys[1])); } - - #[test] - fn test_static_list_compat() { - let mut static_set = HashSet::new(); - static_set.extend(ALL_IDS.iter().cloned()); - static_set.extend(BUILTIN_PROGRAMS_KEYS.iter().cloned()); - - let initial_active_set = ReservedAccountKeys::default().active; - - assert_eq!(initial_active_set, static_set); - } } diff --git a/rpc-client-api/Cargo.toml b/rpc-client-api/Cargo.toml index ba021ed19b3e0c..0ba5f76a88aac7 100644 --- a/rpc-client-api/Cargo.toml +++ b/rpc-client-api/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] anyhow = { workspace = true } jsonrpc-core = { workspace = true } @@ -24,6 +27,3 @@ solana-signer = { workspace = true } solana-transaction-error = { workspace = true } solana-transaction-status-client-types = { workspace = true } thiserror = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/rpc-client-api/src/client_error.rs b/rpc-client-api/src/client_error.rs index e8a7aca9a2a1e2..49f2cad8474d8d 100644 --- a/rpc-client-api/src/client_error.rs +++ b/rpc-client-api/src/client_error.rs @@ -8,6 +8,7 @@ use { }; #[derive(ThisError, Debug)] +#[allow(clippy::large_enum_variant)] pub enum ErrorKind { #[error(transparent)] Io(#[from] io::Error), diff --git a/rpc-client-nonce-utils/Cargo.toml b/rpc-client-nonce-utils/Cargo.toml index e3ebdfea412735..955a14300777da 100644 --- a/rpc-client-nonce-utils/Cargo.toml +++ b/rpc-client-nonce-utils/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +default = [] +clap = ["dep:clap", "dep:solana-clap-utils"] + [dependencies] clap = { version = "2.33.0", optional = true } solana-account = { workspace = true, features = ["bincode"] } @@ -35,10 +42,3 @@ solana-signer = { workspace = true } solana-system-interface = { workspace = true } solana-transaction = { workspace = true } tokio = { workspace = true, features = ["full"] } - -[features] -default = [] -clap = ["dep:clap", "dep:solana-clap-utils"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/rpc-client-types/Cargo.toml b/rpc-client-types/Cargo.toml index b50d48c67354a8..8fb008655cd346 100644 --- a/rpc-client-types/Cargo.toml +++ b/rpc-client-types/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] base64 = { workspace = true } bs58 = { workspace = true, features = ["std"] } @@ -32,6 +35,3 @@ thiserror = { workspace = true } [dev-dependencies] const_format = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/rpc-client-types/src/response.rs b/rpc-client-types/src/response.rs index 05764cbafa77ce..117c5be75976bd 100644 --- a/rpc-client-types/src/response.rs +++ b/rpc-client-types/src/response.rs @@ -401,6 +401,7 @@ pub struct RpcSimulateTransactionResult { pub logs: Option>, pub accounts: Option>>, pub units_consumed: Option, + pub loaded_accounts_data_size: Option, pub return_data: Option, pub inner_instructions: Option>, pub replacement_blockhash: Option, diff --git a/rpc-client/Cargo.toml b/rpc-client/Cargo.toml index f781a0fa670a9f..9db6b57706e833 100644 --- a/rpc-client/Cargo.toml +++ b/rpc-client/Cargo.toml @@ -9,6 +9,15 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +default = ["spinner"] +# Support rpc-client methods that feature a spinner progress bar for +# command-line interfaces +spinner = ["dep:indicatif"] + [dependencies] async-trait = { workspace = true } base64 = { workspace = true } @@ -40,6 +49,7 @@ solana-transaction = { workspace = true, features = ["bincode"] } solana-transaction-error = { workspace = true } solana-transaction-status-client-types = { workspace = true } solana-version = { workspace = true } +solana-vote-interface = { workspace = true } tokio = { workspace = true, features = ["full"] } [dev-dependencies] @@ -50,17 +60,7 @@ jsonrpc-core = { workspace = true } jsonrpc-http-server = { workspace = true } solana-account-decoder = { workspace = true } solana-keypair = { workspace = true } -solana-program = { workspace = true, default-features = false } solana-pubkey = { workspace = true, features = ["rand"] } solana-signer = { workspace = true } solana-system-transaction = { workspace = true } static_assertions = { workspace = true } - -[features] -default = ["spinner"] -# Support rpc-client methods that feature a spinner progress bar for -# command-line interfaces -spinner = ["dep:indicatif"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/rpc-client/src/mock_sender.rs b/rpc-client/src/mock_sender.rs index e0d17b6e27e74e..d433543780933b 100644 --- a/rpc-client/src/mock_sender.rs +++ b/rpc-client/src/mock_sender.rs @@ -9,7 +9,7 @@ use { solana_clock::{Slot, UnixTimestamp}, solana_epoch_info::EpochInfo, solana_epoch_schedule::EpochSchedule, - solana_instruction::error::InstructionError, + solana_instruction::{error::InstructionError, TRANSACTION_LEVEL_STACK_HEIGHT}, solana_message::MessageHeader, solana_pubkey::Pubkey, solana_rpc_client_api::{ @@ -227,7 +227,7 @@ impl RpcSender for MockSender { program_id_index: 2, accounts: vec![0, 1], data: "3Bxs49DitAvXtoDR".to_string(), - stack_height: None, + stack_height: Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32), }], address_table_lookups: None, }) @@ -352,6 +352,7 @@ impl RpcSender for MockSender { logs: None, accounts: None, units_consumed: None, + loaded_accounts_data_size: None, return_data: None, inner_instructions: None, replacement_blockhash: None diff --git a/rpc-client/src/nonblocking/rpc_client.rs b/rpc-client/src/nonblocking/rpc_client.rs index 41c045cba71975..8da0562052e1ab 100644 --- a/rpc-client/src/nonblocking/rpc_client.rs +++ b/rpc-client/src/nonblocking/rpc_client.rs @@ -49,6 +49,7 @@ use { EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus, UiConfirmedBlock, UiTransactionEncoding, }, + solana_vote_interface::state::MAX_LOCKOUT_HISTORY, std::{ net::SocketAddr, str::FromStr, @@ -56,13 +57,6 @@ use { }, tokio::time::sleep, }; -// inlined to avoid a solana_program dep -const MAX_LOCKOUT_HISTORY: usize = 31; -#[cfg(test)] -static_assertions::const_assert_eq!( - MAX_LOCKOUT_HISTORY, - solana_program::vote::state::MAX_LOCKOUT_HISTORY -); /// A client of a remote Solana node. /// diff --git a/rpc-test/Cargo.toml b/rpc-test/Cargo.toml index 7e2bdf0bfc4904..7d7ebb8e6311d8 100644 --- a/rpc-test/Cargo.toml +++ b/rpc-test/Cargo.toml @@ -10,6 +10,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] bincode = { workspace = true } bs58 = { workspace = true } @@ -45,6 +48,3 @@ solana-signature = { workspace = true } solana-signer = { workspace = true } solana-system-transaction = { workspace = true } solana-transaction = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/rpc-test/tests/nonblocking.rs b/rpc-test/tests/nonblocking.rs index 5c2a5c9e2c1b08..d08e136d4682aa 100644 --- a/rpc-test/tests/nonblocking.rs +++ b/rpc-test/tests/nonblocking.rs @@ -13,7 +13,7 @@ use { tokio::time::{sleep, Duration, Instant}, }; -#[tokio::test] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_tpu_send_transaction() { let (test_validator, mint_keypair) = TestValidatorGenesis::default().start_async().await; let rpc_client = Arc::new(test_validator.get_async_rpc_client()); @@ -47,7 +47,7 @@ async fn test_tpu_send_transaction() { tpu_client.shutdown().await; } -#[tokio::test] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_tpu_cache_slot_updates() { let (test_validator, _) = TestValidatorGenesis::default().start_async().await; let rpc_client = Arc::new(test_validator.get_async_rpc_client()); diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index e4501fcb9e3989..93748850d8a779 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_rpc" + +[features] +dev-context-only-utils = ["solana-rpc/dev-context-only-utils"] + [dependencies] agave-feature-set = { workspace = true } base64 = { workspace = true } @@ -110,6 +120,7 @@ solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-runtime-transaction = { workspace = true, features = [ "dev-context-only-utils", ] } +solana-sdk-ids = { workspace = true } solana-send-transaction-service = { workspace = true, features = ["dev-context-only-utils"] } solana-sha256-hasher = { workspace = true } solana-stake-interface = { workspace = true } @@ -118,15 +129,3 @@ solana-vote-interface = { workspace = true } spl-pod = { workspace = true } symlink = { workspace = true } test-case = { workspace = true } - -[features] -dev-context-only-utils = [ - "solana-rpc/dev-context-only-utils", -] - -[lib] -crate-type = ["lib"] -name = "solana_rpc" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/rpc/src/block_meta_service.rs b/rpc/src/block_meta_service.rs deleted file mode 100644 index da99de13c198e3..00000000000000 --- a/rpc/src/block_meta_service.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! The `BlockMetaService` is responsible for persisting block metadata from -//! banks into the `Blockstore` - -pub use solana_ledger::blockstore_processor::BlockMetaSender; -use { - crossbeam_channel::{Receiver, RecvTimeoutError}, - solana_ledger::blockstore::{Blockstore, BlockstoreError}, - solana_runtime::bank::{Bank, KeyedRewardsAndNumPartitions}, - solana_transaction_status::{Reward, RewardsAndNumPartitions}, - std::{ - sync::{ - atomic::{AtomicBool, AtomicU64, Ordering}, - Arc, - }, - thread::{self, Builder, JoinHandle}, - time::Duration, - }, -}; - -pub type BlockMetaReceiver = Receiver>; - -pub struct BlockMetaService { - thread_hdl: JoinHandle<()>, -} - -impl BlockMetaService { - pub fn new( - block_meta_receiver: BlockMetaReceiver, - blockstore: Arc, - max_complete_rewards_slot: Arc, - exit: Arc, - ) -> Self { - let thread_hdl = Builder::new() - .name("solBlockMeta".to_string()) - .spawn(move || { - info!("BlockMetaService has started"); - loop { - if exit.load(Ordering::Relaxed) { - break; - } - - let bank = match block_meta_receiver.recv_timeout(Duration::from_secs(1)) { - Ok(bank) => bank, - Err(RecvTimeoutError::Timeout) => continue, - Err(err @ RecvTimeoutError::Disconnected) => { - info!("BlockMetaService is stopping because: {err}"); - break; - } - }; - - if let Err(err) = - Self::write_block_meta(&bank, &blockstore, &max_complete_rewards_slot) - { - error!("BlockMetaService is stopping because: {err}"); - // Set the exit flag to allow other services to gracefully stop - exit.store(true, Ordering::Relaxed); - break; - } - } - info!("BlockMetaService has stopped"); - }) - .unwrap(); - Self { thread_hdl } - } - - fn write_block_meta( - bank: &Bank, - blockstore: &Blockstore, - max_complete_rewards_slot: &Arc, - ) -> Result<(), BlockstoreError> { - let slot = bank.slot(); - - blockstore.set_block_time(slot, bank.clock().unix_timestamp)?; - blockstore.set_block_height(slot, bank.block_height())?; - - let rewards = bank.get_rewards_and_num_partitions(); - if rewards.should_record() { - let KeyedRewardsAndNumPartitions { - keyed_rewards, - num_partitions, - } = rewards; - let rewards = keyed_rewards - .into_iter() - .map(|(pubkey, reward_info)| Reward { - pubkey: pubkey.to_string(), - lamports: reward_info.lamports, - post_balance: reward_info.post_balance, - reward_type: Some(reward_info.reward_type), - commission: reward_info.commission, - }) - .collect(); - let blockstore_rewards = RewardsAndNumPartitions { - rewards, - num_partitions, - }; - - blockstore.write_rewards(slot, blockstore_rewards)?; - } - max_complete_rewards_slot.fetch_max(slot, Ordering::SeqCst); - - Ok(()) - } - - pub fn join(self) -> thread::Result<()> { - self.thread_hdl.join() - } -} diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 15a660cd029fe1..9763ebd791a162 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -1,5 +1,4 @@ #![allow(clippy::arithmetic_side_effects)] -pub mod block_meta_service; mod cluster_tpu_info; pub mod filter; pub mod max_slots; diff --git a/rpc/src/optimistically_confirmed_bank_tracker.rs b/rpc/src/optimistically_confirmed_bank_tracker.rs index 123bd24fb3aa38..568ddc31b49d2a 100644 --- a/rpc/src/optimistically_confirmed_bank_tracker.rs +++ b/rpc/src/optimistically_confirmed_bank_tracker.rs @@ -439,11 +439,9 @@ mod tests { let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default())); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), block_commitment_cache, optimistically_confirmed_bank.clone(), diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index a946161c2bcf77..1464a290e6c943 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -253,7 +253,6 @@ pub struct JsonRpcRequestProcessor { max_slots: Arc, leader_schedule_cache: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, prioritization_fee_cache: Arc, runtime: Arc, } @@ -417,7 +416,6 @@ impl JsonRpcRequestProcessor { max_slots: Arc, leader_schedule_cache: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, prioritization_fee_cache: Arc, runtime: Arc, ) -> (Self, Receiver) { @@ -440,7 +438,6 @@ impl JsonRpcRequestProcessor { max_slots, leader_schedule_cache, max_complete_transaction_status_slot, - max_complete_rewards_slot, prioritization_fee_cache, runtime, }, @@ -528,7 +525,6 @@ impl JsonRpcRequestProcessor { max_slots: Arc::new(MaxSlots::default()), leader_schedule_cache, max_complete_transaction_status_slot: Arc::new(AtomicU64::default()), - max_complete_rewards_slot: Arc::new(AtomicU64::default()), prioritization_fee_cache: Arc::new(PrioritizationFeeCache::default()), runtime, } @@ -1282,7 +1278,6 @@ impl JsonRpcRequestProcessor { > self .max_complete_transaction_status_slot .load(Ordering::SeqCst) - || slot > self.max_complete_rewards_slot.load(Ordering::SeqCst) { Err(RpcCustomError::BlockStatusNotAvailableYet { slot }.into()) } else { @@ -3904,6 +3899,7 @@ pub mod rpc_full { logs, post_simulation_accounts: _, units_consumed, + loaded_accounts_data_size, return_data, inner_instructions: _, // Always `None` due to `enable_cpi_recording = false` } = preflight_bank.simulate_transaction(&transaction, false) @@ -3923,6 +3919,7 @@ pub mod rpc_full { logs: Some(logs), accounts: None, units_consumed: Some(units_consumed), + loaded_accounts_data_size: Some(loaded_accounts_data_size), return_data: return_data.map(|return_data| return_data.into()), inner_instructions: None, replacement_blockhash: None, @@ -4002,6 +3999,7 @@ pub mod rpc_full { logs, post_simulation_accounts, units_consumed, + loaded_accounts_data_size, return_data, inner_instructions, } = bank.simulate_transaction(&transaction, enable_cpi_recording); @@ -4068,6 +4066,7 @@ pub mod rpc_full { logs: Some(logs), accounts, units_consumed: Some(units_consumed), + loaded_accounts_data_size: Some(loaded_accounts_data_size), return_data: return_data.map(|return_data| return_data.into()), inner_instructions, replacement_blockhash: blockhash, @@ -4548,12 +4547,14 @@ pub mod tests { commitment::{BlockCommitment, CommitmentSlots}, non_circulating_supply::non_circulating_accounts, }, + solana_sdk_ids::bpf_loader_upgradeable, solana_send_transaction_service::{ tpu_info::NullTpuInfo, transaction_client::{ConnectionCacheClient, TpuClientNextClient}, }, solana_sha256_hasher::hash, solana_signer::Signer, + solana_svm::account_loader::TRANSACTION_ACCOUNT_BASE_SIZE, solana_system_interface::{instruction as system_instruction, program as system_program}, solana_system_transaction as system_transaction, solana_sysvar::slot_hashes::SlotHashes, @@ -4630,6 +4631,22 @@ pub mod tests { } } + fn expected_loaded_accounts_data_size(bank: &Bank, tx: &Transaction) -> u32 { + let mut loaded_accounts_data_size = 0; + for key in tx.message.account_keys.iter() { + if let Some(account) = bank.get_account(key) { + assert!( + *account.owner() != bpf_loader_upgradeable::id(), + "LoaderV3 is not supported; to add it, parse the program account and add its programdata size.", + ); + loaded_accounts_data_size += + (account.data().len() + TRANSACTION_ACCOUNT_BASE_SIZE) as u32; + } + } + + loaded_accounts_data_size + } + fn test_builtin_processor( invoke_context: &mut InvokeContext, ) -> std::result::Result> { @@ -4774,7 +4791,6 @@ pub mod tests { let max_slots = Arc::new(MaxSlots::default()); // note that this means that slot 0 will always be considered complete let max_complete_transaction_status_slot = Arc::new(AtomicU64::new(0)); - let max_complete_rewards_slot = Arc::new(AtomicU64::new(0)); let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); @@ -4800,7 +4816,6 @@ pub mod tests { max_slots.clone(), Arc::new(LeaderScheduleCache::new_from_bank(&bank)), max_complete_transaction_status_slot.clone(), - max_complete_rewards_slot, Arc::new(PrioritizationFeeCache::default()), service_runtime(rpc_threads, rpc_blocking_threads, rpc_niceness_adj), ) @@ -5978,6 +5993,8 @@ pub mod tests { // Simulation bank must be frozen bank.freeze(); + let loaded_accounts_data_size = expected_loaded_accounts_data_size(&bank, &tx); + // Good signature with sigVerify=true let req = format!( r#"{{"jsonrpc":"2.0", @@ -6017,6 +6034,7 @@ pub mod tests { ], "err":null, "innerInstructions": null, + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6103,6 +6121,7 @@ pub mod tests { "accounts":null, "err":null, "innerInstructions":null, + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6133,6 +6152,7 @@ pub mod tests { "accounts":null, "err":null, "innerInstructions":null, + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6187,6 +6207,7 @@ pub mod tests { "err":"BlockhashNotFound", "accounts":null, "innerInstructions":null, + "loadedAccountsDataSize":0, "logs":[], "replacementBlockhash": null, "returnData": null, @@ -6220,6 +6241,7 @@ pub mod tests { "accounts":null, "err":null, "innerInstructions":null, + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6312,6 +6334,8 @@ pub mod tests { // Simulation bank must be frozen bank.freeze(); + let loaded_accounts_data_size = expected_loaded_accounts_data_size(&bank, &tx); + let req = format!( r#"{{"jsonrpc":"2.0", "id":1, @@ -6368,6 +6392,7 @@ pub mod tests { ], "err": null, "innerInstructions": null, + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program 11111111111111111111111111111111 invoke [1]", "Program 11111111111111111111111111111111 success" @@ -6424,6 +6449,8 @@ pub mod tests { // Simulation bank must be frozen bank.freeze(); + let loaded_accounts_data_size = expected_loaded_accounts_data_size(&bank, &tx); + // `innerInstructions` not provided, should not be in response let req = format!( r#"{{"jsonrpc":"2.0", @@ -6445,6 +6472,7 @@ pub mod tests { "accounts": null, "err":null, "innerInstructions": null, + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program TestProgram11111111111111111111111111111111 invoke [1]", "I am logging from a builtin program!", @@ -6488,6 +6516,7 @@ pub mod tests { "accounts": null, "err":null, "innerInstructions": null, + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program TestProgram11111111111111111111111111111111 invoke [1]", "I am logging from a builtin program!", @@ -6552,6 +6581,7 @@ pub mod tests { ] } ], + "loadedAccountsDataSize": loaded_accounts_data_size, "logs":[ "Program TestProgram11111111111111111111111111111111 invoke [1]", "I am logging from a builtin program!", @@ -6775,7 +6805,6 @@ pub mod tests { Arc::new(MaxSlots::default()), Arc::new(LeaderScheduleCache::default()), Arc::new(AtomicU64::default()), - Arc::new(AtomicU64::default()), Arc::new(PrioritizationFeeCache::default()), runtime.clone(), ); @@ -6813,7 +6842,7 @@ pub mod tests { assert_eq!( res, Some( - r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Blockhash not found","data":{"accounts":null,"err":"BlockhashNotFound","innerInstructions":null,"logs":[],"replacementBlockhash":null,"returnData":null,"unitsConsumed":0}},"id":1}"#.to_string(), + r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Blockhash not found","data":{"accounts":null,"err":"BlockhashNotFound","innerInstructions":null,"loadedAccountsDataSize":0,"logs":[],"replacementBlockhash":null,"returnData":null,"unitsConsumed":0}},"id":1}"#.to_string(), ) ); @@ -7079,7 +7108,6 @@ pub mod tests { Arc::new(MaxSlots::default()), Arc::new(LeaderScheduleCache::default()), Arc::new(AtomicU64::default()), - Arc::new(AtomicU64::default()), Arc::new(PrioritizationFeeCache::default()), runtime, ); @@ -8749,11 +8777,9 @@ pub mod tests { OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let mut pending_optimistically_confirmed_banks = HashSet::new(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot.clone(), - max_complete_rewards_slot.clone(), bank_forks.clone(), block_commitment_cache.clone(), optimistically_confirmed_bank.clone(), @@ -8782,7 +8808,6 @@ pub mod tests { Arc::new(MaxSlots::default()), Arc::new(LeaderScheduleCache::default()), max_complete_transaction_status_slot, - max_complete_rewards_slot, Arc::new(PrioritizationFeeCache::default()), service_runtime(rpc_threads, rpc_blocking_threads, rpc_niceness_adj), ); diff --git a/rpc/src/rpc_pubsub.rs b/rpc/src/rpc_pubsub.rs index 1ea5892226b26c..5d22eadcf52957 100644 --- a/rpc/src/rpc_pubsub.rs +++ b/rpc/src/rpc_pubsub.rs @@ -701,11 +701,9 @@ mod tests { let blockhash = bank.last_blockhash(); let bank_forks = BankForks::new_rw_arc(bank); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests( Arc::new(AtomicBool::new(false)), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -832,10 +830,8 @@ mod tests { let mut io = IoHandler::<()>::default(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks( max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, )); let (rpc, _receiver) = rpc_pubsub_service::test_connection(&subscriptions); @@ -891,11 +887,9 @@ mod tests { let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1); bank_forks.write().unwrap().insert(bank1); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests( Arc::new(AtomicBool::new(false)), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots( 1, 1, @@ -1019,11 +1013,9 @@ mod tests { let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1); bank_forks.write().unwrap().insert(bank1); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests( Arc::new(AtomicBool::new(false)), max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots( 1, 1, @@ -1107,10 +1099,8 @@ mod tests { let mut io = IoHandler::<()>::default(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks( max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, )); let (rpc, _receiver) = rpc_pubsub_service::test_connection(&subscriptions); @@ -1156,11 +1146,9 @@ mod tests { let exit = Arc::new(AtomicBool::new(false)); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -1212,11 +1200,9 @@ mod tests { let exit = Arc::new(AtomicBool::new(false)); let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), block_commitment_cache, OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks), @@ -1287,10 +1273,8 @@ mod tests { let bank = Bank::new_for_tests(&genesis_config); let bank_forks = BankForks::new_rw_arc(bank); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks( max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, )); let (rpc, mut receiver) = rpc_pubsub_service::test_connection(&rpc_subscriptions); @@ -1320,10 +1304,8 @@ mod tests { let bank = Bank::new_for_tests(&genesis_config); let bank_forks = BankForks::new_rw_arc(bank); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks( max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, )); let (rpc, mut receiver) = rpc_pubsub_service::test_connection(&rpc_subscriptions); @@ -1367,11 +1349,9 @@ mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, block_commitment_cache, optimistically_confirmed_bank, @@ -1405,10 +1385,8 @@ mod tests { let bank = Bank::new_for_tests(&genesis_config); let bank_forks = BankForks::new_rw_arc(bank); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks( max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, )); let (rpc, _receiver) = rpc_pubsub_service::test_connection(&rpc_subscriptions); @@ -1424,10 +1402,8 @@ mod tests { let bank = Bank::new_for_tests(&genesis_config); let bank_forks = BankForks::new_rw_arc(bank); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks( max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, )); let (rpc, _receiver) = rpc_pubsub_service::test_connection(&rpc_subscriptions); diff --git a/rpc/src/rpc_pubsub_service.rs b/rpc/src/rpc_pubsub_service.rs index a239228768c106..0cb602982e707c 100644 --- a/rpc/src/rpc_pubsub_service.rs +++ b/rpc/src/rpc_pubsub_service.rs @@ -496,7 +496,6 @@ mod tests { let pubsub_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); let exit = Arc::new(AtomicBool::new(false)); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000); let bank = Bank::new_for_tests(&genesis_config); let bank_forks = BankForks::new_rw_arc(bank); @@ -505,7 +504,6 @@ mod tests { let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), optimistically_confirmed_bank, diff --git a/rpc/src/rpc_service.rs b/rpc/src/rpc_service.rs index cb1f87be20e251..97e4c5ca83d29b 100644 --- a/rpc/src/rpc_service.rs +++ b/rpc/src/rpc_service.rs @@ -61,6 +61,7 @@ use { tokio_util::{ bytes::Bytes, codec::{BytesCodec, FramedRead}, + sync::CancellationToken, }, }; @@ -483,7 +484,6 @@ pub struct JsonRpcServiceConfig<'a> { pub max_slots: Arc, pub leader_schedule_cache: Arc, pub max_complete_transaction_status_slot: Arc, - pub max_complete_rewards_slot: Arc, pub prioritization_fee_cache: Arc, pub client_option: ClientOption<'a>, } @@ -496,7 +496,7 @@ pub struct JsonRpcServiceConfig<'a> { /// requires a reference to a [`Keypair`]. pub enum ClientOption<'a> { ConnectionCache(Arc), - TpuClientNext(&'a Keypair, UdpSocket, RuntimeHandle), + TpuClientNext(&'a Keypair, UdpSocket, RuntimeHandle, CancellationToken), } impl JsonRpcService { @@ -547,13 +547,17 @@ impl JsonRpcService { config.leader_schedule_cache, client.clone(), config.max_complete_transaction_status_slot, - config.max_complete_rewards_slot, config.prioritization_fee_cache, runtime, )?; Ok(json_rpc_service) } - ClientOption::TpuClientNext(identity_keypair, tpu_client_socket, client_runtime) => { + ClientOption::TpuClientNext( + identity_keypair, + tpu_client_socket, + client_runtime, + cancel, + ) => { let my_tpu_address = config .cluster_info .my_contact_info() @@ -570,6 +574,7 @@ impl JsonRpcService { config.send_transaction_service_config.leader_forward_count, Some(identity_keypair), tpu_client_socket, + cancel, ); let json_rpc_service = Self::new_with_client( @@ -592,7 +597,6 @@ impl JsonRpcService { config.leader_schedule_cache, client, config.max_complete_transaction_status_slot, - config.max_complete_rewards_slot, config.prioritization_fee_cache, runtime, )?; @@ -623,7 +627,6 @@ impl JsonRpcService { leader_schedule_cache: Arc, connection_cache: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, prioritization_fee_cache: Arc, ) -> Result { let runtime = service_runtime( @@ -671,7 +674,6 @@ impl JsonRpcService { leader_schedule_cache, client.clone(), max_complete_transaction_status_slot, - max_complete_rewards_slot, prioritization_fee_cache, runtime, )?; @@ -706,7 +708,6 @@ impl JsonRpcService { leader_schedule_cache: Arc, client: Client, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, prioritization_fee_cache: Arc, runtime: Arc, ) -> Result { @@ -759,7 +760,6 @@ impl JsonRpcService { blockstore.clone(), block_commitment_cache.clone(), max_complete_transaction_status_slot.clone(), - max_complete_rewards_slot.clone(), ConfirmedBlockUploadConfig::default(), exit_bigtable_ledger_upload_service.clone(), ))) @@ -800,7 +800,6 @@ impl JsonRpcService { max_slots, leader_schedule_cache, max_complete_transaction_status_slot, - max_complete_rewards_slot, prioritization_fee_cache, Arc::clone(&runtime), ); @@ -1016,7 +1015,6 @@ mod tests { Arc::new(LeaderScheduleCache::default()), connection_cache, Arc::new(AtomicU64::default()), - Arc::new(AtomicU64::default()), Arc::new(PrioritizationFeeCache::default()), ) .expect("assume successful JsonRpcService start"); diff --git a/rpc/src/rpc_subscriptions.rs b/rpc/src/rpc_subscriptions.rs index 1c716e05d58e65..76a44d9e94d28d 100644 --- a/rpc/src/rpc_subscriptions.rs +++ b/rpc/src/rpc_subscriptions.rs @@ -532,7 +532,6 @@ impl RpcSubscriptions { pub fn new( exit: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, blockstore: Arc, bank_forks: Arc>, block_commitment_cache: Arc>, @@ -541,7 +540,6 @@ impl RpcSubscriptions { Self::new_with_config( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore, bank_forks, block_commitment_cache, @@ -554,7 +552,6 @@ impl RpcSubscriptions { pub fn new_for_tests( exit: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, bank_forks: Arc>, block_commitment_cache: Arc>, optimistically_confirmed_bank: Arc>, @@ -566,7 +563,6 @@ impl RpcSubscriptions { Self::new_for_tests_with_blockstore( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore, bank_forks, block_commitment_cache, @@ -577,7 +573,6 @@ impl RpcSubscriptions { pub fn new_for_tests_with_blockstore( exit: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, blockstore: Arc, bank_forks: Arc>, block_commitment_cache: Arc>, @@ -588,7 +583,6 @@ impl RpcSubscriptions { let rpc_subscriptions = Self::new_with_config( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore, bank_forks, block_commitment_cache, @@ -613,7 +607,6 @@ impl RpcSubscriptions { pub fn new_with_config( exit: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, blockstore: Arc, bank_forks: Arc>, block_commitment_cache: Arc>, @@ -652,7 +645,6 @@ impl RpcSubscriptions { Self::process_notifications( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore, notifier, notification_receiver, @@ -683,7 +675,6 @@ impl RpcSubscriptions { // For tests only... pub fn default_with_bank_forks( max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, bank_forks: Arc>, ) -> Self { let ledger_path = get_tmp_ledger_path!(); @@ -694,7 +685,6 @@ impl RpcSubscriptions { Self::new( Arc::new(AtomicBool::new(false)), max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore, bank_forks, Arc::new(RwLock::new(BlockCommitmentCache::default())), @@ -768,7 +758,6 @@ impl RpcSubscriptions { fn process_notifications( exit: Arc, max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, blockstore: Arc, notifier: RpcNotifier, notification_receiver: Receiver, @@ -854,7 +843,6 @@ impl RpcSubscriptions { const SOURCE: &str = "bank"; RpcSubscriptions::notify_watchers( max_complete_transaction_status_slot.clone(), - max_complete_rewards_slot.clone(), subscriptions.commitment_watchers(), &bank_forks, &blockstore, @@ -871,7 +859,6 @@ impl RpcSubscriptions { const SOURCE: &str = "gossip"; RpcSubscriptions::notify_watchers( max_complete_transaction_status_slot.clone(), - max_complete_rewards_slot.clone(), subscriptions.gossip_watchers(), &bank_forks, &blockstore, @@ -926,7 +913,6 @@ impl RpcSubscriptions { fn notify_watchers( max_complete_transaction_status_slot: Arc, - max_complete_rewards_slot: Arc, subscriptions: &HashMap>, bank_forks: &Arc>, blockstore: &Blockstore, @@ -1020,9 +1006,7 @@ impl RpcSubscriptions { // caused by non-deterministic concurrency accesses, we // break out of the loop. Besides if the current `s` is // greater, then any `s + K` is also greater. - if s > max_complete_transaction_status_slot.load(Ordering::SeqCst) - || s > max_complete_rewards_slot.load(Ordering::SeqCst) - { + if s > max_complete_transaction_status_slot.load(Ordering::SeqCst) { break; } @@ -1312,11 +1296,9 @@ pub(crate) mod tests { let exit = Arc::new(AtomicBool::new(false)); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots( 1, 1, @@ -1457,11 +1439,9 @@ pub(crate) mod tests { let blockstore = Blockstore::open(ledger_path.path()).unwrap(); let blockstore = Arc::new(blockstore); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests_with_blockstore( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore.clone(), bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), @@ -1577,11 +1557,9 @@ pub(crate) mod tests { let blockstore = Blockstore::open(ledger_path.path()).unwrap(); let blockstore = Arc::new(blockstore); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests_with_blockstore( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore.clone(), bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), @@ -1695,11 +1673,9 @@ pub(crate) mod tests { let blockstore = Blockstore::open(ledger_path.path()).unwrap(); let blockstore = Arc::new(blockstore); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests_with_blockstore( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, blockstore.clone(), bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), @@ -1828,11 +1804,9 @@ pub(crate) mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), optimistically_confirmed_bank, @@ -1978,11 +1952,9 @@ pub(crate) mod tests { OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let mut pending_optimistically_confirmed_banks = HashSet::new(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots( 1, 1, @@ -2156,11 +2128,9 @@ pub(crate) mod tests { OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let mut pending_optimistically_confirmed_banks = HashSet::new(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots( 1, 1, @@ -2272,11 +2242,9 @@ pub(crate) mod tests { OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let mut pending_optimistically_confirmed_banks = HashSet::new(); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots( 1, 1, @@ -2469,11 +2437,9 @@ pub(crate) mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, Arc::new(RwLock::new(block_commitment_cache)), optimistically_confirmed_bank, @@ -2645,11 +2611,9 @@ pub(crate) mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), optimistically_confirmed_bank, @@ -2692,11 +2656,9 @@ pub(crate) mod tests { let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), optimistically_confirmed_bank, @@ -2753,11 +2715,9 @@ pub(crate) mod tests { let exit = Arc::new(AtomicBool::new(false)); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests_with_slots( 1, 1, @@ -2957,13 +2917,11 @@ pub(crate) mod tests { let exit = Arc::new(AtomicBool::new(false)); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let optimistically_confirmed_bank = OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks); let subscriptions = Arc::new(RpcSubscriptions::new_for_tests( exit, max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks.clone(), Arc::new(RwLock::new(BlockCommitmentCache::new_for_tests())), optimistically_confirmed_bank, @@ -3034,11 +2992,9 @@ pub(crate) mod tests { let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100); let bank = Bank::new_for_tests(&genesis_config); let max_complete_transaction_status_slot = Arc::new(AtomicU64::default()); - let max_complete_rewards_slot = Arc::new(AtomicU64::default()); let bank_forks = BankForks::new_rw_arc(bank); let subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks( max_complete_transaction_status_slot, - max_complete_rewards_slot, bank_forks, )); diff --git a/rpc/src/transaction_status_service.rs b/rpc/src/transaction_status_service.rs index 67a051eb1e8664..0e2cfe291d867c 100644 --- a/rpc/src/transaction_status_service.rs +++ b/rpc/src/transaction_status_service.rs @@ -1,3 +1,8 @@ +//! The `TransactionStatusService` receives executed transactions and creates +//! transaction metadata objects to persist into the Blockstore and optionally +//! broadcast over geyser. The service also records block metadata for any +//! frozen banks it receives. + use { crate::transaction_notifier_interface::TransactionNotifierArc, crossbeam_channel::{Receiver, RecvTimeoutError}, @@ -6,9 +11,11 @@ use { blockstore::{Blockstore, BlockstoreError}, blockstore_processor::{TransactionStatusBatch, TransactionStatusMessage}, }, + solana_runtime::bank::{Bank, KeyedRewardsAndNumPartitions}, solana_svm::transaction_commit_result::CommittedTransaction, solana_transaction_status::{ - extract_and_fmt_memos, map_inner_instructions, Reward, TransactionStatusMeta, + extract_and_fmt_memos, map_inner_instructions, Reward, RewardsAndNumPartitions, + TransactionStatusMeta, }, std::{ sync::{ @@ -33,6 +40,8 @@ pub struct TransactionStatusService { } impl TransactionStatusService { + const SERVICE_NAME: &str = "TransactionStatusService"; + pub fn new( write_transaction_status_receiver: Receiver, max_complete_transaction_status_slot: Arc, @@ -48,7 +57,7 @@ impl TransactionStatusService { let thread_hdl = Builder::new() .name("solTxStatusWrtr".to_string()) .spawn(move || { - info!("TransactionStatusService has started"); + info!("{} has started", Self::SERVICE_NAME); loop { if exit.load(Ordering::Relaxed) { break; @@ -58,7 +67,8 @@ impl TransactionStatusService { .recv_timeout(Duration::from_secs(1)) { Ok(message) => message, - Err(RecvTimeoutError::Disconnected) => { + Err(err @ RecvTimeoutError::Disconnected) => { + info!("{} is stopping because: {err}", Self::SERVICE_NAME); break; } Err(RecvTimeoutError::Timeout) => { @@ -76,13 +86,13 @@ impl TransactionStatusService { ) { Ok(_) => {} Err(err) => { - error!("TransactionStatusService stopping due to error: {err}"); + error!("{} is stopping because: {err}", Self::SERVICE_NAME); exit.store(true, Ordering::Relaxed); break; } } } - info!("TransactionStatusService has stopped"); + info!("{} has stopped", Self::SERVICE_NAME); }) .unwrap(); Self { @@ -230,13 +240,47 @@ impl TransactionStatusService { blockstore.write_batch(status_and_memos_batch)?; } } - TransactionStatusMessage::Freeze(slot) => { - max_complete_transaction_status_slot.fetch_max(slot, Ordering::SeqCst); + TransactionStatusMessage::Freeze(bank) => { + Self::write_block_meta(&bank, blockstore)?; + max_complete_transaction_status_slot.fetch_max(bank.slot(), Ordering::SeqCst); } } Ok(()) } + fn write_block_meta(bank: &Bank, blockstore: &Blockstore) -> Result<(), BlockstoreError> { + let slot = bank.slot(); + + blockstore.set_block_time(slot, bank.clock().unix_timestamp)?; + blockstore.set_block_height(slot, bank.block_height())?; + + let rewards = bank.get_rewards_and_num_partitions(); + if rewards.should_record() { + let KeyedRewardsAndNumPartitions { + keyed_rewards, + num_partitions, + } = rewards; + let rewards = keyed_rewards + .into_iter() + .map(|(pubkey, reward_info)| Reward { + pubkey: pubkey.to_string(), + lamports: reward_info.lamports, + post_balance: reward_info.post_balance, + reward_type: Some(reward_info.reward_type), + commission: reward_info.commission, + }) + .collect(); + let blockstore_rewards = RewardsAndNumPartitions { + rewards, + num_partitions, + }; + + blockstore.write_rewards(slot, blockstore_rewards)?; + } + + Ok(()) + } + pub fn join(self) -> thread::Result<()> { self.thread_hdl.join() } diff --git a/runtime-transaction/Cargo.toml b/runtime-transaction/Cargo.toml index 9bae40762bd77f..3e3542baa1a357 100644 --- a/runtime-transaction/Cargo.toml +++ b/runtime-transaction/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_runtime_transaction" + +[features] +dev-context-only-utils = ["solana-compute-budget-instruction/dev-context-only-utils"] + [dependencies] agave-transaction-view = { workspace = true } log = { workspace = true } @@ -24,10 +34,6 @@ solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } thiserror = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_runtime_transaction" - [dev-dependencies] agave-feature-set = { workspace = true } agave-reserved-account-keys = { workspace = true } @@ -38,18 +44,12 @@ solana-compute-budget-instruction = { workspace = true, features = ["dev-context solana-compute-budget-interface = { workspace = true } solana-instruction = { workspace = true } solana-keypair = { workspace = true } -solana-program = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } solana-signer = { workspace = true } solana-system-interface = { workspace = true, features = ["bincode"] } solana-system-transaction = { workspace = true } solana-transaction = { workspace = true, features = ["blake3"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = ["solana-compute-budget-instruction/dev-context-only-utils"] +solana-vote-interface = { workspace = true } [[bench]] name = "get_signature_details" diff --git a/runtime-transaction/src/runtime_transaction.rs b/runtime-transaction/src/runtime_transaction.rs index 3d557269bdb498..9626ff3638e52c 100644 --- a/runtime-transaction/src/runtime_transaction.rs +++ b/runtime-transaction/src/runtime_transaction.rs @@ -35,6 +35,12 @@ pub struct RuntimeTransaction { meta: TransactionMeta, } +impl RuntimeTransaction { + pub fn into_inner_transaction(self) -> T { + self.transaction + } +} + impl StaticMeta for RuntimeTransaction { fn message_hash(&self) -> &Hash { &self.meta.message_hash diff --git a/runtime-transaction/src/runtime_transaction/sdk_transactions.rs b/runtime-transaction/src/runtime_transaction/sdk_transactions.rs index 74c93b72d28e8f..f8662918ff14f1 100644 --- a/runtime-transaction/src/runtime_transaction/sdk_transactions.rs +++ b/runtime-transaction/src/runtime_transaction/sdk_transactions.rs @@ -164,10 +164,10 @@ mod tests { solana_instruction::Instruction, solana_keypair::Keypair, solana_message::{Message, SimpleAddressLoader}, - solana_program::vote::{self, state::Vote}, solana_signer::Signer, solana_system_interface::instruction as system_instruction, solana_transaction::{versioned::VersionedTransaction, Transaction}, + solana_vote_interface::{self as vote, state::Vote}, }; fn vote_sanitized_versioned_transaction() -> SanitizedVersionedTransaction { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index d89d22030e33e2..965d139752a46f 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -9,6 +9,43 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_runtime" + +[features] +dev-context-only-utils = [ + "dep:solana-system-program", + "solana-svm/dev-context-only-utils", + "solana-runtime-transaction/dev-context-only-utils", + "solana-vote/dev-context-only-utils", +] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-account/frozen-abi", + "solana-accounts-db/frozen-abi", + "solana-compute-budget/frozen-abi", + "solana-cost-model/frozen-abi", + "solana-epoch-schedule/frozen-abi", + "solana-hard-forks/frozen-abi", + "solana-inflation/frozen-abi", + "solana-instruction/frozen-abi", + "solana-perf/frozen-abi", + "solana-program-runtime/frozen-abi", + "solana-rent/frozen-abi", + "solana-rent-collector/frozen-abi", + "solana-stake-interface/frozen-abi", + "solana-svm/frozen-abi", + "solana-transaction-error/frozen-abi", + "solana-version/frozen-abi", + "solana-vote/frozen-abi", + "solana-vote-program/frozen-abi", +] + [dependencies] agave-feature-set = { workspace = true } agave-precompiles = { workspace = true } @@ -71,7 +108,7 @@ solana-epoch-schedule = { workspace = true } solana-feature-gate-interface = { workspace = true } solana-fee = { workspace = true } solana-fee-calculator = { workspace = true } -solana-fee-structure = { workspace = true } +solana-fee-structure = { workspace = true, features = ["serde"] } solana-frozen-abi = { workspace = true, optional = true, features = [ "frozen-abi", ] } @@ -79,11 +116,11 @@ solana-frozen-abi-macro = { workspace = true, optional = true, features = [ "frozen-abi", ] } solana-genesis-config = { workspace = true } -solana-hard-forks = { workspace = true } +solana-hard-forks = { workspace = true, features = ["serde"] } solana-hash = { workspace = true } solana-inflation = { workspace = true } solana-instruction = { workspace = true } -solana-keypair = { workspace = true } +solana-keypair = { workspace = true, features = ["seed-derivable"] } solana-lattice-hash = { workspace = true } solana-loader-v3-interface = { workspace = true, features = ["bincode"] } solana-loader-v4-interface = { workspace = true, features = ["serde"] } @@ -98,18 +135,15 @@ solana-packet = { workspace = true } solana-perf = { workspace = true } solana-poh-config = { workspace = true } solana-precompile-error = { workspace = true } -solana-program = { workspace = true } solana-program-runtime = { workspace = true, features = ["metrics"] } -solana-pubkey = { workspace = true } +solana-pubkey = { workspace = true, features = ["rand"] } solana-rayon-threadlimit = { workspace = true } solana-rent = { workspace = true } -solana-rent-collector = { workspace = true } +solana-rent-collector = { workspace = true, features = ["serde"] } solana-rent-debits = { workspace = true } solana-reward-info = { workspace = true } solana-runtime-transaction = { workspace = true } -solana-sdk = { workspace = true, features = ["full"] } solana-sdk-ids = { workspace = true } -solana-sdk-macro = { workspace = true } solana-secp256k1-program = { workspace = true } solana-seed-derivable = { workspace = true } solana-serde = { workspace = true } @@ -131,7 +165,7 @@ solana-sysvar = { workspace = true } solana-sysvar-id = { workspace = true } solana-time-utils = { workspace = true } solana-timings = { workspace = true } -solana-transaction = { workspace = true } +solana-transaction = { workspace = true, features = ["verify"] } solana-transaction-context = { workspace = true } solana-transaction-error = { workspace = true } solana-transaction-status-client-types = { workspace = true } @@ -150,10 +184,6 @@ tempfile = { workspace = true } thiserror = { workspace = true } zstd = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_runtime" - [dev-dependencies] agave-transaction-view = { workspace = true } ed25519-dalek = { workspace = true } @@ -164,43 +194,19 @@ rand_chacha = { workspace = true } solana-accounts-db = { workspace = true, features = ["dev-context-only-utils"] } solana-builtins = { workspace = true, features = ["dev-context-only-utils"] } solana-logger = { workspace = true } +solana-rent-debits = { workspace = true, features = ["dev-context-only-utils"] } # See order-crates-for-publishing.py for using this unusual `path = "."` solana-runtime = { path = ".", features = ["dev-context-only-utils"] } solana-runtime-transaction = { workspace = true, features = [ "dev-context-only-utils", ] } -solana-sdk = { workspace = true, features = ["full","dev-context-only-utils"] } solana-sdk-ids = { workspace = true } +solana-signature = { workspace = true, features = ["std"] } solana-svm = { workspace = true, features = ["dev-context-only-utils"] } solana-transaction-context = { workspace = true, features = ["dev-context-only-utils"] } static_assertions = { workspace = true } test-case = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = [ - "dep:solana-system-program", - "solana-svm/dev-context-only-utils", - "solana-runtime-transaction/dev-context-only-utils", - "solana-vote/dev-context-only-utils", -] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-accounts-db/frozen-abi", - "solana-compute-budget/frozen-abi", - "solana-cost-model/frozen-abi", - "solana-perf/frozen-abi", - "solana-program-runtime/frozen-abi", - "solana-sdk/frozen-abi", - "solana-svm/frozen-abi", - "solana-version/frozen-abi", - "solana-vote/frozen-abi", - "solana-vote-program/frozen-abi", -] - [[bench]] name = "prioritization_fee_cache" diff --git a/runtime/src/accounts_background_service.rs b/runtime/src/accounts_background_service.rs index 5a924ec875ea90..aef7bf5a1ffb04 100644 --- a/runtime/src/accounts_background_service.rs +++ b/runtime/src/accounts_background_service.rs @@ -16,7 +16,6 @@ use { }, crossbeam_channel::{Receiver, SendError, Sender}, log::*, - rand::{thread_rng, Rng}, rayon::iter::{IntoParallelIterator, ParallelIterator}, solana_accounts_db::{ accounts_db::CalcAccountsHashDataSource, accounts_hash::CalcAccountsHashConfig, @@ -26,10 +25,11 @@ use { stats::StatsManager, std::{ boxed::Box, - fmt::{Debug, Formatter}, + cmp, + fmt::{self, Debug, Formatter}, sync::{ atomic::{AtomicBool, AtomicU64, Ordering}, - Arc, RwLock, + Arc, LazyLock, RwLock, }, thread::{self, sleep, Builder, JoinHandle}, time::{Duration, Instant}, @@ -37,7 +37,10 @@ use { }; const INTERVAL_MS: u64 = 100; -const CLEAN_INTERVAL_BLOCKS: u64 = 100; +// Set the clean interval duration to be approximately how long before the next incremental +// snapshot request is received, plus some buffer. The default incremental snapshot interval is +// 100 slots, which ends up being 40 seconds plus buffer. +const CLEAN_INTERVAL: Duration = Duration::from_secs(50); const SHRINK_INTERVAL: Duration = Duration::from_secs(1); pub type SnapshotRequestSender = Sender; @@ -68,8 +71,8 @@ impl PrunedBankQueueLenReporter { } } -static BANK_DROP_QUEUE_REPORTER: std::sync::LazyLock = - std::sync::LazyLock::new(PrunedBankQueueLenReporter::default); +static BANK_DROP_QUEUE_REPORTER: LazyLock = + LazyLock::new(PrunedBankQueueLenReporter::default); #[derive(Clone)] pub struct SendDroppedBankCallback { @@ -90,7 +93,7 @@ impl DropCallback for SendDroppedBankCallback { } impl Debug for SendDroppedBankCallback { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "SendDroppedBankCallback({self:p})") } } @@ -112,7 +115,7 @@ pub struct SnapshotRequest { } impl Debug for SnapshotRequest { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SnapshotRequest") .field("request kind", &self.request_kind) .field("bank slot", &self.snapshot_root_bank.slot()) @@ -140,14 +143,14 @@ pub struct SnapshotRequestHandler { } impl SnapshotRequestHandler { - // Returns the latest requested snapshot block height and storages + // Returns the latest requested snapshot slot and storages #[allow(clippy::type_complexity)] pub fn handle_snapshot_requests( &self, test_hash_calculation: bool, non_snapshot_time_us: u128, exit: &AtomicBool, - ) -> Option> { + ) -> Option> { let (snapshot_request, num_outstanding_requests, num_re_enqueued_requests) = self.get_next_snapshot_request()?; @@ -272,7 +275,7 @@ impl SnapshotRequestHandler { snapshot_request: SnapshotRequest, accounts_package_kind: AccountsPackageKind, exit: &AtomicBool, - ) -> Result { + ) -> Result { info!("handling snapshot request: {snapshot_request:?}, {accounts_package_kind:?}"); let mut total_time = Measure::start("snapshot_request_receiver_total_time"); let SnapshotRequest { @@ -413,7 +416,7 @@ impl SnapshotRequestHandler { ("non_snapshot_time_us", non_snapshot_time_us, i64), ("shrink_ancient_time_us", shrink_ancient_time_us, i64), ); - Ok(snapshot_root_bank.block_height()) + Ok(snapshot_root_bank.slot()) } } @@ -489,14 +492,14 @@ pub struct AbsRequestHandlers { } impl AbsRequestHandlers { - // Returns the latest requested snapshot block height, if one exists + // Returns the latest requested snapshot slot, if one exists #[allow(clippy::type_complexity)] pub fn handle_snapshot_requests( &self, test_hash_calculation: bool, non_snapshot_time_us: u128, exit: &AtomicBool, - ) -> Option> { + ) -> Option> { self.snapshot_request_handler.handle_snapshot_requests( test_hash_calculation, non_snapshot_time_us, @@ -519,7 +522,7 @@ impl AccountsBackgroundService { ) -> Self { let is_running = Arc::new(AtomicBool::new(true)); let stop = Arc::new(AtomicBool::new(false)); - let mut last_cleaned_block_height = 0; + let mut last_cleaned_slot = 0; let mut removed_slots_count = 0; let mut total_remove_slots_time = 0; let t_background = Builder::new() @@ -532,6 +535,7 @@ impl AccountsBackgroundService { info!("AccountsBackgroundService has started"); let mut stats = StatsManager::new(); let mut last_snapshot_end_time = None; + let mut previous_clean_time = Instant::now(); let mut previous_shrink_time = Instant::now(); loop { @@ -598,54 +602,67 @@ impl AccountsBackgroundService { last_snapshot_end_time = Some(Instant::now()); match snapshot_handle_result { - Ok(snapshot_block_height) => { - assert!(last_cleaned_block_height <= snapshot_block_height); - last_cleaned_block_height = snapshot_block_height; + Ok(snapshot_slot) => { + assert!( + last_cleaned_slot <= snapshot_slot, + "last cleaned slot: {last_cleaned_slot}, \ + snapshot request slot: {snapshot_slot}, \ + is startup verification complete: {}, \ + enqueued snapshot requests: {:?}", + bank.is_startup_verification_complete(), + request_handlers + .snapshot_request_handler + .snapshot_request_receiver + .try_iter() + .collect::>(), + ); + last_cleaned_slot = snapshot_slot; + previous_clean_time = Instant::now(); + previous_shrink_time = Instant::now(); } Err(err) => { error!( "Stopping AccountsBackgroundService! \ - Fatal error while handling snapshot requests: {err}", + Fatal error while handling snapshot requests: {err}", ); exit.store(true, Ordering::Relaxed); break; } } - } else if bank.block_height() - last_cleaned_block_height - > (CLEAN_INTERVAL_BLOCKS + thread_rng().gen_range(0..10)) - { - // Note that the flush will do an internal clean of the - // cache up to bank.slot(), so should be safe as long - // as any later snapshots that are taken are of - // slots >= bank.slot() - bank.force_flush_accounts_cache(); - bank.clean_accounts(); - last_cleaned_block_height = bank.block_height(); - // Do not 'shrink' until *after* the startup verification is complete. - // This is because startup verification needs to get the snapshot - // storages *as they existed at startup* (to calculate the accounts - // hash). If 'shrink' were to run, then it is possible startup - // verification (1) could race with 'shrink', and fail to assert that - // shrinking is not in progress, or (2) could get snapshot storages - // that were newer than what was in the snapshot itself. - if bank.is_startup_verification_complete() { - bank.shrink_ancient_slots(); - bank.shrink_candidate_slots(); - } } else { - // Note that the flush will do an internal clean of the - // cache up to bank.slot(), so should be safe as long - // as any later snapshots that are taken are of - // slots >= bank.slot() - bank.flush_accounts_cache_if_needed(); - - // See justification above for why we skip 'shrink' here. - if bank.is_startup_verification_complete() { - let duration_since_previous_shrink = previous_shrink_time.elapsed(); - if duration_since_previous_shrink > SHRINK_INTERVAL { - previous_shrink_time = Instant::now(); - bank.shrink_candidate_slots(); + // we didn't handle a snapshot request, so do flush/clean/shrink + + // see the comments in Bank::clean_accounts() for why we sub 1 here + let max_clean_slot_inclusive = bank.slot().saturating_sub(1); + + let duration_since_previous_clean = previous_clean_time.elapsed(); + let should_clean = duration_since_previous_clean > CLEAN_INTERVAL; + + // if we're cleaning, then force flush, otherwise be lazy + let force_flush = should_clean; + bank.rc + .accounts + .accounts_db + .flush_accounts_cache(force_flush, Some(max_clean_slot_inclusive)); + + if should_clean { + bank.clean_accounts(); + last_cleaned_slot = max_clean_slot_inclusive; + previous_clean_time = Instant::now(); + } + + let duration_since_previous_shrink = previous_shrink_time.elapsed(); + let should_shrink = duration_since_previous_shrink > SHRINK_INTERVAL; + // To avoid pathological interactions between the clean and shrink + // timers, call shrink for either should_shrink or should_clean. + if should_shrink || should_clean { + if should_clean { + // We used to only squash (aka shrink ancients) when we also + // cleaned, so keep that same behavior here for now. + bank.shrink_ancient_slots(); } + bank.shrink_candidate_slots(); + previous_shrink_time = Instant::now(); } } stats.record_and_maybe_submit(start_time.elapsed()); @@ -765,7 +782,7 @@ fn new_accounts_package_kind(snapshot_request: &SnapshotRequest) -> Option std::cmp::Ordering { +fn cmp_requests_by_priority(a: &SnapshotRequest, b: &SnapshotRequest) -> cmp::Ordering { let slot_a = a.snapshot_root_bank.slot(); let slot_b = b.snapshot_root_bank.slot(); cmp_snapshot_request_kinds_by_priority(&a.request_kind, &b.request_kind) @@ -782,9 +799,9 @@ fn cmp_requests_by_priority(a: &SnapshotRequest, b: &SnapshotRequest) -> std::cm fn cmp_snapshot_request_kinds_by_priority( a: &SnapshotRequestKind, b: &SnapshotRequestKind, -) -> std::cmp::Ordering { +) -> cmp::Ordering { use { - std::cmp::Ordering::{Equal, Greater, Less}, + cmp::Ordering::{Equal, Greater, Less}, SnapshotRequestKind as Kind, }; match (a, b) { @@ -1122,7 +1139,7 @@ mod test { #[test] fn test_cmp_snapshot_request_kinds_by_priority() { - use std::cmp::Ordering::{Equal, Greater, Less}; + use cmp::Ordering::{Equal, Greater, Less}; for (snapshot_request_kind_a, snapshot_request_kind_b, expected_result) in [ ( SnapshotRequestKind::EpochAccountsHash, diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 4acc11ec7a3b56..cd86ada1a4d03b 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -64,6 +64,7 @@ use { ahash::{AHashSet, RandomState}, dashmap::{DashMap, DashSet}, log::*, + partitioned_epoch_rewards::PartitionedRewardsCalculation, rayon::{ iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator}, ThreadPoolBuilder, @@ -334,6 +335,7 @@ pub struct TransactionSimulationResult { pub logs: TransactionLogMessages, pub post_simulation_accounts: Vec, pub units_consumed: u64, + pub loaded_accounts_data_size: u32, pub return_data: Option, pub inner_instructions: Option>, } @@ -583,6 +585,7 @@ impl PartialEq for Bank { stats_for_accounts_lt_hash: _, block_id, bank_hash_stats: _, + epoch_rewards_calculation_cache: _, // Ignore new fields explicitly if they do not impact PartialEq. // Adding ".." will remove compile-time checks that if a new field // is added to the struct, this PartialEq is accordingly updated. @@ -941,6 +944,11 @@ pub struct Bank { /// Accounts stats for computing the bank hash bank_hash_stats: AtomicBankHashStats, + + /// The cache of epoch rewards calculation results + /// This is used to avoid recalculating the same epoch rewards at epoch boundary. + /// The hashmap is keyed by parent_hash. + epoch_rewards_calculation_cache: Arc>>>, } #[derive(Debug)] @@ -1140,6 +1148,7 @@ impl Bank { stats_for_accounts_lt_hash: AccountsLtHashStats::default(), block_id: RwLock::new(None), bank_hash_stats: AtomicBankHashStats::default(), + epoch_rewards_calculation_cache: Arc::new(Mutex::new(HashMap::default())), }; bank.transaction_processor = @@ -1396,6 +1405,7 @@ impl Bank { stats_for_accounts_lt_hash: AccountsLtHashStats::default(), block_id: RwLock::new(None), bank_hash_stats: AtomicBankHashStats::default(), + epoch_rewards_calculation_cache: parent.epoch_rewards_calculation_cache.clone(), }; let (_, ancestors_time_us) = measure_us!({ @@ -1873,6 +1883,7 @@ impl Bank { stats_for_accounts_lt_hash: AccountsLtHashStats::default(), block_id: RwLock::new(None), bank_hash_stats: AtomicBankHashStats::new(&fields.bank_hash_stats), + epoch_rewards_calculation_cache: Arc::new(Mutex::new(HashMap::default())), }; bank.transaction_processor = @@ -2519,12 +2530,14 @@ impl Bank { fn update_reward_history( &self, stake_rewards: StakeRewards, - mut vote_rewards: Vec<(Pubkey, RewardInfo)>, + vote_rewards: &[(Pubkey, RewardInfo)], ) { let additional_reserve = stake_rewards.len() + vote_rewards.len(); let mut rewards = self.rewards.write().unwrap(); rewards.reserve(additional_reserve); - rewards.append(&mut vote_rewards); + vote_rewards.iter().for_each(|(vote_pubkey, vote_reward)| { + rewards.push((*vote_pubkey, *vote_reward)); + }); stake_rewards .into_iter() .filter(|x| x.get_stake_reward() > 0) @@ -3127,11 +3140,6 @@ impl Bank { self.register_tick_for_test(&Hash::default()) } - #[cfg(feature = "dev-context-only-utils")] - pub fn register_unique_tick(&self) { - self.register_tick_for_test(&Hash::new_unique()) - } - pub fn is_complete(&self) -> bool { self.tick_height() == self.max_tick_height() } @@ -3172,53 +3180,77 @@ impl Bank { ) }) .collect::>>()?; - let tx_account_lock_limit = self.get_transaction_account_lock_limit(); - let lock_results = self - .rc - .accounts - .lock_accounts(sanitized_txs.iter(), tx_account_lock_limit); Ok(TransactionBatch::new( - lock_results, + self.try_lock_accounts(&sanitized_txs), self, OwnedOrBorrowed::Owned(sanitized_txs), )) } /// Attempt to take locks on the accounts in a transaction batch - pub fn try_lock_accounts(&self, txs: &[impl SVMMessage]) -> Vec> { + pub fn try_lock_accounts(&self, txs: &[impl TransactionWithMeta]) -> Vec> { + self.try_lock_accounts_with_results(txs, txs.iter().map(|_| Ok(()))) + } + + /// Attempt to take locks on the accounts in a transaction batch, and their cost + /// limited packing status and duplicate transaction conflict status + pub fn try_lock_accounts_with_results( + &self, + txs: &[impl TransactionWithMeta], + tx_results: impl Iterator>, + ) -> Vec> { let tx_account_lock_limit = self.get_transaction_account_lock_limit(); - self.rc - .accounts - .lock_accounts(txs.iter(), tx_account_lock_limit) + let relax_intrabatch_account_locks = self + .feature_set + .is_active(&feature_set::relax_intrabatch_account_locks::id()); + + // with simd83 enabled, we must fail transactions that duplicate a prior message hash + // previously, conflicting account locks would fail such transactions as a side effect + let mut batch_message_hashes = AHashSet::with_capacity(txs.len()); + let tx_results = tx_results + .enumerate() + .map(|(i, tx_result)| match tx_result { + Ok(()) if relax_intrabatch_account_locks => { + // `HashSet::insert()` returns `true` when the value does *not* already exist + if batch_message_hashes.insert(txs[i].message_hash()) { + Ok(()) + } else { + Err(TransactionError::AlreadyProcessed) + } + } + Ok(()) => Ok(()), + Err(e) => Err(e), + }); + + self.rc.accounts.lock_accounts( + txs.iter(), + tx_results, + tx_account_lock_limit, + relax_intrabatch_account_locks, + ) } /// Prepare a locked transaction batch from a list of sanitized transactions. - pub fn prepare_sanitized_batch<'a, 'b, Tx: SVMMessage>( + pub fn prepare_sanitized_batch<'a, 'b, Tx: TransactionWithMeta>( &'a self, txs: &'b [Tx], ) -> TransactionBatch<'a, 'b, Tx> { - TransactionBatch::new( - self.try_lock_accounts(txs), - self, - OwnedOrBorrowed::Borrowed(txs), - ) + self.prepare_sanitized_batch_with_results(txs, txs.iter().map(|_| Ok(()))) } /// Prepare a locked transaction batch from a list of sanitized transactions, and their cost /// limited packing status - pub fn prepare_sanitized_batch_with_results<'a, 'b, Tx: SVMMessage>( + pub fn prepare_sanitized_batch_with_results<'a, 'b, Tx: TransactionWithMeta>( &'a self, transactions: &'b [Tx], transaction_results: impl Iterator>, ) -> TransactionBatch<'a, 'b, Tx> { // this lock_results could be: Ok, AccountInUse, WouldExceedBlockMaxLimit or WouldExceedAccountMaxLimit - let tx_account_lock_limit = self.get_transaction_account_lock_limit(); - let lock_results = self.rc.accounts.lock_accounts_with_results( - transactions.iter(), - transaction_results, - tx_account_lock_limit, - ); - TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Borrowed(transactions)) + TransactionBatch::new( + self.try_lock_accounts_with_results(transactions, transaction_results), + self, + OwnedOrBorrowed::Borrowed(transactions), + ) } /// Prepare a transaction batch from a single transaction without locking accounts @@ -3238,7 +3270,7 @@ impl Bank { } /// Prepare a transaction batch from a single transaction after locking accounts - pub fn prepare_locked_batch_from_single_tx<'a, Tx: SVMMessage>( + pub fn prepare_locked_batch_from_single_tx<'a, Tx: TransactionWithMeta>( &'a self, transaction: &'a Tx, ) -> TransactionBatch<'a, 'a, Tx> { @@ -3306,6 +3338,7 @@ impl Bank { return_data, inner_instructions, units_consumed, + loaded_accounts_data_size, ) = match processing_result { Ok(processed_tx) => match processed_tx { ProcessedTransaction::Executed(executed_tx) => { @@ -3323,13 +3356,20 @@ impl Bank { details.return_data, details.inner_instructions, details.executed_units, + executed_tx.loaded_transaction.loaded_accounts_data_size, ) } - ProcessedTransaction::FeesOnly(fees_only_tx) => { - (vec![], Err(fees_only_tx.load_error), None, None, None, 0) - } + ProcessedTransaction::FeesOnly(fees_only_tx) => ( + vec![], + Err(fees_only_tx.load_error), + None, + None, + None, + 0, + fees_only_tx.rollback_accounts.data_size() as u32, + ), }, - Err(error) => (vec![], Err(error), None, None, None, 0), + Err(error) => (vec![], Err(error), None, None, None, 0, 0), }; let logs = logs.unwrap_or_default(); @@ -3338,6 +3378,7 @@ impl Bank { logs, post_simulation_accounts, units_consumed, + loaded_accounts_data_size, return_data, inner_instructions, } @@ -6860,6 +6901,10 @@ impl Bank { pub fn get_bank_hash_stats(&self) -> BankHashStats { self.bank_hash_stats.load() } + + pub fn clear_epoch_rewards_cache(&self) { + self.epoch_rewards_calculation_cache.lock().unwrap().clear(); + } } impl InvokeContextCallback for Bank { @@ -7082,16 +7127,15 @@ impl Bank { &self, txs: Vec, ) -> TransactionBatch> { - let transaction_account_lock_limit = self.get_transaction_account_lock_limit(); let sanitized_txs = txs .into_iter() .map(RuntimeTransaction::from_transaction_for_tests) .collect::>(); - let lock_results = self - .rc - .accounts - .lock_accounts(sanitized_txs.iter(), transaction_account_lock_limit); - TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Owned(sanitized_txs)) + TransactionBatch::new( + self.try_lock_accounts(&sanitized_txs), + self, + OwnedOrBorrowed::Owned(sanitized_txs), + ) } /// Set the initial accounts data size diff --git a/runtime/src/bank/accounts_lt_hash.rs b/runtime/src/bank/accounts_lt_hash.rs index 301965b7c7470b..ad87254cc00b55 100644 --- a/runtime/src/bank/accounts_lt_hash.rs +++ b/runtime/src/bank/accounts_lt_hash.rs @@ -4,6 +4,7 @@ use { rayon::prelude::*, solana_account::{accounts_equal, AccountSharedData}, solana_accounts_db::accounts_db::AccountsDb, + solana_hash::Hash, solana_lattice_hash::lt_hash::LtHash, solana_measure::{meas_dur, measure::Measure}, solana_pubkey::Pubkey, @@ -289,6 +290,13 @@ impl Bank { .load(Ordering::Relaxed), i64 ), + ( + "num_inspect_account_after_frozen", + self.stats_for_accounts_lt_hash + .num_inspect_account_after_frozen + .load(Ordering::Relaxed), + i64 + ), ( "inspect_account_lookup_ns", self.stats_for_accounts_lt_hash @@ -330,6 +338,23 @@ impl Bank { let (is_in_cache, lookup_time) = meas_dur!(self.cache_for_accounts_lt_hash.contains_key(address)); if !is_in_cache { + // We need to check if the bank is frozen. In order to do that safely, we + // must hold a read lock on Bank::hash to read the frozen state. + let freeze_guard = self.freeze_lock(); + let is_frozen = *freeze_guard != Hash::default(); + if is_frozen { + // If the bank is frozen, do not add this account to the cache. + // It is possible for the leader to be executing transactions after freeze has + // started, i.e. while any deferred changes to account state is finishing up. + // This means the transaction could load an account *after* it was modified by the + // deferred changes, which would be the wrong initial state of the account. + // Inserting the wrong initial state of an account into the cache will end up + // producing the wrong accounts lt hash. + self.stats_for_accounts_lt_hash + .num_inspect_account_after_frozen + .fetch_add(1, Ordering::Relaxed); + return; + } let (_, insert_time) = meas_dur!({ self.cache_for_accounts_lt_hash .entry(*address) @@ -343,6 +368,7 @@ impl Bank { CacheValue::InspectAccount(initial_state_of_account) }); }); + drop(freeze_guard); self.stats_for_accounts_lt_hash .num_inspect_account_misses @@ -372,6 +398,8 @@ pub struct Stats { num_inspect_account_hits: AtomicU64, /// the number of times the cache *did not* already contain the account being inspected num_inspect_account_misses: AtomicU64, + /// the number of times an account was inspected after the bank was frozen + num_inspect_account_after_frozen: AtomicU64, /// time spent checking if accounts are in the cache inspect_account_lookup_time_ns: AtomicU64, /// time spent inserting accounts into the cache @@ -777,6 +805,16 @@ mod tests { _ => panic!("wrong initial state for account"), }; } + + // ensure accounts are *not* added to the cache if the bank is frozen + // N.B. this test should remain *last*, as Bank::freeze() is not meant to be undone + bank.freeze(); + let address = Pubkey::new_unique(); + let num_cache_entries_prev = bank.cache_for_accounts_lt_hash.len(); + bank.inspect_account_for_accounts_lt_hash(&address, &AccountState::Dead, true); + let num_cache_entries_curr = bank.cache_for_accounts_lt_hash.len(); + assert_eq!(num_cache_entries_curr, num_cache_entries_prev); + assert!(!bank.cache_for_accounts_lt_hash.contains_key(&address)); } #[test_case(Features::None; "no features")] diff --git a/runtime/src/bank/partitioned_epoch_rewards/calculation.rs b/runtime/src/bank/partitioned_epoch_rewards/calculation.rs index 7baad975b11f1c..3c118bfdaa6ff4 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/calculation.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/calculation.rs @@ -28,7 +28,6 @@ use { solana_clock::{Epoch, Slot}, solana_measure::measure_us, solana_pubkey::Pubkey, - solana_reward_info::RewardInfo, solana_stake_interface::state::Delegation, solana_sysvar::epoch_rewards::EpochRewards, solana_vote::vote_account::VoteAccount, @@ -95,6 +94,45 @@ impl Bank { thread_pool: &ThreadPool, metrics: &mut RewardsMetrics, ) -> CalculateRewardsAndDistributeVoteRewardsResult { + // We hold the lock here for the epoch rewards calculation cache to prevent + // rewards computation across multiple forks simultaneously. This aligns with + // how banks are currently created- all banks are created sequentially. + // As such, this lock does not actually introduce contention because bank + // creation (and therefore reward calculation) is always done sequentially. + // + // However, if we plan to support creating banks in parallel in the future, this logic + // would need to change to allow rewards computation on multiple forks concurrently. + // That said, there's still a compelling reason to keep this lock even in a parallel + // bank creation model: we want to avoid calculating rewards multiple times for the same + // parent bank hash. This lock ensures that. + // + // Creating bank for multiple forks in parallel would also introduce contention for compute resources, + // potentially slowing down the performance of both forks. This, in turn, could delay + // vote propagation and consensus for the leading fork—the one most likely to become rooted. + // + // Therefore, it seems beneficial to continue processing forks sequentially at epoch + // boundaries: acquire the lock for the first fork, compute rewards, and let other forks + // wait until the computation is complete. + let mut epoch_rewards_calculation_cache = + self.epoch_rewards_calculation_cache.lock().unwrap(); + let rewards_calculation = epoch_rewards_calculation_cache + .entry(self.parent_hash) + .or_insert_with(|| { + let calculation = self.calculate_rewards_for_partitioning( + prev_epoch, + reward_calc_tracer, + thread_pool, + metrics, + ); + info!( + "calculated rewards for epoch: {}, parent_slot: {}, parent_hash: {}", + self.epoch, self.parent_slot, self.parent_hash + ); + Arc::new(calculation) + }) + .clone(); + drop(epoch_rewards_calculation_cache); + let PartitionedRewardsCalculation { vote_account_rewards, stake_rewards, @@ -103,17 +141,13 @@ impl Bank { prev_epoch_duration_in_years, capitalization, point_value, - } = self.calculate_rewards_for_partitioning( - prev_epoch, - reward_calc_tracer, - thread_pool, - metrics, - ); + } = rewards_calculation.as_ref(); + let total_vote_rewards = vote_account_rewards.total_vote_rewards_lamports; - let vote_rewards = self.store_vote_accounts_partitioned(vote_account_rewards, metrics); + self.store_vote_accounts_partitioned(vote_account_rewards, metrics); // update reward history of JUST vote_rewards, stake_rewards is vec![] here - self.update_reward_history(vec![], vote_rewards); + self.update_reward_history(vec![], &vote_account_rewards.rewards[..]); let StakeRewardCalculation { stake_rewards, @@ -148,12 +182,16 @@ impl Bank { "epoch_rewards", ("slot", self.slot, i64), ("epoch", prev_epoch, i64), - ("validator_rate", validator_rate, f64), - ("foundation_rate", foundation_rate, f64), - ("epoch_duration_in_years", prev_epoch_duration_in_years, f64), + ("validator_rate", *validator_rate, f64), + ("foundation_rate", *foundation_rate, f64), + ( + "epoch_duration_in_years", + *prev_epoch_duration_in_years, + f64 + ), ("validator_rewards", total_vote_rewards, i64), ("active_stake", active_stake, i64), - ("pre_capitalization", capitalization, i64), + ("pre_capitalization", *capitalization, i64), ("post_capitalization", self.capitalization(), i64), ("num_stake_accounts", num_stake_accounts, i64), ("num_vote_accounts", num_vote_accounts, i64), @@ -161,16 +199,16 @@ impl Bank { CalculateRewardsAndDistributeVoteRewardsResult { distributed_rewards: total_vote_rewards, - point_value, - stake_rewards, + point_value: point_value.clone(), + stake_rewards: Arc::clone(stake_rewards), } } fn store_vote_accounts_partitioned( &self, - vote_account_rewards: VoteRewardsAccounts, + vote_account_rewards: &VoteRewardsAccounts, metrics: &RewardsMetrics, - ) -> Vec<(Pubkey, RewardInfo)> { + ) { let (_, measure_us) = measure_us!({ self.store_accounts((self.slot(), &vote_account_rewards.accounts_to_store[..])); }); @@ -178,8 +216,6 @@ impl Bank { metrics .store_vote_accounts_us .fetch_add(measure_us, Relaxed); - - vote_account_rewards.rewards } /// Calculate rewards from previous epoch to prepare for partitioned distribution. @@ -398,7 +434,7 @@ impl Bank { ( vote_rewards, StakeRewardCalculation { - stake_rewards, + stake_rewards: Arc::new(stake_rewards), total_stake_rewards_lamports: total_stake_rewards.load(Relaxed), }, ) @@ -467,7 +503,7 @@ impl Bank { ); self.set_epoch_reward_status_distribution( epoch_rewards_sysvar.distribution_starting_block_height, - Arc::new(stake_rewards), + stake_rewards, partition_indices, ); } @@ -481,7 +517,7 @@ impl Bank { epoch_rewards_sysvar: &EpochRewards, reward_calc_tracer: Option, thread_pool: &ThreadPool, - ) -> (Vec, Vec>) { + ) -> (Arc>, Vec>) { assert!(epoch_rewards_sysvar.active); // If rewards are active, the rewarded epoch is always the immediately // preceding epoch. @@ -535,7 +571,7 @@ mod tests { StartBlockHeightAndPartitionedRewards, }, tests::create_genesis_config, - VoteReward, + RewardInfo, VoteReward, }, stake_account::StakeAccount, stakes::Stakes, @@ -580,9 +616,11 @@ mod tests { let metrics = RewardsMetrics::default(); let total_vote_rewards = vote_rewards_account.total_vote_rewards_lamports; - let stored_vote_accounts = - bank.store_vote_accounts_partitioned(vote_rewards_account, &metrics); - assert_eq!(expected_vote_rewards_num, stored_vote_accounts.len()); + bank.store_vote_accounts_partitioned(&vote_rewards_account, &metrics); + assert_eq!( + expected_vote_rewards_num, + vote_rewards_account.accounts_to_store.len() + ); assert_eq!( vote_rewards .iter() @@ -615,8 +653,8 @@ mod tests { let metrics = RewardsMetrics::default(); let total_vote_rewards = vote_rewards.total_vote_rewards_lamports; - let stored_vote_accounts = bank.store_vote_accounts_partitioned(vote_rewards, &metrics); - assert_eq!(expected, stored_vote_accounts.len()); + bank.store_vote_accounts_partitioned(&vote_rewards, &metrics); + assert_eq!(expected, vote_rewards.accounts_to_store.len()); assert_eq!(0, total_vote_rewards); } @@ -626,7 +664,9 @@ mod tests { solana_logger::setup(); let expected_num_delegations = 100; - let bank = create_default_reward_bank(expected_num_delegations, SLOTS_PER_EPOCH).bank; + let bank = create_default_reward_bank(expected_num_delegations, SLOTS_PER_EPOCH) + .0 + .bank; // Calculate rewards let thread_pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap(); @@ -669,7 +709,7 @@ mod tests { let expected_num_delegations = 100; let RewardBank { bank, .. } = - create_default_reward_bank(expected_num_delegations, SLOTS_PER_EPOCH); + create_default_reward_bank(expected_num_delegations, SLOTS_PER_EPOCH).0; let thread_pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap(); let rewards_metrics = RewardsMetrics::default(); @@ -723,7 +763,7 @@ mod tests { bank, voters, stakers, - } = create_default_reward_bank(expected_num_delegations, SLOTS_PER_EPOCH); + } = create_default_reward_bank(expected_num_delegations, SLOTS_PER_EPOCH).0; let vote_pubkey = voters.first().unwrap(); let stake_pubkey = *stakers.first().unwrap(); @@ -816,7 +856,7 @@ mod tests { let expected_num_delegations = 4; let num_rewards_per_block = 2; // Distribute 4 rewards over 2 blocks - let RewardBank { bank, .. } = create_reward_bank( + let (RewardBank { bank, .. }, _) = create_reward_bank( expected_num_delegations, num_rewards_per_block, SLOTS_PER_EPOCH, @@ -911,7 +951,7 @@ mod tests { let expected_num_delegations = 2; let num_rewards_per_block = 2; // Distribute 2 rewards over 1 block - let RewardBank { bank, .. } = create_reward_bank( + let (RewardBank { bank, .. }, _) = create_reward_bank( expected_num_delegations, num_rewards_per_block, SLOTS_PER_EPOCH, @@ -970,7 +1010,7 @@ mod tests { let mut stakes = vec![2_000_000_000; expected_num_delegations]; // Add stake large enough to be affected by total-rewards discrepancy stakes.push(40_000_000_000); - let RewardBank { bank, .. } = create_reward_bank_with_specific_stakes( + let (RewardBank { bank, .. }, _) = create_reward_bank_with_specific_stakes( stakes, num_rewards_per_block, SLOTS_PER_EPOCH - 1, diff --git a/runtime/src/bank/partitioned_epoch_rewards/mod.rs b/runtime/src/bank/partitioned_epoch_rewards/mod.rs index 1692099271e8f3..e3b9f87973c682 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/mod.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/mod.rs @@ -94,7 +94,7 @@ pub(super) struct VoteRewardsAccounts { /// result of calculating the stake rewards at end of epoch pub(super) struct StakeRewardCalculation { /// each individual stake account to reward - stake_rewards: PartitionedStakeRewards, + stake_rewards: Arc, /// total lamports across all `stake_rewards` total_stake_rewards_lamports: u64, } @@ -129,6 +129,7 @@ pub(super) struct EpochRewardCalculateParamInfo<'a> { /// Hold all results from calculating the rewards for partitioned distribution. /// This struct exists so we can have a function which does all the calculation with no /// side effects. +#[derive(Debug)] pub(super) struct PartitionedRewardsCalculation { pub(super) vote_account_rewards: VoteRewardsAccounts, pub(super) stake_rewards: StakeRewardCalculation, @@ -148,7 +149,7 @@ pub(super) struct CalculateRewardsAndDistributeVoteRewardsResult { /// vote accounts pub(super) point_value: PointValue, /// stake rewards that still need to be distributed - pub(super) stake_rewards: Vec, + pub(super) stake_rewards: Arc>, } pub(crate) type StakeRewards = Vec; @@ -186,12 +187,12 @@ impl Bank { pub(crate) fn set_epoch_reward_status_calculation( &mut self, distribution_starting_block_height: u64, - stake_rewards: Vec, + stake_rewards: Arc>, ) { self.epoch_reward_status = EpochRewardStatus::Active(EpochRewardPhase::Calculation(StartBlockHeightAndRewards { distribution_starting_block_height, - all_stake_rewards: Arc::new(stake_rewards), + all_stake_rewards: stake_rewards, })); } @@ -259,6 +260,7 @@ mod tests { super::*, crate::{ bank::tests::{create_genesis_config, new_bank_from_parent_with_bank_forks}, + bank_forks::BankForks, genesis_utils::{ create_genesis_config_with_vote_accounts, GenesisConfigInfo, ValidatorVoteKeypairs, }, @@ -268,6 +270,7 @@ mod tests { solana_account::{state_traits::StateMut, Account}, solana_accounts_db::accounts_db::{AccountsDbConfig, ACCOUNTS_DB_CONFIG_FOR_TESTING}, solana_epoch_schedule::EpochSchedule, + solana_hash::Hash, solana_keypair::Keypair, solana_native_token::LAMPORTS_PER_SOL, solana_reward_info::RewardType, @@ -278,6 +281,7 @@ mod tests { solana_vote::vote_transaction, solana_vote_interface::state::{VoteStateVersions, MAX_LOCKOUT_HISTORY}, solana_vote_program::vote_state::{self, TowerSync}, + std::sync::{Arc, RwLock}, }; impl PartitionedStakeReward { @@ -358,6 +362,21 @@ mod tests { EpochRewardStatus::Active(EpochRewardPhase::Distribution(_)) ) } + + fn get_epoch_rewards_from_cache( + &self, + parent_hash: &Hash, + ) -> Option> { + self.epoch_rewards_calculation_cache + .lock() + .unwrap() + .get(parent_hash) + .cloned() + } + + fn get_epoch_rewards_cache_len(&self) -> usize { + self.epoch_rewards_calculation_cache.lock().unwrap().len() + } } pub(super) const SLOTS_PER_EPOCH: u64 = 32; @@ -372,7 +391,7 @@ mod tests { pub(super) fn create_default_reward_bank( expected_num_delegations: usize, advance_num_slots: u64, - ) -> RewardBank { + ) -> (RewardBank, Arc>) { create_reward_bank( expected_num_delegations, PartitionedEpochRewardsConfig::default().stake_account_stores_per_block, @@ -384,7 +403,7 @@ mod tests { expected_num_delegations: usize, stake_account_stores_per_block: u64, advance_num_slots: u64, - ) -> RewardBank { + ) -> (RewardBank, Arc>) { create_reward_bank_with_specific_stakes( vec![2_000_000_000; expected_num_delegations], stake_account_stores_per_block, @@ -396,7 +415,7 @@ mod tests { stakes: Vec, stake_account_stores_per_block: u64, advance_num_slots: u64, - ) -> RewardBank { + ) -> (RewardBank, Arc>) { let validator_keypairs = (0..stakes.len()) .map(|_| ValidatorVoteKeypairs::new_rand()) .collect::>(); @@ -458,17 +477,20 @@ mod tests { advance_num_slots, ); - RewardBank { - bank, - voters: validator_keypairs - .iter() - .map(|k| k.vote_keypair.pubkey()) - .collect(), - stakers: validator_keypairs - .iter() - .map(|k| k.stake_keypair.pubkey()) - .collect(), - } + ( + RewardBank { + bank, + voters: validator_keypairs + .iter() + .map(|k| k.vote_keypair.pubkey()) + .collect(), + stakers: validator_keypairs + .iter() + .map(|k| k.stake_keypair.pubkey()) + .collect(), + }, + bank_forks, + ) } #[test] @@ -591,15 +613,23 @@ mod tests { solana_logger::setup(); let starting_slot = SLOTS_PER_EPOCH - 1; - let RewardBank { - bank: mut previous_bank, - .. - } = create_default_reward_bank(100, starting_slot - 1); + let ( + RewardBank { + bank: mut previous_bank, + .. + }, + bank_forks, + ) = create_default_reward_bank(100, starting_slot - 1); // simulate block progress for slot in starting_slot..=(2 * SLOTS_PER_EPOCH) + 2 { let pre_cap = previous_bank.capitalization(); - let curr_bank = Bank::new_from_parent(previous_bank, &Pubkey::default(), slot); + let curr_bank = new_bank_from_parent_with_bank_forks( + bank_forks.as_ref(), + previous_bank.clone(), + &Pubkey::default(), + slot, + ); let post_cap = curr_bank.capitalization(); if slot % SLOTS_PER_EPOCH == 0 { @@ -612,12 +642,16 @@ mod tests { assert!(curr_bank.is_calculated()); - if slot == SLOTS_PER_EPOCH { - // cap should increase because of new epoch rewards - assert!(post_cap > pre_cap); - } else { - assert_eq!(post_cap, pre_cap); - } + // after reward calculation, the cache should be filled. + assert!(curr_bank + .get_epoch_rewards_from_cache(&curr_bank.parent_hash) + .is_some()); + assert_eq!(post_cap, pre_cap); + + // Make a root the bank, which is the first bank in the epoch. + // This will clear the cache. + let _ = bank_forks.write().unwrap().set_root(slot, None, None); + assert_eq!(curr_bank.get_epoch_rewards_cache_len(), 0); } else if slot == SLOTS_PER_EPOCH + 1 { // 1. when curr_slot == SLOTS_PER_EPOCH + 1, the 2nd block of // epoch 1, reward distribution should happen in this block. @@ -628,7 +662,6 @@ mod tests { curr_bank.get_reward_interval(), RewardInterval::OutsideInterval ); - let account = curr_bank .get_account(&solana_sysvar::epoch_rewards::id()) .unwrap(); @@ -655,7 +688,7 @@ mod tests { curr_bank.get_balance(&solana_sysvar::epoch_rewards::id()); assert!(epoch_rewards_lamports > 0); } - previous_bank = Arc::new(curr_bank); + previous_bank = curr_bank; } } @@ -665,10 +698,14 @@ mod tests { solana_logger::setup(); let starting_slot = SLOTS_PER_EPOCH - 1; - let RewardBank { - bank: mut previous_bank, - .. - } = create_reward_bank(100, 50, starting_slot - 1); + let ( + RewardBank { + bank: mut previous_bank, + .. + }, + bank_forks, + ) = create_reward_bank(100, 50, starting_slot - 1); + let mut starting_hash = None; // simulate block progress for slot in starting_slot..=SLOTS_PER_EPOCH + 3 { @@ -680,8 +717,12 @@ mod tests { let pre_epoch_rewards: solana_sysvar::epoch_rewards::EpochRewards = solana_account::from_account(&pre_sysvar_account).unwrap_or_default(); let pre_distributed_rewards = pre_epoch_rewards.distributed_rewards; - - let curr_bank = Bank::new_from_parent(previous_bank, &Pubkey::default(), slot); + let curr_bank = new_bank_from_parent_with_bank_forks( + bank_forks.as_ref(), + previous_bank.clone(), + &Pubkey::default(), + slot, + ); let post_cap = curr_bank.capitalization(); if slot == SLOTS_PER_EPOCH { @@ -695,8 +736,12 @@ mod tests { // calculation block, state should be calculated. assert!(curr_bank.is_calculated()); - // cap should increase because of new epoch rewards - assert!(post_cap > pre_cap); + // after reward calculation, the cache should be filled. + assert!(curr_bank + .get_epoch_rewards_from_cache(&curr_bank.parent_hash) + .is_some()); + assert_eq!(curr_bank.get_epoch_rewards_cache_len(), 1); + starting_hash = Some(curr_bank.parent_hash); } else if slot == SLOTS_PER_EPOCH + 1 { // When curr_slot == SLOTS_PER_EPOCH + 1, the 2nd block of // epoch 1, reward distribution should happen in this block. The @@ -706,6 +751,13 @@ mod tests { RewardInterval::InsideInterval ); + // The first block of the epoch has not rooted yet, so the cache + // should still have the results. + assert!(curr_bank + .get_epoch_rewards_from_cache(&starting_hash.unwrap()) + .is_some()); + assert_eq!(curr_bank.get_epoch_rewards_cache_len(), 1); + // 1st reward distribution block, state should be partitioned. assert!(curr_bank.is_partitioned()); @@ -718,6 +770,11 @@ mod tests { post_cap, pre_cap + epoch_rewards.distributed_rewards - pre_distributed_rewards ); + + // Now make a root the first bank in the epoch. + // This should clear the cache. + let _ = bank_forks.write().unwrap().set_root(slot - 1, None, None); + assert_eq!(curr_bank.get_epoch_rewards_cache_len(), 0); } else if slot == SLOTS_PER_EPOCH + 2 { // When curr_slot == SLOTS_PER_EPOCH + 2, the 3nd block of // epoch 1, reward distribution should happen in this block. @@ -751,7 +808,7 @@ mod tests { // slot is not in rewards, cap should not change assert_eq!(post_cap, pre_cap); } - previous_bank = Arc::new(curr_bank); + previous_bank = curr_bank; } } @@ -879,7 +936,7 @@ mod tests { let starting_slot = SLOTS_PER_EPOCH - 1; let num_rewards = 100; let stake_account_stores_per_block = 50; - let RewardBank { bank, .. } = + let (RewardBank { bank, .. }, _) = create_reward_bank(num_rewards, stake_account_stores_per_block, starting_slot); // Slot before the epoch boundary contains empty rewards (since fees are diff --git a/runtime/src/bank/serde_snapshot.rs b/runtime/src/bank/serde_snapshot.rs index f8007719bc8bc0..3a1764ba0e3014 100644 --- a/runtime/src/bank/serde_snapshot.rs +++ b/runtime/src/bank/serde_snapshot.rs @@ -15,8 +15,9 @@ mod tests { SerdeAccountsHash, SerdeIncrementalAccountsHash, SnapshotStreams, }, snapshot_bank_utils, + snapshot_config::SnapshotConfig, snapshot_utils::{ - create_tmp_accounts_dir_for_tests, get_storages_to_serialize, ArchiveFormat, + create_tmp_accounts_dir_for_tests, get_storages_to_serialize, StorageAndNextAccountsFileId, }, stakes::{SerdeStakesToStakeFormat, Stakes, StakesEnum}, @@ -408,7 +409,7 @@ mod tests { None, full_snapshot_archives_dir.path(), incremental_snapshot_archives_dir.path(), - ArchiveFormat::Tar, + SnapshotConfig::default().archive_format, ) .unwrap(); diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 40907774f5aa60..d603f295e6188e 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -13,15 +13,20 @@ use { create_genesis_config_with_leader, create_genesis_config_with_vote_accounts, genesis_sysvar_and_builtin_program_lamports, GenesisConfigInfo, ValidatorVoteKeypairs, }, - snapshot_bank_utils, snapshot_utils, + snapshot_bank_utils, + snapshot_config::SnapshotConfig, + snapshot_utils, stake_history::StakeHistory, stakes::InvalidCacheEntryReason, status_cache::MAX_CACHE_ENTRIES, }, agave_feature_set::{self as feature_set, FeatureSet}, + agave_reserved_account_keys::ReservedAccount, agave_transaction_view::static_account_keys_frame::MAX_STATIC_ACCOUNTS_PER_PACKET, + ahash::AHashMap, assert_matches::assert_matches, crossbeam_channel::{bounded, unbounded}, + ed25519_dalek::ed25519::signature::Signer as EdSigner, itertools::Itertools, rand::Rng, rayon::{ThreadPool, ThreadPoolBuilder}, @@ -3050,34 +3055,39 @@ fn test_debits_before_credits() { let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); let keypair = Keypair::new(); let tx0 = system_transaction::transfer( - &mint_keypair, - &keypair.pubkey(), - sol_to_lamports(2.), - genesis_config.hash(), - ); - let tx1 = system_transaction::transfer( &keypair, &mint_keypair.pubkey(), sol_to_lamports(1.), genesis_config.hash(), ); + let tx1 = system_transaction::transfer( + &mint_keypair, + &keypair.pubkey(), + sol_to_lamports(2.), + genesis_config.hash(), + ); let txs = vec![tx0, tx1]; let results = bank.process_transactions(txs.iter()); - assert!(results[1].is_err()); + assert!(results[0].is_err()); // Assert bad transactions aren't counted. assert_eq!(bank.transaction_count(), 1); assert_eq!(bank.non_vote_transaction_count_since_restart(), 1); } -#[test] -fn test_readonly_accounts() { +#[test_case(false; "old")] +#[test_case(true; "simd83")] +fn test_readonly_accounts(relax_intrabatch_account_locks: bool) { let GenesisConfigInfo { genesis_config, mint_keypair, .. } = create_genesis_config_with_leader(500, &solana_pubkey::new_rand(), 0); - let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&feature_set::relax_intrabatch_account_locks::id()); + } + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); let vote_pubkey0 = solana_pubkey::new_rand(); let vote_pubkey1 = solana_pubkey::new_rand(); @@ -3141,9 +3151,16 @@ fn test_readonly_accounts() { ); let txs = vec![tx0, tx1]; let results = bank.process_transactions(txs.iter()); - // However, an account may not be locked as read-only and writable at the same time. + // Whether an account can be locked as read-only and writable at the same time depends on features. assert_eq!(results[0], Ok(())); - assert_eq!(results[1], Err(TransactionError::AccountInUse)); + assert_eq!( + results[1], + if relax_intrabatch_account_locks { + Ok(()) + } else { + Err(TransactionError::AccountInUse) + } + ); } #[test] @@ -7175,11 +7192,15 @@ fn test_bank_load_program() { } #[allow(deprecated)] -#[test] -fn test_bpf_loader_upgradeable_deploy_with_max_len() { +#[test_case(false; "informal_loaded_size")] +#[test_case(true; "simd186_loaded_size")] +fn test_bpf_loader_upgradeable_deploy_with_max_len(formalize_loaded_transaction_data_size: bool) { let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(1_000_000_000); let mut bank = Bank::new_for_tests(&genesis_config); bank.feature_set = Arc::new(FeatureSet::all_enabled()); + if !formalize_loaded_transaction_data_size { + bank.deactivate_feature(&feature_set::formalize_loaded_transaction_data_size::id()); + } let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests(); let mut bank_client = BankClient::new_shared(bank.clone()); @@ -8028,25 +8049,32 @@ fn test_compute_active_feature_set() { fn test_reserved_account_keys() { let (bank0, _bank_forks) = create_simple_test_arc_bank(100_000); let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1); - bank.feature_set = Arc::new(FeatureSet::default()); + let test_feature_id = Pubkey::new_unique(); + bank.feature_set = Arc::new(FeatureSet::new( + AHashMap::new(), + AHashSet::from([test_feature_id]), + )); + bank.reserved_account_keys = Arc::new(ReservedAccountKeys::new(&[ + ReservedAccount::new_active(system_program::id()), + ReservedAccount::new_pending(Pubkey::new_unique(), test_feature_id), + ])); assert_eq!( bank.get_reserved_account_keys().len(), - 20, - "before activating the new feature, bank should already have active reserved keys" + 1, + "before activating the test feature, bank should already have an active reserved key" ); - // Activate `add_new_reserved_account_keys` feature bank.store_account( - &feature_set::add_new_reserved_account_keys::id(), + &test_feature_id, &feature::create_account(&Feature::default(), 42), ); bank.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, true); assert_eq!( bank.get_reserved_account_keys().len(), - 30, - "after activating the new feature, bank should have new active reserved keys" + 2, + "after activating the test feature, bank should have another active reserved key" ); } @@ -8374,10 +8402,15 @@ fn test_timestamp_fast() { } } -#[test] -fn test_program_is_native_loader() { +#[test_case(false; "informal_loaded_size")] +#[test_case(true; "simd186_loaded_size")] +fn test_program_is_native_loader(formalize_loaded_transaction_data_size: bool) { let (genesis_config, mint_keypair) = create_genesis_config(50000); - let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if formalize_loaded_transaction_data_size { + bank.activate_feature(&feature_set::formalize_loaded_transaction_data_size::id()); + } + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); let tx = Transaction::new_signed_with_payer( &[Instruction::new_with_bincode( @@ -8389,20 +8422,29 @@ fn test_program_is_native_loader() { &[&mint_keypair], bank.last_blockhash(), ); - assert_eq!( - bank.process_transaction(&tx), - Err(TransactionError::InstructionError( - 0, - InstructionError::UnsupportedProgramId - )) - ); + + let err = bank.process_transaction(&tx).unwrap_err(); + if formalize_loaded_transaction_data_size { + assert_eq!(err, TransactionError::ProgramAccountNotFound); + } else { + assert_eq!( + err, + TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId) + ); + } } -#[test] -fn test_invoke_non_program_account_owned_by_a_builtin() { +#[test_case(false; "informal_loaded_size")] +#[test_case(true; "simd186_loaded_size")] +fn test_invoke_non_program_account_owned_by_a_builtin( + formalize_loaded_transaction_data_size: bool, +) { let (genesis_config, mint_keypair) = create_genesis_config(10000000); let mut bank = Bank::new_for_tests(&genesis_config); bank.activate_feature(&feature_set::remove_accounts_executable_flag_checks::id()); + if formalize_loaded_transaction_data_size { + bank.activate_feature(&feature_set::formalize_loaded_transaction_data_size::id()); + } let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); let bogus_program = Pubkey::new_unique(); @@ -8429,13 +8471,12 @@ fn test_invoke_non_program_account_owned_by_a_builtin() { &[&mint_keypair, &created_account_keypair], bank.last_blockhash(), ); - assert_eq!( - bank.process_transaction(&tx), - Err(TransactionError::InstructionError( - 0, - InstructionError::UnsupportedProgramId - )) - ); + let expected_error = if formalize_loaded_transaction_data_size { + TransactionError::InvalidProgramForExecution + } else { + TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId) + }; + assert_eq!(bank.process_transaction(&tx), Err(expected_error),); } #[test] @@ -9426,8 +9467,9 @@ fn test_vote_epoch_panic() { ); } -#[test] -fn test_tx_log_order() { +#[test_case(false; "old")] +#[test_case(true; "simd83")] +fn test_tx_log_order(relax_intrabatch_account_locks: bool) { let GenesisConfigInfo { genesis_config, mint_keypair, @@ -9437,7 +9479,11 @@ fn test_tx_log_order() { &Pubkey::new_unique(), bootstrap_validator_stake_lamports(), ); - let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&feature_set::relax_intrabatch_account_locks::id()); + } + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); *bank.transaction_log_collector_config.write().unwrap() = TransactionLogCollectorConfig { mentioned_addresses: HashSet::new(), filter: TransactionLogCollectorFilter::All, @@ -9494,7 +9540,11 @@ fn test_tx_log_order() { .as_ref() .unwrap()[2] .contains(&"failed".to_string())); - assert!(commit_results[2].is_err()); + if relax_intrabatch_account_locks { + assert!(commit_results[2].is_ok()); + } else { + assert!(commit_results[2].is_err()); + } let stored_logs = &bank.transaction_log_collector.read().unwrap().logs; let success_log_info = stored_logs @@ -10340,7 +10390,13 @@ fn test_call_precomiled_program() { ed25519_dalek::Keypair { secret, public } }; let message_arr = b"hello"; - let instruction = solana_ed25519_program::new_ed25519_instruction(&privkey, message_arr); + let signature = privkey.sign(message_arr).to_bytes(); + let pubkey = privkey.public.to_bytes(); + let instruction = solana_ed25519_program::new_ed25519_instruction_with_signature( + message_arr, + &signature, + &pubkey, + ); let tx = Transaction::new_signed_with_payer( &[instruction], Some(&mint_keypair.pubkey()), @@ -10561,8 +10617,9 @@ fn test_calculate_fee_secp256k1() { assert_eq!(calculate_test_fee(&message, 1, &fee_structure,), 11); } -#[test] -fn test_an_empty_instruction_without_program() { +#[test_case(false; "informal_loaded_size")] +#[test_case(true; "simd186_loaded_size")] +fn test_an_empty_instruction_without_program(formalize_loaded_transaction_data_size: bool) { let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee_no_rent(1); let destination = solana_pubkey::new_rand(); let mut ix = system_instruction::transfer(&mint_keypair.pubkey(), &destination, 0); @@ -10570,11 +10627,21 @@ fn test_an_empty_instruction_without_program() { let message = Message::new(&[ix], Some(&mint_keypair.pubkey())); let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash()); - let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); - assert_eq!( - bank.process_transaction(&tx).unwrap_err(), - TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId), - ); + let mut bank = Bank::new_for_tests(&genesis_config); + if !formalize_loaded_transaction_data_size { + bank.deactivate_feature(&feature_set::formalize_loaded_transaction_data_size::id()); + } + let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); + + let err = bank.process_transaction(&tx).unwrap_err(); + if formalize_loaded_transaction_data_size { + assert_eq!(err, TransactionError::ProgramAccountNotFound); + } else { + assert_eq!( + err, + TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId) + ); + } } #[test] @@ -12120,8 +12187,11 @@ fn test_is_in_slot_hashes_history() { assert!(!new_bank.is_in_slot_hashes_history(&0)); } -#[test] -fn test_feature_activation_loaded_programs_cache_preparation_phase() { +#[test_case(false; "informal_loaded_size")] +#[test_case(true; "simd186_loaded_size")] +fn test_feature_activation_loaded_programs_cache_preparation_phase( + formalize_loaded_transaction_data_size: bool, +) { solana_logger::setup(); // Bank Setup @@ -12130,6 +12200,9 @@ fn test_feature_activation_loaded_programs_cache_preparation_phase() { let mut feature_set = FeatureSet::all_enabled(); feature_set.deactivate(&feature_set::disable_sbpf_v0_execution::id()); feature_set.deactivate(&feature_set::reenable_sbpf_v0_execution::id()); + if !formalize_loaded_transaction_data_size { + feature_set.deactivate(&feature_set::formalize_loaded_transaction_data_size::id()); + } bank.feature_set = Arc::new(feature_set); let (root_bank, bank_forks) = bank.wrap_with_bank_forks_for_tests(); @@ -12956,7 +13029,7 @@ fn test_rebuild_skipped_rewrites() { None, full_snapshot_archives_dir.path(), incremental_snapshot_archives_dir.path(), - snapshot_utils::ArchiveFormat::Tar, + SnapshotConfig::default().archive_format, ) .unwrap(); @@ -13068,6 +13141,8 @@ fn test_failed_simulation_compute_units() { const TEST_UNITS: u64 = 10_000; const MOCK_BUILTIN_UNITS: u64 = 1; let expected_consumed_units = TEST_UNITS + MOCK_BUILTIN_UNITS; + let expected_loaded_program_account_data_size = + bank.get_account(&program_id).unwrap().data().len() as u32; declare_process_instruction!(MockBuiltin, MOCK_BUILTIN_UNITS, |invoke_context| { invoke_context.consume_checked(TEST_UNITS).unwrap(); Err(InstructionError::InvalidInstructionData) @@ -13083,6 +13158,10 @@ fn test_failed_simulation_compute_units() { let sanitized = RuntimeTransaction::from_transaction_for_tests(transaction); let simulation = bank.simulate_transaction(&sanitized, false); assert_eq!(expected_consumed_units, simulation.units_consumed); + assert_eq!( + expected_loaded_program_account_data_size, + simulation.loaded_accounts_data_size + ); } /// Test that simulations report the load error of fees-only transactions @@ -13112,6 +13191,7 @@ fn test_failed_simulation_load_error() { logs: vec![], post_simulation_accounts: vec![], units_consumed: 0, + loaded_accounts_data_size: 0, return_data: None, inner_instructions: None, } @@ -13279,8 +13359,9 @@ fn test_deploy_last_epoch_slot() { assert_eq!(result_with_feature_enabled, Ok(())); } -#[test] -fn test_loader_v3_to_v4_migration() { +#[test_case(false; "informal_loaded_size")] +#[test_case(true; "simd186_loaded_size")] +fn test_loader_v3_to_v4_migration(formalize_loaded_transaction_data_size: bool) { solana_logger::setup(); // Bank Setup @@ -13291,6 +13372,9 @@ fn test_loader_v3_to_v4_migration() { ); let mut bank = Bank::new_for_tests(&genesis_config); bank.activate_feature(&feature_set::remove_accounts_executable_flag_checks::id()); + if formalize_loaded_transaction_data_size { + bank.activate_feature(&feature_set::formalize_loaded_transaction_data_size::id()); + } let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests(); let fee_calculator = genesis_config.fee_rate_governor.create_fee_calculator(); let mut next_slot = 1; diff --git a/runtime/src/bank_forks.rs b/runtime/src/bank_forks.rs index 050fe60f0beddd..02de3e328efe2a 100644 --- a/runtime/src/bank_forks.rs +++ b/runtime/src/bank_forks.rs @@ -362,6 +362,12 @@ impl BankForks { .unwrap() .node_id_to_vote_accounts() ); + // Now we have rooted a bank in a new epoch, there are no needs to + // keep the epoch rewards cache for current epoch any longer. + info!( + "Clearing epoch rewards cache for epoch {old_epoch} after setting root to slot {root}" + ); + root_bank.clear_epoch_rewards_cache(); } let root_tx_count = root_bank .parents() diff --git a/runtime/src/inflation_rewards/mod.rs b/runtime/src/inflation_rewards/mod.rs index 93d9f5f83a1350..c381c93df25ef2 100644 --- a/runtime/src/inflation_rewards/mod.rs +++ b/runtime/src/inflation_rewards/mod.rs @@ -256,7 +256,7 @@ fn commission_split(commission: u8, on: u64) -> (u64, u64, bool) { mod tests { use { self::points::null_tracer, super::*, solana_native_token::sol_to_lamports, - solana_program::stake::state::Delegation, solana_pubkey::Pubkey, + solana_pubkey::Pubkey, solana_stake_interface::state::Delegation, solana_vote_program::vote_state::VoteState, test_case::test_case, }; diff --git a/runtime/src/non_circulating_supply.rs b/runtime/src/non_circulating_supply.rs index 900be03102cdc9..b931dc51fa0ffb 100644 --- a/runtime/src/non_circulating_supply.rs +++ b/runtime/src/non_circulating_supply.rs @@ -79,138 +79,138 @@ pub fn calculate_non_circulating_supply(bank: &Bank) -> ScanResult Vec { [ - "9huDUZfxoJ7wGMTffUE7vh1xePqef7gyrLJu9NApncqA", - "GK2zqSsXLA2rwVZk347RYhh6jJpRsCA69FjLW93ZGi3B", - "CWeRmXme7LmbaUWTZWFLt6FMnpzLCHaQLuR2TdgFn4Lq", - "HCV5dGFJXRrJ3jhDYA4DCeb9TEDTwGGYXtT3wHksu2Zr", - "14FUT96s9swbmH7ZjpDvfEDywnAYy9zaNhv4xvezySGu", - "HbZ5FfmKWNHC7uwk6TF1hVi6TCs7dtYfdjEcuPGgzFAg", - "C7C8odR8oashR5Feyrq2tJKaXL18id1dSj2zbkDGL2C2", - "Eyr9P5XsjK2NUKNCnfu39eqpGoiLFgVAv1LSQgMZCwiQ", - "DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ", - "CakcnaRDHka2gXyfbEd2d3xsvkJkqsLw2akB3zsN1D2S", - "7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2", - "GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ", - "Mc5XB47H3DKJHym5RLa9mPzWv5snERsF3KNv5AauXK8", - "7cvkjYAkUYs4W8XcXsca7cBrEGFeSUjeZmKoNBvEwyri", - "AG3m2bAibcY8raMt4oXEGqRHwX4FWKPPJVjZxn1LySDX", - "5XdtyEDREHJXXW1CTtCsVjJRjBapAwK78ZquzvnNVRrV", - "6yKHERk8rsbmJxvMpPuwPs1ct3hRiP7xaJF2tvnGU6nK", - "CHmdL15akDcJgBkY6BP3hzs98Dqr6wbdDC5p8odvtSbq", - "FR84wZQy3Y3j2gWz6pgETUiUoJtreMEuWfbg6573UCj9", - "5q54XjQ7vDx4y6KphPeE97LUNiYGtP55spjvXAWPGBuf", - "3o6xgkJ9sTmDeQWyfj3sxwon18fXJB9PV5LDc8sfgR4a", - "GumSE5HsMV5HCwBTv2D2D81yy9x17aDkvobkqAfTRgmo", - "AzVV9ZZDxTgW4wWfJmsG6ytaHpQGSe1yz76Nyy84VbQF", - "8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK", - "CQDYc4ET2mbFhVpgj41gXahL6Exn5ZoPcGAzSHuYxwmE", - "5PLJZLJiRR9vf7d1JCCg7UuWjtyN9nkab9uok6TqSyuP", - "7xJ9CLtEAcEShw9kW2gSoZkRWL566Dg12cvgzANJwbTr", - "BuCEvc9ze8UoAQwwsQLy8d447C8sA4zeVtVpc6m5wQeS", - "8ndGYFjav6NDXvzYcxs449Aub3AxYv4vYpk89zRDwgj7", - "8W58E8JVJjH1jCy5CeHJQgvwFXTyAVyesuXRZGbcSUGG", - "GNiz4Mq886bTNDT3pijGsu2gbw6it7sqrwncro45USeB", - "GhsotwFMH6XUrRLJCxcx62h7748N2Uq8mf87hUGkmPhg", - "Fgyh8EeYGZtbW8sS33YmNQnzx54WXPrJ5KWNPkCfWPot", - "8UVjvYyoqP6sqcctTso3xpCdCfgTMiv3VRh7vraC2eJk", - "BhvLngiqqKeZ8rpxch2uGjeCiC88zzewoWPRuoxpp1aS", - "63DtkW7zuARcd185EmHAkfF44bDcC2SiTSEj2spLP3iA", - "GvpCiTgq9dmEeojCDBivoLoZqc4AkbUDACpqPMwYLWKh", - "7Y8smnoUrYKGGuDq2uaFKVxJYhojgg7DVixHyAtGTYEV", - "DUS1KxwUhUyDKB4A81E8vdnTe3hSahd92Abtn9CXsEcj", - "F9MWFw8cnYVwsRq8Am1PGfFL3cQUZV37mbGoxZftzLjN", - "8vqrX3H2BYLaXVintse3gorPEM4TgTwTFZNN1Fm9TdYs", - "CUageMFi49kzoDqtdU8NvQ4Bq3sbtJygjKDAXJ45nmAi", - "5smrYwb1Hr2T8XMnvsqccTgXxuqQs14iuE8RbHFYf2Cf", - "xQadXQiUTCCFhfHjvQx1hyJK6KVWr1w2fD6DT3cdwj7", - "8DE8fqPfv1fp9DHyGyDFFaMjpopMgDeXspzoi9jpBJjC", - "3itU5ME8L6FDqtMiRoUiT1F7PwbkTtHBbW51YWD5jtjm", - "AsrYX4FeLXnZcrjcZmrASY2Eq1jvEeQfwxtNTxS5zojA", - "8rT45mqpuDBR1vcnDc9kwP9DrZAXDR4ZeuKWw3u1gTGa", - "nGME7HgBT6tAJN1f6YuCCngpqT5cvSTndZUVLjQ4jwA", - "CzAHrrrHKx9Lxf6wdCMrsZkLvk74c7J2vGv8VYPUmY6v", - "AzHQ8Bia1grVVbcGyci7wzueSWkgvu7YZVZ4B9rkL5P6", - "FiWYY85b58zEEcPtxe3PuqzWPjqBJXqdwgZeqSBmT9Cn", - "GpxpMVhrBBBEYbEJxdR62w3daWz444V7m6dxYDZKH77D", - "3bTGcGB9F98XxnrBNftmmm48JGfPgi5sYxDEKiCjQYk3", - "8pNBEppa1VcFAsx4Hzq9CpdXUXZjUXbvQwLX2K7QsCwb", - "HKJgYGTTYYR2ZkfJKHbn58w676fKueQXmvbtpyvrSM3N", - "3jnknRabs7G2V9dKhxd2KP85pNWXKXiedYnYxtySnQMs", - "4sxwau4mdqZ8zEJsfryXq4QFYnMJSCp3HWuZQod8WU5k", - "Fg12tB1tz8w6zJSQ4ZAGotWoCztdMJF9hqK8R11pakog", - "GEWSkfWgHkpiLbeKaAnwvqnECGdRNf49at5nFccVey7c", - "CND6ZjRTzaCFVdX7pSSWgjTfHZuhxqFDoUBqWBJguNoA", - "2WWb1gRzuXDd5viZLQF7pNRR6Y7UiyeaPpaL35X6j3ve", - "BUnRE27mYXN9p8H1Ay24GXhJC88q2CuwLoNU2v2CrW4W", - "CsUqV42gVQLJwQsKyjWHqGkfHarxn9hcY4YeSjgaaeTd", - "5khMKAcvmsFaAhoKkdg3u5abvKsmjUQNmhTNP624WB1F", - "GpYnVDgB7dzvwSgsjQFeHznjG6Kt1DLBFYrKxjGU1LuD", - "DQQGPtj7pphPHCLzzBuEyDDQByUcKGrsJdsH7SP3hAug", - "FwfaykN7ACnsEUDHANzGHqTGQZMcGnUSsahAHUqbdPrz", - "JCwT5Ygmq3VeBEbDjL8s8E82Ra2rP9bq45QfZE7Xyaq7", - "H3Ni7vG1CsmJZdTvxF7RkAf9UM5qk4RsohJsmPvtZNnu", - "CVgyXrbEd1ctEuvq11QdpnCQVnPit8NLdhyqXQHLprM2", - "EAJJD6nDqtXcZ4DnQb19F9XEz8y8bRDHxbWbahatZNbL", - "6o5v1HC7WhBnLfRHp8mQTtCP2khdXXjhuyGyYEoy2Suy", - "3ZrsTmNM6AkMcqFfv3ryfhQ2jMfqP64RQbqVyAaxqhrQ", - "6zw7em7uQdmMpuS9fGz8Nq9TLHa5YQhEKKwPjo5PwDK4", - "CuatS6njAcfkFHnvai7zXCs7syA9bykXWsDCJEWfhjHG", - "Hz9nydgN1k15wnwffKX7CSmZp4VFTnTwLXAEdomFGNXy", - "Ep5Y58PaSyALPrdFxDVAdfKtVdP55vApvsWjb3jSmXsG", - "EziVYi3Sv5kJWxmU77PnbrT8jmkVuqwdiFLLzZpLVEn7", - "H1rt8KvXkNhQExTRfkY8r9wjZbZ8yCih6J4wQ5Fz9HGP", - "6nN69B4uZuESZYxr9nrLDjmKRtjDZQXrehwkfQTKw62U", - "Hm9JW7of5i9dnrboS8pCUCSeoQUPh7JsP1rkbJnW7An4", - "5D5NxsNVTgXHyVziwV7mDFwVDS6voaBsyyGxUbhQrhNW", - "EMAY24PrS6rWfvpqffFCsTsFJypeeYYmtUc26wdh3Wup", - "Br3aeVGapRb2xTq17RU2pYZCoJpWA7bq6TKBCcYtMSmt", - "BUjkdqUuH5Lz9XzcMcR4DdEMnFG6r8QzUMBm16Rfau96", - "Es13uD2p64UVPFpEWfDtd6SERdoNR2XVgqBQBZcZSLqW", - "AVYpwVou2BhdLivAwLxKPALZQsY7aZNkNmGbP2fZw7RU", - "DrKzW5koKSZp4mg4BdHLwr72MMXscd2kTiWgckCvvPXz", - "9hknftBZAQL4f48tWfk3bUEV5YSLcYYtDRqNmpNnhCWG", - "GLUmCeJpXB8veNcchPwibkRYwCwvQbKodex5mEjrgToi", - "9S2M3UYPpnPZTBtbcUvehYmiWFK3kBhwfzV2iWuwvaVy", - "HUAkU5psJXZuw54Lrg1ksbXzHv2fzczQ9sNbmisVMeJU", - "GK8R4uUmrawcREZ5xJy5dAzVV5V7aFvYg77id37pVTK", - "4vuWt1oHRqLMhf8Nv1zyEXZsYaeK7dipwrfKLoYU9Riq", - "EMhn1U3TMimW3bvWYbPUvN2eZnCfsuBN4LGWhzzYhiWR", - "BsKsunvENxAraBrL77UfAn1Gi7unVEmQAdCbhsjUN6tU", - "CTvhdUVf8KNyMbyEdnvRrBCHJjBKtQwkbj6zwoqcEssG", - "3fV2GaDKa3pZxyDcpMh5Vrh2FVAMUiWUKbYmnBFv8As3", - "4pV47TiPzZ7SSBPHmgUvSLmH9mMSe8tjyPhQZGbi1zPC", - "P8aKfWQPeRnsZtpBrwWTYzyAoRk74KMz56xc6NEpC4J", - "HuqDWJodFhAEWh6aWdsDVUqsjRket5DYXMYyDYtD8hdN", - "Ab1UcdsFXZVnkSt1Z3vcYU65GQk5MvCbs54SviaiaqHb", - "Dc2oHxFXQaC2QfLStuU7txtD3U5HZ82MrCSGDooWjbsv", - "3iPvAS4xdhYr6SkhVDHCLr7tJjMAFK4wvvHWJxFQVg15", - "GmyW1nqYcrw7P7JqrcyP9ivU9hYNbrgZ1r5SYJJH41Fs", - "E8jcgWvrvV7rwYHJThwfiBeQ8VAH4FgNEEMG9aAuCMAq", - "CY7X5o3Wi2eQhTocLmUS6JSWyx1NinBfW7AXRrkRCpi8", - "HQJtLqvEGGxgNYfRXUurfxV8E1swvCnsbC3456ik27HY", - "9xbcBZoGYFnfJZe81EDuDYKUm8xGkjzW8z4EgnVhNvsv", + solana_pubkey::pubkey!("9huDUZfxoJ7wGMTffUE7vh1xePqef7gyrLJu9NApncqA"), + solana_pubkey::pubkey!("GK2zqSsXLA2rwVZk347RYhh6jJpRsCA69FjLW93ZGi3B"), + solana_pubkey::pubkey!("CWeRmXme7LmbaUWTZWFLt6FMnpzLCHaQLuR2TdgFn4Lq"), + solana_pubkey::pubkey!("HCV5dGFJXRrJ3jhDYA4DCeb9TEDTwGGYXtT3wHksu2Zr"), + solana_pubkey::pubkey!("14FUT96s9swbmH7ZjpDvfEDywnAYy9zaNhv4xvezySGu"), + solana_pubkey::pubkey!("HbZ5FfmKWNHC7uwk6TF1hVi6TCs7dtYfdjEcuPGgzFAg"), + solana_pubkey::pubkey!("C7C8odR8oashR5Feyrq2tJKaXL18id1dSj2zbkDGL2C2"), + solana_pubkey::pubkey!("Eyr9P5XsjK2NUKNCnfu39eqpGoiLFgVAv1LSQgMZCwiQ"), + solana_pubkey::pubkey!("DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ"), + solana_pubkey::pubkey!("CakcnaRDHka2gXyfbEd2d3xsvkJkqsLw2akB3zsN1D2S"), + solana_pubkey::pubkey!("7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2"), + solana_pubkey::pubkey!("GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ"), + solana_pubkey::pubkey!("Mc5XB47H3DKJHym5RLa9mPzWv5snERsF3KNv5AauXK8"), + solana_pubkey::pubkey!("7cvkjYAkUYs4W8XcXsca7cBrEGFeSUjeZmKoNBvEwyri"), + solana_pubkey::pubkey!("AG3m2bAibcY8raMt4oXEGqRHwX4FWKPPJVjZxn1LySDX"), + solana_pubkey::pubkey!("5XdtyEDREHJXXW1CTtCsVjJRjBapAwK78ZquzvnNVRrV"), + solana_pubkey::pubkey!("6yKHERk8rsbmJxvMpPuwPs1ct3hRiP7xaJF2tvnGU6nK"), + solana_pubkey::pubkey!("CHmdL15akDcJgBkY6BP3hzs98Dqr6wbdDC5p8odvtSbq"), + solana_pubkey::pubkey!("FR84wZQy3Y3j2gWz6pgETUiUoJtreMEuWfbg6573UCj9"), + solana_pubkey::pubkey!("5q54XjQ7vDx4y6KphPeE97LUNiYGtP55spjvXAWPGBuf"), + solana_pubkey::pubkey!("3o6xgkJ9sTmDeQWyfj3sxwon18fXJB9PV5LDc8sfgR4a"), + solana_pubkey::pubkey!("GumSE5HsMV5HCwBTv2D2D81yy9x17aDkvobkqAfTRgmo"), + solana_pubkey::pubkey!("AzVV9ZZDxTgW4wWfJmsG6ytaHpQGSe1yz76Nyy84VbQF"), + solana_pubkey::pubkey!("8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK"), + solana_pubkey::pubkey!("CQDYc4ET2mbFhVpgj41gXahL6Exn5ZoPcGAzSHuYxwmE"), + solana_pubkey::pubkey!("5PLJZLJiRR9vf7d1JCCg7UuWjtyN9nkab9uok6TqSyuP"), + solana_pubkey::pubkey!("7xJ9CLtEAcEShw9kW2gSoZkRWL566Dg12cvgzANJwbTr"), + solana_pubkey::pubkey!("BuCEvc9ze8UoAQwwsQLy8d447C8sA4zeVtVpc6m5wQeS"), + solana_pubkey::pubkey!("8ndGYFjav6NDXvzYcxs449Aub3AxYv4vYpk89zRDwgj7"), + solana_pubkey::pubkey!("8W58E8JVJjH1jCy5CeHJQgvwFXTyAVyesuXRZGbcSUGG"), + solana_pubkey::pubkey!("GNiz4Mq886bTNDT3pijGsu2gbw6it7sqrwncro45USeB"), + solana_pubkey::pubkey!("GhsotwFMH6XUrRLJCxcx62h7748N2Uq8mf87hUGkmPhg"), + solana_pubkey::pubkey!("Fgyh8EeYGZtbW8sS33YmNQnzx54WXPrJ5KWNPkCfWPot"), + solana_pubkey::pubkey!("8UVjvYyoqP6sqcctTso3xpCdCfgTMiv3VRh7vraC2eJk"), + solana_pubkey::pubkey!("BhvLngiqqKeZ8rpxch2uGjeCiC88zzewoWPRuoxpp1aS"), + solana_pubkey::pubkey!("63DtkW7zuARcd185EmHAkfF44bDcC2SiTSEj2spLP3iA"), + solana_pubkey::pubkey!("GvpCiTgq9dmEeojCDBivoLoZqc4AkbUDACpqPMwYLWKh"), + solana_pubkey::pubkey!("7Y8smnoUrYKGGuDq2uaFKVxJYhojgg7DVixHyAtGTYEV"), + solana_pubkey::pubkey!("DUS1KxwUhUyDKB4A81E8vdnTe3hSahd92Abtn9CXsEcj"), + solana_pubkey::pubkey!("F9MWFw8cnYVwsRq8Am1PGfFL3cQUZV37mbGoxZftzLjN"), + solana_pubkey::pubkey!("8vqrX3H2BYLaXVintse3gorPEM4TgTwTFZNN1Fm9TdYs"), + solana_pubkey::pubkey!("CUageMFi49kzoDqtdU8NvQ4Bq3sbtJygjKDAXJ45nmAi"), + solana_pubkey::pubkey!("5smrYwb1Hr2T8XMnvsqccTgXxuqQs14iuE8RbHFYf2Cf"), + solana_pubkey::pubkey!("xQadXQiUTCCFhfHjvQx1hyJK6KVWr1w2fD6DT3cdwj7"), + solana_pubkey::pubkey!("8DE8fqPfv1fp9DHyGyDFFaMjpopMgDeXspzoi9jpBJjC"), + solana_pubkey::pubkey!("3itU5ME8L6FDqtMiRoUiT1F7PwbkTtHBbW51YWD5jtjm"), + solana_pubkey::pubkey!("AsrYX4FeLXnZcrjcZmrASY2Eq1jvEeQfwxtNTxS5zojA"), + solana_pubkey::pubkey!("8rT45mqpuDBR1vcnDc9kwP9DrZAXDR4ZeuKWw3u1gTGa"), + solana_pubkey::pubkey!("nGME7HgBT6tAJN1f6YuCCngpqT5cvSTndZUVLjQ4jwA"), + solana_pubkey::pubkey!("CzAHrrrHKx9Lxf6wdCMrsZkLvk74c7J2vGv8VYPUmY6v"), + solana_pubkey::pubkey!("AzHQ8Bia1grVVbcGyci7wzueSWkgvu7YZVZ4B9rkL5P6"), + solana_pubkey::pubkey!("FiWYY85b58zEEcPtxe3PuqzWPjqBJXqdwgZeqSBmT9Cn"), + solana_pubkey::pubkey!("GpxpMVhrBBBEYbEJxdR62w3daWz444V7m6dxYDZKH77D"), + solana_pubkey::pubkey!("3bTGcGB9F98XxnrBNftmmm48JGfPgi5sYxDEKiCjQYk3"), + solana_pubkey::pubkey!("8pNBEppa1VcFAsx4Hzq9CpdXUXZjUXbvQwLX2K7QsCwb"), + solana_pubkey::pubkey!("HKJgYGTTYYR2ZkfJKHbn58w676fKueQXmvbtpyvrSM3N"), + solana_pubkey::pubkey!("3jnknRabs7G2V9dKhxd2KP85pNWXKXiedYnYxtySnQMs"), + solana_pubkey::pubkey!("4sxwau4mdqZ8zEJsfryXq4QFYnMJSCp3HWuZQod8WU5k"), + solana_pubkey::pubkey!("Fg12tB1tz8w6zJSQ4ZAGotWoCztdMJF9hqK8R11pakog"), + solana_pubkey::pubkey!("GEWSkfWgHkpiLbeKaAnwvqnECGdRNf49at5nFccVey7c"), + solana_pubkey::pubkey!("CND6ZjRTzaCFVdX7pSSWgjTfHZuhxqFDoUBqWBJguNoA"), + solana_pubkey::pubkey!("2WWb1gRzuXDd5viZLQF7pNRR6Y7UiyeaPpaL35X6j3ve"), + solana_pubkey::pubkey!("BUnRE27mYXN9p8H1Ay24GXhJC88q2CuwLoNU2v2CrW4W"), + solana_pubkey::pubkey!("CsUqV42gVQLJwQsKyjWHqGkfHarxn9hcY4YeSjgaaeTd"), + solana_pubkey::pubkey!("5khMKAcvmsFaAhoKkdg3u5abvKsmjUQNmhTNP624WB1F"), + solana_pubkey::pubkey!("GpYnVDgB7dzvwSgsjQFeHznjG6Kt1DLBFYrKxjGU1LuD"), + solana_pubkey::pubkey!("DQQGPtj7pphPHCLzzBuEyDDQByUcKGrsJdsH7SP3hAug"), + solana_pubkey::pubkey!("FwfaykN7ACnsEUDHANzGHqTGQZMcGnUSsahAHUqbdPrz"), + solana_pubkey::pubkey!("JCwT5Ygmq3VeBEbDjL8s8E82Ra2rP9bq45QfZE7Xyaq7"), + solana_pubkey::pubkey!("H3Ni7vG1CsmJZdTvxF7RkAf9UM5qk4RsohJsmPvtZNnu"), + solana_pubkey::pubkey!("CVgyXrbEd1ctEuvq11QdpnCQVnPit8NLdhyqXQHLprM2"), + solana_pubkey::pubkey!("EAJJD6nDqtXcZ4DnQb19F9XEz8y8bRDHxbWbahatZNbL"), + solana_pubkey::pubkey!("6o5v1HC7WhBnLfRHp8mQTtCP2khdXXjhuyGyYEoy2Suy"), + solana_pubkey::pubkey!("3ZrsTmNM6AkMcqFfv3ryfhQ2jMfqP64RQbqVyAaxqhrQ"), + solana_pubkey::pubkey!("6zw7em7uQdmMpuS9fGz8Nq9TLHa5YQhEKKwPjo5PwDK4"), + solana_pubkey::pubkey!("CuatS6njAcfkFHnvai7zXCs7syA9bykXWsDCJEWfhjHG"), + solana_pubkey::pubkey!("Hz9nydgN1k15wnwffKX7CSmZp4VFTnTwLXAEdomFGNXy"), + solana_pubkey::pubkey!("Ep5Y58PaSyALPrdFxDVAdfKtVdP55vApvsWjb3jSmXsG"), + solana_pubkey::pubkey!("EziVYi3Sv5kJWxmU77PnbrT8jmkVuqwdiFLLzZpLVEn7"), + solana_pubkey::pubkey!("H1rt8KvXkNhQExTRfkY8r9wjZbZ8yCih6J4wQ5Fz9HGP"), + solana_pubkey::pubkey!("6nN69B4uZuESZYxr9nrLDjmKRtjDZQXrehwkfQTKw62U"), + solana_pubkey::pubkey!("Hm9JW7of5i9dnrboS8pCUCSeoQUPh7JsP1rkbJnW7An4"), + solana_pubkey::pubkey!("5D5NxsNVTgXHyVziwV7mDFwVDS6voaBsyyGxUbhQrhNW"), + solana_pubkey::pubkey!("EMAY24PrS6rWfvpqffFCsTsFJypeeYYmtUc26wdh3Wup"), + solana_pubkey::pubkey!("Br3aeVGapRb2xTq17RU2pYZCoJpWA7bq6TKBCcYtMSmt"), + solana_pubkey::pubkey!("BUjkdqUuH5Lz9XzcMcR4DdEMnFG6r8QzUMBm16Rfau96"), + solana_pubkey::pubkey!("Es13uD2p64UVPFpEWfDtd6SERdoNR2XVgqBQBZcZSLqW"), + solana_pubkey::pubkey!("AVYpwVou2BhdLivAwLxKPALZQsY7aZNkNmGbP2fZw7RU"), + solana_pubkey::pubkey!("DrKzW5koKSZp4mg4BdHLwr72MMXscd2kTiWgckCvvPXz"), + solana_pubkey::pubkey!("9hknftBZAQL4f48tWfk3bUEV5YSLcYYtDRqNmpNnhCWG"), + solana_pubkey::pubkey!("GLUmCeJpXB8veNcchPwibkRYwCwvQbKodex5mEjrgToi"), + solana_pubkey::pubkey!("9S2M3UYPpnPZTBtbcUvehYmiWFK3kBhwfzV2iWuwvaVy"), + solana_pubkey::pubkey!("HUAkU5psJXZuw54Lrg1ksbXzHv2fzczQ9sNbmisVMeJU"), + solana_pubkey::pubkey!("GK8R4uUmrawcREZ5xJy5dAzVV5V7aFvYg77id37pVTK"), + solana_pubkey::pubkey!("4vuWt1oHRqLMhf8Nv1zyEXZsYaeK7dipwrfKLoYU9Riq"), + solana_pubkey::pubkey!("EMhn1U3TMimW3bvWYbPUvN2eZnCfsuBN4LGWhzzYhiWR"), + solana_pubkey::pubkey!("BsKsunvENxAraBrL77UfAn1Gi7unVEmQAdCbhsjUN6tU"), + solana_pubkey::pubkey!("CTvhdUVf8KNyMbyEdnvRrBCHJjBKtQwkbj6zwoqcEssG"), + solana_pubkey::pubkey!("3fV2GaDKa3pZxyDcpMh5Vrh2FVAMUiWUKbYmnBFv8As3"), + solana_pubkey::pubkey!("4pV47TiPzZ7SSBPHmgUvSLmH9mMSe8tjyPhQZGbi1zPC"), + solana_pubkey::pubkey!("P8aKfWQPeRnsZtpBrwWTYzyAoRk74KMz56xc6NEpC4J"), + solana_pubkey::pubkey!("HuqDWJodFhAEWh6aWdsDVUqsjRket5DYXMYyDYtD8hdN"), + solana_pubkey::pubkey!("Ab1UcdsFXZVnkSt1Z3vcYU65GQk5MvCbs54SviaiaqHb"), + solana_pubkey::pubkey!("Dc2oHxFXQaC2QfLStuU7txtD3U5HZ82MrCSGDooWjbsv"), + solana_pubkey::pubkey!("3iPvAS4xdhYr6SkhVDHCLr7tJjMAFK4wvvHWJxFQVg15"), + solana_pubkey::pubkey!("GmyW1nqYcrw7P7JqrcyP9ivU9hYNbrgZ1r5SYJJH41Fs"), + solana_pubkey::pubkey!("E8jcgWvrvV7rwYHJThwfiBeQ8VAH4FgNEEMG9aAuCMAq"), + solana_pubkey::pubkey!("CY7X5o3Wi2eQhTocLmUS6JSWyx1NinBfW7AXRrkRCpi8"), + solana_pubkey::pubkey!("HQJtLqvEGGxgNYfRXUurfxV8E1swvCnsbC3456ik27HY"), + solana_pubkey::pubkey!("9xbcBZoGYFnfJZe81EDuDYKUm8xGkjzW8z4EgnVhNvsv"), ] -); + .into() +} // Withdraw authority for autostaked accounts on mainnet-beta -solana_sdk_macro::pubkeys!( - withdraw_authority, +pub fn withdraw_authority() -> Vec { [ - "8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK", - "3FFaheyqtyAXZSYxDzsr5CVKvJuvZD1WE1VEsBtDbRqB", - "FdGYQdiRky8NZzN9wZtczTBcWLYYRXrJ3LMDhqDPn5rM", - "4e6KwQpyzGQPfgVr5Jn3g5jLjbXB4pKPa2jRLohEb1QA", - "FjiEiVKyMGzSLpqoB27QypukUfyWHrwzPcGNtopzZVdh", - "DwbVjia1mYeSGoJipzhaf4L5hfer2DJ1Ys681VzQm5YY", - "GeMGyvsTEsANVvcT5cme65Xq5MVU8fVVzMQ13KAZFNS2", - "Bj3aQ2oFnZYfNR1njzRjmWizzuhvfcYLckh76cqsbuBM", - "4ZJhPQAgUseCsWhKvJLTmmRRUV74fdoTpQLNfKoekbPY", - "HXdYQ5gixrY2H6Y9gqsD8kPM2JQKSaRiohDQtLbZkRWE", + solana_pubkey::pubkey!("8CUUMKYNGxdgYio5CLHRHyzMEhhVRMcqefgE6dLqnVRK"), + solana_pubkey::pubkey!("3FFaheyqtyAXZSYxDzsr5CVKvJuvZD1WE1VEsBtDbRqB"), + solana_pubkey::pubkey!("FdGYQdiRky8NZzN9wZtczTBcWLYYRXrJ3LMDhqDPn5rM"), + solana_pubkey::pubkey!("4e6KwQpyzGQPfgVr5Jn3g5jLjbXB4pKPa2jRLohEb1QA"), + solana_pubkey::pubkey!("FjiEiVKyMGzSLpqoB27QypukUfyWHrwzPcGNtopzZVdh"), + solana_pubkey::pubkey!("DwbVjia1mYeSGoJipzhaf4L5hfer2DJ1Ys681VzQm5YY"), + solana_pubkey::pubkey!("GeMGyvsTEsANVvcT5cme65Xq5MVU8fVVzMQ13KAZFNS2"), + solana_pubkey::pubkey!("Bj3aQ2oFnZYfNR1njzRjmWizzuhvfcYLckh76cqsbuBM"), + solana_pubkey::pubkey!("4ZJhPQAgUseCsWhKvJLTmmRRUV74fdoTpQLNfKoekbPY"), + solana_pubkey::pubkey!("HXdYQ5gixrY2H6Y9gqsD8kPM2JQKSaRiohDQtLbZkRWE"), ] -); + .into() +} #[cfg(test)] mod tests { diff --git a/runtime/src/serde_snapshot.rs b/runtime/src/serde_snapshot.rs index bb3980d84fc601..05d78fc4f5438c 100644 --- a/runtime/src/serde_snapshot.rs +++ b/runtime/src/serde_snapshot.rs @@ -798,7 +798,7 @@ impl Serialize for SerializableAccountsDb<'_> { x.first().unwrap().slot(), utils::serialize_iter_as_seq( x.iter() - .map(|x| SerializableAccountStorageEntry::from(x.as_ref())), + .map(|x| SerializableAccountStorageEntry::new(x.as_ref(), self.slot)), ), ) })); diff --git a/runtime/src/serde_snapshot/storage.rs b/runtime/src/serde_snapshot/storage.rs index c079a6f34d39cc..6cbc1510d4637c 100644 --- a/runtime/src/serde_snapshot/storage.rs +++ b/runtime/src/serde_snapshot/storage.rs @@ -1,6 +1,7 @@ use { serde::{Deserialize, Serialize}, solana_accounts_db::accounts_db::AccountStorageEntry, + solana_clock::Slot, }; /// The serialized AccountsFileId type is fixed as usize @@ -13,6 +14,25 @@ pub struct SerializableAccountStorageEntry { accounts_current_len: usize, } +impl SerializableAccountStorageEntry { + /// Creates a new SerializableAccountStorageEntry from the current + /// AccountStorageEntry and a given snapshot slot. When obsolete accounts + /// are enabled, the saved size is decreased by the amount of obsolete bytes + /// in the storage. The number of obsolete bytes is determined by the snapshot + /// slot, as an entry's obsolescence is dependent on the slot that marked it + /// as such. + pub fn new( + accounts: &AccountStorageEntry, + snapshot_slot: Slot, + ) -> SerializableAccountStorageEntry { + SerializableAccountStorageEntry { + id: accounts.id() as SerializedAccountsFileId, + accounts_current_len: accounts.accounts.len() + - accounts.get_obsolete_bytes(Some(snapshot_slot)), + } + } +} + pub(super) trait SerializableStorage { fn id(&self) -> SerializedAccountsFileId; fn current_len(&self) -> usize; @@ -27,14 +47,5 @@ impl SerializableStorage for SerializableAccountStorageEntry { } } -impl From<&AccountStorageEntry> for SerializableAccountStorageEntry { - fn from(rhs: &AccountStorageEntry) -> Self { - Self { - id: rhs.id() as SerializedAccountsFileId, - accounts_current_len: rhs.accounts.len(), - } - } -} - #[cfg(feature = "frozen-abi")] impl solana_frozen_abi::abi_example::TransparentAsHelper for SerializableAccountStorageEntry {} diff --git a/runtime/src/serde_snapshot/tests.rs b/runtime/src/serde_snapshot/tests.rs index e01b9155a8f305..a778c9757c1640 100644 --- a/runtime/src/serde_snapshot/tests.rs +++ b/runtime/src/serde_snapshot/tests.rs @@ -15,6 +15,7 @@ mod serde_snapshot_tests { solana_account::{AccountSharedData, ReadableAccount}, solana_accounts_db::{ account_storage::AccountStorageMap, + account_storage_reader::AccountStorageReader, accounts::Accounts, accounts_db::{ get_temp_accounts_paths, test_utils::create_test_accounts, AccountStorageEntry, @@ -33,7 +34,7 @@ mod serde_snapshot_tests { solana_rent_collector::RentCollector, std::{ fs::File, - io::{BufReader, Cursor, Read, Write}, + io::{self, BufReader, Cursor, Read, Write}, ops::RangeFull, path::{Path, PathBuf}, sync::{ @@ -139,17 +140,15 @@ mod serde_snapshot_tests { let mut next_append_vec_id = 0; for storage_entry in storage_entries.into_iter() { // Copy file to new directory - let storage_path = storage_entry.path(); let file_name = AccountsFile::file_name(storage_entry.slot(), storage_entry.id()); let output_path = output_dir.as_ref().join(file_name); - std::fs::copy(storage_path, &output_path)?; + let mut reader = AccountStorageReader::new(&storage_entry, None).unwrap(); + let mut writer = File::create(&output_path)?; + io::copy(&mut reader, &mut writer)?; // Read new file into append-vec and build new entry - let (accounts_file, num_accounts) = AccountsFile::new_from_file( - output_path, - storage_entry.accounts.len(), - storage_access, - )?; + let (accounts_file, num_accounts) = + AccountsFile::new_from_file(output_path, reader.len(), storage_access)?; let new_storage_entry = AccountStorageEntry::new_existing( storage_entry.slot(), storage_entry.id(), diff --git a/runtime/src/snapshot_bank_utils.rs b/runtime/src/snapshot_bank_utils.rs index 3fd9f9391ddf4b..17cab92dfe8bbb 100644 --- a/runtime/src/snapshot_bank_utils.rs +++ b/runtime/src/snapshot_bank_utils.rs @@ -1,11 +1,15 @@ +#[cfg(feature = "dev-context-only-utils")] +use { + crate::{bank::BankFieldsToDeserialize, serde_snapshot::fields_from_streams}, + solana_accounts_db::accounts_file::StorageAccess, + tempfile::TempDir, +}; use { crate::{ - bank::{Bank, BankFieldsToDeserialize, BankSlotDelta}, + bank::{Bank, BankSlotDelta}, epoch_stakes::EpochStakes, runtime_config::RuntimeConfig, - serde_snapshot::{ - bank_from_streams, fields_from_streams, BankIncrementalSnapshotPersistence, - }, + serde_snapshot::{bank_from_streams, BankIncrementalSnapshotPersistence}, snapshot_archive_info::{ FullSnapshotArchiveInfo, IncrementalSnapshotArchiveInfo, SnapshotArchiveInfoGetter, }, @@ -31,7 +35,6 @@ use { AccountStorageEntry, AccountsDbConfig, AtomicAccountsFileId, CalcAccountsHashDataSource, DuplicatesLtHash, }, - accounts_file::StorageAccess, accounts_hash::MerkleOrLatticeAccountsHash, accounts_update_notifier_interface::AccountsUpdateNotifier, utils::delete_contents_of_path, @@ -48,7 +51,6 @@ use { path::{Path, PathBuf}, sync::{atomic::AtomicBool, Arc}, }, - tempfile::TempDir, }; pub const DEFAULT_FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS: Slot = 50_000; @@ -79,8 +81,9 @@ pub struct BankFromDirTimings { pub rebuild_bank_us: u64, } -/// Utility for parsing out bank specific information from a snapshot archive. This utility can be used -/// to parse out bank specific information like the leader schedule, epoch schedule, etc. +/// Parses out bank specific information from a snapshot archive including the leader schedule. +/// epoch schedule, etc. +#[cfg(feature = "dev-context-only-utils")] pub fn bank_fields_from_snapshot_archives( full_snapshot_archives_dir: impl AsRef, incremental_snapshot_archives_dir: impl AsRef, @@ -120,6 +123,32 @@ pub fn bank_fields_from_snapshot_archives( ) } +#[cfg(feature = "dev-context-only-utils")] +fn bank_fields_from_snapshots( + full_snapshot_unpacked_snapshots_dir_and_version: &UnpackedSnapshotsDirAndVersion, + incremental_snapshot_unpacked_snapshots_dir_and_version: Option< + &UnpackedSnapshotsDirAndVersion, + >, +) -> snapshot_utils::Result { + let (snapshot_version, snapshot_root_paths) = snapshot_version_and_root_paths( + full_snapshot_unpacked_snapshots_dir_and_version, + incremental_snapshot_unpacked_snapshots_dir_and_version, + )?; + + info!( + "Loading bank from full snapshot {} and incremental snapshot {:?}", + snapshot_root_paths.full_snapshot_root_file_path.display(), + snapshot_root_paths.incremental_snapshot_root_file_path, + ); + + deserialize_snapshot_data_files(&snapshot_root_paths, |snapshot_streams| { + Ok(match snapshot_version { + SnapshotVersion::V1_2_0 => fields_from_streams(snapshot_streams) + .map(|(bank_fields, _accountsdb_fields)| bank_fields.collapse_into()), + }?) + }) +} + /// Rebuild bank from snapshot archives. Handles either just a full snapshot, or both a full /// snapshot and an incremental snapshot. #[allow(clippy::too_many_arguments)] @@ -381,7 +410,7 @@ pub fn bank_from_snapshot_dir( storage, next_append_vec_id, }; - let ((bank, _info), measure_rebuild_bank) = measure_time!( + let ((bank, info), measure_rebuild_bank) = measure_time!( rebuild_bank_from_snapshot( bank_snapshot, account_paths, @@ -400,9 +429,27 @@ pub fn bank_from_snapshot_dir( ); info!("{}", measure_rebuild_bank); - // Skip bank.verify_snapshot_bank. Subsequent snapshot requests/accounts hash verification requests - // will calculate and check the accounts hash, so we will still have safety/correctness there. - bank.set_initial_accounts_hash_verification_completed(); + if bank + .feature_set + .is_active(&feature_set::accounts_lt_hash::id()) + { + // Skip bank.verify_snapshot_bank. Subsequent snapshot requests/accounts hash verification requests + // will calculate and check the accounts hash, so we will still have safety/correctness there. + bank.set_initial_accounts_hash_verification_completed(); + } else { + // Until the accounts lattice hash feature is enabled, always do accounts verification + if !bank.verify_snapshot_bank( + false, // do not test hash calculation + true, // do not shrink + false, // do not clean + Slot::MIN, // doesn't matter, only used for calling clean (which we are skipping) + None, // not used for lt hash + info.duplicates_lt_hash, + ) && limit_load_slot_count_from_snapshot.is_none() + { + panic!("Snapshot bank for slot {} failed to verify", bank.slot()); + } + } let timings = BankFromDirTimings { rebuild_storages_us: measure_rebuild_storages.as_us(), @@ -498,12 +545,13 @@ fn verify_bank_against_expected_slot_hash( } } -fn bank_fields_from_snapshots( +/// Returns the validated version and root paths for the given snapshots. +fn snapshot_version_and_root_paths( full_snapshot_unpacked_snapshots_dir_and_version: &UnpackedSnapshotsDirAndVersion, incremental_snapshot_unpacked_snapshots_dir_and_version: Option< &UnpackedSnapshotsDirAndVersion, >, -) -> snapshot_utils::Result { +) -> snapshot_utils::Result<(SnapshotVersion, SnapshotRootPaths)> { let (full_snapshot_version, full_snapshot_root_paths) = verify_unpacked_snapshots_dir_and_version( full_snapshot_unpacked_snapshots_dir_and_version, @@ -512,35 +560,22 @@ fn bank_fields_from_snapshots( if let Some(snapshot_unpacked_snapshots_dir_and_version) = incremental_snapshot_unpacked_snapshots_dir_and_version { - let (snapshot_version, bank_snapshot_info) = verify_unpacked_snapshots_dir_and_version( + Some(verify_unpacked_snapshots_dir_and_version( snapshot_unpacked_snapshots_dir_and_version, - )?; - (Some(snapshot_version), Some(bank_snapshot_info)) + )?) } else { - (None, None) - }; - info!( - "Loading bank from full snapshot {} and incremental snapshot {:?}", - full_snapshot_root_paths.snapshot_path().display(), - incremental_snapshot_root_paths - .as_ref() - .map(|paths| paths.snapshot_path()), - ); + None + } + .unzip(); + let snapshot_version = incremental_snapshot_version.unwrap_or(full_snapshot_version); let snapshot_root_paths = SnapshotRootPaths { full_snapshot_root_file_path: full_snapshot_root_paths.snapshot_path(), incremental_snapshot_root_file_path: incremental_snapshot_root_paths .map(|root_paths| root_paths.snapshot_path()), }; - deserialize_snapshot_data_files(&snapshot_root_paths, |snapshot_streams| { - Ok( - match incremental_snapshot_version.unwrap_or(full_snapshot_version) { - SnapshotVersion::V1_2_0 => fields_from_streams(snapshot_streams) - .map(|(bank_fields, _accountsdb_fields)| bank_fields.collapse_into()), - }?, - ) - }) + Ok((snapshot_version, snapshot_root_paths)) } fn deserialize_status_cache( @@ -584,54 +619,34 @@ fn rebuild_bank_from_unarchived_snapshots( accounts_update_notifier: Option, exit: Arc, ) -> snapshot_utils::Result<(Bank, RebuiltBankInfo)> { - let (full_snapshot_version, full_snapshot_root_paths) = - verify_unpacked_snapshots_dir_and_version( - full_snapshot_unpacked_snapshots_dir_and_version, - )?; - let (incremental_snapshot_version, incremental_snapshot_root_paths) = - if let Some(snapshot_unpacked_snapshots_dir_and_version) = - incremental_snapshot_unpacked_snapshots_dir_and_version - { - Some(verify_unpacked_snapshots_dir_and_version( - snapshot_unpacked_snapshots_dir_and_version, - )?) - } else { - None - } - .unzip(); + let (snapshot_version, snapshot_root_paths) = snapshot_version_and_root_paths( + full_snapshot_unpacked_snapshots_dir_and_version, + incremental_snapshot_unpacked_snapshots_dir_and_version, + )?; + info!( "Rebuilding bank from full snapshot {} and incremental snapshot {:?}", - full_snapshot_root_paths.snapshot_path().display(), - incremental_snapshot_root_paths - .as_ref() - .map(|paths| paths.snapshot_path()), + snapshot_root_paths.full_snapshot_root_file_path.display(), + snapshot_root_paths.incremental_snapshot_root_file_path, ); - let snapshot_root_paths = SnapshotRootPaths { - full_snapshot_root_file_path: full_snapshot_root_paths.snapshot_path(), - incremental_snapshot_root_file_path: incremental_snapshot_root_paths - .map(|root_paths| root_paths.snapshot_path()), - }; - let (bank, info) = deserialize_snapshot_data_files(&snapshot_root_paths, |snapshot_streams| { - Ok( - match incremental_snapshot_version.unwrap_or(full_snapshot_version) { - SnapshotVersion::V1_2_0 => bank_from_streams( - snapshot_streams, - account_paths, - storage_and_next_append_vec_id, - genesis_config, - runtime_config, - debug_keys, - additional_builtins, - limit_load_slot_count_from_snapshot, - verify_index, - accounts_db_config, - accounts_update_notifier, - exit, - ), - }?, - ) + Ok(match snapshot_version { + SnapshotVersion::V1_2_0 => bank_from_streams( + snapshot_streams, + account_paths, + storage_and_next_append_vec_id, + genesis_config, + runtime_config, + debug_keys, + additional_builtins, + limit_load_slot_count_from_snapshot, + verify_index, + accounts_db_config, + accounts_update_notifier, + exit, + ), + }?) })?; verify_epoch_stakes(&bank)?; @@ -1106,9 +1121,8 @@ mod tests { purge_all_bank_snapshots, purge_bank_snapshot, purge_bank_snapshots_older_than_slot, purge_incomplete_bank_snapshots, purge_old_bank_snapshots, purge_old_bank_snapshots_at_startup, - snapshot_storage_rebuilder::get_slot_and_append_vec_id, ArchiveFormat, - BankSnapshotKind, BANK_SNAPSHOT_PRE_FILENAME_EXTENSION, - SNAPSHOT_FULL_SNAPSHOT_SLOT_FILENAME, + snapshot_storage_rebuilder::get_slot_and_append_vec_id, BankSnapshotKind, + BANK_SNAPSHOT_PRE_FILENAME_EXTENSION, SNAPSHOT_FULL_SNAPSHOT_SLOT_FILENAME, }, status_cache::Status, }, @@ -1156,7 +1170,7 @@ mod tests { SnapshotVersion::default(), &snapshot_archives_dir, &snapshot_archives_dir, - ArchiveFormat::Tar, + SnapshotConfig::default().archive_format, should_flush_and_hard_link_storages, ) .unwrap(); @@ -1194,15 +1208,13 @@ mod tests { let genesis_config = GenesisConfig::default(); let original_bank = Bank::new_for_tests(&genesis_config); - while !original_bank.is_complete() { - original_bank.register_unique_tick(); - } + original_bank.fill_bank_with_ticks_for_tests(); let (_tmp_dir, accounts_dir) = create_tmp_accounts_dir_for_tests(); let bank_snapshots_dir = tempfile::TempDir::new().unwrap(); let full_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); let incremental_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); - let snapshot_archive_format = ArchiveFormat::Tar; + let snapshot_archive_format = SnapshotConfig::default().archive_format; let snapshot_archive_info = bank_to_full_snapshot_archive( &bank_snapshots_dir, @@ -1237,6 +1249,107 @@ mod tests { assert_eq!(original_bank, roundtrip_bank); } + /// This tests handling of obsolete accounts during a full snapshot with obsolete accounts + /// marked in the accounts database. This test injects them directly + #[test] + fn test_roundtrip_bank_to_and_from_full_snapshot_with_obsolete_account() { + let collector = Pubkey::new_unique(); + let key1 = Keypair::new(); + let key2 = Keypair::new(); + let key3 = Keypair::new(); + + // Create a few accounts + let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1_000_000.)); + let (bank0, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); + bank0 + .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) + .unwrap(); + bank0 + .transfer(sol_to_lamports(2.), &mint_keypair, &key2.pubkey()) + .unwrap(); + bank0 + .transfer(sol_to_lamports(3.), &mint_keypair, &key3.pubkey()) + .unwrap(); + bank0.fill_bank_with_ticks_for_tests(); + + // Force flush the bank to create the account storage entry + bank0.squash(); + bank0.force_flush_accounts_cache(); + + // Find the account storage entry for slot 0 + let target_slot = 0; + let account_storage_entry = bank0 + .accounts() + .accounts_db + .storage + .get_slot_storage_entry(target_slot) + .unwrap(); + + // Find all the accounts in slot 0 + let accounts = bank0 + .accounts() + .accounts_db + .get_unique_accounts_from_storage(&account_storage_entry); + + // Find the offset of pubkey `key1` in the accounts db slot0 and save the offset. + let offset = accounts + .stored_accounts + .iter() + .find(|account| key1.pubkey() == *account.pubkey()) + .map(|account| account.index_info.offset()) + .expect("Pubkey1 is present in Slot0"); + + // Create a new slot, and invalidate the account for key1 in slot0 + let slot = 1; + let bank1 = + new_bank_from_parent_with_bank_forks(bank_forks.as_ref(), bank0, &collector, slot); + bank1 + .transfer(sol_to_lamports(1.), &key3, &key1.pubkey()) + .unwrap(); + + bank1.fill_bank_with_ticks_for_tests(); + + // Mark the entry for pubkey1 as obsolete in slot0 + account_storage_entry.mark_account_obsolete(offset, 0, slot); + + let (_tmp_dir, accounts_dir) = create_tmp_accounts_dir_for_tests(); + let bank_snapshots_dir = tempfile::TempDir::new().unwrap(); + let snapshot_archives_dir = tempfile::TempDir::new().unwrap(); + let snapshot_archive_format = SnapshotConfig::default().archive_format; + + let full_snapshot_archive_info = bank_to_full_snapshot_archive( + bank_snapshots_dir.path(), + &bank1, + None, + snapshot_archives_dir.path(), + snapshot_archives_dir.path(), + snapshot_archive_format, + ) + .unwrap(); + + let (roundtrip_bank, _) = bank_from_snapshot_archives( + &[accounts_dir], + bank_snapshots_dir.path(), + &full_snapshot_archive_info, + None, + &genesis_config, + &RuntimeConfig::default(), + None, + None, + None, + false, + false, + false, + false, + Some(ACCOUNTS_DB_CONFIG_FOR_TESTING), + None, + Arc::default(), + ) + .unwrap(); + roundtrip_bank.wait_for_initial_accounts_hash_verification_completed_for_tests(); + assert_eq!(*bank1, roundtrip_bank); + } + /// Test roundtrip of bank to a full snapshot, then back again. This test is more involved /// than the simple version above; creating multiple banks over multiple slots and doing /// multiple transfers. So this full snapshot should contain more data. @@ -1260,9 +1373,7 @@ mod tests { bank0 .transfer(sol_to_lamports(3.), &mint_keypair, &key3.pubkey()) .unwrap(); - while !bank0.is_complete() { - bank0.register_unique_tick(); - } + bank0.fill_bank_with_ticks_for_tests(); let slot = 1; let bank1 = @@ -1276,9 +1387,7 @@ mod tests { bank1 .transfer(sol_to_lamports(5.), &mint_keypair, &key5.pubkey()) .unwrap(); - while !bank1.is_complete() { - bank1.register_unique_tick(); - } + bank1.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank2 = @@ -1286,9 +1395,7 @@ mod tests { bank2 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank2.is_complete() { - bank2.register_unique_tick(); - } + bank2.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank3 = @@ -1296,9 +1403,7 @@ mod tests { bank3 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank3.is_complete() { - bank3.register_unique_tick(); - } + bank3.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank4 = @@ -1306,15 +1411,13 @@ mod tests { bank4 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank4.is_complete() { - bank4.register_unique_tick(); - } + bank4.fill_bank_with_ticks_for_tests(); let (_tmp_dir, accounts_dir) = create_tmp_accounts_dir_for_tests(); let bank_snapshots_dir = tempfile::TempDir::new().unwrap(); let full_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); let incremental_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); - let snapshot_archive_format = ArchiveFormat::Tar; + let snapshot_archive_format = SnapshotConfig::default().archive_format; let full_snapshot_archive_info = bank_to_full_snapshot_archive( bank_snapshots_dir.path(), @@ -1378,9 +1481,7 @@ mod tests { bank0 .transfer(sol_to_lamports(3.), &mint_keypair, &key3.pubkey()) .unwrap(); - while !bank0.is_complete() { - bank0.register_unique_tick(); - } + bank0.fill_bank_with_ticks_for_tests(); let slot = 1; let bank1 = @@ -1394,15 +1495,13 @@ mod tests { bank1 .transfer(sol_to_lamports(5.), &mint_keypair, &key5.pubkey()) .unwrap(); - while !bank1.is_complete() { - bank1.register_unique_tick(); - } + bank1.fill_bank_with_ticks_for_tests(); let (_tmp_dir, accounts_dir) = create_tmp_accounts_dir_for_tests(); let bank_snapshots_dir = tempfile::TempDir::new().unwrap(); let full_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); let incremental_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); - let snapshot_archive_format = ArchiveFormat::Tar; + let snapshot_archive_format = SnapshotConfig::default().archive_format; let full_snapshot_slot = slot; let full_snapshot_archive_info = bank_to_full_snapshot_archive( @@ -1421,9 +1520,7 @@ mod tests { bank2 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank2.is_complete() { - bank2.register_unique_tick(); - } + bank2.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank3 = @@ -1431,9 +1528,7 @@ mod tests { bank3 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank3.is_complete() { - bank3.register_unique_tick(); - } + bank3.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank4 = @@ -1441,9 +1536,7 @@ mod tests { bank4 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank4.is_complete() { - bank4.register_unique_tick(); - } + bank4.fill_bank_with_ticks_for_tests(); let incremental_snapshot_archive_info = bank_to_incremental_snapshot_archive( bank_snapshots_dir.path(), @@ -1498,9 +1591,7 @@ mod tests { bank0 .transfer(sol_to_lamports(3.), &mint_keypair, &key3.pubkey()) .unwrap(); - while !bank0.is_complete() { - bank0.register_unique_tick(); - } + bank0.fill_bank_with_ticks_for_tests(); let slot = 1; let bank1 = @@ -1514,15 +1605,13 @@ mod tests { bank1 .transfer(sol_to_lamports(3.), &mint_keypair, &key3.pubkey()) .unwrap(); - while !bank1.is_complete() { - bank1.register_unique_tick(); - } + bank1.fill_bank_with_ticks_for_tests(); let (_tmp_dir, accounts_dir) = create_tmp_accounts_dir_for_tests(); let bank_snapshots_dir = tempfile::TempDir::new().unwrap(); let full_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); let incremental_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); - let snapshot_archive_format = ArchiveFormat::Tar; + let snapshot_archive_format = SnapshotConfig::default().archive_format; let full_snapshot_slot = slot; bank_to_full_snapshot_archive( @@ -1541,9 +1630,7 @@ mod tests { bank2 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank2.is_complete() { - bank2.register_unique_tick(); - } + bank2.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank3 = @@ -1551,9 +1638,7 @@ mod tests { bank3 .transfer(sol_to_lamports(2.), &mint_keypair, &key2.pubkey()) .unwrap(); - while !bank3.is_complete() { - bank3.register_unique_tick(); - } + bank3.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank4 = @@ -1561,9 +1646,7 @@ mod tests { bank4 .transfer(sol_to_lamports(3.), &mint_keypair, &key3.pubkey()) .unwrap(); - while !bank4.is_complete() { - bank4.register_unique_tick(); - } + bank4.fill_bank_with_ticks_for_tests(); bank_to_incremental_snapshot_archive( &bank_snapshots_dir, @@ -1631,7 +1714,7 @@ mod tests { let bank_snapshots_dir = tempfile::TempDir::new().unwrap(); let full_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); let incremental_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); - let snapshot_archive_format = ArchiveFormat::Tar; + let snapshot_archive_format = SnapshotConfig::default().archive_format; let (mut genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1_000_000.)); // test expects 0 transaction fee @@ -1648,9 +1731,7 @@ mod tests { bank0 .transfer(lamports_to_transfer, &mint_keypair, &key2.pubkey()) .unwrap(); - while !bank0.is_complete() { - bank0.register_unique_tick(); - } + bank0.fill_bank_with_ticks_for_tests(); let slot = 1; let bank1 = @@ -1658,9 +1739,7 @@ mod tests { bank1 .transfer(lamports_to_transfer, &key2, &key1.pubkey()) .unwrap(); - while !bank1.is_complete() { - bank1.register_unique_tick(); - } + bank1.fill_bank_with_ticks_for_tests(); let full_snapshot_slot = slot; let full_snapshot_archive_info = bank_to_full_snapshot_archive( @@ -1696,9 +1775,7 @@ mod tests { 0, "Ensure Account1's balance is zero" ); - while !bank2.is_complete() { - bank2.register_unique_tick(); - } + bank2.fill_bank_with_ticks_for_tests(); // Take an incremental snapshot and then do a roundtrip on the bank and ensure it // deserializes correctly. @@ -1744,16 +1821,12 @@ mod tests { bank3 .transfer(lamports_to_transfer, &mint_keypair, &key2.pubkey()) .unwrap(); - while !bank3.is_complete() { - bank3.register_unique_tick(); - } + bank3.fill_bank_with_ticks_for_tests(); let slot = slot + 1; let bank4 = new_bank_from_parent_with_bank_forks(bank_forks.as_ref(), bank3, &collector, slot); - while !bank4.is_complete() { - bank4.register_unique_tick(); - } + bank4.fill_bank_with_ticks_for_tests(); // Ensure account1 has been cleaned/purged from everywhere bank4.squash(); @@ -1816,19 +1889,15 @@ mod tests { let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1_000_000.)); let (bank0, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); - while !bank0.is_complete() { - bank0.register_unique_tick(); - } + bank0.fill_bank_with_ticks_for_tests(); let slot = 1; let bank1 = new_bank_from_parent_with_bank_forks(bank_forks.as_ref(), bank0, &collector, slot); - while !bank1.is_complete() { - bank1.register_unique_tick(); - } + bank1.fill_bank_with_ticks_for_tests(); let all_snapshots_dir = tempfile::TempDir::new().unwrap(); - let snapshot_archive_format = ArchiveFormat::Tar; + let snapshot_archive_format = SnapshotConfig::default().archive_format; let full_snapshot_slot = slot; bank_to_full_snapshot_archive( @@ -1847,9 +1916,7 @@ mod tests { bank2 .transfer(sol_to_lamports(1.), &mint_keypair, &key1.pubkey()) .unwrap(); - while !bank2.is_complete() { - bank2.register_unique_tick(); - } + bank2.fill_bank_with_ticks_for_tests(); bank_to_incremental_snapshot_archive( &all_snapshots_dir, @@ -1885,7 +1952,7 @@ mod tests { SnapshotVersion::default(), &snapshot_archives_dir, &snapshot_archives_dir, - ArchiveFormat::Tar, + SnapshotConfig::default().archive_format, true, ) .unwrap(); @@ -2123,7 +2190,7 @@ mod tests { None, &full_snapshot_archives_dir, &incremental_snapshot_archives_dir, - ArchiveFormat::Tar, + SnapshotConfig::default().archive_format, ) .unwrap(); let full_accounts_hash = bank @@ -2153,7 +2220,7 @@ mod tests { None, &full_snapshot_archives_dir, &incremental_snapshot_archives_dir, - ArchiveFormat::Tar, + SnapshotConfig::default().archive_format, ) .unwrap(); let incremental_accounts_hash = bank @@ -2252,7 +2319,7 @@ mod tests { let bank_snapshots_dir = tempfile::TempDir::new().unwrap(); let full_snapshot_archives_dir = tempfile::TempDir::new().unwrap(); - let snapshot_archive_format = ArchiveFormat::Tar; + let snapshot_archive_format = SnapshotConfig::default().archive_format; let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1_000_000.)); diff --git a/runtime/src/snapshot_utils.rs b/runtime/src/snapshot_utils.rs index a02c1fa92e870f..6361ac4b81212d 100644 --- a/runtime/src/snapshot_utils.rs +++ b/runtime/src/snapshot_utils.rs @@ -16,15 +16,16 @@ use { RebuiltSnapshotStorage, SnapshotStorageRebuilder, }, }, - bzip2::bufread::BzDecoder, + bzip2::read::BzDecoder, crossbeam_channel::Sender, flate2::read::GzDecoder, log::*, regex::Regex, solana_accounts_db::{ account_storage::AccountStorageMap, + account_storage_reader::AccountStorageReader, accounts_db::{AccountStorageEntry, AtomicAccountsFileId}, - accounts_file::{AccountsFile, AccountsFileError, InternalsForArchive, StorageAccess}, + accounts_file::{AccountsFile, AccountsFileError, StorageAccess}, accounts_hash::{AccountsDeltaHash, AccountsHash}, epoch_accounts_hash::EpochAccountsHash, hardened_unpack::{self, ParallelSelector, UnpackError}, @@ -516,6 +517,9 @@ pub enum ArchiveSnapshotPackageError { #[error("failed to move archive from '{1}' to '{2}': {0}")] MoveArchive(#[source] IoError, PathBuf, PathBuf), + + #[error("failed to create account storage reader '{1}': {0}")] + AccountStorageReaderError(#[source] IoError, PathBuf), } /// Errors that can happen in `hard_link_storages_to_snapshot()` @@ -1085,7 +1089,7 @@ fn archive_snapshot( )); { - let mut archive_file = fs::File::create(&staging_archive_path) + let archive_file = fs::File::create(&staging_archive_path) .map_err(|err| E::CreateArchiveFile(err, staging_archive_path.clone()))?; let do_archive_files = |encoder: &mut dyn Write| -> std::result::Result<(), E> { @@ -1111,21 +1115,20 @@ fn archive_snapshot( for storage in snapshot_storages { let path_in_archive = Path::new(ACCOUNTS_DIR) .join(AccountsFile::file_name(storage.slot(), storage.id())); - match storage.accounts.internals_for_archive() { - InternalsForArchive::Mmap(data) => { - let mut header = tar::Header::new_gnu(); - header.set_path(path_in_archive).map_err(|err| { - E::ArchiveAccountStorageFile(err, storage.path().to_path_buf()) - })?; - header.set_size(storage.capacity()); - header.set_cksum(); - archive.append(&header, data) - } - InternalsForArchive::FileIo(path) => { - archive.append_path_with_name(path, path_in_archive) - } - } - .map_err(|err| E::ArchiveAccountStorageFile(err, storage.path().to_path_buf()))?; + + let reader = + AccountStorageReader::new(storage, Some(snapshot_slot)).map_err(|err| { + E::AccountStorageReaderError(err, storage.path().to_path_buf()) + })?; + let mut header = tar::Header::new_gnu(); + header.set_path(path_in_archive).map_err(|err| { + E::ArchiveAccountStorageFile(err, storage.path().to_path_buf()) + })?; + header.set_size(reader.len() as u64); + header.set_cksum(); + archive.append(&header, reader).map_err(|err| { + E::ArchiveAccountStorageFile(err, storage.path().to_path_buf()) + })?; } archive.into_inner().map_err(E::FinishArchive)?; @@ -1133,18 +1136,6 @@ fn archive_snapshot( }; match archive_format { - ArchiveFormat::TarBzip2 => { - let mut encoder = - bzip2::write::BzEncoder::new(archive_file, bzip2::Compression::best()); - do_archive_files(&mut encoder)?; - encoder.finish().map_err(E::FinishEncoder)?; - } - ArchiveFormat::TarGzip => { - let mut encoder = - flate2::write::GzEncoder::new(archive_file, flate2::Compression::default()); - do_archive_files(&mut encoder)?; - encoder.finish().map_err(E::FinishEncoder)?; - } ArchiveFormat::TarZstd { config } => { let mut encoder = zstd::stream::Encoder::new(archive_file, config.compression_level) @@ -1161,9 +1152,7 @@ fn archive_snapshot( let (_output, result) = encoder.finish(); result.map_err(E::FinishEncoder)?; } - ArchiveFormat::Tar => { - do_archive_files(&mut archive_file)?; - } + _ => panic!("archiving snapshot with '{archive_format}' is not supported"), }; } @@ -2324,15 +2313,14 @@ fn untar_snapshot_create_shared_buffer( }) .unwrap() }; + // Apply buffered reader for decoders that do not buffer internally. match archive_format { - ArchiveFormat::TarBzip2 => SharedBuffer::new(BzDecoder::new(BufReader::new(open_file()))), - ArchiveFormat::TarGzip => SharedBuffer::new(GzDecoder::new(BufReader::new(open_file()))), - ArchiveFormat::TarZstd { .. } => SharedBuffer::new( - zstd::stream::read::Decoder::new(BufReader::new(open_file())).unwrap(), - ), - ArchiveFormat::TarLz4 => { - SharedBuffer::new(lz4::Decoder::new(BufReader::new(open_file())).unwrap()) + ArchiveFormat::TarBzip2 => SharedBuffer::new(BzDecoder::new(open_file())), + ArchiveFormat::TarGzip => SharedBuffer::new(GzDecoder::new(open_file())), + ArchiveFormat::TarZstd { .. } => { + SharedBuffer::new(zstd::stream::read::Decoder::new(open_file()).unwrap()) } + ArchiveFormat::TarLz4 => SharedBuffer::new(lz4::Decoder::new(open_file()).unwrap()), ArchiveFormat::Tar => SharedBuffer::new(BufReader::new(open_file())), } } diff --git a/runtime/src/transaction_batch.rs b/runtime/src/transaction_batch.rs index 58eda791a01c24..8198381943a036 100644 --- a/runtime/src/transaction_batch.rs +++ b/runtime/src/transaction_batch.rs @@ -120,11 +120,13 @@ mod tests { solana_system_transaction as system_transaction, solana_transaction::sanitized::SanitizedTransaction, solana_transaction_error::TransactionError, + test_case::test_case, }; - #[test] - fn test_transaction_batch() { - let (bank, txs) = setup(false); + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_transaction_batch(relax_intrabatch_account_locks: bool) { + let (bank, txs) = setup(false, relax_intrabatch_account_locks); // Test getting locked accounts let batch = bank.prepare_sanitized_batch(&txs); @@ -144,9 +146,10 @@ mod tests { assert!(batch2.lock_results().iter().all(|x| x.is_ok())); } - #[test] - fn test_simulation_batch() { - let (bank, txs) = setup(false); + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_simulation_batch(relax_intrabatch_account_locks: bool) { + let (bank, txs) = setup(false, relax_intrabatch_account_locks); // Prepare batch without locks let batch = bank.prepare_unlocked_batch_from_single_tx(&txs[0]); @@ -161,20 +164,23 @@ mod tests { assert!(batch3.lock_results().iter().all(|x| x.is_ok())); } - #[test] - fn test_unlock_failures() { - let (bank, txs) = setup(true); + #[test_case(false; "old")] + #[test_case(true; "simd83")] + fn test_unlock_failures(relax_intrabatch_account_locks: bool) { + let (bank, txs) = setup(true, relax_intrabatch_account_locks); + let expected_lock_results = if relax_intrabatch_account_locks { + vec![Ok(()), Ok(()), Ok(())] + } else { + vec![Ok(()), Err(TransactionError::AccountInUse), Ok(())] + }; // Test getting locked accounts let mut batch = bank.prepare_sanitized_batch(&txs); - assert_eq!( - batch.lock_results, - vec![Ok(()), Err(TransactionError::AccountInUse), Ok(())] - ); + assert_eq!(batch.lock_results, expected_lock_results,); let qos_results = vec![ Ok(()), - Err(TransactionError::AccountInUse), + Err(TransactionError::WouldExceedMaxBlockCostLimit), Err(TransactionError::WouldExceedMaxBlockCostLimit), ]; batch.unlock_failures(qos_results.clone()); @@ -183,22 +189,25 @@ mod tests { // Dropping the batch should unlock remaining locked transactions drop(batch); - // The next batch should be able to lock all but the conflicting tx + // The next batch should be able to take all the same locks as before let batch2 = bank.prepare_sanitized_batch(&txs); - assert_eq!( - batch2.lock_results, - vec![Ok(()), Err(TransactionError::AccountInUse), Ok(())] - ); + assert_eq!(batch2.lock_results, expected_lock_results,); } - fn setup(insert_conflicting_tx: bool) -> (Bank, Vec>) { + fn setup( + insert_conflicting_tx: bool, + relax_intrabatch_account_locks: bool, + ) -> (Bank, Vec>) { let dummy_leader_pubkey = solana_pubkey::new_rand(); let GenesisConfigInfo { genesis_config, mint_keypair, .. } = create_genesis_config_with_leader(500, &dummy_leader_pubkey, 100); - let bank = Bank::new_for_tests(&genesis_config); + let mut bank = Bank::new_for_tests(&genesis_config); + if !relax_intrabatch_account_locks { + bank.deactivate_feature(&agave_feature_set::relax_intrabatch_account_locks::id()); + } let pubkey = solana_pubkey::new_rand(); let keypair2 = Keypair::new(); diff --git a/scripts/cargo-install-all.sh b/scripts/cargo-install-all.sh index 525d8249aab3cc..a23ec58b6070a7 100755 --- a/scripts/cargo-install-all.sh +++ b/scripts/cargo-install-all.sh @@ -170,7 +170,7 @@ check_dcou() { grep -q -F '"feature=\"dev-context-only-utils\""' } -# Some binaries (like the notable agave-ledger-tool) need to acitivate +# Some binaries (like the notable agave-ledger-tool) need to activate # the dev-context-only-utils feature flag to build. # Build those binaries separately to avoid the unwanted feature unification. # Note that `--workspace --exclude ` is needed to really diff --git a/send-transaction-service/Cargo.toml b/send-transaction-service/Cargo.toml index 80afe59d2ec85a..5d23109806f354 100644 --- a/send-transaction-service/Cargo.toml +++ b/send-transaction-service/Cargo.toml @@ -9,6 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +dev-context-only-utils = ["solana-net-utils"] + [dependencies] async-trait = { workspace = true } crossbeam-channel = { workspace = true } @@ -43,9 +49,3 @@ solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-signer = { workspace = true } solana-system-interface = { workspace = true } solana-system-transaction = { workspace = true } - -[features] -dev-context-only-utils = ["solana-net-utils"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/send-transaction-service/src/test_utils.rs b/send-transaction-service/src/test_utils.rs index 4a55019457c1de..aa54398b3d5f6a 100644 --- a/send-transaction-service/src/test_utils.rs +++ b/send-transaction-service/src/test_utils.rs @@ -11,6 +11,7 @@ use { solana_client::connection_cache::ConnectionCache, std::{net::SocketAddr, sync::Arc}, tokio::runtime::Handle, + tokio_util::sync::CancellationToken, }; // `maybe_runtime` argument is introduced to be able to use runtime from test @@ -62,6 +63,7 @@ impl CreateClient for TpuClientNextClient { leader_forward_count, None, bind_socket, + CancellationToken::new(), ) } } diff --git a/send-transaction-service/src/transaction_client.rs b/send-transaction-service/src/transaction_client.rs index 4295f37c725505..407c00afce3a8f 100644 --- a/send-transaction-service/src/transaction_client.rs +++ b/send-transaction-service/src/transaction_client.rs @@ -246,6 +246,7 @@ impl TpuClientNextClient { leader_forward_count: u64, identity: Option<&Keypair>, bind_socket: UdpSocket, + cancel: CancellationToken, ) -> Self where T: TpuInfoWithSendStatic + Clone, @@ -256,8 +257,6 @@ impl TpuClientNextClient { let (update_certificate_sender, update_certificate_receiver) = watch::channel(None); - let cancel = CancellationToken::new(); - let leader_info_provider = CurrentLeaderInfo::new(leader_info); let leader_updater: SendTransactionServiceLeaderUpdater = SendTransactionServiceLeaderUpdater { @@ -302,8 +301,9 @@ impl TpuClientNextClient { // experimentally found parameter values worker_channel_size: 64, max_reconnect_attempts: 4, + // We open connection to one more leader in advance, which time-wise means ~1.6s leaders_fanout: Fanout { - connect: leader_forward_count, + connect: leader_forward_count + 1, send: leader_forward_count, }, } diff --git a/stake-accounts/Cargo.toml b/stake-accounts/Cargo.toml index 996c6c02e1f8c4..6513c5f05d2e44 100644 --- a/stake-accounts/Cargo.toml +++ b/stake-accounts/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] clap = { workspace = true } solana-account = { workspace = true } @@ -35,6 +38,3 @@ solana-version = { workspace = true } [dev-dependencies] solana-client-traits = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/storage-bigtable/Cargo.toml b/storage-bigtable/Cargo.toml index ab10bf2590f384..eb1cce510b3d20 100644 --- a/storage-bigtable/Cargo.toml +++ b/storage-bigtable/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_storage_bigtable" + [dependencies] agave-reserved-account-keys = { workspace = true } backoff = { workspace = true, features = ["tokio"] } @@ -53,10 +60,3 @@ solana-keypair = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } solana-system-transaction = { workspace = true } solana-transaction-context = { workspace = true } - -[lib] -crate-type = ["lib"] -name = "solana_storage_bigtable" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/storage-proto/Cargo.toml b/storage-proto/Cargo.toml index acecf3aebf37d5..e617cddcb82c96 100644 --- a/storage-proto/Cargo.toml +++ b/storage-proto/Cargo.toml @@ -9,6 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_storage_proto" + [dependencies] bincode = { workspace = true } bs58 = { workspace = true } @@ -26,16 +33,6 @@ solana-transaction-context = { workspace = true, features = ["serde"] } solana-transaction-error = { workspace = true } solana-transaction-status = { workspace = true } -[dev-dependencies] -enum-iterator = { workspace = true } - -[lib] -crate-type = ["lib"] -name = "solana_storage_proto" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [build-dependencies] tonic-build = { workspace = true } @@ -43,3 +40,6 @@ tonic-build = { workspace = true } # envar to point to the installed binary [target."cfg(not(windows))".build-dependencies] protobuf-src = { workspace = true } + +[dev-dependencies] +enum-iterator = { workspace = true } diff --git a/streamer/Cargo.toml b/streamer/Cargo.toml index 74bcfb777d1895..761881e9816280 100644 --- a/streamer/Cargo.toml +++ b/streamer/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_streamer" + +[features] +dev-context-only-utils = [] + [dependencies] async-channel = { workspace = true } bytes = { workspace = true } @@ -55,13 +65,3 @@ assert_matches = { workspace = true } solana-logger = { workspace = true } solana-net-utils = { workspace = true, features = ["dev-context-only-utils"] } solana-streamer = { path = ".", features = ["dev-context-only-utils"] } - -[features] -dev-context-only-utils = [] - -[lib] -crate-type = ["lib"] -name = "solana_streamer" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/svm-callback/Cargo.toml b/svm-callback/Cargo.toml index b60f61c40c4d40..f2a5b68f59aae1 100644 --- a/svm-callback/Cargo.toml +++ b/svm-callback/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "solana-svm-callback" -version = "2.3.0" +version = "3.0.0" description = "Solana SVM callback" authors = { workspace = true } repository = { workspace = true } diff --git a/svm-conformance/Cargo.toml b/svm-conformance/Cargo.toml index 2958a425f64276..78a2a3d8d870ea 100644 --- a/svm-conformance/Cargo.toml +++ b/svm-conformance/Cargo.toml @@ -9,12 +9,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] prost = { workspace = true } prost-types = { workspace = true } [build-dependencies] prost-build = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/svm-feature-set/Cargo.toml b/svm-feature-set/Cargo.toml index ffd5851fbc23bc..6dbfb4b68d869b 100644 --- a/svm-feature-set/Cargo.toml +++ b/svm-feature-set/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "solana-svm-feature-set" -version = "2.3.0" +version = "3.0.0" description = "Solana SVM Feature Set" authors = { workspace = true } repository = { workspace = true } diff --git a/svm-feature-set/src/lib.rs b/svm-feature-set/src/lib.rs index d7cb6aa445a215..c421b8b9aac351 100644 --- a/svm-feature-set/src/lib.rs +++ b/svm-feature-set/src/lib.rs @@ -36,6 +36,7 @@ pub struct SVMFeatureSet { pub increase_tx_account_lock_limit: bool, pub disable_rent_fees_collection: bool, pub enable_extend_program_checked: bool, + pub formalize_loaded_transaction_data_size: bool, } impl SVMFeatureSet { @@ -77,6 +78,7 @@ impl SVMFeatureSet { increase_tx_account_lock_limit: true, disable_rent_fees_collection: true, enable_extend_program_checked: true, + formalize_loaded_transaction_data_size: true, } } } diff --git a/svm/Cargo.toml b/svm/Cargo.toml index 72ca6cb92026c8..adb4e03dc8779b 100644 --- a/svm/Cargo.toml +++ b/svm/Cargo.toml @@ -9,6 +9,28 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_svm" + +[features] +dev-context-only-utils = ["dep:qualifier_attr"] +frozen-abi = [ + "dep:solana-frozen-abi", + "dep:solana-frozen-abi-macro", + "solana-program-runtime/frozen-abi", +] +shuttle-test = [ + "solana-type-overrides/shuttle-test", + "solana-program-runtime/shuttle-test", + "solana-bpf-loader-program/shuttle-test", + "solana-loader-v4-program/shuttle-test", +] +svm-internal = [] + [dependencies] ahash = { workspace = true } itertools = { workspace = true } @@ -59,10 +81,6 @@ solana-type-overrides = { workspace = true } spl-generic-token = { workspace = true } thiserror = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_svm" - [dev-dependencies] agave-feature-set = { workspace = true } agave-reserved-account-keys = { workspace = true } @@ -90,7 +108,6 @@ solana-program-runtime = { workspace = true, features = ["dev-context-only-utils solana-pubkey = { workspace = true, features = [ "rand" ] } solana-rent = { workspace = true } solana-sbpf = { workspace = true } -solana-sdk = { workspace = true } solana-secp256k1-program = { workspace = true } solana-secp256r1-program = { workspace = true, features = ["openssl-vendored"] } solana-signature = { workspace = true, features = [ "rand" ] } @@ -106,24 +123,5 @@ solana-transaction-context = { workspace = true, features = ["dev-context-only-u spl-token = { workspace = true } test-case = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = ["dep:qualifier_attr"] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", - "solana-program-runtime/frozen-abi", - "solana-sdk/frozen-abi", -] -shuttle-test = [ - "solana-type-overrides/shuttle-test", - "solana-program-runtime/shuttle-test", - "solana-bpf-loader-program/shuttle-test", - "solana-loader-v4-program/shuttle-test", -] -svm-internal = [] - [lints] workspace = true diff --git a/svm/examples/Cargo.lock b/svm/examples/Cargo.lock index 94244fee88cb07..72f768c1bac92e 100644 --- a/svm/examples/Cargo.lock +++ b/svm/examples/Cargo.lock @@ -65,7 +65,7 @@ dependencies = [ [[package]] name = "agave-banking-stage-ingress-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "solana-perf", @@ -73,7 +73,7 @@ dependencies = [ [[package]] name = "agave-feature-set" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "solana-epoch-schedule", @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "agave-geyser-plugin-interface" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "solana-clock", @@ -97,7 +97,7 @@ dependencies = [ [[package]] name = "agave-precompiles" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -117,7 +117,7 @@ dependencies = [ [[package]] name = "agave-reserved-account-keys" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-pubkey", @@ -126,7 +126,7 @@ dependencies = [ [[package]] name = "agave-transaction-view" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-hash", "solana-message", @@ -140,7 +140,7 @@ dependencies = [ [[package]] name = "agave-xdp" -version = "2.3.0" +version = "3.0.0" dependencies = [ "aya", "caps", @@ -676,7 +676,7 @@ dependencies = [ "bitflags 2.9.1", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "proc-macro2", @@ -750,7 +750,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" dependencies = [ "borsh-derive 0.10.4", - "hashbrown 0.13.2", + "hashbrown 0.12.3", ] [[package]] @@ -2229,9 +2229,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hidapi" @@ -2471,16 +2471,21 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.2.0", "http-body 1.0.1", "hyper 1.6.0", + "ipnet", + "libc", + "percent-encoding 2.3.1", "pin-project-lite", "socket2", "tokio", @@ -2766,6 +2771,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2833,7 +2848,7 @@ dependencies = [ [[package]] name = "json-rpc-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "borsh 1.5.7", "clap", @@ -2852,7 +2867,7 @@ dependencies = [ [[package]] name = "json-rpc-server" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -2883,7 +2898,6 @@ dependencies = [ "solana-program-runtime", "solana-pubkey", "solana-rpc-client-api", - "solana-sdk", "solana-sdk-ids", "solana-signature", "solana-svm", @@ -2893,7 +2907,7 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-validator-exit", @@ -3581,11 +3595,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.1", "libc", ] @@ -4459,7 +4473,7 @@ dependencies = [ "once_cell", "percent-encoding 2.3.1", "pin-project-lite", - "rustls-pemfile 1.0.4", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -4477,9 +4491,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" dependencies = [ "async-compression", "base64 0.22.1", @@ -4502,7 +4516,6 @@ dependencies = [ "pin-project-lite", "quinn", "rustls 0.23.27", - "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_json", @@ -4512,13 +4525,13 @@ dependencies = [ "tokio-rustls 0.26.2", "tokio-util 0.7.15", "tower 0.5.2", + "tower-http", "tower-service", "url 2.5.4", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.8", - "windows-registry", + "webpki-roots 1.0.0", ] [[package]] @@ -4530,7 +4543,7 @@ dependencies = [ "anyhow", "async-trait", "http 1.2.0", - "reqwest 0.12.15", + "reqwest 0.12.19", "serde", "thiserror 1.0.69", "tower-service", @@ -4699,15 +4712,6 @@ dependencies = [ "base64 0.21.7", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.11.0" @@ -5134,9 +5138,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -5177,7 +5181,7 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "base64 0.22.1", @@ -5218,7 +5222,7 @@ dependencies = [ [[package]] name = "solana-account-decoder-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bs58", @@ -5232,9 +5236,9 @@ dependencies = [ [[package]] name = "solana-account-info" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c17d606a298a205fae325489fbed88ee6dc4463c111672172327e741c8905d" +checksum = "c8f5152a288ef1912300fc6efa6c2d1f9bb55d9398eb6c72326360b8063987da" dependencies = [ "bincode", "serde", @@ -5245,7 +5249,7 @@ dependencies = [ [[package]] name = "solana-accounts-db" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "bincode", @@ -5294,7 +5298,7 @@ dependencies = [ "solana-sysvar", "solana-time-utils", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "spl-generic-token", "static_assertions", @@ -5331,18 +5335,23 @@ dependencies = [ [[package]] name = "solana-banks-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "borsh 1.5.7", "futures 0.3.31", "solana-account", "solana-banks-interface", + "solana-clock", "solana-commitment-config", + "solana-hash", "solana-message", - "solana-program", + "solana-program-pack", + "solana-pubkey", + "solana-rent", "solana-signature", + "solana-sysvar", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "tarpc", "thiserror 2.0.12", @@ -5352,7 +5361,7 @@ dependencies = [ [[package]] name = "solana-banks-interface" -version = "2.3.0" +version = "3.0.0" dependencies = [ "serde", "serde_derive", @@ -5364,14 +5373,14 @@ dependencies = [ "solana-pubkey", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "tarpc", ] [[package]] name = "solana-banks-server" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -5433,7 +5442,7 @@ dependencies = [ [[package]] name = "solana-bloom" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bv", "fnv", @@ -5471,7 +5480,7 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "libsecp256k1", @@ -5486,7 +5495,7 @@ dependencies = [ "solana-bn254", "solana-clock", "solana-cpi", - "solana-curve25519", + "solana-curve25519 3.0.0", "solana-hash", "solana-instruction", "solana-keccak-hasher", @@ -5509,14 +5518,14 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "thiserror 2.0.12", ] [[package]] name = "solana-bucket-map" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bv", "bytemuck", @@ -5533,7 +5542,7 @@ dependencies = [ [[package]] name = "solana-builtins" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-bpf-loader-program", @@ -5552,7 +5561,7 @@ dependencies = [ [[package]] name = "solana-builtins-default-costs" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "ahash 0.8.11", @@ -5569,7 +5578,7 @@ dependencies = [ [[package]] name = "solana-clap-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "chrono", "clap", @@ -5596,7 +5605,7 @@ dependencies = [ [[package]] name = "solana-cli-config" -version = "2.3.0" +version = "3.0.0" dependencies = [ "dirs-next", "serde", @@ -5609,7 +5618,7 @@ dependencies = [ [[package]] name = "solana-cli-output" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "agave-reserved-account-keys", @@ -5634,11 +5643,11 @@ dependencies = [ "solana-message", "solana-native-token", "solana-packet", - "solana-program", "solana-pubkey", "solana-rpc-client-api", "solana-sdk-ids", "solana-signature", + "solana-stake-interface", "solana-system-interface", "solana-sysvar", "solana-transaction", @@ -5650,7 +5659,7 @@ dependencies = [ [[package]] name = "solana-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -5749,7 +5758,7 @@ dependencies = [ [[package]] name = "solana-compute-budget" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-fee-structure", "solana-program-runtime", @@ -5757,7 +5766,7 @@ dependencies = [ [[package]] name = "solana-compute-budget-instruction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "log", @@ -5781,35 +5790,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8432d2c4c22d0499aa06d62e4f7e333f81777b3d7c96050ae9e5cb71a8c3aee4" dependencies = [ "borsh 1.5.7", - "serde", - "serde_derive", "solana-instruction", "solana-sdk-ids", ] [[package]] name = "solana-compute-budget-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-program-runtime", ] +[[package]] +name = "solana-config-interface" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbdbcfedb467322ac9686ca61da0a1fdede2fd99a01fb2ed52b49452abd22e0" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-short-vec", + "solana-system-interface", +] + [[package]] name = "solana-config-program-client" -version = "0.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53aceac36f105fd4922e29b4f0c1f785b69d7b3e7e387e384b8985c8e0c3595e" +checksum = "ef9867b9ffae6e48a97ce6349e7796fcb34084298e909a8fa1fe427f41b52fd4" dependencies = [ "bincode", "borsh 0.10.4", "kaigan", "serde", + "solana-config-interface", "solana-program", ] [[package]] name = "solana-connection-cache" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -5830,7 +5855,7 @@ dependencies = [ [[package]] name = "solana-core" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "agave-feature-set", @@ -5848,6 +5873,7 @@ dependencies = [ "conditional-mod", "crossbeam-channel", "dashmap", + "derive_more 1.0.0", "etcd-client", "futures 0.3.31", "histogram", @@ -5962,7 +5988,7 @@ dependencies = [ [[package]] name = "solana-cost-model" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "ahash 0.8.11", @@ -6002,7 +6028,21 @@ dependencies = [ [[package]] name = "solana-curve25519" -version = "2.3.0" +version = "2.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def3cfe5279edb64fc39111cff6dcf77b01fbfba2c02c13ced41e6a48baf4cbe" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-define-syscall", + "subtle", + "thiserror 2.0.12", +] + +[[package]] +name = "solana-curve25519" +version = "3.0.0" dependencies = [ "bytemuck", "bytemuck_derive", @@ -6040,9 +6080,9 @@ dependencies = [ [[package]] name = "solana-ed25519-program" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0fc717048fdbe5d2ee7d673d73e6a30a094002f4a29ca7630ac01b6bddec04" +checksum = "a1feafa1691ea3ae588f99056f4bdd1293212c7ece28243d7da257c443e84753" dependencies = [ "bytemuck", "bytemuck_derive", @@ -6055,7 +6095,7 @@ dependencies = [ [[package]] name = "solana-entry" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "crossbeam-channel", @@ -6148,7 +6188,7 @@ dependencies = [ [[package]] name = "solana-faucet" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "clap", @@ -6212,7 +6252,7 @@ dependencies = [ [[package]] name = "solana-fee" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-fee-structure", @@ -6232,9 +6272,9 @@ dependencies = [ [[package]] name = "solana-fee-structure" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f45f94a88efdb512805563181dfa1c85c60a21b6e6d602bf24a2ea88f9399d6e" +checksum = "33adf673581c38e810bf618f745bf31b683a0a4a4377682e6aaac5d9a058dd4e" dependencies = [ "serde", "serde_derive", @@ -6275,7 +6315,7 @@ dependencies = [ [[package]] name = "solana-geyser-plugin-manager" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-geyser-plugin-interface", "bs58", @@ -6304,7 +6344,7 @@ dependencies = [ [[package]] name = "solana-gossip" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "arrayvec", @@ -6406,9 +6446,9 @@ dependencies = [ [[package]] name = "solana-instruction" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce496a475e5062ba5de97215ab39d9c358f9c9df4bb7f3a45a1f1a8bd9065ed" +checksum = "47298e2ce82876b64f71e9d13a46bc4b9056194e7f9937ad3084385befa50885" dependencies = [ "bincode", "borsh 1.5.7", @@ -6485,7 +6525,7 @@ dependencies = [ [[package]] name = "solana-lattice-hash" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "blake3", @@ -6495,7 +6535,7 @@ dependencies = [ [[package]] name = "solana-ledger" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", @@ -6572,7 +6612,7 @@ dependencies = [ "solana-time-utils", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-vote", @@ -6649,7 +6689,7 @@ dependencies = [ [[package]] name = "solana-loader-v4-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", "qualifier_attr", @@ -6666,13 +6706,13 @@ dependencies = [ "solana-pubkey", "solana-sbpf", "solana-sdk-ids", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", ] [[package]] name = "solana-log-collector" -version = "2.3.0" +version = "3.0.0" dependencies = [ "log", ] @@ -6692,11 +6732,11 @@ dependencies = [ [[package]] name = "solana-measure" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-merkle-tree" -version = "2.3.0" +version = "3.0.0" dependencies = [ "fast-math", "solana-hash", @@ -6705,9 +6745,9 @@ dependencies = [ [[package]] name = "solana-message" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6bf99c4570173710107a1f233f3bee226feea5fc817308707d4f7cb100a72d" +checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b" dependencies = [ "bincode", "blake3", @@ -6728,12 +6768,12 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "gethostname", "log", - "reqwest 0.12.15", + "reqwest 0.12.19", "solana-cluster-type", "solana-sha256-hasher", "solana-time-utils", @@ -6757,7 +6797,7 @@ checksum = "307fb2f78060995979e9b4f68f833623565ed4e55d3725f100454ce78a99a1a3" [[package]] name = "solana-net-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "bincode", @@ -6815,7 +6855,6 @@ dependencies = [ "num_enum", "solana-hash", "solana-packet", - "solana-pubkey", "solana-sanitize", "solana-sha256-hasher", "solana-signature", @@ -6838,7 +6877,7 @@ dependencies = [ [[package]] name = "solana-perf" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "bincode", @@ -6868,7 +6907,7 @@ dependencies = [ [[package]] name = "solana-poh" -version = "2.3.0" +version = "3.0.0" dependencies = [ "core_affinity", "crossbeam-channel", @@ -6900,7 +6939,7 @@ dependencies = [ [[package]] name = "solana-poseidon" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ark-bn254", "light-poseidon", @@ -6910,31 +6949,14 @@ dependencies = [ [[package]] name = "solana-precompile-error" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff64daa2933c22982b323d88d0cdf693201ef56ac381ae16737fd5f579e07d6" +checksum = "4d87b2c1f5de77dfe2b175ee8dd318d196aaca4d0f66f02842f80c852811f9f8" dependencies = [ "num-traits", "solana-decode-error", ] -[[package]] -name = "solana-precompiles" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a460ab805ec063802105b463ecb5eb02c3ffe469e67a967eea8a6e778e0bc06" -dependencies = [ - "lazy_static", - "solana-ed25519-program", - "solana-feature-set", - "solana-message", - "solana-precompile-error", - "solana-pubkey", - "solana-sdk-ids", - "solana-secp256k1-program", - "solana-secp256r1-program", -] - [[package]] name = "solana-presigner" version = "2.2.1" @@ -7040,9 +7062,9 @@ dependencies = [ [[package]] name = "solana-program-error" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8ae2c1a8d0d4ae865882d5770a7ebca92bab9c685e43f0461682c6c05a35bfa" +checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" dependencies = [ "borsh 1.5.7", "num-traits", @@ -7081,7 +7103,7 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -7115,14 +7137,14 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "thiserror 2.0.12", ] [[package]] name = "solana-program-test" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "assert_matches", @@ -7142,7 +7164,6 @@ dependencies = [ "solana-clock", "solana-commitment-config", "solana-compute-budget", - "solana-cpi", "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", @@ -7164,9 +7185,7 @@ dependencies = [ "solana-rent", "solana-runtime", "solana-sbpf", - "solana-sdk", "solana-sdk-ids", - "solana-sdk-macro", "solana-signer", "solana-stable-layout", "solana-stake-interface", @@ -7176,7 +7195,7 @@ dependencies = [ "solana-sysvar-id", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-vote-program", "spl-generic-token", @@ -7213,7 +7232,7 @@ dependencies = [ [[package]] name = "solana-pubsub-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "futures-util", @@ -7238,7 +7257,7 @@ dependencies = [ [[package]] name = "solana-quic-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-lock", "async-trait", @@ -7275,14 +7294,14 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "2.3.0" +version = "3.0.0" dependencies = [ "num_cpus", ] [[package]] name = "solana-remote-wallet" -version = "2.3.0" +version = "3.0.0" dependencies = [ "console", "dialoguer", @@ -7342,18 +7361,6 @@ dependencies = [ "solana-reward-info", ] -[[package]] -name = "solana-reserved-account-keys" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b293f4246626c0e0a991531f08848a713ada965612e99dc510963f04d12cae7" -dependencies = [ - "lazy_static", - "solana-feature-set", - "solana-pubkey", - "solana-sdk-ids", -] - [[package]] name = "solana-reward-info" version = "2.2.1" @@ -7366,7 +7373,7 @@ dependencies = [ [[package]] name = "solana-rpc" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "base64 0.22.1", @@ -7432,7 +7439,7 @@ dependencies = [ "solana-time-utils", "solana-tpu-client", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "solana-validator-exit", @@ -7450,7 +7457,7 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "base64 0.22.1", @@ -7459,7 +7466,7 @@ dependencies = [ "futures 0.3.31", "indicatif", "log", - "reqwest 0.12.15", + "reqwest 0.12.19", "reqwest-middleware", "semver", "serde", @@ -7482,16 +7489,17 @@ dependencies = [ "solana-transaction-error", "solana-transaction-status-client-types", "solana-version", + "solana-vote-interface", "tokio", ] [[package]] name = "solana-rpc-client-api" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "jsonrpc-core", - "reqwest 0.12.15", + "reqwest 0.12.19", "reqwest-middleware", "serde", "serde_derive", @@ -7507,7 +7515,7 @@ dependencies = [ [[package]] name = "solana-rpc-client-nonce-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-commitment-config", @@ -7522,7 +7530,7 @@ dependencies = [ [[package]] name = "solana-rpc-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bs58", @@ -7546,7 +7554,7 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-precompiles", @@ -7630,7 +7638,6 @@ dependencies = [ "solana-perf", "solana-poh-config", "solana-precompile-error", - "solana-program", "solana-program-runtime", "solana-pubkey", "solana-rayon-threadlimit", @@ -7639,9 +7646,7 @@ dependencies = [ "solana-rent-debits", "solana-reward-info", "solana-runtime-transaction", - "solana-sdk", "solana-sdk-ids", - "solana-sdk-macro", "solana-secp256k1-program", "solana-seed-derivable", "solana-serde", @@ -7663,7 +7668,7 @@ dependencies = [ "solana-time-utils", "solana-timings", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status-client-types", "solana-unified-scheduler-logic", @@ -7684,7 +7689,7 @@ dependencies = [ [[package]] name = "solana-runtime-transaction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-transaction-view", "log", @@ -7725,90 +7730,19 @@ dependencies = [ ] [[package]] -name = "solana-sdk" -version = "2.2.2" +name = "solana-sdk-ids" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8af90d2ce445440e0548fa4a5f96fe8b265c22041a68c942012ffadd029667d" -dependencies = [ - "bincode", - "bs58", - "getrandom 0.1.16", - "js-sys", - "serde", - "serde_json", - "solana-account", - "solana-bn254", - "solana-client-traits", - "solana-cluster-type", - "solana-commitment-config", - "solana-compute-budget-interface", - "solana-decode-error", - "solana-derivation-path", - "solana-ed25519-program", - "solana-epoch-info", - "solana-epoch-rewards-hasher", - "solana-feature-set", - "solana-fee-structure", - "solana-genesis-config", - "solana-hard-forks", - "solana-inflation", - "solana-instruction", - "solana-keypair", - "solana-message", - "solana-native-token", - "solana-nonce-account", - "solana-offchain-message", - "solana-packet", - "solana-poh-config", - "solana-precompile-error", - "solana-precompiles", - "solana-presigner", - "solana-program", - "solana-program-memory", - "solana-pubkey", - "solana-quic-definitions", - "solana-rent-collector", - "solana-rent-debits", - "solana-reserved-account-keys", - "solana-reward-info", - "solana-sanitize", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-secp256k1-program", - "solana-secp256k1-recover", - "solana-secp256r1-program", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-serde", - "solana-serde-varint", - "solana-short-vec", - "solana-shred-version", - "solana-signature", - "solana-signer", - "solana-system-transaction", - "solana-time-utils", - "solana-transaction", - "solana-transaction-context 2.2.1", - "solana-transaction-error", - "solana-validator-exit", - "thiserror 2.0.12", - "wasm-bindgen", -] - -[[package]] -name = "solana-sdk-ids" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5d8b9cc68d5c88b062a33e23a6466722467dde0035152d8fb1afbcdf350a5f" -dependencies = [ - "solana-pubkey", -] - -[[package]] -name = "solana-sdk-macro" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86280da8b99d03560f6ab5aca9de2e38805681df34e0bb8f238e69b29433b9df" +checksum = "5c5d8b9cc68d5c88b062a33e23a6466722467dde0035152d8fb1afbcdf350a5f" +dependencies = [ + "solana-pubkey", +] + +[[package]] +name = "solana-sdk-macro" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86280da8b99d03560f6ab5aca9de2e38805681df34e0bb8f238e69b29433b9df" dependencies = [ "bs58", "proc-macro2", @@ -7822,16 +7756,11 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0a1caa972414cc78122c32bdae65ac5fe89df7db598585a5cde19d16a20280a" dependencies = [ - "bincode", "digest 0.10.7", "libsecp256k1", "serde", "serde_derive", "sha3", - "solana-feature-set", - "solana-instruction", - "solana-precompile-error", - "solana-sdk-ids", ] [[package]] @@ -7847,9 +7776,9 @@ dependencies = [ [[package]] name = "solana-secp256r1-program" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cda2aa1bbaceda14763c4f142a00b486f2f262cfd901bd0410649ad0404d5f7" +checksum = "cf903cbdc36a161533812f90acfccdb434ed48982bd5dd71f3217930572c4a80" dependencies = [ "bytemuck", "openssl", @@ -7887,7 +7816,7 @@ dependencies = [ [[package]] name = "solana-send-transaction-service" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "crossbeam-channel", @@ -7979,7 +7908,6 @@ checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c" dependencies = [ "ed25519-dalek", "five8", - "rand 0.8.5", "serde", "serde-big-array", "serde_derive", @@ -8056,7 +7984,7 @@ dependencies = [ [[package]] name = "solana-stake-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -8076,14 +8004,14 @@ dependencies = [ "solana-sdk-ids", "solana-stake-interface", "solana-sysvar", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", "solana-vote-interface", ] [[package]] name = "solana-storage-bigtable" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-reserved-account-keys", "backoff", @@ -8123,7 +8051,7 @@ dependencies = [ [[package]] name = "solana-storage-proto" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "bs58", @@ -8138,7 +8066,7 @@ dependencies = [ "solana-serde", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-transaction-status", "tonic-build", @@ -8146,7 +8074,7 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-channel", "bytes", @@ -8191,7 +8119,7 @@ dependencies = [ [[package]] name = "solana-svm" -version = "2.3.0" +version = "3.0.0" dependencies = [ "ahash 0.8.11", "itertools 0.12.1", @@ -8229,7 +8157,7 @@ dependencies = [ "solana-system-interface", "solana-sysvar-id", "solana-timings", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "solana-type-overrides", "spl-generic-token", @@ -8238,7 +8166,7 @@ dependencies = [ [[package]] name = "solana-svm-callback" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-precompile-error", @@ -8247,7 +8175,7 @@ dependencies = [ [[package]] name = "solana-svm-example-paytube" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "solana-account", @@ -8283,11 +8211,11 @@ dependencies = [ [[package]] name = "solana-svm-feature-set" -version = "2.3.0" +version = "3.0.0" [[package]] name = "solana-svm-rent-collector" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-account", "solana-clock", @@ -8295,13 +8223,13 @@ dependencies = [ "solana-rent", "solana-rent-collector", "solana-sdk-ids", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", ] [[package]] name = "solana-svm-transaction" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-hash", "solana-message", @@ -8329,7 +8257,7 @@ dependencies = [ [[package]] name = "solana-system-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "log", @@ -8348,7 +8276,7 @@ dependencies = [ "solana-sdk-ids", "solana-system-interface", "solana-sysvar", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-type-overrides", ] @@ -8416,7 +8344,7 @@ dependencies = [ [[package]] name = "solana-test-validator" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "base64 0.22.1", @@ -8463,7 +8391,7 @@ dependencies = [ [[package]] name = "solana-thin-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "log", @@ -8496,7 +8424,7 @@ checksum = "6af261afb0e8c39252a04d026e3ea9c405342b08c871a2ad8aa5448e068c784c" [[package]] name = "solana-timings" -version = "2.3.0" +version = "3.0.0" dependencies = [ "eager", "enum-iterator", @@ -8505,7 +8433,7 @@ dependencies = [ [[package]] name = "solana-tls-utils" -version = "2.3.0" +version = "3.0.0" dependencies = [ "rustls 0.23.27", "solana-keypair", @@ -8516,7 +8444,7 @@ dependencies = [ [[package]] name = "solana-tpu-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "bincode", @@ -8548,7 +8476,7 @@ dependencies = [ [[package]] name = "solana-tpu-client-next" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "log", @@ -8581,12 +8509,10 @@ dependencies = [ "serde", "serde_derive", "solana-bincode", - "solana-feature-set", "solana-hash", "solana-instruction", "solana-keypair", "solana-message", - "solana-precompiles", "solana-pubkey", "solana-sanitize", "solana-sdk-ids", @@ -8600,23 +8526,7 @@ dependencies = [ [[package]] name = "solana-transaction-context" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5022de04cbba05377f68bf848c8c1322ead733f88a657bf792bb40f3257b8218" -dependencies = [ - "bincode", - "serde", - "serde_derive", - "solana-account", - "solana-instruction", - "solana-pubkey", - "solana-rent", - "solana-signature", -] - -[[package]] -name = "solana-transaction-context" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bincode", "serde", @@ -8644,7 +8554,7 @@ dependencies = [ [[package]] name = "solana-transaction-metrics-tracker" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -8658,7 +8568,7 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "2.3.0" +version = "3.0.0" dependencies = [ "Inflector", "agave-reserved-account-keys", @@ -8700,7 +8610,7 @@ dependencies = [ [[package]] name = "solana-transaction-status-client-types" -version = "2.3.0" +version = "3.0.0" dependencies = [ "base64 0.22.1", "bincode", @@ -8714,14 +8624,14 @@ dependencies = [ "solana-reward-info", "solana-signature", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-transaction-error", "thiserror 2.0.12", ] [[package]] name = "solana-turbine" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "agave-xdp", @@ -8772,14 +8682,14 @@ dependencies = [ [[package]] name = "solana-type-overrides" -version = "2.3.0" +version = "3.0.0" dependencies = [ "rand 0.8.5", ] [[package]] name = "solana-udp-client" -version = "2.3.0" +version = "3.0.0" dependencies = [ "async-trait", "solana-connection-cache", @@ -8793,7 +8703,7 @@ dependencies = [ [[package]] name = "solana-unified-scheduler-logic" -version = "2.3.0" +version = "3.0.0" dependencies = [ "assert_matches", "solana-pubkey", @@ -8805,7 +8715,7 @@ dependencies = [ [[package]] name = "solana-unified-scheduler-pool" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-banking-stage-ingress-types", "aquamarine", @@ -8844,7 +8754,7 @@ checksum = "7bbf6d7a3c0b28dd5335c52c0e9eae49d0ae489a8f324917faf0ded65a812c1d" [[package]] name = "solana-version" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "rand 0.8.5", @@ -8857,7 +8767,7 @@ dependencies = [ [[package]] name = "solana-vortexor-receiver" -version = "2.3.0" +version = "3.0.0" dependencies = [ "solana-perf", "solana-streamer", @@ -8865,7 +8775,7 @@ dependencies = [ [[package]] name = "solana-vote" -version = "2.3.0" +version = "3.0.0" dependencies = [ "itertools 0.12.1", "log", @@ -8915,7 +8825,7 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bincode", @@ -8939,14 +8849,14 @@ dependencies = [ "solana-signer", "solana-slot-hashes", "solana-transaction", - "solana-transaction-context 2.3.0", + "solana-transaction-context", "solana-vote-interface", "thiserror 2.0.12", ] [[package]] name = "solana-wen-restart" -version = "2.3.0" +version = "3.0.0" dependencies = [ "anyhow", "log", @@ -8960,19 +8870,19 @@ dependencies = [ "solana-gossip", "solana-hash", "solana-ledger", - "solana-program", "solana-pubkey", "solana-runtime", "solana-shred-version", "solana-time-utils", "solana-timings", "solana-vote", + "solana-vote-interface", "solana-vote-program", ] [[package]] name = "solana-zk-elgamal-proof-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "bytemuck", "num-derive", @@ -8981,12 +8891,49 @@ dependencies = [ "solana-log-collector", "solana-program-runtime", "solana-sdk-ids", - "solana-zk-sdk", + "solana-zk-sdk 3.0.0", ] [[package]] name = "solana-zk-sdk" -version = "2.3.0" +version = "2.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15045540c315a9b8ea056323e73320e76098dfdaac9e65b1b33fe9c2f3c9b9e1" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "js-sys", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-derivation-path", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", + "subtle", + "thiserror 2.0.12", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-zk-sdk" +version = "3.0.0" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -9020,7 +8967,7 @@ dependencies = [ [[package]] name = "solana-zk-token-proof-program" -version = "2.3.0" +version = "3.0.0" dependencies = [ "agave-feature-set", "bytemuck", @@ -9035,7 +8982,7 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "2.3.0" +version = "3.0.0" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -9052,7 +8999,7 @@ dependencies = [ "serde_derive", "serde_json", "sha3", - "solana-curve25519", + "solana-curve25519 3.0.0", "solana-derivation-path", "solana-instruction", "solana-pubkey", @@ -9161,7 +9108,7 @@ dependencies = [ "solana-sdk-ids", "solana-system-interface", "solana-sysvar", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-pod", "spl-token-confidential-transfer-proof-extraction", ] @@ -9206,7 +9153,7 @@ dependencies = [ "solana-program-error", "solana-program-option", "solana-pubkey", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "thiserror 2.0.12", ] @@ -9316,7 +9263,7 @@ dependencies = [ "solana-security-txt", "solana-system-interface", "solana-sysvar", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-elgamal-registry", "spl-memo", "spl-pod", @@ -9339,8 +9286,8 @@ checksum = "94ab20faf7b5edaa79acd240e0f21d5a2ef936aa99ed98f698573a2825b299c4" dependencies = [ "base64 0.22.1", "bytemuck", - "solana-curve25519", - "solana-zk-sdk", + "solana-curve25519 2.2.15", + "solana-zk-sdk 2.2.15", ] [[package]] @@ -9351,14 +9298,14 @@ checksum = "fe2629860ff04c17bafa9ba4bed8850a404ecac81074113e1f840dbd0ebb7bd6" dependencies = [ "bytemuck", "solana-account-info", - "solana-curve25519", + "solana-curve25519 2.2.15", "solana-instruction", "solana-instructions-sysvar", "solana-msg", "solana-program-error", "solana-pubkey", "solana-sdk-ids", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "spl-pod", "thiserror 2.0.12", ] @@ -9370,7 +9317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae5b124840d4aed474cef101d946a798b806b46a509ee4df91021e1ab1cef3ef" dependencies = [ "curve25519-dalek 4.1.3", - "solana-zk-sdk", + "solana-zk-sdk 2.2.15", "thiserror 2.0.12", ] @@ -10045,7 +9992,7 @@ dependencies = [ "percent-encoding 2.3.1", "pin-project", "prost", - "rustls-pemfile 1.0.4", + "rustls-pemfile", "tokio", "tokio-rustls 0.24.1", "tokio-stream", @@ -10103,6 +10050,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.1", + "bytes", + "futures-util", + "http 1.2.0", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -10566,6 +10531,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" @@ -10646,35 +10620,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.53.0", -] - -[[package]] -name = "windows-result" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -10750,29 +10695,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -10791,12 +10720,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -10815,12 +10738,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -10839,24 +10756,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -10875,12 +10780,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -10899,12 +10798,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -10923,12 +10816,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -10947,12 +10834,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" version = "0.6.25" diff --git a/svm/examples/Cargo.toml b/svm/examples/Cargo.toml index 6d7ba0570e97b6..8ee272f561e4ee 100644 --- a/svm/examples/Cargo.toml +++ b/svm/examples/Cargo.toml @@ -4,7 +4,7 @@ members = ["json-rpc/client", "json-rpc/server", "paytube"] resolver = "2" [workspace.package] -version = "2.3.0" +version = "3.0.0" authors = ["Anza Maintainers "] repository = "https://github.com/anza-xyz/agave" homepage = "https://anza.xyz/" @@ -29,23 +29,44 @@ jsonrpc-http-server = "18.0.0" log = "0.4.22" serde = "1.0.214" serde_json = "1.0.132" +solana-account = "2.2.1" solana-account-decoder = { path = "../../account-decoder" } solana-bpf-loader-program = { path = "../../programs/bpf_loader" } solana-client = { path = "../../client" } +solana-clock = "2.2.1" +solana-commitment-config = "2.2.1" solana-compute-budget = { path = "../../compute-budget" } +solana-compute-budget-interface = "2.2.2" +solana-epoch-schedule = "2.2.1" +solana-hash = "2.2.1" +solana-instruction = "2.2.1" +solana-keypair = "2.2.1" solana-logger = "=2.3.1" +solana-message = "2.3.0" +solana-nonce = "2.2.1" solana-perf = { path = "../../perf" } +solana-program-pack = "2.2.1" solana-program-runtime = { path = "../../program-runtime" } +solana-pubkey = "2.3.0" +solana-rent-collector = "2.2.1" solana-rpc-client-api = { path = "../../rpc-client-api" } -solana-sdk = { version = "=2.2.2", default-features = false } +solana-sdk-ids = "2.2.1" +solana-signature = "2.2.1" +solana-signer = "2.2.1" solana-svm = { path = "../" } solana-svm-callback = { path = "../../svm-callback" } solana-svm-feature-set = { path = "../../svm-feature-set" } +solana-system-interface = "1.0" solana-system-program = { path = "../../programs/system" } -solana-version = { path = "../../version" } +solana-sysvar = "2.2.1" +solana-sysvar-id = "2.2.1" solana-test-validator = { path = "../../test-validator" } +solana-transaction = "2.2.2" solana-transaction-context = { path = "../../transaction-context" } +solana-transaction-error = "2.2.1" solana-transaction-status = { path = "../../transaction-status" } +solana-validator-exit = "2.2.1" +solana-version = { path = "../../version" } spl-associated-token-account = "7.0.0" spl-token = "8.0.0" spl-token-2022 = "8.0.0" @@ -54,28 +75,6 @@ thiserror = "1.0.68" tokio = "1.29.1" tokio-util = "0.7" yaml-rust = "0.4" -solana-account = "2.2.1" -solana-clock = "2.2.1" -solana-commitment-config = "2.2.1" -solana-compute-budget-interface = "2.2.2" -solana-message = "2.3.0" -solana-nonce = "2.2.1" -solana-pubkey = "2.3.0" -solana-sdk-ids = "2.2.1" -solana-signature = "2.2.1" -solana-system-interface = "1.0" -solana-sysvar = "2.2.1" -solana-sysvar-id = "2.2.1" -solana-transaction = "2.2.2" -solana-transaction-error = "2.2.1" -solana-validator-exit = "2.2.1" -solana-instruction = "2.2.1" -solana-keypair = "2.2.1" -solana-signer = "2.2.1" -solana-hash = "2.2.1" -solana-rent-collector = "2.2.1" -solana-epoch-schedule = "2.2.1" -solana-program-pack = "2.2.1" [patch.crates-io] crossbeam-epoch = { git = "https://github.com/anza-xyz/crossbeam", rev = "fd279d707025f0e60951e429bf778b4813d1b6bf" } diff --git a/svm/examples/json-rpc/client/Cargo.toml b/svm/examples/json-rpc/client/Cargo.toml index 3a5207e7155ce7..4a59f7ce81233b 100644 --- a/svm/examples/json-rpc/client/Cargo.toml +++ b/svm/examples/json-rpc/client/Cargo.toml @@ -5,6 +5,10 @@ version = { workspace = true } edition = { workspace = true } publish = false +[features] +dummy-for-ci-check = [] +frozen-abi = [] + [dependencies] borsh = { workspace = true } clap = { workspace = true } @@ -19,7 +23,3 @@ solana-signer = { workspace = true } solana-transaction = { workspace = true } thiserror = { workspace = true } yaml-rust = { workspace = true } - -[features] -dummy-for-ci-check = [] -frozen-abi = [] diff --git a/svm/examples/json-rpc/program/Cargo.toml b/svm/examples/json-rpc/program/Cargo.toml index 17651617250b76..a46d473ee48924 100644 --- a/svm/examples/json-rpc/program/Cargo.toml +++ b/svm/examples/json-rpc/program/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json-rpc-example-program" -version = "2.3.0" +version = "3.0.0" edition = "2021" [features] @@ -10,7 +10,10 @@ frozen-abi = [] [dependencies] borsh = "0.9" -solana-program = { path = "../../../../sdk/program", version = "=2.2.0" } +solana-account-info = "2.3.0" +solana-program-entrypoint = "2.2.1" +solana-msg = "2.2.1" +solana-pubkey = "2.4.0" [lib] name = "program" diff --git a/svm/examples/json-rpc/program/src/lib.rs b/svm/examples/json-rpc/program/src/lib.rs index 22d425f27fbbc4..b087968b704d62 100644 --- a/svm/examples/json-rpc/program/src/lib.rs +++ b/svm/examples/json-rpc/program/src/lib.rs @@ -1,10 +1,9 @@ use { borsh::{BorshDeserialize, BorshSerialize}, - solana_program::{ - account_info::{next_account_info, AccountInfo}, - entrypoint, msg, - pubkey::Pubkey, - }, + solana_account_info::{next_account_info, AccountInfo}, + solana_msg::msg, + solana_program_entrypoint::entrypoint, + solana_pubkey::Pubkey, }; /// The type of state managed by this program. The type defined here @@ -21,7 +20,7 @@ pub fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], _instruction_data: &[u8], -) -> entrypoint::ProgramResult { +) -> solana_program_entrypoint::ProgramResult { // Get the account that stores greeting count information. let accounts_iter = &mut accounts.iter(); let account = next_account_info(accounts_iter)?; diff --git a/svm/examples/json-rpc/server/Cargo.toml b/svm/examples/json-rpc/server/Cargo.toml index 82121a5ea170c9..0db261047239e9 100644 --- a/svm/examples/json-rpc/server/Cargo.toml +++ b/svm/examples/json-rpc/server/Cargo.toml @@ -5,6 +5,10 @@ version = { workspace = true } edition = { workspace = true } publish = false +[features] +dummy-for-ci-check = [] +frozen-abi = [] + [dependencies] agave-feature-set = { workspace = true } agave-reserved-account-keys = { workspace = true } @@ -35,7 +39,6 @@ solana-perf = { workspace = true } solana-program-runtime = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client-api = { workspace = true } -solana-sdk = { workspace = true } solana-sdk-ids = { workspace = true } solana-signature = { workspace = true } solana-svm = { workspace = true } @@ -53,7 +56,3 @@ solana-version = { workspace = true } spl-token-2022 = { workspace = true, features = ["no-entrypoint"] } tokio = { workspace = true, features = ["full"] } tokio-util = { workspace = true, features = ["codec", "compat"] } - -[features] -dummy-for-ci-check = [] -frozen-abi = [] diff --git a/svm/examples/json-rpc/server/src/rpc_process.rs b/svm/examples/json-rpc/server/src/rpc_process.rs index 06843746846d6c..00b266891f31e7 100644 --- a/svm/examples/json-rpc/server/src/rpc_process.rs +++ b/svm/examples/json-rpc/server/src/rpc_process.rs @@ -126,6 +126,7 @@ struct TransactionSimulationResult { pub logs: TransactionLogMessages, pub post_simulation_accounts: Vec, pub units_consumed: u64, + pub loaded_accounts_data_size: u32, pub return_data: Option, pub inner_instructions: Option>, } @@ -371,12 +372,14 @@ impl JsonRpcRequestProcessor { }; let logs = logs.unwrap_or_default(); let units_consumed: u64 = 0; + let loaded_accounts_data_size: u32 = 0; TransactionSimulationResult { result: flattened_result, logs, post_simulation_accounts, units_consumed, + loaded_accounts_data_size, return_data, inner_instructions, } @@ -692,6 +695,7 @@ pub mod rpc { logs, post_simulation_accounts, units_consumed, + loaded_accounts_data_size, return_data, inner_instructions, } = meta.simulate_transaction_unchecked(&transaction, enable_cpi_recording); @@ -757,6 +761,7 @@ pub mod rpc { logs: Some(logs), accounts, units_consumed: Some(units_consumed), + loaded_accounts_data_size: Some(loaded_accounts_data_size), return_data: return_data.map(|return_data| return_data.into()), inner_instructions, replacement_blockhash: None, diff --git a/svm/examples/paytube/Cargo.toml b/svm/examples/paytube/Cargo.toml index a1cda4df15ebbb..6cd4c0056a39a3 100644 --- a/svm/examples/paytube/Cargo.toml +++ b/svm/examples/paytube/Cargo.toml @@ -5,6 +5,10 @@ version = { workspace = true } edition = { workspace = true } publish = false +[features] +dummy-for-ci-check = [] +frozen-abi = [] + [dependencies] agave-feature-set = { workspace = true } solana-account = { workspace = true } @@ -14,7 +18,7 @@ solana-clock = { workspace = true } solana-commitment-config = { workspace = true } solana-compute-budget = { workspace = true } solana-epoch-schedule = { workspace = true } -solana-fee-structure = "=2.2.1" +solana-fee-structure = "=2.3.0" solana-hash = { workspace = true } solana-instruction = { workspace = true } solana-keypair = { workspace = true } @@ -30,7 +34,7 @@ solana-svm-callback = { workspace = true } solana-svm-feature-set = { workspace = true } solana-system-interface = { workspace = true } solana-system-program = { workspace = true } -solana-transaction = { workspace = true } +solana-transaction = { workspace = true, features = ["blake3"] } solana-transaction-error = { workspace = true } spl-associated-token-account = { workspace = true } spl-token = { workspace = true } @@ -38,7 +42,3 @@ termcolor = { workspace = true } [dev-dependencies] solana-test-validator = { workspace = true } - -[features] -dummy-for-ci-check = [] -frozen-abi = [] diff --git a/svm/src/account_loader.rs b/svm/src/account_loader.rs index ea4f133e24c9fc..8608a8d4dad311 100644 --- a/svm/src/account_loader.rs +++ b/svm/src/account_loader.rs @@ -1,5 +1,5 @@ #[cfg(feature = "dev-context-only-utils")] -use qualifier_attr::field_qualifiers; +use qualifier_attr::{field_qualifiers, qualifiers}; use { crate::{ account_overrides::AccountOverrides, nonce_info::NonceInfo, @@ -8,11 +8,13 @@ use { }, ahash::{AHashMap, AHashSet}, solana_account::{ - Account, AccountSharedData, ReadableAccount, WritableAccount, PROGRAM_OWNERS, + state_traits::StateMut, Account, AccountSharedData, ReadableAccount, WritableAccount, + PROGRAM_OWNERS, }, solana_fee_structure::FeeDetails, solana_instruction::{BorrowedAccountMeta, BorrowedInstruction}, solana_instructions_sysvar::construct_instructions_data, + solana_loader_v3_interface::state::UpgradeableLoaderState, solana_nonce::state::State as NonceState, solana_nonce_account::{get_system_account_kind, SystemAccountKind}, solana_program_runtime::execution_budget::{ @@ -23,7 +25,7 @@ use { solana_rent_collector::{CollectedInfo, RENT_EXEMPT_RENT_EPOCH}, solana_rent_debits::RentDebits, solana_sdk_ids::{ - native_loader, + bpf_loader_upgradeable, native_loader, sysvar::{self, slot_history}, }, solana_svm_callback::{AccountState, TransactionProcessingCallback}, @@ -35,6 +37,15 @@ use { std::num::{NonZeroU32, Saturating}, }; +// Per SIMD-0186, all accounts are assigned a base size of 64 bytes to cover +// the storage cost of metadata. +#[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))] +pub(crate) const TRANSACTION_ACCOUNT_BASE_SIZE: usize = 64; + +// Per SIMD-0186, resolved address lookup tables are assigned a base size of 8248 +// bytes: 8192 bytes for the maximum table size plus 56 bytes for metadata. +const ADDRESS_LOOKUP_TABLE_BASE_SIZE: usize = 8248; + // for the load instructions pub(crate) type TransactionRent = u64; pub(crate) type TransactionProgramIndices = Vec>; @@ -123,11 +134,7 @@ pub(crate) struct LoadedTransactionAccount { #[cfg_attr(feature = "dev-context-only-utils", derive(Default))] #[cfg_attr( feature = "dev-context-only-utils", - field_qualifiers( - program_indices(pub), - loaded_accounts_data_size(pub), - compute_budget(pub) - ) + field_qualifiers(program_indices(pub), compute_budget(pub)) )] pub struct LoadedTransaction { pub accounts: Vec, @@ -137,7 +144,7 @@ pub struct LoadedTransaction { pub(crate) compute_budget: SVMTransactionExecutionBudget, pub rent: TransactionRent, pub rent_debits: RentDebits, - pub(crate) loaded_accounts_data_size: u32, + pub loaded_accounts_data_size: u32, } #[derive(PartialEq, Eq, Debug, Clone)] @@ -194,6 +201,12 @@ impl<'a, CB: TransactionProcessingCallback> AccountLoader<'a, CB> { account_key: &Pubkey, is_writable: bool, ) -> Option { + let base_account_size = if self.feature_set.formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + let account = self.load_account(account_key); // Inspect prior to collecting rent, since rent collection can modify the account. @@ -208,7 +221,7 @@ impl<'a, CB: TransactionProcessingCallback> AccountLoader<'a, CB> { ); account.map(|account| LoadedTransactionAccount { - loaded_size: account.data().len(), + loaded_size: base_account_size.saturating_add(account.data().len()), account, rent_collected: 0, }) @@ -477,6 +490,31 @@ struct LoadedTransactionAccounts { pub(crate) loaded_accounts_data_size: u32, } +impl LoadedTransactionAccounts { + fn increase_calculated_data_size( + &mut self, + data_size_delta: usize, + requested_loaded_accounts_data_size_limit: NonZeroU32, + error_metrics: &mut TransactionErrorMetrics, + ) -> Result<()> { + let Ok(data_size_delta) = u32::try_from(data_size_delta) else { + error_metrics.max_loaded_accounts_data_size_exceeded += 1; + return Err(TransactionError::MaxLoadedAccountsDataSizeExceeded); + }; + + self.loaded_accounts_data_size = self + .loaded_accounts_data_size + .saturating_add(data_size_delta); + + if self.loaded_accounts_data_size > requested_loaded_accounts_data_size_limit.get() { + error_metrics.max_loaded_accounts_data_size_exceeded += 1; + Err(TransactionError::MaxLoadedAccountsDataSizeExceeded) + } else { + Ok(()) + } + } +} + fn load_transaction_accounts( account_loader: &mut AccountLoader, message: &impl SVMMessage, @@ -484,6 +522,179 @@ fn load_transaction_accounts( loaded_accounts_bytes_limit: NonZeroU32, error_metrics: &mut TransactionErrorMetrics, rent_collector: &dyn SVMRentCollector, +) -> Result { + if account_loader + .feature_set + .formalize_loaded_transaction_data_size + { + load_transaction_accounts_simd186( + account_loader, + message, + loaded_fee_payer_account, + loaded_accounts_bytes_limit, + error_metrics, + rent_collector, + ) + } else { + load_transaction_accounts_old( + account_loader, + message, + loaded_fee_payer_account, + loaded_accounts_bytes_limit, + error_metrics, + rent_collector, + ) + } +} + +fn load_transaction_accounts_simd186( + account_loader: &mut AccountLoader, + message: &impl SVMMessage, + loaded_fee_payer_account: LoadedTransactionAccount, + loaded_accounts_bytes_limit: NonZeroU32, + error_metrics: &mut TransactionErrorMetrics, + rent_collector: &dyn SVMRentCollector, +) -> Result { + let account_keys = message.account_keys(); + let mut additional_loaded_accounts: AHashSet = AHashSet::new(); + + let mut loaded_transaction_accounts = LoadedTransactionAccounts { + accounts: Vec::with_capacity(account_keys.len()), + program_indices: Vec::with_capacity(message.num_instructions()), + rent: 0, + rent_debits: RentDebits::default(), + loaded_accounts_data_size: 0, + }; + + // Transactions pay a base fee per address lookup table. + loaded_transaction_accounts.increase_calculated_data_size( + message + .num_lookup_tables() + .saturating_mul(ADDRESS_LOOKUP_TABLE_BASE_SIZE), + loaded_accounts_bytes_limit, + error_metrics, + )?; + + let mut collect_loaded_account = + |account_loader: &mut AccountLoader, key, loaded_account| -> Result<()> { + let LoadedTransactionAccount { + account, + loaded_size, + rent_collected, + } = loaded_account; + + loaded_transaction_accounts.increase_calculated_data_size( + loaded_size, + loaded_accounts_bytes_limit, + error_metrics, + )?; + + loaded_transaction_accounts.rent = loaded_transaction_accounts + .rent + .saturating_add(rent_collected); + + loaded_transaction_accounts + .rent_debits + .insert(key, rent_collected, account.lamports()); + + // This has been annotated branch-by-branch because collapsing the logic is infeasible. + // Its purpose is to ensure programdata accounts are counted once and *only* once per + // transaction. By checking account_keys, we never double-count a programdata account + // that was explictly included in the transaction. We also use a hashset to gracefully + // handle cases that LoaderV3 presumably makes impossible, such as self-referential + // program accounts or multiply-referenced programdata accounts, for added safety. + // + // If in the future LoaderV3 programs are migrated to LoaderV4, this entire code block + // can be deleted. + // + // If this is a valid LoaderV3 program... + if bpf_loader_upgradeable::check_id(account.owner()) { + if let Ok(UpgradeableLoaderState::Program { + programdata_address, + }) = account.state() + { + // ...its programdata was not already counted and will not later be counted... + if !account_keys.iter().any(|key| programdata_address == *key) + && !additional_loaded_accounts.contains(&programdata_address) + { + // ...and the programdata account exists (if it doesn't, it is *not* a load failure)... + if let Some(programdata_account) = + account_loader.load_account(&programdata_address) + { + // ...count programdata toward this transaction's total size. + loaded_transaction_accounts.increase_calculated_data_size( + TRANSACTION_ACCOUNT_BASE_SIZE + .saturating_add(programdata_account.data().len()), + loaded_accounts_bytes_limit, + error_metrics, + )?; + additional_loaded_accounts.insert(programdata_address); + } + } + } + } + + loaded_transaction_accounts.accounts.push((*key, account)); + + Ok(()) + }; + + // Since the fee payer is always the first account, collect it first. + // We can use it directly because it was already loaded during validation. + collect_loaded_account( + account_loader, + message.fee_payer(), + loaded_fee_payer_account, + )?; + + // Attempt to load and collect remaining non-fee payer accounts. + for (account_index, account_key) in account_keys.iter().enumerate().skip(1) { + let loaded_account = load_transaction_account( + account_loader, + message, + account_key, + account_index, + rent_collector, + ); + collect_loaded_account(account_loader, account_key, loaded_account)?; + } + + for (program_id, instruction) in message.program_instructions_iter() { + let Some(program_account) = account_loader.load_account(program_id) else { + error_metrics.account_not_found += 1; + return Err(TransactionError::ProgramAccountNotFound); + }; + + if !account_loader + .feature_set + .remove_accounts_executable_flag_checks + && !program_account.executable() + { + error_metrics.invalid_program_for_execution += 1; + return Err(TransactionError::InvalidProgramForExecution); + } + + let owner_id = program_account.owner(); + if !native_loader::check_id(owner_id) && !PROGRAM_OWNERS.contains(owner_id) { + error_metrics.invalid_program_for_execution += 1; + return Err(TransactionError::InvalidProgramForExecution); + } + + loaded_transaction_accounts + .program_indices + .push(vec![instruction.program_id_index as IndexOfAccount]); + } + + Ok(loaded_transaction_accounts) +} + +fn load_transaction_accounts_old( + account_loader: &mut AccountLoader, + message: &impl SVMMessage, + loaded_fee_payer_account: LoadedTransactionAccount, + loaded_accounts_bytes_limit: NonZeroU32, + error_metrics: &mut TransactionErrorMetrics, + rent_collector: &dyn SVMRentCollector, ) -> Result { let mut tx_rent: TransactionRent = 0; let account_keys = message.account_keys(); @@ -560,22 +771,6 @@ fn load_transaction_accounts( } if !validated_loaders.contains(owner_id) { - // NOTE there are several feature gate activations that affect this code: - // * `remove_accounts_executable_flag_checks`: this implicitly makes system, vote, stake, et al valid loaders - // it is impossible to mark an account executable and also have it be owned by one of them - // so, with the feature disabled, we always fail the executable check if they are a program id owner - // however, with the feature enabled, any account owned by an account owned by native loader is a "program" - // this is benign (any such transaction will fail at execution) but it affects which transactions pay fees - // * `enable_transaction_loading_failure_fees`: loading failures behave the same as execution failures - // at this point we can restrict valid loaders to those contained in `PROGRAM_OWNERS` - // since any other pseudo-loader owner is destined to fail at execution - // * SIMD-186: explicitly defines a sensible transaction data size algorithm - // at this point we stop counting loaders toward transaction data size entirely - // - // when _all three_ of `remove_accounts_executable_flag_checks`, `enable_transaction_loading_failure_fees`, - // and SIMD-186 are active, we do not need to load loaders at all to comply with consensus rules - // we may verify program ids are owned by `PROGRAM_OWNERS` purely as an optimization - // this could even be done before loading the rest of the accounts for a transaction if let Some(owner_account) = account_loader.load_account(owner_id) { if !native_loader::check_id(owner_account.owner()) || (!account_loader @@ -719,6 +914,7 @@ mod tests { super::*, crate::transaction_account_state_info::TransactionAccountStateInfo, agave_reserved_account_keys::ReservedAccountKeys, + rand0_7::prelude::*, solana_account::{Account, AccountSharedData, ReadableAccount, WritableAccount}, solana_epoch_schedule::EpochSchedule, solana_hash::Hash, @@ -750,9 +946,10 @@ mod tests { solana_transaction_context::{TransactionAccount, TransactionContext}, solana_transaction_error::{TransactionError, TransactionResult as Result}, std::{borrow::Cow, cell::RefCell, collections::HashMap, fs::File, io::Read}, + test_case::test_case, }; - #[derive(Clone, Default)] + #[derive(Clone)] struct TestCallbacks { accounts_map: HashMap, #[allow(clippy::type_complexity)] @@ -761,6 +958,16 @@ mod tests { feature_set: SVMFeatureSet, } + impl Default for TestCallbacks { + fn default() -> Self { + Self { + accounts_map: HashMap::default(), + inspected_accounts: RefCell::default(), + feature_set: SVMFeatureSet::all_enabled(), + } + } + } + impl InvokeContextCallback for TestCallbacks {} impl TransactionProcessingCallback for TestCallbacks { @@ -843,22 +1050,9 @@ mod tests { )) } - fn load_accounts_aux_test( - tx: Transaction, - accounts: &[TransactionAccount], - error_metrics: &mut TransactionErrorMetrics, - ) -> TransactionLoadResult { - load_accounts_with_features_and_rent( - tx, - accounts, - &RentCollector::default(), - error_metrics, - SVMFeatureSet::all_enabled(), - ) - } - - #[test] - fn test_load_accounts_unknown_program_id() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_accounts_unknown_program_id(formalize_loaded_transaction_data_size: bool) { let mut accounts: Vec = Vec::new(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -881,7 +1075,16 @@ mod tests { instructions, ); - let load_results = load_accounts_aux_test(tx, &accounts, &mut error_metrics); + let mut feature_set = SVMFeatureSet::all_enabled(); + feature_set.formalize_loaded_transaction_data_size = formalize_loaded_transaction_data_size; + + let load_results = load_accounts_with_features_and_rent( + tx, + &accounts, + &RentCollector::default(), + &mut error_metrics, + feature_set, + ); assert_eq!(error_metrics.account_not_found.0, 1); assert!(matches!( @@ -893,8 +1096,9 @@ mod tests { )); } - #[test] - fn test_load_accounts_no_loaders() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_accounts_no_loaders(formalize_loaded_transaction_data_size: bool) { let mut accounts: Vec = Vec::new(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -919,29 +1123,43 @@ mod tests { instructions, ); + let mut feature_set = SVMFeatureSet::all_enabled(); + feature_set.formalize_loaded_transaction_data_size = formalize_loaded_transaction_data_size; + let loaded_accounts = load_accounts_with_features_and_rent( tx, &accounts, &RentCollector::default(), &mut error_metrics, - SVMFeatureSet::all_enabled(), + feature_set, ); - assert_eq!(error_metrics.account_not_found.0, 0); match &loaded_accounts { - TransactionLoadResult::Loaded(loaded_transaction) => { + TransactionLoadResult::Loaded(loaded_transaction) + if !formalize_loaded_transaction_data_size => + { + assert_eq!(error_metrics.account_not_found.0, 0); assert_eq!(loaded_transaction.accounts.len(), 3); assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1); assert_eq!(loaded_transaction.program_indices.len(), 1); assert_eq!(loaded_transaction.program_indices[0].len(), 0); } - TransactionLoadResult::FeesOnly(fees_only_tx) => panic!("{}", fees_only_tx.load_error), - TransactionLoadResult::NotLoaded(e) => panic!("{e}"), + TransactionLoadResult::FeesOnly(fees_only_tx) + if formalize_loaded_transaction_data_size => + { + assert_eq!(error_metrics.account_not_found.0, 1); + assert_eq!( + fees_only_tx.load_error, + TransactionError::ProgramAccountNotFound, + ); + } + result => panic!("unexpected result: {:?}", result), } } - #[test] - fn test_load_accounts_bad_owner() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_accounts_bad_owner(formalize_loaded_transaction_data_size: bool) { let mut accounts: Vec = Vec::new(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -953,7 +1171,6 @@ mod tests { accounts.push((key0, account)); let mut account = AccountSharedData::new(40, 1, &Pubkey::default()); - account.set_owner(bpf_loader_upgradeable::id()); account.set_executable(true); accounts.push((key1, account)); @@ -966,20 +1183,41 @@ mod tests { instructions, ); - let load_results = load_accounts_aux_test(tx, &accounts, &mut error_metrics); + let mut feature_set = SVMFeatureSet::all_enabled(); + feature_set.formalize_loaded_transaction_data_size = formalize_loaded_transaction_data_size; - assert_eq!(error_metrics.account_not_found.0, 1); - assert!(matches!( - load_results, - TransactionLoadResult::FeesOnly(FeesOnlyTransaction { - load_error: TransactionError::ProgramAccountNotFound, - .. - }), - )); + let load_results = load_accounts_with_features_and_rent( + tx, + &accounts, + &RentCollector::default(), + &mut error_metrics, + feature_set, + ); + + if formalize_loaded_transaction_data_size { + assert_eq!(error_metrics.invalid_program_for_execution.0, 1); + assert!(matches!( + load_results, + TransactionLoadResult::FeesOnly(FeesOnlyTransaction { + load_error: TransactionError::InvalidProgramForExecution, + .. + }), + )); + } else { + assert_eq!(error_metrics.account_not_found.0, 1); + assert!(matches!( + load_results, + TransactionLoadResult::FeesOnly(FeesOnlyTransaction { + load_error: TransactionError::ProgramAccountNotFound, + .. + }), + )); + } } - #[test] - fn test_load_accounts_not_executable() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_accounts_not_executable(formalize_loaded_transaction_data_size: bool) { let mut accounts: Vec = Vec::new(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -1004,6 +1242,8 @@ mod tests { let mut feature_set = SVMFeatureSet::all_enabled(); feature_set.remove_accounts_executable_flag_checks = false; + feature_set.formalize_loaded_transaction_data_size = formalize_loaded_transaction_data_size; + let load_results = load_accounts_with_features_and_rent( tx, &accounts, @@ -1022,8 +1262,9 @@ mod tests { )); } - #[test] - fn test_load_accounts_multiple_loaders() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_accounts_multiple_loaders(formalize_loaded_transaction_data_size: bool) { let mut accounts: Vec = Vec::new(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -1060,12 +1301,15 @@ mod tests { instructions, ); + let mut feature_set = SVMFeatureSet::all_enabled(); + feature_set.formalize_loaded_transaction_data_size = formalize_loaded_transaction_data_size; + let loaded_accounts = load_accounts_with_features_and_rent( tx, &accounts, &RentCollector::default(), &mut error_metrics, - SVMFeatureSet::all_enabled(), + feature_set, ); assert_eq!(error_metrics.account_not_found.0, 0); @@ -1149,17 +1393,28 @@ mod tests { let keypair = Keypair::new(); let account = AccountSharedData::new(1_000_000, 0, &Pubkey::default()); + let mut program_account = AccountSharedData::default(); + program_account.set_lamports(1); + program_account.set_executable(true); + program_account.set_owner(native_loader::id()); + let instructions = vec![CompiledInstruction::new(2, &(), vec![0])]; let tx = Transaction::new_with_compiled_instructions( &[&keypair], &[slot_history_id], Hash::default(), - vec![native_loader::id()], + vec![bpf_loader::id()], instructions, ); - let loaded_accounts = - load_accounts_no_store(&[(keypair.pubkey(), account)], tx, Some(&account_overrides)); + let loaded_accounts = load_accounts_no_store( + &[ + (keypair.pubkey(), account), + (bpf_loader::id(), program_account), + ], + tx, + Some(&account_overrides), + ); match &loaded_accounts { TransactionLoadResult::Loaded(loaded_transaction) => { assert_eq!(loaded_transaction.accounts[0].0, keypair.pubkey()); @@ -1420,8 +1675,9 @@ mod tests { ); } - #[test] - fn test_load_transaction_accounts_native_loader() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_transaction_accounts_native_loader(formalize_loaded_transaction_data_size: bool) { let key1 = Keypair::new(); let message = Message { account_keys: vec![key1.pubkey(), native_loader::id()], @@ -1436,6 +1692,8 @@ mod tests { let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; mock_bank .accounts_map .insert(native_loader::id(), AccountSharedData::default()); @@ -1453,11 +1711,19 @@ mod tests { vec![Signature::new_unique()], false, ); + + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + let result = load_transaction_accounts( &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount { account: fee_payer_account.clone(), + loaded_size: base_account_size, ..LoadedTransactionAccount::default() }, MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES, @@ -1465,22 +1731,30 @@ mod tests { &RentCollector::default(), ); - assert_eq!( - result.unwrap(), - LoadedTransactionAccounts { - accounts: vec![ - (key1.pubkey(), fee_payer_account), - ( - native_loader::id(), - mock_bank.accounts_map[&native_loader::id()].clone() - ) - ], - program_indices: vec![vec![]], - rent: 0, - rent_debits: RentDebits::default(), - loaded_accounts_data_size: 0, - } - ); + if formalize_loaded_transaction_data_size { + assert_eq!( + result.unwrap_err(), + TransactionError::ProgramAccountNotFound, + ); + } else { + let loaded_accounts_data_size = base_account_size as u32 * 2; + assert_eq!( + result.unwrap(), + LoadedTransactionAccounts { + accounts: vec![ + (key1.pubkey(), fee_payer_account), + ( + native_loader::id(), + mock_bank.accounts_map[&native_loader::id()].clone() + ) + ], + program_indices: vec![vec![]], + rent: 0, + rent_debits: RentDebits::default(), + loaded_accounts_data_size, + } + ); + } } #[test] @@ -1570,8 +1844,11 @@ mod tests { ); } - #[test] - fn test_load_transaction_accounts_native_loader_owner() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_transaction_accounts_native_loader_owner( + formalize_loaded_transaction_data_size: bool, + ) { let key1 = Keypair::new(); let key2 = Keypair::new(); @@ -1588,6 +1865,8 @@ mod tests { let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; let mut account_data = AccountSharedData::default(); account_data.set_owner(native_loader::id()); account_data.set_lamports(1); @@ -1608,11 +1887,19 @@ mod tests { vec![Signature::new_unique()], false, ); + + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + let result = load_transaction_accounts( &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount { account: fee_payer_account.clone(), + loaded_size: base_account_size, ..LoadedTransactionAccount::default() }, MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES, @@ -1620,6 +1907,8 @@ mod tests { &RentCollector::default(), ); + let loaded_accounts_data_size = base_account_size as u32 * 2; + assert_eq!( result.unwrap(), LoadedTransactionAccounts { @@ -1633,7 +1922,7 @@ mod tests { program_indices: vec![vec![1]], rent: 0, rent_debits: RentDebits::default(), - loaded_accounts_data_size: 0, + loaded_accounts_data_size, } ); } @@ -1739,11 +2028,13 @@ mod tests { ); } - #[test] - fn test_load_transaction_accounts_program_success_complete() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_transaction_accounts_program_success_complete( + formalize_loaded_transaction_data_size: bool, + ) { let key1 = Keypair::new(); let key2 = Keypair::new(); - let key3 = Keypair::new(); let message = Message { account_keys: vec![key2.pubkey(), key1.pubkey()], @@ -1758,10 +2049,12 @@ mod tests { let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; let mut account_data = AccountSharedData::default(); account_data.set_lamports(1); account_data.set_executable(true); - account_data.set_owner(key3.pubkey()); + account_data.set_owner(bpf_loader::id()); mock_bank.accounts_map.insert(key1.pubkey(), account_data); let mut fee_payer_account = AccountSharedData::default(); @@ -1774,7 +2067,9 @@ mod tests { account_data.set_lamports(1); account_data.set_executable(true); account_data.set_owner(native_loader::id()); - mock_bank.accounts_map.insert(key3.pubkey(), account_data); + mock_bank + .accounts_map + .insert(bpf_loader::id(), account_data); let mut account_loader = (&mock_bank).into(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -1784,11 +2079,19 @@ mod tests { vec![Signature::new_unique()], false, ); + + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + let result = load_transaction_accounts( &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount { account: fee_payer_account.clone(), + loaded_size: base_account_size, ..LoadedTransactionAccount::default() }, MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES, @@ -1796,6 +2099,8 @@ mod tests { &RentCollector::default(), ); + let loaded_accounts_data_size = base_account_size as u32 * 2; + assert_eq!( result.unwrap(), LoadedTransactionAccounts { @@ -1809,20 +2114,22 @@ mod tests { program_indices: vec![vec![1]], rent: 0, rent_debits: RentDebits::default(), - loaded_accounts_data_size: 0, + loaded_accounts_data_size, } ); } - #[test] - fn test_load_transaction_accounts_program_builtin_saturating_add() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_transaction_accounts_program_builtin_saturating_add( + formalize_loaded_transaction_data_size: bool, + ) { let key1 = Keypair::new(); let key2 = Keypair::new(); let key3 = Keypair::new(); - let key4 = Keypair::new(); let message = Message { - account_keys: vec![key2.pubkey(), key1.pubkey(), key4.pubkey()], + account_keys: vec![key2.pubkey(), key1.pubkey(), key3.pubkey()], header: MessageHeader::default(), instructions: vec![ CompiledInstruction { @@ -1841,10 +2148,12 @@ mod tests { let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; let mut account_data = AccountSharedData::default(); account_data.set_lamports(1); account_data.set_executable(true); - account_data.set_owner(key3.pubkey()); + account_data.set_owner(bpf_loader::id()); mock_bank.accounts_map.insert(key1.pubkey(), account_data); let mut fee_payer_account = AccountSharedData::default(); @@ -1857,7 +2166,9 @@ mod tests { account_data.set_lamports(1); account_data.set_executable(true); account_data.set_owner(native_loader::id()); - mock_bank.accounts_map.insert(key3.pubkey(), account_data); + mock_bank + .accounts_map + .insert(bpf_loader::id(), account_data); let mut account_loader = (&mock_bank).into(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -1867,11 +2178,19 @@ mod tests { vec![Signature::new_unique()], false, ); + + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + let result = load_transaction_accounts( &mut account_loader, sanitized_transaction.message(), LoadedTransactionAccount { account: fee_payer_account.clone(), + loaded_size: base_account_size, ..LoadedTransactionAccount::default() }, MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES, @@ -1879,6 +2198,8 @@ mod tests { &RentCollector::default(), ); + let loaded_accounts_data_size = base_account_size as u32 * 2; + let mut account_data = AccountSharedData::default(); account_data.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH); assert_eq!( @@ -1890,12 +2211,12 @@ mod tests { key1.pubkey(), mock_bank.accounts_map[&key1.pubkey()].clone() ), - (key4.pubkey(), account_data), + (key3.pubkey(), account_data), ], program_indices: vec![vec![1], vec![1]], rent: 0, rent_debits: RentDebits::default(), - loaded_accounts_data_size: 0, + loaded_accounts_data_size, } ); } @@ -1965,15 +2286,15 @@ mod tests { ); } - #[test] - fn test_load_accounts_success() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_load_accounts_success(formalize_loaded_transaction_data_size: bool) { let key1 = Keypair::new(); let key2 = Keypair::new(); let key3 = Keypair::new(); - let key4 = Keypair::new(); let message = Message { - account_keys: vec![key2.pubkey(), key1.pubkey(), key4.pubkey()], + account_keys: vec![key2.pubkey(), key1.pubkey(), key3.pubkey()], header: MessageHeader::default(), instructions: vec![ CompiledInstruction { @@ -1992,10 +2313,12 @@ mod tests { let sanitized_message = new_unchecked_sanitized_message(message); let mut mock_bank = TestCallbacks::default(); + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; let mut account_data = AccountSharedData::default(); account_data.set_lamports(1); account_data.set_executable(true); - account_data.set_owner(key3.pubkey()); + account_data.set_owner(bpf_loader::id()); mock_bank.accounts_map.insert(key1.pubkey(), account_data); let mut fee_payer_account = AccountSharedData::default(); @@ -2008,7 +2331,9 @@ mod tests { account_data.set_lamports(1); account_data.set_executable(true); account_data.set_owner(native_loader::id()); - mock_bank.accounts_map.insert(key3.pubkey(), account_data); + mock_bank + .accounts_map + .insert(bpf_loader::id(), account_data); let mut account_loader = (&mock_bank).into(); let mut error_metrics = TransactionErrorMetrics::default(); @@ -2018,9 +2343,17 @@ mod tests { vec![Signature::new_unique()], false, ); + + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + let validation_result = Ok(ValidatedTransactionDetails { loaded_fee_payer_account: LoadedTransactionAccount { account: fee_payer_account, + loaded_size: base_account_size, ..LoadedTransactionAccount::default() }, ..ValidatedTransactionDetails::default() @@ -2034,6 +2367,8 @@ mod tests { &RentCollector::default(), ); + let loaded_accounts_data_size = base_account_size as u32 * 2; + let mut account_data = AccountSharedData::default(); account_data.set_rent_epoch(RENT_EXEMPT_RENT_EPOCH); @@ -2052,7 +2387,7 @@ mod tests { key1.pubkey(), mock_bank.accounts_map[&key1.pubkey()].clone() ), - (key4.pubkey(), account_data), + (key3.pubkey(), account_data), ], program_indices: vec![vec![1], vec![1]], fee_details: FeeDetails::default(), @@ -2060,7 +2395,7 @@ mod tests { compute_budget: SVMTransactionExecutionBudget::default(), rent: 0, rent_debits: RentDebits::default(), - loaded_accounts_data_size: 0, + loaded_accounts_data_size, } ); } @@ -2287,6 +2622,7 @@ mod tests { #[test] fn test_load_transaction_accounts_data_sizes() { let mut mock_bank = TestCallbacks::default(); + mock_bank.feature_set.formalize_loaded_transaction_data_size = false; let loader_v2 = bpf_loader::id(); let loader_v3 = bpf_loader_upgradeable::id(); @@ -2368,10 +2704,13 @@ mod tests { let mut program_accounts = HashMap::new(); program_accounts.insert(program1, (&loader_v2, 0)); program_accounts.insert(program2, (&loader_v3, 0)); - let feature_set = SVMFeatureSet::default(); let test_transaction_data_size = |transaction, expected_size| { - let mut account_loader = - AccountLoader::new_with_loaded_accounts_capacity(None, &mock_bank, &feature_set, 0); + let mut account_loader = AccountLoader::new_with_loaded_accounts_capacity( + None, + &mock_bank, + &mock_bank.feature_set, + 0, + ); let loaded_transaction_accounts = load_transaction_accounts( &mut account_loader, @@ -2644,4 +2983,195 @@ mod tests { assert_eq!(account_loader.load_account(&fee_payer), None); assert_eq!(account_loader.get_account_shared_data(&fee_payer), None); } + + // note all magic numbers (how many accounts, how many instructions, how big to size buffers) are arbitrary + // other than trying not to swamp programs with blank accounts and keep transaction size below the 64mb limit + #[test_case(false; "executable_mandatory")] + #[test_case(true; "executable_optional")] + fn test_load_transaction_accounts_data_sizes_simd186( + remove_accounts_executable_flag_checks: bool, + ) { + let mut rng = rand0_7::thread_rng(); + let mut mock_bank = TestCallbacks::default(); + mock_bank.feature_set.remove_accounts_executable_flag_checks = + remove_accounts_executable_flag_checks; + + // arbitrary accounts + for _ in 0..128 { + let account = AccountSharedData::create( + 1, + vec![0; rng.gen_range(0, 128)], + Pubkey::new_unique(), + rng.gen(), + u64::MAX, + ); + mock_bank.accounts_map.insert(Pubkey::new_unique(), account); + } + + // fee-payers + let mut fee_payers = vec![]; + for _ in 0..8 { + let fee_payer = Pubkey::new_unique(); + let account = AccountSharedData::create( + LAMPORTS_PER_SOL, + vec![0; rng.gen_range(0, 32)], + system_program::id(), + rng.gen(), + u64::MAX, + ); + mock_bank.accounts_map.insert(fee_payer, account); + fee_payers.push(fee_payer); + } + + // programs + let mut loader_owned_accounts = vec![]; + let mut programdata_tracker = AHashMap::new(); + for loader in PROGRAM_OWNERS { + for _ in 0..16 { + let program_id = Pubkey::new_unique(); + let mut account = AccountSharedData::create( + 1, + vec![0; rng.gen_range(0, 512)], + *loader, + !remove_accounts_executable_flag_checks || rng.gen(), + u64::MAX, + ); + + // give half loaderv3 accounts (if theyre long enough) a valid programdata + // a quarter a dead pointer and a quarter nothing + // we set executable like a program because after the flag is disabled... + // ...programdata and buffer accounts can be used as program ids without aborting loading + // this will always fail at execution but we are merely testing the data size accounting here + if *loader == bpf_loader_upgradeable::id() && account.data().len() >= 64 { + let programdata_address = Pubkey::new_unique(); + let has_programdata = rng.gen(); + + if has_programdata { + let programdata_account = AccountSharedData::create( + 1, + vec![0; rng.gen_range(0, 512)], + *loader, + !remove_accounts_executable_flag_checks || rng.gen(), + u64::MAX, + ); + programdata_tracker.insert( + program_id, + (programdata_address, programdata_account.data().len()), + ); + mock_bank + .accounts_map + .insert(programdata_address, programdata_account); + loader_owned_accounts.push(programdata_address); + } + + if has_programdata || rng.gen() { + account + .set_state(&UpgradeableLoaderState::Program { + programdata_address, + }) + .unwrap(); + } + } + + mock_bank.accounts_map.insert(program_id, account); + loader_owned_accounts.push(program_id); + } + } + + let mut all_accounts = mock_bank.accounts_map.keys().copied().collect::>(); + + // append some to-be-created accounts + // this is to test that their size is 0 rather than 64 + for _ in 0..32 { + all_accounts.push(Pubkey::new_unique()); + } + + let mut account_loader = (&mock_bank).into(); + + // now generate arbitrary transactions using this accounts + // we ensure valid fee-payers and that all program ids are loader-owned + // otherwise any account can appear anywhere + // some edge cases we hope to hit (not necessarily all in every run): + // * programs used multiple times as program ids and/or normal accounts are counted once + // * loaderv3 programdata used explicitly zero one or multiple times is counted once + // * loaderv3 programs with missing programdata are allowed through + // * loaderv3 programdata used as program id does nothing weird + // * loaderv3 programdata used as a regular account does nothing weird + // * the programdata conditions hold regardless of ordering + for _ in 0..1024 { + let mut instructions = vec![]; + for _ in 0..rng.gen_range(1, 8) { + let mut accounts = vec![]; + for _ in 0..rng.gen_range(1, 16) { + all_accounts.shuffle(&mut rng); + let pubkey = all_accounts[0]; + + accounts.push(AccountMeta { + pubkey, + is_writable: rng.gen(), + is_signer: rng.gen() && rng.gen(), + }); + } + + loader_owned_accounts.shuffle(&mut rng); + let program_id = loader_owned_accounts[0]; + instructions.push(Instruction { + accounts, + program_id, + data: vec![], + }); + } + + fee_payers.shuffle(&mut rng); + let fee_payer = fee_payers[0]; + let fee_payer_account = mock_bank.accounts_map.get(&fee_payer).cloned().unwrap(); + + let transaction = SanitizedTransaction::from_transaction_for_tests( + Transaction::new_with_payer(&instructions, Some(&fee_payer)), + ); + + let mut expected_size = 0; + let mut counted_programdatas = transaction + .account_keys() + .iter() + .copied() + .collect::>(); + + for pubkey in transaction.account_keys().iter() { + if let Some(account) = mock_bank.accounts_map.get(pubkey) { + expected_size += TRANSACTION_ACCOUNT_BASE_SIZE + account.data().len(); + }; + + if let Some((programdata_address, programdata_size)) = + programdata_tracker.get(pubkey) + { + if counted_programdatas.get(programdata_address).is_none() { + expected_size += TRANSACTION_ACCOUNT_BASE_SIZE + programdata_size; + counted_programdatas.insert(*programdata_address); + } + } + } + + assert!(expected_size <= MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES.get() as usize); + + let loaded_transaction_accounts = load_transaction_accounts( + &mut account_loader, + &transaction, + LoadedTransactionAccount { + loaded_size: TRANSACTION_ACCOUNT_BASE_SIZE + fee_payer_account.data().len(), + account: fee_payer_account, + rent_collected: 0, + }, + MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES, + &mut TransactionErrorMetrics::default(), + &RentCollector::default(), + ) + .unwrap(); + + assert_eq!( + loaded_transaction_accounts.loaded_accounts_data_size, + expected_size as u32, + ); + } + } } diff --git a/svm/src/message_processor.rs b/svm/src/message_processor.rs index 978aa735ce3f75..6d3b80e1173fc9 100644 --- a/svm/src/message_processor.rs +++ b/svm/src/message_processor.rs @@ -101,6 +101,7 @@ mod tests { use { super::*, agave_reserved_account_keys::ReservedAccountKeys, + ed25519_dalek::ed25519::signature::Signer, openssl::{ ec::{EcGroup, EcKey}, nid::Nid, @@ -110,7 +111,7 @@ mod tests { Account, AccountSharedData, ReadableAccount, WritableAccount, DUMMY_INHERITABLE_ACCOUNT_FIELDS, }, - solana_ed25519_program::new_ed25519_instruction, + solana_ed25519_program::new_ed25519_instruction_with_signature, solana_hash::Hash, solana_instruction::{error::InstructionError, AccountMeta, Instruction}, solana_message::{AccountKeys, Message, SanitizedMessage}, @@ -126,7 +127,7 @@ mod tests { solana_rent::Rent, solana_sdk_ids::{ed25519_program, native_loader, secp256k1_program, system_program}, solana_secp256k1_program::new_secp256k1_instruction, - solana_secp256r1_program::new_secp256r1_instruction, + solana_secp256r1_program::{new_secp256r1_instruction_with_signature, sign_message}, solana_svm_callback::InvokeContextCallback, solana_svm_feature_set::SVMFeatureSet, solana_transaction_context::TransactionContext, @@ -603,13 +604,25 @@ mod tests { fn ed25519_instruction_for_test() -> Instruction { let secret_key = ed25519_dalek::Keypair::generate(&mut thread_rng()); - new_ed25519_instruction(&secret_key, b"hello") + let signature = secret_key.sign(b"hello").to_bytes(); + let pubkey = secret_key.public.to_bytes(); + new_ed25519_instruction_with_signature(b"hello", &signature, &pubkey) } fn secp256r1_instruction_for_test() -> Instruction { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let secret_key = EcKey::generate(&group).unwrap(); - new_secp256r1_instruction(b"hello", secret_key).unwrap() + let signature = sign_message(b"hello", &secret_key.private_key_to_der().unwrap()).unwrap(); + let mut ctx = openssl::bn::BigNumContext::new().unwrap(); + let pubkey = secret_key + .public_key() + .to_bytes( + &group, + openssl::ec::PointConversionForm::COMPRESSED, + &mut ctx, + ) + .unwrap(); + new_secp256r1_instruction_with_signature(b"hello", &signature, &pubkey.try_into().unwrap()) } #[test] diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index 6e7c4229c74800..7d00785a6fa492 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -1099,7 +1099,10 @@ mod tests { use { super::*, crate::{ - account_loader::{LoadedTransactionAccount, ValidatedTransactionDetails}, + account_loader::{ + LoadedTransactionAccount, ValidatedTransactionDetails, + TRANSACTION_ACCOUNT_BASE_SIZE, + }, nonce_info::NonceInfo, rollback_accounts::RollbackAccounts, }, @@ -1147,7 +1150,7 @@ mod tests { } } - #[derive(Default, Clone)] + #[derive(Clone)] struct MockBankCallback { account_shared_data: Arc>>, #[allow(clippy::type_complexity)] @@ -1156,6 +1159,16 @@ mod tests { feature_set: SVMFeatureSet, } + impl Default for MockBankCallback { + fn default() -> Self { + Self { + account_shared_data: Arc::default(), + inspected_accounts: Arc::default(), + feature_set: SVMFeatureSet::all_enabled(), + } + } + } + impl InvokeContextCallback for MockBankCallback {} impl TransactionProcessingCallback for MockBankCallback { @@ -2036,8 +2049,11 @@ mod tests { assert_eq!(entry, Arc::new(program)); } - #[test] - fn test_validate_transaction_fee_payer_exact_balance() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_validate_transaction_fee_payer_exact_balance( + formalize_loaded_transaction_data_size: bool, + ) { let lamports_per_signature = 5000; let message = new_unchecked_sanitized_message(Message::new_with_blockhash( &[ @@ -2075,10 +2091,12 @@ mod tests { ); let mut mock_accounts = HashMap::new(); mock_accounts.insert(*fee_payer_address, fee_payer_account.clone()); - let mock_bank = MockBankCallback { + let mut mock_bank = MockBankCallback { account_shared_data: Arc::new(RwLock::new(mock_accounts)), ..Default::default() }; + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; let mut account_loader = (&mock_bank).into(); let mut error_counters = TransactionErrorMetrics::default(); @@ -2107,6 +2125,12 @@ mod tests { account }; + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + assert_eq!( result, Ok(ValidatedTransactionDetails { @@ -2122,7 +2146,7 @@ mod tests { .loaded_accounts_data_size_limit, fee_details: FeeDetails::new(transaction_fee, priority_fee), loaded_fee_payer_account: LoadedTransactionAccount { - loaded_size: fee_payer_account.data().len(), + loaded_size: base_account_size + fee_payer_account.data().len(), account: post_validation_fee_payer_account, rent_collected: fee_payer_rent_debit, }, @@ -2130,8 +2154,11 @@ mod tests { ); } - #[test] - fn test_validate_transaction_fee_payer_rent_paying() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_validate_transaction_fee_payer_rent_paying( + formalize_loaded_transaction_data_size: bool, + ) { let lamports_per_signature = 5000; let message = new_unchecked_sanitized_message(Message::new_with_blockhash( &[], @@ -2156,10 +2183,13 @@ mod tests { let mut mock_accounts = HashMap::new(); mock_accounts.insert(*fee_payer_address, fee_payer_account.clone()); - let mock_bank = MockBankCallback { + let mut mock_bank = MockBankCallback { account_shared_data: Arc::new(RwLock::new(mock_accounts)), ..Default::default() }; + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; + mock_bank.feature_set.disable_rent_fees_collection = false; let mut account_loader = (&mock_bank).into(); let mut error_counters = TransactionErrorMetrics::default(); @@ -2183,6 +2213,12 @@ mod tests { account }; + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + assert_eq!( result, Ok(ValidatedTransactionDetails { @@ -2198,7 +2234,7 @@ mod tests { .loaded_accounts_data_size_limit, fee_details: FeeDetails::new(transaction_fee, 0), loaded_fee_payer_account: LoadedTransactionAccount { - loaded_size: fee_payer_account.data().len(), + loaded_size: base_account_size + fee_payer_account.data().len(), account: post_validation_fee_payer_account, rent_collected: fee_payer_rent_debit, } @@ -2381,8 +2417,9 @@ mod tests { assert_eq!(result, Err(TransactionError::DuplicateInstruction(1u8))); } - #[test] - fn test_validate_transaction_fee_payer_is_nonce() { + #[test_case(false; "informal_loaded_size")] + #[test_case(true; "simd186_loaded_size")] + fn test_validate_transaction_fee_payer_is_nonce(formalize_loaded_transaction_data_size: bool) { let lamports_per_signature = 5000; let rent_collector = RentCollector::default(); let compute_unit_limit = 1000u64; @@ -2421,10 +2458,12 @@ mod tests { let mut mock_accounts = HashMap::new(); mock_accounts.insert(*fee_payer_address, fee_payer_account.clone()); - let mock_bank = MockBankCallback { + let mut mock_bank = MockBankCallback { account_shared_data: Arc::new(RwLock::new(mock_accounts)), ..Default::default() }; + mock_bank.feature_set.formalize_loaded_transaction_data_size = + formalize_loaded_transaction_data_size; let mut account_loader = (&mock_bank).into(); let mut error_counters = TransactionErrorMetrics::default(); @@ -2457,6 +2496,12 @@ mod tests { account }; + let base_account_size = if formalize_loaded_transaction_data_size { + TRANSACTION_ACCOUNT_BASE_SIZE + } else { + 0 + }; + assert_eq!( result, Ok(ValidatedTransactionDetails { @@ -2472,7 +2517,7 @@ mod tests { .loaded_accounts_data_size_limit, fee_details: FeeDetails::new(transaction_fee, priority_fee), loaded_fee_payer_account: LoadedTransactionAccount { - loaded_size: fee_payer_account.data().len(), + loaded_size: base_account_size + fee_payer_account.data().len(), account: post_validation_fee_payer_account, rent_collected: 0, } diff --git a/svm/tests/example-programs/clock-sysvar/Cargo.toml b/svm/tests/example-programs/clock-sysvar/Cargo.toml index dc7ebba713aeff..8d4456ec8fd278 100644 --- a/svm/tests/example-programs/clock-sysvar/Cargo.toml +++ b/svm/tests/example-programs/clock-sysvar/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "clock-sysvar-program" -version = "2.3.0" +version = "3.0.0" edition = "2021" [dependencies] -solana-program = { path = "../../../../sdk/program", version = "=2.2.0" } [lib] crate-type = ["cdylib", "rlib"] diff --git a/svm/tests/example-programs/clock-sysvar/src/lib.rs b/svm/tests/example-programs/clock-sysvar/src/lib.rs index 4907487d962c5b..16c161c3990a5d 100644 --- a/svm/tests/example-programs/clock-sysvar/src/lib.rs +++ b/svm/tests/example-programs/clock-sysvar/src/lib.rs @@ -1,6 +1,7 @@ -use solana_program::{ - account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey, - sysvar::{clock::Clock, Sysvar}, program::set_return_data +use { + solana_account_info::AccountInfo, solana_program_entrypoint::entrypoint, + solana_program_error::ProgramResult, solana_pubkey::Pubkey, + solana_sysvar::{clock::Clock, Sysvar}, solana_program::program::set_return_data }; entrypoint!(process_instruction); diff --git a/svm/tests/example-programs/hello-solana/Cargo.toml b/svm/tests/example-programs/hello-solana/Cargo.toml index b40de3b996b0c7..3a01690f137c39 100644 --- a/svm/tests/example-programs/hello-solana/Cargo.toml +++ b/svm/tests/example-programs/hello-solana/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "hello-solana-program" -version = "2.3.0" +version = "3.0.0" edition = "2021" [dependencies] -solana-program = { path = "../../../../sdk/program", version = "=2.2.0" } [lib] crate-type = ["cdylib", "rlib"] diff --git a/svm/tests/example-programs/hello-solana/src/lib.rs b/svm/tests/example-programs/hello-solana/src/lib.rs index 249179a6617b5d..e20aa92e545eee 100644 --- a/svm/tests/example-programs/hello-solana/src/lib.rs +++ b/svm/tests/example-programs/hello-solana/src/lib.rs @@ -1,5 +1,9 @@ -use solana_program::{ - account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey, +use { + solana_account_info::AccountInfo, + solana_program_entrypoint::entrypoint, + solana_program_error::ProgramResult, + solana_msg::msg, + solana_pubkey::Pubkey, }; entrypoint!(process_instruction); diff --git a/svm/tests/example-programs/simple-transfer/Cargo.toml b/svm/tests/example-programs/simple-transfer/Cargo.toml index 58446dec814fe8..73a40bc89561fa 100644 --- a/svm/tests/example-programs/simple-transfer/Cargo.toml +++ b/svm/tests/example-programs/simple-transfer/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "simple-transfer-program" -version = "2.3.0" +version = "3.0.0" edition = "2021" [dependencies] -solana-program = { path = "../../../../sdk/program", version = "=2.2.0" } [lib] crate-type = ["cdylib", "rlib"] diff --git a/svm/tests/example-programs/simple-transfer/src/lib.rs b/svm/tests/example-programs/simple-transfer/src/lib.rs index dc82f8d83330e5..e9f624c7f2a3f5 100644 --- a/svm/tests/example-programs/simple-transfer/src/lib.rs +++ b/svm/tests/example-programs/simple-transfer/src/lib.rs @@ -1,6 +1,10 @@ -use solana_program::{ - account_info::{AccountInfo, next_account_info}, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey, - program::invoke, system_instruction, +use { + solana_account_info::{AccountInfo, next_account_info}, + solana_program_entrypoint::entrypoint, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, + solana_program::program::invoke, + solana_system_interface::instruction as system_instruction, }; entrypoint!(process_instruction); diff --git a/svm/tests/example-programs/transfer-from-account/Cargo.toml b/svm/tests/example-programs/transfer-from-account/Cargo.toml index 1e7bd9da8b525f..ec14dca501a30e 100644 --- a/svm/tests/example-programs/transfer-from-account/Cargo.toml +++ b/svm/tests/example-programs/transfer-from-account/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "transfer-from-account" -version = "2.3.0" +version = "3.0.0" edition = "2021" [dependencies] -solana-program = { path = "../../../../sdk/program", version = "=2.2.0" } [lib] crate-type = ["cdylib", "rlib"] diff --git a/svm/tests/example-programs/transfer-from-account/src/lib.rs b/svm/tests/example-programs/transfer-from-account/src/lib.rs index 08494a13ce0395..4cf5eb99494987 100644 --- a/svm/tests/example-programs/transfer-from-account/src/lib.rs +++ b/svm/tests/example-programs/transfer-from-account/src/lib.rs @@ -1,6 +1,10 @@ -use solana_program::{ - account_info::{AccountInfo, next_account_info}, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey, - program::invoke, system_instruction, +use { + solana_account_info::{AccountInfo, next_account_info}, + solana_program_entrypoint::entrypoint, + solana_program_error::ProgramResult, + solana_pubkey::Pubkey, + solana_program::program::invoke, + solana_system_interface::instruction as system_instruction, }; entrypoint!(process_instruction); diff --git a/svm/tests/example-programs/write-to-account/Cargo.toml b/svm/tests/example-programs/write-to-account/Cargo.toml index 87baecef2e6610..428e8441916c17 100644 --- a/svm/tests/example-programs/write-to-account/Cargo.toml +++ b/svm/tests/example-programs/write-to-account/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "write-to-account" -version = "2.3.0" +version = "3.0.0" edition = "2021" [dependencies] -solana-program = { path = "../../../../sdk/program", version = "=2.2.0" } [lib] crate-type = ["cdylib", "rlib"] diff --git a/svm/tests/example-programs/write-to-account/src/lib.rs b/svm/tests/example-programs/write-to-account/src/lib.rs index bb7e6065547336..bcaa7a45411a4c 100644 --- a/svm/tests/example-programs/write-to-account/src/lib.rs +++ b/svm/tests/example-programs/write-to-account/src/lib.rs @@ -1,10 +1,10 @@ -use solana_program::{ - account_info::{next_account_info, AccountInfo}, - entrypoint, - entrypoint::ProgramResult, - incinerator, msg, - program_error::ProgramError, - pubkey::Pubkey, +use { + solana_account_info::{next_account_info, AccountInfo}, + solana_program_entrypoint::entrypoint, + solana_program_error::ProgramResult, + solana_sdk_ids::incinerator, solana_msg::msg, + solana_program_error::ProgramError, + solana_pubkey::Pubkey, }; entrypoint!(process_instruction); @@ -50,7 +50,7 @@ fn process_instruction( // reallocate account 3 => { let new_size = usize::from_le_bytes(data[1..9].try_into().unwrap()); - target_account_info.realloc(new_size, false)?; + target_account_info.realloc(new_size, true)?; } // bad ixn _ => { diff --git a/svm/tests/integration_test.rs b/svm/tests/integration_test.rs index d0eae11f560c3f..80768774e7624f 100644 --- a/svm/tests/integration_test.rs +++ b/svm/tests/integration_test.rs @@ -4,8 +4,8 @@ use { crate::mock_bank::{ create_custom_loader, deploy_program_with_upgrade_authority, program_address, - register_builtins, MockBankCallback, MockForkGraph, EXECUTION_EPOCH, EXECUTION_SLOT, - WALLCLOCK_TIME, + program_data_size, register_builtins, MockBankCallback, MockForkGraph, EXECUTION_EPOCH, + EXECUTION_SLOT, WALLCLOCK_TIME, }, agave_feature_set::{self as feature_set, FeatureSet}, solana_account::{AccountSharedData, ReadableAccount, WritableAccount, PROGRAM_OWNERS}, @@ -2193,14 +2193,20 @@ fn simd83_fee_payer_deallocate() -> Vec { vec![test_entry] } -fn simd83_account_reallocate() -> Vec { +fn simd83_account_reallocate(formalize_loaded_transaction_data_size: bool) -> Vec { let mut test_entries = vec![]; let program_name = "write-to-account"; let program_id = program_address(program_name); + let program_size = program_data_size(program_name); let mut common_test_entry = SvmTestEntry::default(); common_test_entry.add_initial_program(program_name); + if !formalize_loaded_transaction_data_size { + common_test_entry + .disabled_features + .push(feature_set::formalize_loaded_transaction_data_size::id()); + } let fee_payer_keypair = Keypair::new(); let fee_payer = fee_payer_keypair.pubkey(); @@ -2223,11 +2229,20 @@ fn simd83_account_reallocate() -> Vec { let target_start_size = 100; common_test_entry.add_initial_account(target, &mk_target(target_start_size)); + // we set a budget that is enough pre-large-realloc but not enough post-large-realloc + // the relevant feature counts programdata size, so if enabled, we add breathing room + // this test has nothing to do with the feature + let size_budget = Some(if formalize_loaded_transaction_data_size { + (program_size + MAX_PERMITTED_DATA_INCREASE) as u32 + } else { + MAX_PERMITTED_DATA_INCREASE as u32 + }); + let print_transaction = WriteProgramInstruction::Print.create_transaction( program_id, &fee_payer_keypair, target, - Some(MAX_PERMITTED_DATA_INCREASE.try_into().unwrap()), + size_budget, ); common_test_entry.decrease_expected_lamports(&fee_payer, LAMPORTS_PER_SIGNATURE * 2); @@ -2338,7 +2353,8 @@ fn program_cache_update_tombstone() -> Vec { #[test_case(simd83_nonce_reuse(true))] #[test_case(simd83_account_deallocate())] #[test_case(simd83_fee_payer_deallocate())] -#[test_case(simd83_account_reallocate())] +#[test_case(simd83_account_reallocate(false))] +#[test_case(simd83_account_reallocate(true))] #[test_case(program_cache_update_tombstone())] fn svm_integration(test_entries: Vec) { for test_entry in test_entries { diff --git a/test-validator/Cargo.toml b/test-validator/Cargo.toml index d9264d2fff9bd8..513445e3a3ef66 100644 --- a/test-validator/Cargo.toml +++ b/test-validator/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] agave-feature-set = { workspace = true } base64 = { workspace = true } @@ -54,6 +57,3 @@ tokio = { workspace = true, features = ["full"] } [dev-dependencies] solana-sdk-ids = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/test-validator/src/lib.rs b/test-validator/src/lib.rs index 71c0bee1e5aea7..46ada12caa809f 100644 --- a/test-validator/src/lib.rs +++ b/test-validator/src/lib.rs @@ -50,6 +50,7 @@ use { runtime_config::RuntimeConfig, snapshot_config::SnapshotConfig, }, + solana_sdk_ids::address_lookup_table, solana_signer::Signer, solana_streamer::socket::SocketAddrSpace, solana_tpu_client::tpu_client::DEFAULT_TPU_ENABLE_UDP, @@ -372,6 +373,55 @@ impl TestValidatorGenesis { ) } + pub fn deep_clone_address_lookup_table_accounts( + &mut self, + addresses: T, + rpc_client: &RpcClient, + ) -> Result<&mut Self, String> + where + T: IntoIterator, + { + const LOOKUP_TABLE_META_SIZE: usize = 56; + let addresses: Vec = addresses.into_iter().collect(); + let mut alt_entries: Vec = Vec::new(); + + for chunk in addresses.chunks(MAX_MULTIPLE_ACCOUNTS) { + info!("Fetching {:?} over RPC...", chunk); + let responses = rpc_client + .get_multiple_accounts(chunk) + .map_err(|err| format!("Failed to fetch: {err}"))?; + for (address, res) in chunk.iter().zip(responses) { + if let Some(account) = res { + if address_lookup_table::check_id(account.owner()) { + let raw_addresses_data = account + .data() + .get(LOOKUP_TABLE_META_SIZE..) + .ok_or(format!("Failed to get addresses data from {address}"))?; + + if raw_addresses_data.len() % std::mem::size_of::() != 0 { + return Err(format!("Invalid alt account data length for {address}")); + } + + for address_slice in + raw_addresses_data.chunks_exact(std::mem::size_of::()) + { + // safe because size was checked earlier + let address = Pubkey::try_from(address_slice).unwrap(); + alt_entries.push(address); + } + self.add_account(*address, AccountSharedData::from(account)); + } else { + return Err(format!("Account {address} is not an address lookup table")); + } + } else { + return Err(format!("Failed to fetch {address}")); + } + } + } + + self.clone_accounts(alt_entries, rpc_client, true) + } + pub fn clone_programdata_accounts( &mut self, addresses: T, @@ -1194,7 +1244,7 @@ mod test { rpc_client.get_health().expect("health"); } - #[tokio::test] + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn nonblocking_get_health() { let (test_validator, _payer) = TestValidatorGenesis::default().start_async().await; test_validator.set_startup_verification_complete_for_tests(); @@ -1202,14 +1252,14 @@ mod test { rpc_client.get_health().await.expect("health"); } - #[tokio::test] + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[should_panic] async fn document_tokio_panic() { // `start()` blows up when run within tokio let (_test_validator, _payer) = TestValidatorGenesis::default().start(); } - #[tokio::test] + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_deactivate_features() { let mut control = FeatureSet::default().inactive().clone(); let mut deactivate_features = Vec::new(); @@ -1253,7 +1303,7 @@ mod test { } } - #[tokio::test] + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_override_feature_account() { let with_deactivate_flag = agave_feature_set::deprecate_rewards_sysvar::id(); let without_deactivate_flag = agave_feature_set::disable_fees_sysvar::id(); @@ -1291,7 +1341,7 @@ mod test { assert!(feature_state.activated_at.is_some()); } - #[tokio::test] + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_core_bpf_programs() { let (test_validator, _payer) = TestValidatorGenesis::default() .deactivate_features(&[ diff --git a/thin-client/Cargo.toml b/thin-client/Cargo.toml index ef982440b26e0f..b3b5e0eaca9391 100644 --- a/thin-client/Cargo.toml +++ b/thin-client/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] bincode = { workspace = true } log = { workspace = true } @@ -34,6 +37,3 @@ solana-transaction-error = { workspace = true } [dev-dependencies] solana-logger = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/thread-manager/Cargo.toml b/thread-manager/Cargo.toml index 195bb4203e5e3a..1482012b578bfd 100644 --- a/thread-manager/Cargo.toml +++ b/thread-manager/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +dev-context-only-utils = [] + [dependencies] anyhow = { workspace = true } cfg-if = { workspace = true } @@ -31,6 +34,3 @@ hyper = { workspace = true, features = ["http1", "client", "stream", "tcp"] } serde_json = { workspace = true } toml = { workspace = true } tower = { workspace = true } - -[features] -dev-context-only-utils = [] diff --git a/timings/Cargo.toml b/timings/Cargo.toml index 2f16de53426f30..5d66b66cde6b6f 100644 --- a/timings/Cargo.toml +++ b/timings/Cargo.toml @@ -9,10 +9,10 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] eager = { workspace = true } enum-iterator = { workspace = true } solana-pubkey = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/tps-client/Cargo.toml b/tps-client/Cargo.toml index b27f0d19e4ab35..201ede15561bc3 100644 --- a/tps-client/Cargo.toml +++ b/tps-client/Cargo.toml @@ -8,6 +8,14 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + +[features] +bank-client = ["dep:solana-client-traits", "dep:solana-runtime"] + [dependencies] log = { workspace = true } solana-account = { workspace = true } @@ -37,11 +45,3 @@ thiserror = { workspace = true } [dev-dependencies] solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } tempfile = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] -all-features = true -rustdoc-args = ["--cfg=docsrs"] - -[features] -bank-client = ["dep:solana-client-traits", "dep:solana-runtime"] diff --git a/tpu-client-next/Cargo.toml b/tpu-client-next/Cargo.toml index d5c922acc966aa..d2d2bdc459d635 100644 --- a/tpu-client-next/Cargo.toml +++ b/tpu-client-next/Cargo.toml @@ -8,6 +8,12 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +metrics = ["dep:solana-metrics"] + [dependencies] async-trait = { workspace = true } log = { workspace = true } @@ -18,7 +24,7 @@ solana-clock = { workspace = true } solana-connection-cache = { workspace = true } solana-keypair = { workspace = true } solana-measure = { workspace = true } -solana-metrics ={ workspace = true, optional = true } +solana-metrics = { workspace = true, optional = true } solana-quic-definitions = { workspace = true } solana-rpc-client = { workspace = true } solana-streamer = { workspace = true } @@ -38,9 +44,3 @@ solana-net-utils = { workspace = true } solana-pubkey = { workspace = true } solana-signer = { workspace = true } solana-streamer = { workspace = true, features = ["dev-context-only-utils"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -metrics =["dep:solana-metrics"] diff --git a/tpu-client/Cargo.toml b/tpu-client/Cargo.toml index 846c7207dee587..96fdc2f26288a2 100644 --- a/tpu-client/Cargo.toml +++ b/tpu-client/Cargo.toml @@ -9,6 +9,19 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[features] +default = ["spinner"] +# Support tpu-client methods that feature a spinner progress bar for +# command-line interfaces +spinner = [ + "dep:indicatif", + "dep:solana-message", + "solana-rpc-client/spinner", +] + [dependencies] async-trait = { workspace = true } bincode = { workspace = true } @@ -36,16 +49,3 @@ solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } - -[features] -default = ["spinner"] -# Support tpu-client methods that feature a spinner progress bar for -# command-line interfaces -spinner = [ - "dep:indicatif", - "dep:solana-message", - "solana-rpc-client/spinner" -] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/transaction-context/Cargo.toml b/transaction-context/Cargo.toml index 790c93c7f555c5..9a76f58ae22c17 100644 --- a/transaction-context/Cargo.toml +++ b/transaction-context/Cargo.toml @@ -9,6 +9,21 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] +all-features = true +rustdoc-args = ["--cfg=docsrs"] + +[features] +bincode = ["dep:bincode", "serde", "solana-account/bincode"] +debug-signature = ["dep:solana-signature"] +dev-context-only-utils = [ + "bincode", + "debug-signature", + "solana-account/dev-context-only-utils", +] +serde = ["dep:serde", "dep:serde_derive"] + [dependencies] serde = { workspace = true, optional = true } serde_derive = { workspace = true, optional = true } @@ -17,11 +32,6 @@ solana-instruction = { workspace = true, features = ["std"] } solana-instructions-sysvar = { workspace = true } solana-pubkey = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] -all-features = true -rustdoc-args = ["--cfg=docsrs"] - [target.'cfg(not(target_os = "solana"))'.dependencies] bincode = { workspace = true, optional = true } solana-rent = { workspace = true } @@ -36,15 +46,5 @@ solana-transaction-context = { path = ".", features = [ ] } static_assertions = { workspace = true } -[features] -bincode = ["dep:bincode", "serde", "solana-account/bincode"] -debug-signature = ["dep:solana-signature"] -dev-context-only-utils = [ - "bincode", - "debug-signature", - "solana-account/dev-context-only-utils" -] -serde = ["dep:serde", "dep:serde_derive"] - [lints] workspace = true diff --git a/transaction-dos/Cargo.toml b/transaction-dos/Cargo.toml index efc1affdbb6595..dae57acdd5fcdb 100644 --- a/transaction-dos/Cargo.toml +++ b/transaction-dos/Cargo.toml @@ -8,6 +8,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] bincode = { workspace = true } clap = { workspace = true } @@ -43,6 +46,3 @@ solana-hash = { workspace = true } solana-local-cluster = { workspace = true } solana-poh-config = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/transaction-metrics-tracker/Cargo.toml b/transaction-metrics-tracker/Cargo.toml index e52c64c3f81dc3..74c897122a38dd 100644 --- a/transaction-metrics-tracker/Cargo.toml +++ b/transaction-metrics-tracker/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] base64 = { workspace = true } bincode = { workspace = true } @@ -27,6 +30,3 @@ solana-packet = { workspace = true, features = ["dev-context-only-utils"] } solana-perf = { workspace = true, features = ["dev-context-only-utils"] } solana-pubkey = { workspace = true, features = ["rand"] } solana-system-transaction = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/transaction-status-client-types/Cargo.toml b/transaction-status-client-types/Cargo.toml index 7c1fec2a45b2b9..d67ad700d692c4 100644 --- a/transaction-status-client-types/Cargo.toml +++ b/transaction-status-client-types/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] base64 = { workspace = true } bincode = { workspace = true } @@ -25,6 +28,3 @@ solana-transaction = { workspace = true, features = ["serde"] } solana-transaction-context = { workspace = true } solana-transaction-error = { workspace = true, features = ["serde"] } thiserror = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/transaction-status/Cargo.toml b/transaction-status/Cargo.toml index cbac0c960a9c1b..129f547db604b1 100644 --- a/transaction-status/Cargo.toml +++ b/transaction-status/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] Inflector = { workspace = true } agave-reserved-account-keys = { workspace = true } @@ -51,6 +54,3 @@ thiserror = { workspace = true } bytemuck = { workspace = true } solana-pubkey = { workspace = true, features = ["rand"] } spl-token-confidential-transfer-proof-extraction = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/transaction-status/src/lib.rs b/transaction-status/src/lib.rs index 84e8a75fbefabb..449fe355f6f6d4 100644 --- a/transaction-status/src/lib.rs +++ b/transaction-status/src/lib.rs @@ -26,6 +26,7 @@ use { base64::{prelude::BASE64_STANDARD, Engine}, solana_clock::{Slot, UnixTimestamp}, solana_hash::Hash, + solana_instruction::TRANSACTION_LEVEL_STACK_HEIGHT, solana_message::{ compiled_instruction::CompiledInstruction, v0::{self, LoadedAddresses, LoadedMessage}, @@ -741,7 +742,13 @@ impl Encodable for Message { instructions: self .instructions .iter() - .map(|instruction| parse_ui_instruction(instruction, &account_keys, None)) + .map(|instruction| { + parse_ui_instruction( + instruction, + &account_keys, + Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32), + ) + }) .collect(), address_table_lookups: None, }) @@ -753,7 +760,9 @@ impl Encodable for Message { instructions: self .instructions .iter() - .map(|ix| UiCompiledInstruction::from(ix, None)) + .map(|ix| { + UiCompiledInstruction::from(ix, Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32)) + }) .collect(), address_table_lookups: None, }) @@ -775,7 +784,13 @@ impl Encodable for v0::Message { instructions: self .instructions .iter() - .map(|instruction| parse_ui_instruction(instruction, &account_keys, None)) + .map(|instruction| { + parse_ui_instruction( + instruction, + &account_keys, + Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32), + ) + }) .collect(), address_table_lookups: None, }) @@ -787,7 +802,9 @@ impl Encodable for v0::Message { instructions: self .instructions .iter() - .map(|ix| UiCompiledInstruction::from(ix, None)) + .map(|ix| { + UiCompiledInstruction::from(ix, Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32)) + }) .collect(), address_table_lookups: None, }) @@ -816,7 +833,13 @@ impl EncodableWithMeta for v0::Message { instructions: self .instructions .iter() - .map(|instruction| parse_ui_instruction(instruction, &account_keys, None)) + .map(|instruction| { + parse_ui_instruction( + instruction, + &account_keys, + Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32), + ) + }) .collect(), address_table_lookups: Some( self.address_table_lookups.iter().map(Into::into).collect(), @@ -834,7 +857,9 @@ impl EncodableWithMeta for v0::Message { instructions: self .instructions .iter() - .map(|ix| UiCompiledInstruction::from(ix, None)) + .map(|ix| { + UiCompiledInstruction::from(ix, Some(TRANSACTION_LEVEL_STACK_HEIGHT as u32)) + }) .collect(), address_table_lookups: Some( self.address_table_lookups.iter().map(Into::into).collect(), diff --git a/transaction-view/Cargo.toml b/transaction-view/Cargo.toml index 575e2022139d50..256136558ea661 100644 --- a/transaction-view/Cargo.toml +++ b/transaction-view/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +dev-context-only-utils = [] + [dependencies] solana-hash = { workspace = true } solana-message = { workspace = true } @@ -32,9 +35,6 @@ solana-signer = { workspace = true } solana-system-interface = { workspace = true, features = ["bincode"] } solana-transaction = { workspace = true, features = ["bincode"] } -[features] -dev-context-only-utils = [] - [[bench]] name = "bytes" harness = false diff --git a/transaction-view/src/resolved_transaction_view.rs b/transaction-view/src/resolved_transaction_view.rs index 057991fabbdf21..584c95c9a4be6e 100644 --- a/transaction-view/src/resolved_transaction_view.rs +++ b/transaction-view/src/resolved_transaction_view.rs @@ -149,6 +149,10 @@ impl ResolvedTransactionView { pub fn loaded_addresses(&self) -> Option<&LoadedAddresses> { self.resolved_addresses.as_ref() } + + pub fn into_view(self) -> TransactionView { + self.view + } } impl SVMMessage for ResolvedTransactionView { diff --git a/transaction-view/src/transaction_view.rs b/transaction-view/src/transaction_view.rs index 21c91d029c7980..f15db6b95a9a9d 100644 --- a/transaction-view/src/transaction_view.rs +++ b/transaction-view/src/transaction_view.rs @@ -166,6 +166,11 @@ impl TransactionView { pub fn message_data(&self) -> &[u8] { &self.data()[usize::from(self.frame.message_offset())..] } + + #[inline] + pub fn into_inner_data(self) -> D { + self.data + } } // Implementation that relies on sanitization checks having been run. diff --git a/turbine/src/retransmit_stage.rs b/turbine/src/retransmit_stage.rs index a3bedb2f9ecdad..c972daeae49e53 100644 --- a/turbine/src/retransmit_stage.rs +++ b/turbine/src/retransmit_stage.rs @@ -219,6 +219,9 @@ enum RetransmitSocket<'a> { Xdp(&'a XdpSender), } +/// The number of shreds to pull from the retransmit_receiver at a time. +const RETRANSMIT_BATCH_SIZE: usize = 4096; + // pull the shreds from the shreds_receiver until empty, then retransmit them. // uses a thread_pool to parallelize work if there are enough shreds to justify that #[allow(clippy::too_many_arguments)] @@ -238,12 +241,15 @@ fn retransmit( max_slots: &MaxSlots, rpc_subscriptions: Option<&RpcSubscriptions>, slot_status_notifier: Option<&SlotStatusNotifier>, + shred_buf: &mut Vec>, ) -> Result<(), RecvError> { // Try to receive shreds from the channel without blocking. If the channel // is empty precompute turbine trees speculatively. If no cache updates are // made then block on the channel until some shreds are received. - let mut shreds = match retransmit_receiver.try_recv() { - Ok(shreds) => shreds, + match retransmit_receiver.try_recv() { + Ok(shreds) => { + shred_buf.push(shreds); + } Err(TryRecvError::Disconnected) => return Err(RecvError), Err(TryRecvError::Empty) => { if cache_retransmit_addrs( @@ -256,14 +262,23 @@ fn retransmit( ) { return Ok(()); } - retransmit_receiver.recv()? + shred_buf.push(retransmit_receiver.recv()?); } }; // now the batch has started let mut timer_start = Measure::start("retransmit"); - // drain the channel until it is empty to form a batch - shreds.extend(retransmit_receiver.try_iter().flatten()); - stats.num_shreds += shreds.len(); + let mut num_shreds = shred_buf[0].len(); + // Create a RETRANSMIT_BATCH_SIZE sized batch from the channel + for shreds in retransmit_receiver + .try_iter() + // We already pulled 1 batch + .take(RETRANSMIT_BATCH_SIZE - 1) + { + num_shreds += shreds.len(); + shred_buf.push(shreds); + } + + stats.num_shreds += num_shreds; stats.total_batches += 1; let mut epoch_fetch = Measure::start("retransmit_epoch_fetch"); @@ -283,8 +298,9 @@ fn retransmit( epoch_cache_update.stop(); stats.epoch_cache_update += epoch_cache_update.as_us(); // Lookup slot leader and cluster nodes for each slot. - let cache: HashMap = shreds + let cache: HashMap = shred_buf .iter() + .flatten() .filter_map(|shred| shred::layout::get_slot(shred)) .collect::>() .into_iter() @@ -297,7 +313,7 @@ fn retransmit( // skip the shred. let Some(slot_leader) = leader_schedule_cache.slot_leader_at(slot, Some(&working_bank)) else { - stats.unknown_shred_slot_leader += shreds.len(); + stats.unknown_shred_slot_leader += num_shreds; return None; }; let cluster_nodes = @@ -333,17 +349,19 @@ fn retransmit( socket }; - let slot_stats = if shreds.len() < PAR_ITER_MIN_NUM_SHREDS { + let slot_stats = if num_shreds < PAR_ITER_MIN_NUM_SHREDS { stats.num_small_batches += 1; - shreds - .into_iter() + shred_buf + .drain(..) + .flatten() .enumerate() .filter_map(|(index, shred)| retransmit_shred(shred, retransmit_socket(index), stats)) .fold(HashMap::new(), record) } else { thread_pool.install(|| { - shreds - .into_par_iter() + shred_buf + .par_drain(..) + .flatten() .filter_map(|shred| { retransmit_shred( shred, @@ -604,6 +622,7 @@ impl RetransmitStage { .name("solRetransmittr".to_string()) .spawn({ move || { + let mut shred_buf = Vec::with_capacity(RETRANSMIT_BATCH_SIZE); while retransmit( &thread_pool, &bank_forks, @@ -620,6 +639,7 @@ impl RetransmitStage { &max_slots, rpc_subscriptions.as_deref(), slot_status_notifier.as_ref(), + &mut shred_buf, ) .is_ok() {} diff --git a/type-overrides/Cargo.toml b/type-overrides/Cargo.toml index c0378bebbd9013..8acf34abdfc1a7 100644 --- a/type-overrides/Cargo.toml +++ b/type-overrides/Cargo.toml @@ -8,11 +8,11 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +shuttle-test = ["dep:shuttle"] +executor = ["dep:futures"] + [dependencies] futures = { workspace = true, optional = true } rand = { workspace = true } shuttle = { workspace = true, optional = true } - -[features] -shuttle-test = ["dep:shuttle"] -executor = ["dep:futures"] diff --git a/unified-scheduler-logic/src/lib.rs b/unified-scheduler-logic/src/lib.rs index d479bd46a2a426..48765a604d872e 100644 --- a/unified-scheduler-logic/src/lib.rs +++ b/unified-scheduler-logic/src/lib.rs @@ -927,13 +927,15 @@ impl SchedulingStateMachine { /// Rewind the inactive state machine to be initialized /// /// This isn't called _reset_ to indicate this isn't safe to call this at any given moment. - /// This panics if the state machine hasn't properly been finished (i.e. there should be no + /// This panics if the state machine hasn't properly been finished (i.e. there should be no /// active task) to uphold invariants of [`UsageQueue`]s. /// /// This method is intended to reuse SchedulingStateMachine instance (to avoid its `unsafe` /// [constructor](SchedulingStateMachine::exclusively_initialize_current_thread_for_scheduling) /// as much as possible) and its (possibly cached) associated [`UsageQueue`]s for processing /// other slots. + /// + /// There's a related method called [`clear_and_reinitialize()`](Self::clear_and_reinitialize). pub fn reinitialize(&mut self) { assert!(self.has_no_active_task()); assert_eq!(self.running_task_count.current(), 0); @@ -957,6 +959,39 @@ impl SchedulingStateMachine { total_task_count.reset_to_zero(); } + /// Clear all buffered tasks and immediately rewind the state machine to be initialized + /// + /// This method _may_ panic if there are tasks which has been scheduled but hasn't been + /// descheduled yet (called active tasks). This is due to the invocation of + /// [`reinitialize()`](Self::reinitialize) at last. On the other hand, it's guaranteed not to + /// panic otherwise. That's because the first clearing step effectively relaxes the runtime + /// invariant of `reinitialize()` by making the state machine _inactive_ beforehand. After a + /// successful operation, this method returns the number of cleared tasks. + /// + /// Somewhat surprisingly, the clearing logic is same as the normal (de-)scheduling operation + /// because it is still the fastest way to just clear all tasks, under the consideration of + /// potential later use of [`UsageQueue`]s. That's because `state_machine` doesn't maintain _the + /// global list_ of tasks. Maintaining such one would incur a needless overhead on scheduling, + /// which isn't strictly needed otherwise. + /// + /// Moreover, the descheduling operation is rather heavily optimized to begin with. All + /// collection ops are just O(1) over total N of addresses accessed by all active tasks with + /// no amortized mem ops. + /// + /// Whatever the algorithm is chosen, the ultimate goal of this operation is to clear all usage + /// queues. Toward to that end, one may create a temporary hash set over [`UsageQueue`]s on the + /// fly alternatively. However, that would be costlier than the above usual descheduling + /// approach due to extra mem ops and many lookups/insertions. + pub fn clear_and_reinitialize(&mut self) -> usize { + let mut count = ShortCounter::zero(); + while let Some(task) = self.schedule_next_unblocked_task() { + self.deschedule_task(&task); + count.increment_self(); + } + self.reinitialize(); + count.current().try_into().unwrap() + } + /// Creates a new instance of [`SchedulingStateMachine`] with its `unsafe` fields created as /// well, thus carrying over `unsafe`. /// diff --git a/unified-scheduler-pool/Cargo.toml b/unified-scheduler-pool/Cargo.toml index 478afcf5caa339..179b422d5580fe 100644 --- a/unified-scheduler-pool/Cargo.toml +++ b/unified-scheduler-pool/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[features] +dev-context-only-utils = [] + [dependencies] agave-banking-stage-ingress-types = { workspace = true } aquamarine = { workspace = true } @@ -48,6 +51,3 @@ solana-logger = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-system-transaction = { workspace = true } test-case = { workspace = true } - -[features] -dev-context-only-utils = [] diff --git a/unified-scheduler-pool/src/lib.rs b/unified-scheduler-pool/src/lib.rs index 38b8c6981ae407..85071cf3aded59 100644 --- a/unified-scheduler-pool/src/lib.rs +++ b/unified-scheduler-pool/src/lib.rs @@ -85,6 +85,8 @@ enum CheckPoint<'a> { IdleSchedulerCleaned(usize), TrashedSchedulerCleaned(usize), TimeoutListenerTriggered(usize), + DiscardRequested, + Discarded(usize), } type CountOrDefault = Option; @@ -171,6 +173,13 @@ impl, TH: TaskHandler> BlockProductionSchedulerInner Option<&S::Inner> { + match self { + Self::NotSpawned | Self::Taken(_) => None, + Self::Pooled(inner) => Some(inner), + } + } + fn take_pooled(&mut self) -> S::Inner { let id = { let Self::Pooled(inner) = &self else { @@ -250,6 +259,7 @@ struct BankingStageHandlerContext { #[debug("{banking_packet_handler:p}")] banking_packet_handler: Box, transaction_recorder: TransactionRecorder, + banking_stage_monitor: Box, } trait_set! { @@ -419,6 +429,8 @@ where idle_inner_count }; + let banking_stage_status = scheduler_pool.banking_stage_status(); + let trashed_inner_count = { let Ok(mut trashed_scheduler_inners) = scheduler_pool.trashed_scheduler_inners.lock() @@ -457,6 +469,22 @@ where count }; + if matches!(banking_stage_status, Some(BankingStageStatus::Inactive)) { + let inner = scheduler_pool + .block_production_scheduler_inner + .lock() + .unwrap(); + if let Some(pooled) = inner.peek_pooled() { + pooled.discard_buffer(); + // Prevent replay stage's OpenSubchannel from winning the race by holding + // the inner lock for the duration of discard message sending just above. + // The message (internally SubchanneledPayload::Reset) must be sent only + // during gaps of subchannels of the new task channel. + sleepless_testing::at(CheckPoint::DiscardRequested); + drop(inner); + } + } + info!( "Scheduler pool cleaner: dropped {} idle inners, {} trashed inners, triggered {} timeout listeners", idle_inner_count, trashed_inner_count, triggered_timeout_listener_count, @@ -603,12 +631,14 @@ where banking_packet_receiver: BankingPacketReceiver, banking_packet_handler: Box, transaction_recorder: TransactionRecorder, + banking_stage_monitor: Box, ) { *self.banking_stage_handler_context.lock().unwrap() = Some(BankingStageHandlerContext { banking_thread_count, banking_packet_receiver, banking_packet_handler, transaction_recorder, + banking_stage_monitor, }); // Immediately start a block production scheduler, so that the scheduler can start // buffering tasks, which are preprocessed as much as possible. @@ -617,6 +647,14 @@ where ); } + fn banking_stage_status(&self) -> Option { + self.banking_stage_handler_context + .lock() + .unwrap() + .as_mut() + .map(|respawner| respawner.banking_stage_monitor.status()) + } + fn create_handler_context( &self, mode: SchedulingMode, @@ -918,6 +956,7 @@ enum SubchanneledPayload { OpenSubchannel(P2), UnpauseOpenedSubchannel, CloseSubchannel, + Reset, } type NewTaskPayload = SubchanneledPayload>; @@ -1749,6 +1788,7 @@ impl, TH: TaskHandler> ThreadManager { Ok( NewTaskPayload::OpenSubchannel(_) | NewTaskPayload::UnpauseOpenedSubchannel + | NewTaskPayload::Reset ) => unreachable!(), Err(RecvError) => { // Mostly likely is that this scheduler is dropped for pruned blocks of @@ -1804,7 +1844,20 @@ impl, TH: TaskHandler> ThreadManager { // session_result_sender just above let mut new_result_with_timings = None; + let mut discard_on_reset = false; loop { + if discard_on_reset { + discard_on_reset = false; + // Gracefully clear all buffered tasks to discard all outstanding stale + // tasks; we're not aborting scheduler here. So, `state_machine` needs + // to be reusable after this. + // + // As for panic safety of .clear_and_reinitialize(), it's safe because + // there should be _no scheduled tasks (i.e. owned by us, not by + // state_machine) on the call stack by now. + let count = state_machine.clear_and_reinitialize(); + sleepless_testing::at(CheckPoint::Discarded(count)); + } // Prepare for the new session. match new_task_receiver.recv() { Ok(NewTaskPayload::Payload(task)) => { @@ -1849,6 +1902,10 @@ impl, TH: TaskHandler> ThreadManager { // or abort is hinted from task results, before explicit // session ending is sent from the poh or the replay thread. } + Ok(NewTaskPayload::Reset) => { + assert_matches!(scheduling_mode, BlockProduction); + discard_on_reset = true; + } Err(RecvError) => { // This unusual condition must be triggered by ThreadManager::drop(). // Initialize result_with_timings with a harmless value... @@ -2128,6 +2185,10 @@ impl, TH: TaskHandler> ThreadManager { .expect("no new session after aborted"); } + fn discard_buffered_tasks(&self) { + self.new_task_sender.send(NewTaskPayload::Reset).unwrap(); + } + fn disconnect_new_task_sender(&mut self) { self.new_task_sender = crossbeam_channel::unbounded().0; } @@ -2136,6 +2197,7 @@ impl, TH: TaskHandler> ThreadManager { pub trait SchedulerInner { fn id(&self) -> SchedulerId; fn is_trashed(&self) -> bool; + fn discard_buffer(&self); } pub trait SpawnableScheduler: InstalledScheduler { @@ -2198,6 +2260,16 @@ impl SpawnableScheduler for PooledScheduler { } } +#[derive(Debug)] +pub enum BankingStageStatus { + Active, + Inactive, +} + +pub trait BankingStageMonitor: Send + Debug { + fn status(&mut self) -> BankingStageStatus; +} + impl InstalledScheduler for PooledScheduler { fn id(&self) -> SchedulerId { self.inner.id() @@ -2265,6 +2337,10 @@ where fn is_trashed(&self) -> bool { self.is_aborted() || self.is_overgrown() } + + fn discard_buffer(&self) { + self.thread_manager.discard_buffered_tasks(); + } } impl UninstalledScheduler for PooledSchedulerInner @@ -2332,6 +2408,7 @@ mod tests { BeforeThreadManagerDrop, BeforeEndSession, AfterSession, + AfterDiscarded, } #[test] @@ -3462,6 +3539,7 @@ mod tests { banking_packet_receiver, Box::new(|_, _| unreachable!()), transaction_recorder, + Box::new(DummyBankingMinitor), ); } @@ -3589,6 +3667,7 @@ mod tests { banking_packet_receiver, Box::new(|_, _| unreachable!()), transaction_recorder, + Box::new(DummyBankingMinitor), ); let bank = Arc::new(Bank::new_from_parent( @@ -3837,6 +3916,10 @@ mod tests { fn is_trashed(&self) -> bool { false } + + fn discard_buffer(&self) { + unimplemented!() + } } impl UninstalledScheduler @@ -4151,6 +4234,15 @@ mod tests { poh_service.join().unwrap(); } + #[derive(Debug)] + struct DummyBankingMinitor; + + impl BankingStageMonitor for DummyBankingMinitor { + fn status(&mut self) -> BankingStageStatus { + BankingStageStatus::Active + } + } + #[test] fn test_block_production_scheduler_schedule_execution_success() { solana_logger::setup(); @@ -4185,6 +4277,7 @@ mod tests { // we don't use the banking packet channel in this test. so, pass panicking handler. Box::new(|_, _| unreachable!()), transaction_recorder, + Box::new(DummyBankingMinitor), ); assert_eq!(bank.transaction_count(), 0); @@ -4261,6 +4354,7 @@ mod tests { banking_packet_receiver, fixed_banking_packet_handler, transaction_recorder, + Box::new(DummyBankingMinitor), ); // Confirm the banking packet channel is cleared, even before taking scheduler @@ -4329,6 +4423,7 @@ mod tests { banking_packet_receiver, fixed_banking_packet_handler, transaction_recorder, + Box::new(DummyBankingMinitor), ); // Quickly take and return the scheduler so that this test can test the behavior while @@ -4404,6 +4499,7 @@ mod tests { banking_packet_receiver, Box::new(|_, _| unreachable!()), transaction_recorder, + Box::new(DummyBankingMinitor), ); let context = SchedulingContext::for_production(bank.clone()); @@ -4457,6 +4553,7 @@ mod tests { banking_packet_receiver, Box::new(|_, _| unreachable!()), transaction_recorder, + Box::new(DummyBankingMinitor), ); let context = SchedulingContext::for_production(bank); @@ -4513,6 +4610,7 @@ mod tests { banking_packet_receiver, Box::new(|_, _| unreachable!()), transaction_recorder, + Box::new(DummyBankingMinitor), ); // Make sure the assertion in BlockProductionSchedulerInner::can_put() doesn't cause false @@ -4525,4 +4623,96 @@ mod tests { exit.store(true, Ordering::Relaxed); poh_service.join().unwrap(); } + + #[test] + fn test_block_production_scheduler_discard_on_reset() { + #[derive(Debug)] + struct SimpleBankingMinitor; + static START_DISCARD: Mutex = Mutex::new(false); + + impl BankingStageMonitor for SimpleBankingMinitor { + fn status(&mut self) -> BankingStageStatus { + if *START_DISCARD.lock().unwrap() { + BankingStageStatus::Inactive + } else { + BankingStageStatus::Active + } + } + } + + solana_logger::setup(); + + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config_for_block_production(10_000); + + const DISCARDED_TASK_COUNT: usize = 3; + let _progress = sleepless_testing::setup(&[ + &CheckPoint::NewBufferedTask(DISCARDED_TASK_COUNT - 1), + &CheckPoint::DiscardRequested, + &CheckPoint::Discarded(DISCARDED_TASK_COUNT), + &TestCheckPoint::AfterDiscarded, + ]); + + let bank = Bank::new_for_tests(&genesis_config); + let (bank, _bank_forks) = setup_dummy_fork_graph(bank); + + let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64)); + let pool = DefaultSchedulerPool::do_new( + None, + None, + None, + None, + ignored_prioritization_fee_cache, + SHORTENED_POOL_CLEANER_INTERVAL, + DEFAULT_MAX_POOLING_DURATION, + DEFAULT_MAX_USAGE_QUEUE_COUNT, + DEFAULT_TIMEOUT_DURATION, + ); + + let tx0 = RuntimeTransaction::from_transaction_for_tests(system_transaction::transfer( + &mint_keypair, + &solana_pubkey::new_rand(), + 2, + genesis_config.hash(), + )); + let fixed_banking_packet_handler = + Box::new(move |helper: &BankingStageHelper, _banking_packet| { + for index in 0..DISCARDED_TASK_COUNT { + helper.send_new_task(helper.create_new_task(tx0.clone(), index)) + } + }); + + let (banking_packet_sender, banking_packet_receiver) = crossbeam_channel::unbounded(); + banking_packet_sender + .send(BankingPacketBatch::default()) + .unwrap(); + let (ledger_path, _blockhash) = create_new_tmp_ledger_auto_delete!(&genesis_config); + let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap()); + let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank)); + let (exit, _poh_recorder, transaction_recorder, poh_service, _signal_receiver) = + create_test_recorder_with_index_tracking( + bank.clone(), + blockstore.clone(), + None, + Some(leader_schedule_cache), + ); + pool.register_banking_stage( + None, + banking_packet_receiver, + fixed_banking_packet_handler, + transaction_recorder, + Box::new(SimpleBankingMinitor), + ); + + // By now, there shuold be a bufferd transaction. Let's discard it. + *START_DISCARD.lock().unwrap() = true; + + sleepless_testing::at(TestCheckPoint::AfterDiscarded); + + exit.store(true, Ordering::Relaxed); + poh_service.join().unwrap(); + } } diff --git a/upload-perf/Cargo.toml b/upload-perf/Cargo.toml index cceca061d37f70..544acc55c76f20 100644 --- a/upload-perf/Cargo.toml +++ b/upload-perf/Cargo.toml @@ -9,13 +9,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } -[dependencies] -serde_json = { workspace = true } -solana-metrics = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] [[bin]] name = "solana-upload-perf" path = "src/upload-perf.rs" -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +[dependencies] +serde_json = { workspace = true } +solana-metrics = { workspace = true } diff --git a/validator/Cargo.toml b/validator/Cargo.toml index 9a396eb357a7ba..c7d01f78545072 100644 --- a/validator/Cargo.toml +++ b/validator/Cargo.toml @@ -10,6 +10,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] agave-geyser-plugin-interface = { workspace = true } chrono = { workspace = true, features = ["default", "serde"] } @@ -82,6 +85,13 @@ symlink = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } +[target.'cfg(not(any(target_env = "msvc", target_os = "freebsd")))'.dependencies] +jemallocator = { workspace = true } + +[target."cfg(unix)".dependencies] +libc = { workspace = true } +signal-hook = { workspace = true } + [dev-dependencies] assert_cmd = { workspace = true } predicates = { workspace = true } @@ -93,13 +103,3 @@ solana-time-utils = { workspace = true } spl-generic-token = { workspace = true } spl-token-2022 = { workspace = true, features = ["no-entrypoint"] } tempfile = { workspace = true } - -[target.'cfg(not(any(target_env = "msvc", target_os = "freebsd")))'.dependencies] -jemallocator = { workspace = true } - -[target."cfg(unix)".dependencies] -libc = { workspace = true } -signal-hook = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/validator/src/admin_rpc_service.rs b/validator/src/admin_rpc_service.rs index 716a8bda8001be..bbf4166fdf44d1 100644 --- a/validator/src/admin_rpc_service.rs +++ b/validator/src/admin_rpc_service.rs @@ -1449,6 +1449,7 @@ mod tests { KeyUpdaterType::TpuForwards, KeyUpdaterType::TpuVote, KeyUpdaterType::Forward, + KeyUpdaterType::RpcService ]) ); let mut io = MetaIoHandler::default(); diff --git a/validator/src/bin/solana-test-validator.rs b/validator/src/bin/solana-test-validator.rs index e738f40cdb584c..c95d626b5fe12c 100644 --- a/validator/src/bin/solana-test-validator.rs +++ b/validator/src/bin/solana-test-validator.rs @@ -284,6 +284,10 @@ fn main() { .map(|v| v.into_iter().collect()) .unwrap_or_default(); + let alt_accounts_to_clone: HashSet<_> = pubkeys_of(&matches, "deep_clone_address_lookup_table") + .map(|v| v.into_iter().collect()) + .unwrap_or_default(); + let clone_feature_set = matches.is_present("clone_feature_set"); let warp_slot = if matches.is_present("warp_slot") { @@ -489,6 +493,18 @@ fn main() { } } + if !alt_accounts_to_clone.is_empty() { + if let Err(e) = genesis.deep_clone_address_lookup_table_accounts( + alt_accounts_to_clone, + cluster_rpc_client + .as_ref() + .expect("--deep-clone-address-lookup-table requires --json-rpc-url argument"), + ) { + println!("Error: alt_accounts_to_clone failed: {e}"); + exit(1); + } + } + if !accounts_to_maybe_clone.is_empty() { if let Err(e) = genesis.clone_accounts( accounts_to_maybe_clone, diff --git a/validator/src/cli.rs b/validator/src/cli.rs index dd4a20122b2781..1c8fc6129467cd 100644 --- a/validator/src/cli.rs +++ b/validator/src/cli.rs @@ -881,6 +881,19 @@ pub fn test_app<'a>(version: &'a str, default_args: &'a DefaultTestArgs) -> App< silently ignored", ), ) + .arg( + Arg::with_name("deep_clone_address_lookup_table") + .long("deep-clone-address-lookup-table") + .takes_value(true) + .validator(is_pubkey_or_keypair) + .multiple(true) + .requires("json_rpc_url") + .help( + "Copy an address lookup table and all accounts it references from the cluster referenced by the --url \ + argument in the genesis configuration. If the ledger already exists then this \ + parameter is silently ignored", + ), + ) .arg( Arg::with_name("maybe_clone_account") .long("maybe-clone") diff --git a/validator/src/commands/run/args.rs b/validator/src/commands/run/args.rs index 4547a0183a6c5a..7acb31bbe667c7 100644 --- a/validator/src/commands/run/args.rs +++ b/validator/src/commands/run/args.rs @@ -1664,12 +1664,12 @@ pub fn add_args<'a>(app: App<'a, 'a>, default_args: &'a DefaultArgs) -> App<'a, .help("EXPERIMENTAL: Enable XDP zero copy. Requires hardware support"), ) .arg( - Arg::with_name("use_tpu_client_next") - .long("use-tpu-client-next") + Arg::with_name("use_connection_cache") + .long("use-connection-cache") .takes_value(false) .help( - "Use tpu-client-next crate to send transactions over TPU ports. If not set,\ - ConnectionCache is used instead.", + "Use connection-cache crate to send transactions over TPU ports. If not set,\ + tpu-client-next is used by default.", ), ) } diff --git a/validator/src/commands/run/execute.rs b/validator/src/commands/run/execute.rs index c8c93c691adcc8..d74ccba9f2ef56 100644 --- a/validator/src/commands/run/execute.rs +++ b/validator/src/commands/run/execute.rs @@ -776,7 +776,7 @@ pub fn execute( wen_restart_proto_path: value_t!(matches, "wen_restart", PathBuf).ok(), wen_restart_coordinator: value_t!(matches, "wen_restart_coordinator", Pubkey).ok(), retransmit_xdp, - use_tpu_client_next: matches.is_present("use_tpu_client_next"), + use_tpu_client_next: !matches.is_present("use_connection_cache"), ..ValidatorConfig::default() }; diff --git a/version/Cargo.toml b/version/Cargo.toml index 812995cd1f33db..d1762073c4084e 100644 --- a/version/Cargo.toml +++ b/version/Cargo.toml @@ -9,6 +9,16 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_version" + +[features] +dummy-for-ci-check = [] +frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] + [dependencies] agave-feature-set = { workspace = true } rand = { workspace = true } @@ -24,18 +34,5 @@ solana-frozen-abi-macro = { workspace = true, optional = true, features = [ solana-sanitize = { workspace = true } solana-serde-varint = { workspace = true } -[features] -dummy-for-ci-check = [] -frozen-abi = [ - "dep:solana-frozen-abi", - "dep:solana-frozen-abi-macro", -] - -[lib] -name = "solana_version" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - [lints] workspace = true diff --git a/vortexor-receiver/Cargo.toml b/vortexor-receiver/Cargo.toml index c8843c9ab86c71..372886b745c81c 100644 --- a/vortexor-receiver/Cargo.toml +++ b/vortexor-receiver/Cargo.toml @@ -10,6 +10,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_vortexor_receiver" + [dependencies] solana-perf = { workspace = true } solana-streamer = { workspace = true } @@ -17,10 +24,3 @@ solana-streamer = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } solana-streamer = { workspace = true, features = ["dev-context-only-utils"] } - -[lib] -crate-type = ["lib"] -name = "solana_vortexor_receiver" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/vortexor/Cargo.toml b/vortexor/Cargo.toml index 1afdc32d232340..de3ea9a62c24b9 100644 --- a/vortexor/Cargo.toml +++ b/vortexor/Cargo.toml @@ -11,6 +11,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_vortexor" + [dependencies] agave-banking-stage-ingress-types = { workspace = true } async-channel = { workspace = true } @@ -63,10 +70,3 @@ assert_matches = { workspace = true } solana-local-cluster = { workspace = true } solana-native-token = { workspace = true } solana-streamer = { workspace = true, features = ["dev-context-only-utils"] } - -[lib] -crate-type = ["lib"] -name = "solana_vortexor" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/vortexor/src/main.rs b/vortexor/src/main.rs index 9db1eef71df659..86c177d5bf8b62 100644 --- a/vortexor/src/main.rs +++ b/vortexor/src/main.rs @@ -182,7 +182,7 @@ pub fn main() { vortexor, add the following arguments in the validator's start command: \ --tpu-vortexor-receiver-address {destination} \ --public-tpu-address {tpu_public_address} \ - --public-tpu-forward-address {tpu_fwd_public_address}", + --public-tpu-forwards-address {tpu_fwd_public_address}", ); } diff --git a/vote/Cargo.toml b/vote/Cargo.toml index dc8253e1b0a5e9..00ddcb095a37f1 100644 --- a/vote/Cargo.toml +++ b/vote/Cargo.toml @@ -9,6 +9,17 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +crate-type = ["lib"] +name = "solana_vote" + +[features] +dev-context-only-utils = ["dep:rand", "dep:bincode"] +frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] + [dependencies] bincode = { workspace = true, optional = true } itertools = { workspace = true } @@ -39,10 +50,6 @@ solana-transaction = { workspace = true, features = ["bincode"] } solana-vote-interface = { workspace = true, features = ["bincode"] } thiserror = { workspace = true } -[lib] -crate-type = ["lib"] -name = "solana_vote" - [dev-dependencies] arbitrary = { workspace = true } bincode = { workspace = true } @@ -55,12 +62,5 @@ solana-transaction = { workspace = true, features = ["bincode"] } solana-vote-interface = { workspace = true, features = ["bincode", "dev-context-only-utils"] } static_assertions = { workspace = true } -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[features] -dev-context-only-utils = ["dep:rand", "dep:bincode"] -frozen-abi = ["dep:solana-frozen-abi", "dep:solana-frozen-abi-macro"] - [lints] workspace = true diff --git a/watchtower/Cargo.toml b/watchtower/Cargo.toml index acc5eb1a199f10..3b4518197c1de9 100644 --- a/watchtower/Cargo.toml +++ b/watchtower/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + [dependencies] clap = { workspace = true } humantime = { workspace = true } @@ -25,6 +28,3 @@ solana-pubkey = { version = "=2.4.0", default-features = false } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } solana-version = { workspace = true } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/wen-restart/Cargo.toml b/wen-restart/Cargo.toml index 894c6a0101c931..b7e4b4455dd878 100644 --- a/wen-restart/Cargo.toml +++ b/wen-restart/Cargo.toml @@ -10,6 +10,12 @@ license = { workspace = true } edition = { workspace = true } publish = true +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +name = "solana_wen_restart" + [dependencies] anyhow = { workspace = true } log = { workspace = true } @@ -21,15 +27,23 @@ solana-entry = { workspace = true } solana-gossip = { workspace = true } solana-hash = { workspace = true } solana-ledger = { workspace = true } -solana-program = { workspace = true } solana-pubkey = { workspace = true } solana-runtime = { workspace = true } solana-shred-version = { workspace = true } solana-time-utils = { workspace = true } solana-timings = { workspace = true } solana-vote = { workspace = true } +solana-vote-interface = { workspace = true } solana-vote-program = { workspace = true } +[build-dependencies] +prost-build = { workspace = true } + +# windows users should install the protobuf compiler manually and set the PROTOC +# envar to point to the installed binary +[target."cfg(not(windows))".build-dependencies] +protobuf-src = { workspace = true } + [dev-dependencies] assert_matches = { workspace = true } crossbeam-channel = { workspace = true } @@ -43,17 +57,3 @@ solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-signer = { workspace = true } solana-streamer = { workspace = true } tempfile = { workspace = true } - -[build-dependencies] -prost-build = { workspace = true } - -# windows users should install the protobuf compiler manually and set the PROTOC -# envar to point to the installed binary -[target."cfg(not(windows))".build-dependencies] -protobuf-src = { workspace = true } - -[lib] -name = "solana_wen_restart" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/wen-restart/src/heaviest_fork_aggregate.rs b/wen-restart/src/heaviest_fork_aggregate.rs index d022882eedd80c..cc57d8a77a6578 100644 --- a/wen-restart/src/heaviest_fork_aggregate.rs +++ b/wen-restart/src/heaviest_fork_aggregate.rs @@ -184,9 +184,10 @@ mod tests { heaviest_fork_aggregate::{HeaviestForkAggregate, HeaviestForkAggregateResult}, solana::wen_restart_proto::HeaviestForkRecord, }, + solana_clock::Slot, solana_gossip::restart_crds_values::RestartHeaviestFork, solana_hash::Hash, - solana_program::{clock::Slot, pubkey::Pubkey}, + solana_pubkey::Pubkey, solana_runtime::{ bank::Bank, genesis_utils::{ diff --git a/wen-restart/src/last_voted_fork_slots_aggregate.rs b/wen-restart/src/last_voted_fork_slots_aggregate.rs index 85600eaf8de649..d130c1c0147da7 100644 --- a/wen-restart/src/last_voted_fork_slots_aggregate.rs +++ b/wen-restart/src/last_voted_fork_slots_aggregate.rs @@ -244,9 +244,9 @@ mod tests { crate::{ last_voted_fork_slots_aggregate::*, solana::wen_restart_proto::LastVotedForkSlotsRecord, }, + solana_clock::Slot, solana_gossip::restart_crds_values::RestartLastVotedForkSlots, solana_hash::Hash, - solana_program::clock::Slot, solana_runtime::{ bank::Bank, epoch_stakes::EpochStakes, diff --git a/wen-restart/src/wen_restart.rs b/wen-restart/src/wen_restart.rs index c7b06f870eb502..d49e05d7f03112 100644 --- a/wen-restart/src/wen_restart.rs +++ b/wen-restart/src/wen_restart.rs @@ -17,21 +17,19 @@ use { anyhow::Result, log::*, prost::Message, + solana_clock::{Epoch, Slot}, solana_entry::entry::VerifyRecyclers, solana_gossip::{ cluster_info::{ClusterInfo, GOSSIP_SLEEP_MILLIS}, restart_crds_values::RestartLastVotedForkSlots, }, + solana_hash::Hash, solana_ledger::{ ancestor_iterator::AncestorIterator, blockstore::Blockstore, blockstore_processor::{process_single_slot, ConfirmationProgress, ProcessOptions}, leader_schedule_cache::LeaderScheduleCache, }, - solana_program::{ - clock::{Epoch, Slot}, - hash::Hash, - }, solana_pubkey::Pubkey, solana_runtime::{ accounts_background_service::AbsStatus, @@ -191,7 +189,7 @@ impl std::error::Error for WenRestartError {} // We need a WenRestartProgressInternalState so we can convert the protobuf written in file // into internal data structure in the initialize function. It should be easily -// convertable to and from WenRestartProgress protobuf. +// convertible to and from WenRestartProgress protobuf. #[derive(Debug, PartialEq)] pub(crate) enum WenRestartProgressInternalState { Init { @@ -666,7 +664,6 @@ pub(crate) fn find_bankhash_of_heaviest_fork( None, None, None, - None, &mut timing, ) { return Err( @@ -1443,6 +1440,7 @@ mod tests { crds_value::CrdsValue, restart_crds_values::{RestartHeaviestFork, RestartLastVotedForkSlots}, }, + solana_hash::Hash, solana_keypair::Keypair, solana_ledger::{ blockstore::{create_new_ledger, entries_to_test_shreds, Blockstore}, @@ -1450,10 +1448,6 @@ mod tests { blockstore_processor::{fill_blockstore_slot_with_ticks, test_process_blockstore}, get_tmp_ledger_path_auto_delete, }, - solana_program::{ - hash::Hash, - vote::state::{TowerSync, Vote}, - }, solana_pubkey::Pubkey, solana_runtime::{ epoch_stakes::EpochStakes, @@ -1469,6 +1463,7 @@ mod tests { solana_streamer::socket::SocketAddrSpace, solana_time_utils::timestamp, solana_vote::vote_account::VoteAccount, + solana_vote_interface::state::{TowerSync, Vote}, solana_vote_program::vote_state::create_account_with_authorized, std::{fs::remove_file, sync::Arc, thread::Builder}, tempfile::TempDir, @@ -2056,7 +2051,6 @@ mod tests { None, None, None, - None, &mut timing, ) { panic!("process_single_slot failed: {:?}", e); diff --git a/zk-keygen/Cargo.toml b/zk-keygen/Cargo.toml index b7ab25493709bb..4465c17219c4d7 100644 --- a/zk-keygen/Cargo.toml +++ b/zk-keygen/Cargo.toml @@ -15,6 +15,13 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[[bin]] +name = "solana-zk-keygen" +path = "src/main.rs" + [dependencies] bs58 = { workspace = true } clap = { version = "3.1.5", features = ["cargo", "derive"] } @@ -31,10 +38,3 @@ tiny-bip39 = { workspace = true } [dev-dependencies] solana-pubkey = { workspace = true, features = ["rand"] } tempfile = { workspace = true } - -[[bin]] -name = "solana-zk-keygen" -path = "src/main.rs" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/zk-sdk/Cargo.toml b/zk-sdk/Cargo.toml index e0fb4ed118c960..22b02e6a67090a 100644 --- a/zk-sdk/Cargo.toml +++ b/zk-sdk/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib", "rlib"] + [dependencies] base64 = { workspace = true } bytemuck = { workspace = true } @@ -21,9 +24,8 @@ solana-pubkey = { workspace = true, features = ["bytemuck"] } solana-sdk-ids = { workspace = true } thiserror = { workspace = true } -[dev-dependencies] -solana-keypair = { workspace = true } -tiny-bip39 = { workspace = true } +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +solana-pubkey = { workspace = true, features = ["bytemuck"] } [target.'cfg(not(target_os = "solana"))'.dependencies] aes-gcm-siv = { workspace = true } @@ -43,15 +45,13 @@ solana-signer = { workspace = true } subtle = { workspace = true } zeroize = { workspace = true, features = ["zeroize_derive"] } -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -solana-pubkey = { workspace = true, features = ["bytemuck"] } - [target.'cfg(target_arch = "wasm32")'.dependencies] js-sys = { workspace = true } wasm-bindgen = { workspace = true } -[lib] -crate-type = ["cdylib", "rlib"] +[dev-dependencies] +solana-keypair = { workspace = true } +tiny-bip39 = { workspace = true } [lints] workspace = true diff --git a/zk-sdk/src/encryption/elgamal.rs b/zk-sdk/src/encryption/elgamal.rs index dd69a17192bae7..a1f1a9c10dc75c 100644 --- a/zk-sdk/src/encryption/elgamal.rs +++ b/zk-sdk/src/encryption/elgamal.rs @@ -486,7 +486,7 @@ impl ElGamalSecretKey { ElGamal::decrypt(self, ciphertext) } - /// Decrypts a ciphertext using the ElGamal secret key interpretting the message as type `u32`. + /// Decrypts a ciphertext using the ElGamal secret key interpreting the message as type `u32`. pub fn decrypt_u32(&self, ciphertext: &ElGamalCiphertext) -> Option { ElGamal::decrypt_u32(self, ciphertext) } diff --git a/zk-sdk/src/zk_elgamal_proof_program/instruction.rs b/zk-sdk/src/zk_elgamal_proof_program/instruction.rs index dd44b8f57d478a..d98580cd59546d 100644 --- a/zk-sdk/src/zk_elgamal_proof_program/instruction.rs +++ b/zk-sdk/src/zk_elgamal_proof_program/instruction.rs @@ -10,7 +10,7 @@ //! dedicated [`context-state`] account. //! //! In step 1, the zero-knowledge proof can either be included directly as the instruction data or -//! pre-written to an account. The progrma determines whether the proof is provided as instruction +//! pre-written to an account. The program determines whether the proof is provided as instruction //! data or pre-written to an account by inspecting the length of the data. If the instruction data //! is exactly 5 bytes (instruction discriminator + unsigned 32-bit integer), then the program //! assumes that the first account provided with the instruction contains the zero-knowledge proof diff --git a/zk-token-sdk/Cargo.toml b/zk-token-sdk/Cargo.toml index 430222911f7c68..c7329cb5be4686 100644 --- a/zk-token-sdk/Cargo.toml +++ b/zk-token-sdk/Cargo.toml @@ -9,6 +9,9 @@ homepage = { workspace = true } license = { workspace = true } edition = { workspace = true } +[lib] +crate-type = ["cdylib", "rlib"] + [dependencies] base64 = { workspace = true } bytemuck = { workspace = true } @@ -21,10 +24,6 @@ solana-pubkey = { workspace = true, features = ["bytemuck"] } solana-sdk-ids = { workspace = true } thiserror = { workspace = true } -[dev-dependencies] -solana-keypair = { workspace = true } -tiny-bip39 = { workspace = true } - [target.'cfg(not(target_os = "solana"))'.dependencies] aes-gcm-siv = { workspace = true } bincode = { workspace = true } @@ -44,8 +43,9 @@ solana-signer = { workspace = true } subtle = { workspace = true } zeroize = { workspace = true, features = ["zeroize_derive"] } -[lib] -crate-type = ["cdylib", "rlib"] +[dev-dependencies] +solana-keypair = { workspace = true } +tiny-bip39 = { workspace = true } [lints] workspace = true