From 8e01c0bfae19712f1bf8cf337ce653a5d496a6f2 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 23 Apr 2026 12:48:34 +0200 Subject: [PATCH 001/110] feat: chainlink with compression --- .github/workflows/ci-test-integration.yml | 19 + Cargo.lock | 4186 ++++++++++++++--- Cargo.toml | 39 +- compressed-delegation-api/Cargo.toml | 14 + compressed-delegation-api/src/instruction.rs | 279 ++ compressed-delegation-api/src/lib.rs | 19 + compressed-delegation-api/src/state.rs | 51 + compressed-delegation-client/Cargo.toml | 36 + .../src/builders/commit_finalize.rs | 40 + .../src/builders/delegate.rs | 40 + .../src/builders/init_delegation_record.rs | 40 + .../src/builders/mod.rs | 8 + .../src/builders/undelegate.rs | 46 + .../src/cpi/commit_finalize.rs | 43 + .../src/cpi/delegate.rs | 43 + .../src/cpi/helpers.rs | 24 + .../src/cpi/init_delegation_record.rs | 43 + compressed-delegation-client/src/cpi/mod.rs | 10 + .../src/cpi/undelegate.rs | 54 + compressed-delegation-client/src/lib.rs | 26 + compressed-delegation-client/src/mod.rs | 9 + compressed-delegation-client/src/programs.rs | 7 + compressed-delegation-client/src/shared.rs | 16 + config.example.toml | 9 + .../src/scheduled_commits_processor.rs | 2 + magicblock-aperture/src/state/mod.rs | 2 + magicblock-api/Cargo.toml | 1 + magicblock-api/src/magic_validator.rs | 11 +- magicblock-chainlink/Cargo.toml | 2 + .../account_still_undelegating_on_chain.rs | 35 + magicblock-chainlink/src/chainlink/errors.rs | 6 + .../chainlink/fetch_cloner/ata_projection.rs | 14 +- .../src/chainlink/fetch_cloner/compression.rs | 113 + .../src/chainlink/fetch_cloner/delegation.rs | 20 +- .../src/chainlink/fetch_cloner/mod.rs | 251 +- .../src/chainlink/fetch_cloner/pipeline.rs | 77 +- .../chainlink/fetch_cloner/program_loader.rs | 6 +- .../chainlink/fetch_cloner/subscription.rs | 9 +- .../src/chainlink/fetch_cloner/tests.rs | 28 +- .../src/chainlink/fetch_cloner/types.rs | 1 + magicblock-chainlink/src/chainlink/mod.rs | 42 +- .../chain_updates_client.rs | 5 + .../src/remote_account_provider/endpoint.rs | 25 +- .../src/remote_account_provider/errors.rs | 3 + .../src/remote_account_provider/mod.rs | 707 ++- .../remote_account_provider/photon_client.rs | 116 + .../remote_account_provider/remote_account.rs | 37 + magicblock-chainlink/src/testing/accounts.rs | 29 + magicblock-chainlink/src/testing/mod.rs | 2 + .../src/testing/photon_client_mock.rs | 69 + .../tests/01_ensure-accounts.rs | 136 +- .../tests/03_deleg_after_sub.rs | 124 +- .../tests/04_redeleg_other_separate_slots.rs | 122 +- .../tests/05_redeleg_other_same_slot.rs | 95 +- .../tests/06_redeleg_us_separate_slots.rs | 112 +- .../tests/07_redeleg_us_same_slot.rs | 98 +- .../tests/utils/test_context.rs | 52 +- magicblock-config/README.md | 9 +- magicblock-config/src/config/compression.rs | 19 + magicblock-config/src/config/mod.rs | 2 + magicblock-config/src/consts.rs | 4 + magicblock-config/src/lib.rs | 5 +- magicblock-config/src/tests.rs | 19 + magicblock-core/Cargo.toml | 7 +- magicblock-core/src/compression.rs | 44 + magicblock-core/src/lib.rs | 1 + magicblock-core/src/traits.rs | 26 + .../src/instruction.rs | 34 + magicblock-metrics/src/metrics/mod.rs | 61 + .../src/magic_scheduled_base_intent.rs | 28 + .../magicblock/src/magicblock_processor.rs | 21 + .../process_mutate_accounts.rs | 11 + .../process_schedule_commit.rs | 1 + .../process_schedule_commit_finalize.rs | 28 +- .../magicblock/src/utils/instruction_utils.rs | 71 + .../compressed_delegation.so | Bin 0 -> 172744 bytes 76 files changed, 6774 insertions(+), 1070 deletions(-) create mode 100644 compressed-delegation-api/Cargo.toml create mode 100644 compressed-delegation-api/src/instruction.rs create mode 100644 compressed-delegation-api/src/lib.rs create mode 100644 compressed-delegation-api/src/state.rs create mode 100644 compressed-delegation-client/Cargo.toml create mode 100644 compressed-delegation-client/src/builders/commit_finalize.rs create mode 100644 compressed-delegation-client/src/builders/delegate.rs create mode 100644 compressed-delegation-client/src/builders/init_delegation_record.rs create mode 100644 compressed-delegation-client/src/builders/mod.rs create mode 100644 compressed-delegation-client/src/builders/undelegate.rs create mode 100644 compressed-delegation-client/src/cpi/commit_finalize.rs create mode 100644 compressed-delegation-client/src/cpi/delegate.rs create mode 100644 compressed-delegation-client/src/cpi/helpers.rs create mode 100644 compressed-delegation-client/src/cpi/init_delegation_record.rs create mode 100644 compressed-delegation-client/src/cpi/mod.rs create mode 100644 compressed-delegation-client/src/cpi/undelegate.rs create mode 100644 compressed-delegation-client/src/lib.rs create mode 100644 compressed-delegation-client/src/mod.rs create mode 100644 compressed-delegation-client/src/programs.rs create mode 100644 compressed-delegation-client/src/shared.rs create mode 100644 magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs create mode 100644 magicblock-chainlink/src/remote_account_provider/photon_client.rs create mode 100644 magicblock-chainlink/src/testing/photon_client_mock.rs create mode 100644 magicblock-config/src/config/compression.rs create mode 100644 magicblock-core/src/compression.rs create mode 100755 test-integration/programs/compressed_delegation/compressed_delegation.so diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index 0d7729e5f..54afcc86b 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -70,6 +70,25 @@ jobs: - uses: ./magicblock-validator/.github/actions/setup-solana + - name: Install Photon indexer + if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' + shell: bash + env: + RUSTFLAGS: "-A dead-code" + run: cargo install --git https://github.com/lightprotocol/photon.git --rev ac7df6c388db847b7693a7a1cb766a7c9d7809b5 --locked --forceExpand commentComment on lines R74 to R79Resolved + + - name: Setup Node.js + if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install zk-compression CLI + if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' + run: | + npm i -g @lightprotocol/zk-compression-cli@0.27.1-alpha.10 + shell: bash + - name: Run integration tests - ${{ matrix.batch_tests }} run: | sudo prlimit --pid $$ --nofile=1048576:1048576 diff --git a/Cargo.lock b/Cargo.lock index bab081d30..b0caec379 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "agave-feature-set" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a2c365c0245cbb8959de725fc2b44c754b673fdf34c9a7f9d4a25c35a7bf1" +dependencies = [ + "ahash 0.8.12", + "solana-epoch-schedule 2.2.1", + "solana-hash 2.3.0", + "solana-pubkey 2.4.0", + "solana-sha256-hasher 2.3.0", + "solana-svm-feature-set 2.3.13", +] + [[package]] name = "agave-feature-set" version = "3.1.12" @@ -67,11 +81,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6200f3b8cfbe5992fde00d443f60e62a79d2d8f6a658af1ffb7c4f0baa3c7028" dependencies = [ "ahash 0.8.12", - "solana-epoch-schedule", + "solana-epoch-schedule 3.1.0", "solana-hash 3.1.0", "solana-pubkey 3.0.0", "solana-sha256-hasher 3.1.0", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", ] [[package]] @@ -81,10 +95,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d93caf9e6dd35ba4193fe778c1e52ee69433ba53b9eaeebc00c7bcd4d699081" dependencies = [ "log", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-signature", - "solana-transaction", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", "solana-transaction-status", "thiserror 2.0.18", ] @@ -95,7 +109,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c0fa80ea1037091eff64931fc53b6a89f153f5a88c33035cedfa79265b985cb" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "bincode", "digest 0.10.7", "ed25519-dalek 1.0.1", @@ -103,10 +117,10 @@ dependencies = [ "openssl", "sha3", "solana-ed25519-program", - "solana-message", + "solana-message 3.1.0", "solana-precompile-error", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-secp256k1-program", "solana-secp256r1-program", ] @@ -117,9 +131,9 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c3998a6ec388df954d8f78eeaf73ff487b50a8bdaebd48c8573af22c7b6db72" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", ] [[package]] @@ -131,37 +145,37 @@ dependencies = [ "bincode", "libsecp256k1", "num-traits", - "solana-account", - "solana-account-info", - "solana-big-mod-exp", - "solana-blake3-hasher", - "solana-bn254", - "solana-clock", - "solana-cpi", - "solana-curve25519", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-big-mod-exp 3.0.0", + "solana-blake3-hasher 3.1.0", + "solana-bn254 3.2.1", + "solana-clock 3.0.1", + "solana-cpi 3.1.0", + "solana-curve25519 3.1.12", "solana-hash 3.1.0", - "solana-instruction", - "solana-keccak-hasher", - "solana-loader-v3-interface", + "solana-instruction 3.4.0", + "solana-keccak-hasher 3.1.0", + "solana-loader-v3-interface 6.1.1", "solana-poseidon", - "solana-program-entrypoint", + "solana-program-entrypoint 3.1.1", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-sbpf", - "solana-sdk-ids", - "solana-secp256k1-recover", + "solana-sdk-ids 3.1.0", + "solana-secp256k1-recover 3.1.1", "solana-sha256-hasher 3.1.0", - "solana-stable-layout", - "solana-stake-interface", + "solana-stable-layout 3.0.1", + "solana-stake-interface 2.0.2", "solana-svm-callback", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-timings", "solana-svm-type-overrides", - "solana-sysvar", - "solana-sysvar-id", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", ] @@ -198,6 +212,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-sized" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48a526ec4434d531d488af59fe866f36b310fe8906691c75dffa664450a3800a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -345,7 +370,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.5", + "hashbrown 0.15.2", "itertools 0.13.0", "num-bigint 0.4.6", "num-integer", @@ -464,7 +489,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.5", + "hashbrown 0.15.2", ] [[package]] @@ -532,6 +557,7 @@ checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ "num-traits", "rand 0.8.5", + "rayon", ] [[package]] @@ -633,6 +659,28 @@ dependencies = [ "cc", ] +[[package]] +name = "aws-lc-rs" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.7.9" @@ -735,6 +783,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -866,17 +920,40 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "borsh" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" +dependencies = [ + "borsh-derive 0.10.4", + "hashbrown 0.13.2", +] + [[package]] name = "borsh" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ - "borsh-derive", + "borsh-derive 1.6.1", "bytes", "cfg_aliases", ] +[[package]] +name = "borsh-derive" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "borsh-derive" version = "1.6.1" @@ -884,12 +961,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", - "proc-macro-crate", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.117", ] +[[package]] +name = "borsh-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "brotli" version = "8.0.2" @@ -1027,6 +1126,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -1134,6 +1239,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "cmov" version = "0.5.3" @@ -1159,6 +1273,16 @@ dependencies = [ "unreachable", ] +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "compact_str" version = "0.8.1" @@ -1173,6 +1297,39 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "compressed-delegation-api" +version = "0.1.0" +dependencies = [ + "borsh 1.6.1", + "light-compressed-account", + "light-hasher", + "light-sdk", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "compressed-delegation-client" +version = "0.1.0" +dependencies = [ + "borsh 1.6.1", + "compressed-delegation-api", + "light-compressed-account", + "light-hasher", + "light-sdk", + "light-sdk-types", + "num-derive", + "num-traits", + "serde", + "serde_with", + "solana-account-info 3.1.1", + "solana-cpi 3.1.0", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", + "solana-pubkey 3.0.0", + "thiserror 2.0.18", +] + [[package]] name = "compression-codecs" version = "0.4.37" @@ -1191,6 +1348,19 @@ version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width 0.2.0", + "windows-sys 0.59.0", +] + [[package]] name = "console" version = "0.16.3" @@ -1243,6 +1413,26 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + [[package]] name = "const-crypto" version = "0.3.0" @@ -1345,6 +1535,25 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -1705,6 +1914,12 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -1991,7 +2206,7 @@ dependencies = [ "atomic", "pear", "serde", - "toml", + "toml 0.8.23", "uncased", "version_check", ] @@ -2256,9 +2471,9 @@ dependencies = [ "base64 0.21.7", "clap", "magicblock-accounts-db", - "solana-commitment-config", + "solana-commitment-config 3.1.1", "solana-pubkey 3.0.0", - "solana-rpc-client", + "solana-rpc-client 3.1.12", "sonic-rs", "tempfile", ] @@ -2350,6 +2565,21 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "groth16-solana" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6d1ffb18dbf5cfc60b11bd7da88474c672870247c1e5b498619bcb6ba3d8f5" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "num-bigint 0.4.6", + "solana-bn254 2.2.2", + "thiserror 1.0.69", +] + [[package]] name = "group" version = "0.13.0" @@ -2368,7 +2598,7 @@ dependencies = [ "bincode", "magicblock-magic-program-api", "serde", - "solana-program", + "solana-program 3.0.0", ] [[package]] @@ -2438,9 +2668,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -2470,7 +2700,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.15.2", ] [[package]] @@ -2962,13 +3192,26 @@ dependencies = [ "serde_core", ] +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console 0.15.11", + "number_prefix", + "portable-atomic", + "unicode-width 0.2.0", + "web-time", +] + [[package]] name = "indicatif" version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ - "console", + "console 0.16.3", "portable-atomic", "unicode-width 0.2.0", "unit-prefix", @@ -3086,6 +3329,50 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine 4.6.7", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -3185,16 +3472,16 @@ dependencies = [ "prost 0.14.3", "prost-types 0.14.3", "protobuf-src", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.2.0", "solana-transaction-status", "tonic 0.14.5", "tonic-build 0.14.5", @@ -3230,11 +3517,11 @@ dependencies = [ "magicblock-ledger", "num-format", "pretty-hex", - "solana-account", - "solana-clock", - "solana-message", + "solana-account 3.4.0", + "solana-clock 3.0.1", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", + "solana-signature 3.4.0", "solana-transaction-status", ] @@ -3407,67 +3694,647 @@ dependencies = [ ] [[package]] -name = "light-poseidon" -version = "0.2.0" +name = "light-account" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +checksum = "ec4f3acf8345ca221e4c7a7d277924ca52daea0dea5d5cf8c8f0951a3cad60dc" dependencies = [ - "ark-bn254 0.4.0", - "ark-ff 0.4.2", - "num-bigint 0.4.6", - "thiserror 1.0.69", + "light-account-checks", + "light-compressed-account", + "light-compressible", + "light-hasher", + "light-macros", + "light-sdk-macros", + "light-sdk-types", + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", ] [[package]] -name = "light-poseidon" -version = "0.4.0" +name = "light-account-checks" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a1ccadd0bb5a32c196da536fd72c59183de24a055f6bf0513bf845fefab862" +checksum = "34d74dd13535c6014abb4cac694e14083b206a7f6cf1bbbc9611aa5c2e11cdd1" dependencies = [ - "ark-bn254 0.5.0", - "ark-ff 0.5.0", - "num-bigint 0.4.6", - "thiserror 1.0.69", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-system-interface 1.0.0", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", ] [[package]] -name = "linux-raw-sys" -version = "0.4.15" +name = "light-array-map" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "9bdd13b18028ac9d80d0a987551c0dad7fe81be8140e87cc9d568b80f3728203" +dependencies = [ + "tinyvec", +] [[package]] -name = "linux-raw-sys" -version = "0.12.1" +name = "light-batched-merkle-tree" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +checksum = "3702b96798a1cc93c9d4b0d9eb6ee980481beb147ab663cfd260c71ec258c5f0" +dependencies = [ + "aligned-sized", + "borsh 0.10.4", + "light-account-checks", + "light-bloom-filter", + "light-compressed-account", + "light-hasher", + "light-macros", + "light-merkle-tree-metadata", + "light-verifier", + "light-zero-copy", + "solana-account-info 2.3.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", + "zerocopy", +] [[package]] -name = "litemap" -version = "0.8.2" +name = "light-bloom-filter" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +checksum = "380b8cf734ccf5fbc1f5fed8e5308b57ebde6774d9304c167bcb0de2854412d8" +dependencies = [ + "bitvec", + "num-bigint 0.4.6", + "solana-nostd-keccak", + "solana-program-error 2.2.2", + "thiserror 2.0.18", +] [[package]] -name = "lmdb-rkv" -version = "0.14.0" +name = "light-bounded-vec" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447a296f7aca299cfbb50f4e4f3d49451549af655fb7215d7f8c0c3d64bad42b" +checksum = "58cfa375d028164719e3ffef93d2e5c27855cc8a5bb5bf257b868d17c12a3e66" dependencies = [ - "bitflags 1.3.2", - "byteorder", - "libc", - "lmdb-rkv-sys", + "bytemuck", + "memoffset", + "solana-program-error 2.2.2", + "thiserror 1.0.69", ] [[package]] -name = "lmdb-rkv-sys" -version = "0.11.2" +name = "light-client" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b9ce6b3be08acefa3003c57b7565377432a89ec24476bbe72e11d101f852fe" +checksum = "4830579bed474120d4c8b79be18ecd7443ed62bf2d692fdfc591ef7cdee3f3de" dependencies = [ - "cc", - "libc", + "async-trait", + "base64 0.13.1", + "borsh 0.10.4", + "bs58", + "futures", + "lazy_static", + "light-account", + "light-compressed-account", + "light-compressed-token-sdk", + "light-compressible", + "light-concurrent-merkle-tree", + "light-event", + "light-hasher", + "light-indexed-merkle-tree", + "light-merkle-tree-metadata", + "light-prover-client", + "light-sdk", + "light-sdk-types", + "light-token", + "light-token-interface", + "num-bigint 0.4.6", + "photon-api", + "rand 0.8.5", + "reqwest 0.12.28", + "serde_json", + "smallvec", + "solana-account 2.2.1", + "solana-account-decoder-client-types 2.3.13", + "solana-address-lookup-table-interface 2.2.2", + "solana-clock 2.2.3", + "solana-commitment-config 2.2.1", + "solana-compute-budget-interface 2.2.2", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-keypair 2.2.3", + "solana-message 2.4.0", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-rpc-client 2.3.13", + "solana-rpc-client-api 2.3.13", + "solana-signature 2.3.0", + "solana-transaction 2.2.3", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "spl-pod 0.5.1", + "spl-token-2022-interface 1.0.0", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "light-compressed-account" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ce168f42dab1a4c01ad83993d68b17cd2dc1bb31ced8ab4edecaf5b666a8ad" +dependencies = [ + "borsh 0.10.4", + "bytemuck", + "light-hasher", + "light-macros", + "light-poseidon 0.3.0", + "light-program-profiler", + "light-zero-copy", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "thiserror 2.0.18", + "tinyvec", + "zerocopy", +] + +[[package]] +name = "light-compressed-token-sdk" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af361443099082c3f7b0e8afe18a770512c494b25219aad951c80daba76beb86" +dependencies = [ + "arrayvec", + "borsh 0.10.4", + "light-account", + "light-account-checks", + "light-compressed-account", + "light-program-profiler", + "light-sdk", + "light-sdk-types", + "light-token-interface", + "light-token-types", + "light-zero-copy", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "thiserror 2.0.18", +] + +[[package]] +name = "light-compressible" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54745d82dab271a4178b48c48d5768ff54af0a6e01aae62425003c25ed394fc5" +dependencies = [ + "aligned-sized", + "borsh 0.10.4", + "bytemuck", + "light-account-checks", + "light-compressed-account", + "light-hasher", + "light-macros", + "light-program-profiler", + "light-zero-copy", + "pinocchio-pubkey", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "thiserror 2.0.18", + "zerocopy", +] + +[[package]] +name = "light-concurrent-merkle-tree" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db96f47253a0907aaa46dac15cecb27b5510130e48da0b36690dcd2e99a6d558" +dependencies = [ + "borsh 0.10.4", + "light-bounded-vec", + "light-hasher", + "memoffset", + "solana-program-error 2.2.2", + "thiserror 2.0.18", +] + +[[package]] +name = "light-event" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0c2e68b31f5fc890eb0e0c43bc7d5007cd2e02f4b46f3d601f3a91b4c7262c" +dependencies = [ + "borsh 0.10.4", + "light-compressed-account", + "light-hasher", + "light-token-interface", + "light-zero-copy", + "thiserror 2.0.18", +] + +[[package]] +name = "light-hasher" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c822662e6e109bac0e132a43fd52a4ef684811245a794e048cf9cda001e934c8" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "borsh 0.10.4", + "light-poseidon 0.3.0", + "num-bigint 0.4.6", + "sha2 0.10.9", + "sha3", + "solana-program-error 2.2.2", + "thiserror 2.0.18", + "tinyvec", +] + +[[package]] +name = "light-indexed-array" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f14f984030d86b6f07bd8f5ae04e2c40fcd0c3bdfcc7a291fff1ed59c9e6554" +dependencies = [ + "light-hasher", + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.18", +] + +[[package]] +name = "light-indexed-merkle-tree" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0824755289075f28de2820fc7d4ec4e6b9e99d404e033c07338b91cce8c71fb8" +dependencies = [ + "light-bounded-vec", + "light-concurrent-merkle-tree", + "light-hasher", + "light-merkle-tree-reference", + "num-bigint 0.4.6", + "num-traits", + "solana-program-error 2.2.2", + "thiserror 2.0.18", +] + +[[package]] +name = "light-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "179ac51cadc1d0ca047b4d6265a7cc245ca3affc16a20a2749585aa6464d39c2" +dependencies = [ + "bs58", + "proc-macro2", + "quote", + "solana-pubkey 2.4.0", + "syn 2.0.117", +] + +[[package]] +name = "light-merkle-tree-metadata" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2ef127f8b968a22203515fca1822cb54bb8f0bd84de392fcb9fb0b77855393" +dependencies = [ + "borsh 0.10.4", + "bytemuck", + "light-compressed-account", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", + "zerocopy", +] + +[[package]] +name = "light-merkle-tree-reference" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8d480f62ca32b38a6231bbc5310d693f91d6b5bdcc18bb13c2d9aab7a1c90e8" +dependencies = [ + "light-hasher", + "light-indexed-array", + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.18", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254 0.4.0", + "ark-ff 0.4.2", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "light-poseidon" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3d87542063daaccbfecd78b60f988079b6ec4e089249658b9455075c78d42" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "light-poseidon" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47a1ccadd0bb5a32c196da536fd72c59183de24a055f6bf0513bf845fefab862" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "light-profiler-macro" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a8be18fe4de58a6f754caa74a3fbc6d8a758a26f1f3c24d5b0f5b55df5f5408" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "light-program-profiler" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1d345871581aebd8825868a3f08410290aa1cdddcb189ca7f7e588f61d79fcf" +dependencies = [ + "light-profiler-macro", +] + +[[package]] +name = "light-prover-client" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9b434c4819c575c53b439a04cef23e14a7359728d9438a10e6de3641a6d3ba" +dependencies = [ + "ark-bn254 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "light-compressed-account", + "light-hasher", + "light-indexed-array", + "light-sparse-merkle-tree", + "num-bigint 0.4.6", + "num-traits", + "reqwest 0.11.27", + "serde", + "serde_json", + "solana-bn254 2.2.2", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "light-sdk" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f982db1ecc2998f3f9af539f282a355582f094036024918627e468e9e29ab418" +dependencies = [ + "bincode", + "borsh 0.10.4", + "bytemuck", + "light-account-checks", + "light-compressed-account", + "light-hasher", + "light-macros", + "light-program-profiler", + "light-sdk-macros", + "light-sdk-types", + "light-token-interface", + "light-zero-copy", + "num-bigint 0.4.6", + "solana-account-info 2.3.0", + "solana-clock 2.2.3", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-loader-v3-interface 5.0.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-system-interface 1.0.0", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", +] + +[[package]] +name = "light-sdk-macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2160586e2b381827d1ca921b5b9e3383e65c013e2c32e8c14a09d913ca7e1312" +dependencies = [ + "darling 0.21.3", + "light-hasher", + "light-sdk-types", + "proc-macro2", + "quote", + "solana-pubkey 2.4.0", + "syn 2.0.117", +] + +[[package]] +name = "light-sdk-types" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbd944a80033d928d0abf6152595d2e69aa1af07a3dd0e5b86f0b7e4fc9f484" +dependencies = [ + "borsh 0.10.4", + "bytemuck", + "light-account-checks", + "light-compressed-account", + "light-compressible", + "light-hasher", + "light-macros", + "light-token-interface", + "solana-msg 2.2.1", + "thiserror 2.0.18", +] + +[[package]] +name = "light-sparse-merkle-tree" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4251e79b6c63f4946572dcfd7623680ad0f9e0efe1a761a944733333c5645063" +dependencies = [ + "light-hasher", + "light-indexed-array", + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.18", +] + +[[package]] +name = "light-token" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "962fc0c26808f218cd4fb782a15adc24a2163e2e64cacd74c9ca86540cf9afb3" +dependencies = [ + "arrayvec", + "borsh 0.10.4", + "light-account", + "light-account-checks", + "light-batched-merkle-tree", + "light-compressed-account", + "light-compressed-token-sdk", + "light-compressible", + "light-macros", + "light-program-profiler", + "light-sdk", + "light-sdk-types", + "light-token-interface", + "light-token-types", + "light-zero-copy", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-pod 0.5.1", + "thiserror 2.0.18", +] + +[[package]] +name = "light-token-interface" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b14661b6592711d90b1cac2402fa10310d90e0517e035c6b1f47c30a14883461" +dependencies = [ + "aligned-sized", + "borsh 0.10.4", + "bytemuck", + "light-array-map", + "light-compressed-account", + "light-compressible", + "light-hasher", + "light-macros", + "light-program-profiler", + "light-zero-copy", + "pinocchio 0.9.3", + "pinocchio-pubkey", + "solana-account-info 2.3.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sysvar 2.3.0", + "spl-pod 0.5.1", + "spl-token-2022", + "thiserror 2.0.18", + "tinyvec", + "zerocopy", +] + +[[package]] +name = "light-token-types" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e5a8ab668ed571a98a01b4eb4df1e671386e89dc0075e614ede972e34c22742" +dependencies = [ + "borsh 0.10.4", + "light-account-checks", + "light-compressed-account", + "light-macros", + "light-sdk-types", + "solana-msg 2.2.1", + "thiserror 2.0.18", +] + +[[package]] +name = "light-verifier" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d829f997b17c7c65198bb93f0d645a4b2818aed2bd14bf2716e36171d4a9f3f" +dependencies = [ + "groth16-solana", + "light-compressed-account", + "thiserror 2.0.18", +] + +[[package]] +name = "light-zero-copy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5621fb515e14af46148699c0b65334aabe230a1d2cbd06736ccc7a408c8a4af" +dependencies = [ + "light-zero-copy-derive", + "solana-program-error 2.2.2", + "zerocopy", +] + +[[package]] +name = "light-zero-copy-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c46425e5c7ab5203ff5c86ae2615b169cca55f9283f5f60f5dd74143be6934" +dependencies = [ + "lazy_static", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lmdb-rkv" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447a296f7aca299cfbb50f4e4f3d49451549af655fb7215d7f8c0c3d64bad42b" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "libc", + "lmdb-rkv-sys", +] + +[[package]] +name = "lmdb-rkv-sys" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b9ce6b3be08acefa3003c57b7565377432a89ec24476bbe72e11d101f852fe" +dependencies = [ + "cc", + "libc", "pkg-config", ] @@ -3492,7 +4359,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.15.2", ] [[package]] @@ -3525,9 +4392,9 @@ name = "magic-domain-program" version = "0.3.0" source = "git+https://github.com/magicblock-labs/magic-domain-program.git?rev=335a22#335a22ba5aa7b8c4bc84d5053444c74c3b05cdac" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck_derive", - "solana-program", + "solana-program 3.0.0", "solana-system-interface 3.2.0", ] @@ -3548,17 +4415,17 @@ dependencies = [ "magicblock-program", "magicblock-rpc-client", "rand 0.9.3", - "solana-account", + "solana-account 3.4.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-signature", - "solana-signer", - "solana-sysvar", - "solana-transaction", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -3578,8 +4445,8 @@ dependencies = [ "magicblock-program", "solana-hash 3.1.0", "solana-pubkey 3.0.0", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", "tokio-util", @@ -3596,7 +4463,7 @@ dependencies = [ "memmap2", "parking_lot", "reflink-copy", - "solana-account", + "solana-account 3.4.0", "solana-pubkey 3.0.0", "tempfile", "thiserror 2.0.18", @@ -3609,7 +4476,7 @@ dependencies = [ name = "magicblock-aperture" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "agave-geyser-plugin-interface", "arc-swap", "base64 0.21.7", @@ -3634,19 +4501,19 @@ dependencies = [ "reqwest 0.12.28", "scc", "serde", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", "solana-fee-structure", - "solana-keypair", - "solana-message", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-pubsub-client", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", "solana-system-transaction", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status", "sonic-rs", "test-kit", @@ -3660,10 +4527,11 @@ dependencies = [ name = "magicblock-api" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "anyhow", - "borsh", + "borsh 1.6.1", "fd-lock", + "light-client", "magic-domain-program", "magicblock-account-cloner", "magicblock-accounts", @@ -3684,30 +4552,30 @@ dependencies = [ "magicblock-validator-admin", "num_cpus", "paste", - "solana-account", - "solana-clock", - "solana-commitment-config", - "solana-feature-gate-interface", - "solana-fee-calculator", + "solana-account 3.4.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-feature-gate-interface 3.1.0", + "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-message", - "solana-native-token", - "solana-program", - "solana-program-option", - "solana-program-pack", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", + "solana-native-token 3.0.0", + "solana-program 3.0.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-rpc-client", - "solana-sdk-ids", + "solana-rpc-client 3.1.12", + "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-system-program", - "solana-sysvar", - "solana-transaction", - "solana-transaction-error", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "spl-token-interface", "thiserror 2.0.18", "tokio", @@ -3719,14 +4587,16 @@ dependencies = [ name = "magicblock-chainlink" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "arc-swap", "assert_matches", "async-trait", "bincode", - "borsh", + "borsh 1.6.1", + "compressed-delegation-client", "futures-util", "helius-laserstream", + "light-client", "lru 0.16.3", "magicblock-accounts-db", "magicblock-chainlink", @@ -3737,31 +4607,31 @@ dependencies = [ "magicblock-metrics", "parking_lot", "scc", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-account-decoder-client-types", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-commitment-config", + "solana-account-decoder-client-types 3.1.12", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-loader-v3-interface", - "solana-loader-v4-interface", - "solana-message", - "solana-program", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", + "solana-message 3.1.0", + "solana-program 3.0.0", "solana-pubkey 3.0.0", "solana-pubsub-client", "solana-rent 3.1.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-sdk-ids", - "solana-signature", - "solana-signer", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-system-interface 3.2.0", - "solana-transaction", - "solana-transaction-error", - "spl-token-2022-interface", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", + "spl-token-2022-interface 2.1.0", "spl-token-interface", "thiserror 2.0.18", "tokio", @@ -3776,13 +4646,13 @@ dependencies = [ name = "magicblock-committor-program" version = "0.9.0" dependencies = [ - "borsh", + "borsh 1.6.1", "paste", - "solana-account", - "solana-account-info", - "solana-program", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-program 3.0.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", "thiserror 2.0.18", ] @@ -3794,7 +4664,7 @@ dependencies = [ "async-trait", "base64 0.21.7", "bincode", - "borsh", + "borsh 1.6.1", "futures-util", "lazy_static", "lru 0.16.3", @@ -3808,25 +4678,25 @@ dependencies = [ "rand 0.9.3", "rusqlite", "serde_json", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-address-lookup-table-interface", - "solana-commitment-config", - "solana-compute-budget-interface", + "solana-address-lookup-table-interface 3.1.0", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-message", - "solana-program", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", + "solana-program 3.0.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-signer", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-system-program", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", "static_assertions", "tempfile", "test-kit", @@ -3850,11 +4720,11 @@ dependencies = [ "serde", "serde_with", "serial_test", - "solana-keypair", + "solana-keypair 3.1.2", "solana-pubkey 3.0.0", - "solana-signer", + "solana-signer 3.0.0", "tempfile", - "toml", + "toml 0.8.23", "url", ] @@ -3862,25 +4732,31 @@ dependencies = [ name = "magicblock-core" version = "0.9.0" dependencies = [ + "async-trait", "bincode", + "compressed-delegation-client", "console-subscriber", "flume", + "light-client", + "light-compressed-account", + "light-sdk", "magicblock-magic-program-api", "serde", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-message", - "solana-program", + "solana-message 3.1.0", + "solana-program 3.0.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", - "solana-transaction-status-client-types", - "spl-token-2022-interface", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", + "spl-token-2022-interface 2.1.0", "spl-token-interface", + "thiserror 2.0.18", "tokio", "tracing", "tracing-log", @@ -3893,7 +4769,7 @@ version = "0.3.0" source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" dependencies = [ "bincode", - "borsh", + "borsh 1.6.1", "bytemuck", "const-crypto", "libsodium-rs", @@ -3905,11 +4781,11 @@ dependencies = [ "rkyv 0.7.46", "serde", "solana-address 2.6.0", - "solana-instruction", - "solana-loader-v3-interface", - "solana-program", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-program 3.0.0", "solana-sdk", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-system-interface 2.0.0", "static_assertions", @@ -3935,21 +4811,21 @@ dependencies = [ "rocksdb", "serde", "solana-account-decoder", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-message", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-metrics", "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-storage-proto", "solana-svm-measure", "solana-system-transaction", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.2.0", "solana-transaction-status", "tempfile", "test-kit", @@ -3966,8 +4842,8 @@ dependencies = [ "bincode", "const-crypto", "serde", - "solana-program", - "solana-signature", + "solana-program 3.0.0", + "solana-signature 3.4.0", ] [[package]] @@ -3979,7 +4855,7 @@ dependencies = [ "hyper-util", "lazy_static", "prometheus", - "solana-signature", + "solana-signature 3.4.0", "tokio", "tokio-util", "tracing", @@ -3989,7 +4865,7 @@ dependencies = [ name = "magicblock-processor" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "agave-precompiles", "agave-syscalls", "bincode", @@ -4003,30 +4879,30 @@ dependencies = [ "parking_lot", "rustc-hash 2.1.2", "serde", - "solana-account", + "solana-account 3.4.0", "solana-bpf-loader-program", "solana-compute-budget", "solana-compute-budget-program", - "solana-feature-gate-interface", + "solana-feature-gate-interface 3.1.0", "solana-fee-structure", - "solana-instruction", - "solana-keypair", - "solana-loader-v3-interface", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-loader-v3-interface 6.1.1", "solana-loader-v4-program", "solana-precompile-error", - "solana-program", + "solana-program 3.0.0", "solana-program-runtime", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-signature", - "solana-signer", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-svm", "solana-svm-callback", "solana-svm-transaction", "solana-system-program", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.2.0", "solana-transaction-status", "solana-zk-elgamal-proof-program", "test-kit", @@ -4051,25 +4927,25 @@ dependencies = [ "rand 0.9.3", "serde", "serial_test", - "solana-account", - "solana-account-info", - "solana-clock", - "solana-fee-calculator", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", + "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-program-runtime", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-seed-derivable", - "solana-signature", - "solana-signer", + "solana-sdk-ids 3.1.0", + "solana-seed-derivable 3.0.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-svm-log-collector", - "solana-sysvar", - "solana-transaction", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "test-kit", "thiserror 2.0.18", ] @@ -4078,19 +4954,19 @@ dependencies = [ name = "magicblock-rpc-client" version = "0.9.0" dependencies = [ - "solana-account", - "solana-account-decoder-client-types", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-commitment-config", + "solana-account 3.4.0", + "solana-account-decoder-client-types 3.1.12", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", "thiserror 2.0.18", "tokio", "tracing", @@ -4104,14 +4980,14 @@ dependencies = [ "futures-util", "magicblock-core", "magicblock-magic-program-api", - "solana-instruction", - "solana-keypair", - "solana-message", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-signature", - "solana-signer", - "solana-transaction", + "solana-rpc-client 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -4126,18 +5002,18 @@ dependencies = [ "magicblock-rpc-client", "rand 0.9.3", "sha3", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-commitment-config", - "solana-compute-budget-interface", - "solana-instruction", - "solana-keypair", - "solana-message", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", - "solana-slot-hashes", - "solana-transaction", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-slot-hashes 3.0.1", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -4155,14 +5031,14 @@ dependencies = [ "magicblock-ledger", "magicblock-program", "rusqlite", - "solana-instruction", - "solana-message", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-transaction", - "solana-transaction-error", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", "tokio-util", @@ -4183,7 +5059,7 @@ dependencies = [ "serde", "serde_json", "solana-pubsub-client", - "solana-rpc-client-api", + "solana-rpc-client-api 3.1.12", "tokio", "tokio-util", "tracing", @@ -4202,7 +5078,7 @@ dependencies = [ "magicblock-tui-client", "magicblock-version", "num_cpus", - "solana-signer", + "solana-signer 3.0.0", "tokio", "tracing", ] @@ -4214,11 +5090,11 @@ dependencies = [ "magicblock-delegation-program-api", "magicblock-program", "magicblock-rpc-client", - "solana-commitment-config", - "solana-rpc-client", - "solana-signature", - "solana-signer", - "solana-transaction", + "solana-commitment-config 3.1.1", + "solana-rpc-client 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", "tokio", "tokio-util", "tracing", @@ -4228,13 +5104,13 @@ dependencies = [ name = "magicblock-version" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "git-version", "rustc_version", "semver", "serde", "solana-frozen-abi-macro", - "solana-rpc-client-api", + "solana-rpc-client-api 3.1.12", "solana-sanitize 3.0.1", ] @@ -4439,6 +5315,7 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "serde", ] [[package]] @@ -4545,12 +5422,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.117", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "once_cell" version = "1.21.4" @@ -4722,10 +5605,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset 0.5.7", - "hashbrown 0.15.5", + "hashbrown 0.15.2", "indexmap 2.14.0", ] +[[package]] +name = "photon-api" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95609d4f08f2cf86d6e41f5b483cfbbfd914099eb0f7c6ea15e98b358f4614f8" +dependencies = [ + "progenitor-client", + "reqwest 0.13.2", + "serde", + "serde_json", +] + [[package]] name = "pin-project" version = "1.1.11" @@ -4768,7 +5663,7 @@ dependencies = [ "solana-address 2.6.0", "solana-define-syscall 4.0.1", "solana-instruction-view", - "solana-program-error", + "solana-program-error 3.0.1", ] [[package]] @@ -4892,6 +5787,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -4923,6 +5827,21 @@ dependencies = [ "yansi", ] +[[package]] +name = "progenitor-client" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffab7b358944dba033a7b324e7558e66e6bcb1fb4705cf57f26fd5092bcae630" +dependencies = [ + "bytes", + "futures-core", + "percent-encoding", + "reqwest 0.13.2", + "serde", + "serde_json", + "serde_urlencoded", +] + [[package]] name = "prometheus" version = "0.13.4" @@ -5174,6 +6093,7 @@ version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -5360,6 +6280,26 @@ dependencies = [ "unicode-width 0.2.0", ] +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -5546,6 +6486,47 @@ dependencies = [ "webpki-roots 1.0.6", ] +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.9.0", + "hyper-rustls 0.27.8", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.38", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tokio-rustls 0.26.4", + "tokio-util", + "tower 0.5.3", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "reqwest-middleware" version = "0.4.2" @@ -5743,6 +6724,7 @@ version = "0.23.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -5792,6 +6774,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.38", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.11", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -5808,6 +6817,7 @@ version = "0.103.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -5825,6 +6835,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scc" version = "2.4.0" @@ -6241,21 +7260,39 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "solana-account" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f949fe4edaeaea78c844023bfc1c898e0b1f5a100f8a8d2d0f85d0a7b090258" +dependencies = [ + "bincode", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info 2.3.0", + "solana-clock 2.2.3", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-sysvar 2.3.0", +] + [[package]] name = "solana-account" version = "3.4.0" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "bincode", "qualifier_attr", "serde", "serde_bytes", - "solana-account-info", - "solana-clock", - "solana-instruction", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-sysvar", + "solana-sdk-ids 3.1.0", + "solana-sysvar 3.1.1", ] [[package]] @@ -6271,35 +7308,51 @@ dependencies = [ "bv", "serde", "serde_json", - "solana-account", - "solana-account-decoder-client-types", - "solana-address-lookup-table-interface", - "solana-clock", + "solana-account 3.4.0", + "solana-account-decoder-client-types 3.1.12", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", "solana-config-interface", - "solana-epoch-schedule", - "solana-fee-calculator", - "solana-instruction", - "solana-loader-v3-interface", - "solana-nonce", - "solana-program-option", - "solana-program-pack", + "solana-epoch-schedule 3.1.0", + "solana-fee-calculator 3.2.0", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-nonce 3.2.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-slot-hashes", - "solana-slot-history", - "solana-stake-interface", - "solana-sysvar", - "solana-vote-interface", - "spl-generic-token", - "spl-token-2022-interface", - "spl-token-group-interface", + "solana-sdk-ids 3.1.0", + "solana-slot-hashes 3.0.1", + "solana-slot-history 3.0.0", + "solana-stake-interface 2.0.2", + "solana-sysvar 3.1.1", + "solana-vote-interface 4.0.4", + "spl-generic-token 2.0.1", + "spl-token-2022-interface 2.1.0", + "spl-token-group-interface 0.7.2", "spl-token-interface", - "spl-token-metadata-interface", + "spl-token-metadata-interface 0.8.0", "thiserror 2.0.18", "zstd", ] +[[package]] +name = "solana-account-decoder-client-types" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5519e8343325b707f17fbed54fcefb325131b692506d0af9e08a539d15e4f8cf" +dependencies = [ + "base64 0.22.1", + "bs58", + "serde", + "serde_derive", + "serde_json", + "solana-account 2.2.1", + "solana-pubkey 2.4.0", + "zstd", +] + [[package]] name = "solana-account-decoder-client-types" version = "3.1.12" @@ -6310,11 +7363,24 @@ dependencies = [ "bs58", "serde", "serde_json", - "solana-account", + "solana-account 3.4.0", "solana-pubkey 3.0.0", "zstd", ] +[[package]] +name = "solana-account-info" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8f5152a288ef1912300fc6efa6c2d1f9bb55d9398eb6c72326360b8063987da" +dependencies = [ + "bincode", + "serde", + "solana-program-error 2.2.2", + "solana-program-memory 2.3.1", + "solana-pubkey 2.4.0", +] + [[package]] name = "solana-account-info" version = "3.1.1" @@ -6324,8 +7390,8 @@ dependencies = [ "bincode", "serde_core", "solana-address 2.6.0", - "solana-program-error", - "solana-program-memory", + "solana-program-error 3.0.1", + "solana-program-memory 3.1.0", ] [[package]] @@ -6335,7 +7401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37ca34c37f92ee341b73d5ce7c8ef5bb38e9a87955b4bd343c63fa18b149215" dependencies = [ "solana-address 2.6.0", - "solana-program-error", + "solana-program-error 3.0.1", ] [[package]] @@ -6353,7 +7419,7 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1384b52c435a750cc9c538760fc7bb472fd78e65a9900a2d07312c5bb335b72" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", @@ -6366,12 +7432,29 @@ dependencies = [ "solana-atomic-u64 3.0.1", "solana-define-syscall 5.0.0", "solana-nullable", - "solana-program-error", + "solana-program-error 3.0.1", "solana-sanitize 3.0.1", "solana-sha256-hasher 3.1.0", "wincode", ] +[[package]] +name = "solana-address-lookup-table-interface" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1673f67efe870b64a65cb39e6194be5b26527691ce5922909939961a6e6b395" +dependencies = [ + "bincode", + "bytemuck", + "serde", + "serde_derive", + "solana-clock 2.2.3", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-slot-hashes 2.2.1", +] + [[package]] name = "solana-address-lookup-table-interface" version = "3.1.0" @@ -6382,12 +7465,12 @@ dependencies = [ "bytemuck", "serde", "serde_derive", - "solana-clock", - "solana-instruction", + "solana-clock 3.0.1", + "solana-instruction 3.4.0", "solana-instruction-error", "solana-pubkey 4.2.0", - "solana-sdk-ids", - "solana-slot-hashes", + "solana-sdk-ids 3.1.0", + "solana-slot-hashes 3.0.1", ] [[package]] @@ -6408,6 +7491,17 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "solana-big-mod-exp" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "solana-define-syscall 2.3.0", +] + [[package]] name = "solana-big-mod-exp" version = "3.0.0" @@ -6419,6 +7513,17 @@ dependencies = [ "solana-define-syscall 3.0.0", ] +[[package]] +name = "solana-bincode" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a3787b8cf9c9fe3dd360800e8b70982b9e5a8af9e11c354b6665dd4a003adc" +dependencies = [ + "bincode", + "serde", + "solana-instruction 2.3.3", +] + [[package]] name = "solana-bincode" version = "3.1.0" @@ -6430,6 +7535,18 @@ dependencies = [ "solana-instruction-error", ] +[[package]] +name = "solana-blake3-hasher" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" +dependencies = [ + "blake3", + "solana-define-syscall 2.3.0", + "solana-hash 2.3.0", + "solana-sanitize 2.2.1", +] + [[package]] name = "solana-blake3-hasher" version = "3.1.0" @@ -6441,6 +7558,21 @@ dependencies = [ "solana-hash 4.3.0", ] +[[package]] +name = "solana-bn254" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4420f125118732833f36facf96a27e7b78314b2d642ba07fa9ffdacd8d79e243" +dependencies = [ + "ark-bn254 0.4.0", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "bytemuck", + "solana-define-syscall 2.3.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-bn254" version = "3.2.1" @@ -6456,13 +7588,23 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "solana-borsh" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718333bcd0a1a7aed6655aa66bef8d7fb047944922b2d3a18f49cbc13e73d004" +dependencies = [ + "borsh 0.10.4", + "borsh 1.6.1", +] + [[package]] name = "solana-borsh" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c04abbae16f57178a163125805637b8a076175bb5c0002fb04f4792bea901cf7" dependencies = [ - "borsh", + "borsh 1.6.1", ] [[package]] @@ -6474,24 +7616,37 @@ dependencies = [ "agave-syscalls", "bincode", "qualifier_attr", - "solana-account", - "solana-bincode", - "solana-clock", - "solana-instruction", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-account 3.4.0", + "solana-bincode 3.1.0", + "solana-clock 3.0.1", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-packet", - "solana-program-entrypoint", + "solana-program-entrypoint 3.1.1", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-sbpf", - "solana-sdk-ids", - "solana-svm-feature-set", + "solana-sdk-ids 3.1.0", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-transaction-context", + "solana-transaction-context 3.1.12", +] + +[[package]] +name = "solana-clock" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8584296123df8fe229b95e2ebfd37ae637fe9db9b7d4dd677ac5a78e80dbfce" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -6502,9 +7657,9 @@ checksum = "95cf11109c3b6115cc510f1e31f06fdd52f504271bc24ef5f1249fbbcae5f9f3" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -6516,6 +7671,16 @@ dependencies = [ "solana-hash 2.3.0", ] +[[package]] +name = "solana-commitment-config" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac49c4dde3edfa832de1697e9bcdb7c3b3f7cb7a1981b7c62526c8bb6700fb73" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "solana-commitment-config" version = "3.1.1" @@ -6536,14 +7701,24 @@ dependencies = [ "solana-program-runtime", ] +[[package]] +name = "solana-compute-budget-interface" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8432d2c4c22d0499aa06d62e4f7e333f81777b3d7c96050ae9e5cb71a8c3aee4" +dependencies = [ + "solana-instruction 2.3.3", + "solana-sdk-ids 2.2.1", +] + [[package]] name = "solana-compute-budget-interface" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8292c436b269ad23cecc8b24f7da3ab07ca111661e25e00ce0e1d22771951ab9" dependencies = [ - "solana-instruction", - "solana-sdk-ids", + "solana-instruction 3.4.0", + "solana-sdk-ids 3.1.0", ] [[package]] @@ -6564,26 +7739,54 @@ dependencies = [ "bincode", "serde", "serde_derive", - "solana-account", - "solana-instruction", + "solana-account 3.4.0", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-short-vec", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", "solana-system-interface 2.0.0", ] +[[package]] +name = "solana-cpi" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11" +dependencies = [ + "solana-account-info 2.3.0", + "solana-define-syscall 2.3.0", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-stable-layout 2.2.1", +] + [[package]] name = "solana-cpi" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dea26709d867aada85d0d3617db0944215c8bb28d3745b912de7db13a23280c" dependencies = [ - "solana-account-info", + "solana-account-info 3.1.1", "solana-define-syscall 4.0.1", - "solana-instruction", - "solana-program-error", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", "solana-pubkey 4.2.0", - "solana-stable-layout", + "solana-stable-layout 3.0.1", +] + +[[package]] +name = "solana-curve25519" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae4261b9a8613d10e77ac831a8fa60b6fa52b9b103df46d641deff9f9812a23" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-define-syscall 2.3.0", + "subtle", + "thiserror 2.0.18", ] [[package]] @@ -6600,6 +7803,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "solana-decode-error" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c781686a18db2f942e70913f7ca15dc120ec38dcab42ff7557db2c70c625a35" +dependencies = [ + "num-traits", +] + [[package]] name = "solana-define-syscall" version = "2.3.0" @@ -6624,6 +7836,17 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03aacdd7a61e2109887a7a7f046caebafce97ddf1150f33722eeac04f9039c73" +[[package]] +name = "solana-derivation-path" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "939756d798b25c5ec3cca10e06212bdca3b1443cb9bb740a38124f58b258737b" +dependencies = [ + "derivation-path", + "qstring", + "uriparse", +] + [[package]] name = "solana-derivation-path" version = "3.0.0" @@ -6643,8 +7866,18 @@ checksum = "e1419197f1c06abf760043f6d64ba9d79a03ad5a43f18c7586471937122094da" dependencies = [ "bytemuck", "bytemuck_derive", - "solana-instruction", - "solana-sdk-ids", + "solana-instruction 3.4.0", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-epoch-info" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ef6f0b449290b0b9f32973eefd95af35b01c5c0c34c569f936c34c5b20d77b" +dependencies = [ + "serde", + "serde_derive", ] [[package]] @@ -6657,6 +7890,20 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-epoch-rewards" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" +dependencies = [ + "serde", + "serde_derive", + "solana-hash 2.3.0", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", +] + [[package]] name = "solana-epoch-rewards" version = "3.0.1" @@ -6666,9 +7913,9 @@ dependencies = [ "serde", "serde_derive", "solana-hash 4.3.0", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -6682,6 +7929,19 @@ dependencies = [ "solana-hash 4.3.0", ] +[[package]] +name = "solana-epoch-schedule" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fce071fbddecc55d727b1d7ed16a629afe4f6e4c217bc8d00af3b785f6f67ed" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", +] + [[package]] name = "solana-epoch-schedule" version = "3.1.0" @@ -6690,9 +7950,9 @@ checksum = "9ce264b7b42322325947c4136a09460bf5c73d9aa8262c9b0a2064be63ba8639" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -6705,6 +7965,27 @@ dependencies = [ "solana-pubkey 4.2.0", ] +[[package]] +name = "solana-example-mocks" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84461d56cbb8bb8d539347151e0525b53910102e4bced875d49d5139708e39d3" +dependencies = [ + "serde", + "serde_derive", + "solana-address-lookup-table-interface 2.2.2", + "solana-clock 2.2.3", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-keccak-hasher 2.2.1", + "solana-message 2.4.0", + "solana-nonce 2.2.1", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-example-mocks" version = "3.0.0" @@ -6713,19 +7994,38 @@ checksum = "978855d164845c1b0235d4b4d101cadc55373fffaf0b5b6cfa2194d25b2ed658" dependencies = [ "serde", "serde_derive", - "solana-address-lookup-table-interface", - "solana-clock", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-keccak-hasher", - "solana-message", - "solana-nonce", + "solana-instruction 3.4.0", + "solana-keccak-hasher 3.1.0", + "solana-message 3.1.0", + "solana-nonce 3.2.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 2.0.0", "thiserror 2.0.18", ] +[[package]] +name = "solana-feature-gate-interface" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f5c5382b449e8e4e3016fb05e418c53d57782d8b5c30aa372fc265654b956d" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account 2.2.1", + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", +] + [[package]] name = "solana-feature-gate-interface" version = "3.1.0" @@ -6735,16 +8035,27 @@ dependencies = [ "bincode", "serde", "serde_derive", - "solana-account", - "solana-account-info", - "solana-instruction", - "solana-program-error", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", "solana-pubkey 4.2.0", "solana-rent 4.2.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", ] +[[package]] +name = "solana-fee-calculator" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89bc408da0fb3812bc3008189d148b4d3e08252c79ad810b245482a3f70cd8d" +dependencies = [ + "log", + "serde", + "serde_derive", +] + [[package]] name = "solana-fee-calculator" version = "3.2.0" @@ -6789,8 +8100,13 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63" dependencies = [ + "borsh 1.6.1", + "bytemuck", + "bytemuck_derive", "five8 0.2.1", "js-sys", + "serde", + "serde_derive", "solana-atomic-u64 2.2.1", "solana-sanitize 2.2.1", "wasm-bindgen", @@ -6811,7 +8127,7 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1b113239362cee7093bfb250467138f079a2a03673181dc15bff6ccd677912d" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "five8 1.0.0", @@ -6822,6 +8138,12 @@ dependencies = [ "wincode", ] +[[package]] +name = "solana-inflation" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23eef6a09eb8e568ce6839573e4966850e85e9ce71e6ae1a6c930c1c43947de3" + [[package]] name = "solana-inflation" version = "3.1.0" @@ -6832,6 +8154,25 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-instruction" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab5682934bd1f65f8d2c16f21cb532526fcc1a09f796e2cacdb091eee5774ad" +dependencies = [ + "bincode", + "borsh 1.6.1", + "getrandom 0.2.17", + "js-sys", + "num-traits", + "serde", + "serde_derive", + "serde_json", + "solana-define-syscall 2.3.0", + "solana-pubkey 2.4.0", + "wasm-bindgen", +] + [[package]] name = "solana-instruction" version = "3.4.0" @@ -6839,7 +8180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ebb0ffd19263051bc3f683fcc086134b8ff23af894dcb63f7563c7137b42f1" dependencies = [ "bincode", - "borsh", + "borsh 1.6.1", "serde", "serde_derive", "solana-define-syscall 5.0.0", @@ -6856,7 +8197,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-program-error", + "solana-program-error 3.0.1", ] [[package]] @@ -6868,7 +8209,24 @@ dependencies = [ "solana-account-view", "solana-address 2.6.0", "solana-define-syscall 4.0.1", - "solana-program-error", + "solana-program-error 3.0.1", +] + +[[package]] +name = "solana-instructions-sysvar" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0e85a6fad5c2d0c4f5b91d34b8ca47118fc593af706e523cdbedf846a954f57" +dependencies = [ + "bitflags 2.11.0", + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-serialize-utils 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -6878,15 +8236,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf67876c541aa1e21ee1acae35c95c6fbc61119814bfef70579317a5e26955" dependencies = [ "bitflags 2.11.0", - "solana-account-info", - "solana-instruction", + "solana-account-info 3.1.1", + "solana-instruction 3.4.0", "solana-instruction-error", - "solana-program-error", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-serialize-utils", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-serialize-utils 3.1.1", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-keccak-hasher" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" +dependencies = [ + "sha3", + "solana-define-syscall 2.3.0", + "solana-hash 2.3.0", + "solana-sanitize 2.2.1", ] [[package]] @@ -6900,6 +8270,22 @@ dependencies = [ "solana-hash 4.3.0", ] +[[package]] +name = "solana-keypair" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd3f04aa1a05c535e93e121a95f66e7dcccf57e007282e8255535d24bf1e98bb" +dependencies = [ + "ed25519-dalek 1.0.1", + "five8 0.2.1", + "rand 0.7.3", + "solana-pubkey 2.4.0", + "solana-seed-phrase 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "wasm-bindgen", +] + [[package]] name = "solana-keypair" version = "3.1.2" @@ -6912,11 +8298,24 @@ dependencies = [ "five8_core 1.0.0", "rand 0.9.3", "solana-address 2.6.0", - "solana-derivation-path", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-signature", - "solana-signer", + "solana-derivation-path 3.0.0", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", +] + +[[package]] +name = "solana-last-restart-slot" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a6360ac2fdc72e7463565cd256eedcf10d7ef0c28a1249d261ec168c1b55cdd" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -6927,9 +8326,23 @@ checksum = "dcda154ec827f5fc1e4da0af3417951b7e9b8157540f81f936c4a8b1156134d0" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-loader-v2-interface" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ab08006dad78ae7cd30df8eea0539e207d08d91eaefb3e1d49a446e1c49654" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", ] [[package]] @@ -6941,9 +8354,24 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-loader-v3-interface" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f7162a05b8b0773156b443bccd674ea78bb9aa406325b467ea78c06c99a63a2" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", ] [[package]] @@ -6955,12 +8383,27 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 4.2.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", ] +[[package]] +name = "solana-loader-v4-interface" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "706a777242f1f39a83e2a96a2a6cb034cb41169c6ecbee2cf09cb873d9659e7e" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", +] + [[package]] name = "solana-loader-v4-interface" version = "3.1.0" @@ -6970,9 +8413,9 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 2.0.0", ] @@ -6983,21 +8426,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e88b98ba6b408fe6fcf180784fc378d07ae63100c7dd413ff97474b6de30c5d" dependencies = [ "log", - "solana-account", - "solana-bincode", + "solana-account 3.4.0", + "solana-bincode 3.1.0", "solana-bpf-loader-program", - "solana-instruction", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-packet", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-sbpf", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-type-overrides", - "solana-transaction-context", + "solana-transaction-context 3.1.12", +] + +[[package]] +name = "solana-message" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b" +dependencies = [ + "bincode", + "blake3", + "lazy_static", + "serde", + "serde_derive", + "solana-bincode 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-short-vec 2.2.1", + "solana-system-interface 1.0.0", + "solana-transaction-error 2.2.1", + "wasm-bindgen", ] [[package]] @@ -7013,11 +8479,11 @@ dependencies = [ "serde_derive", "solana-address 2.6.0", "solana-hash 4.3.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-short-vec", - "solana-transaction-error", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", + "solana-transaction-error 3.2.0", ] [[package]] @@ -7036,6 +8502,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "solana-msg" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092" +dependencies = [ + "solana-define-syscall 2.3.0", +] + [[package]] name = "solana-msg" version = "3.1.0" @@ -7045,12 +8520,32 @@ dependencies = [ "solana-define-syscall 5.0.0", ] +[[package]] +name = "solana-native-token" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61515b880c36974053dd499c0510066783f0cc6ac17def0c7ef2a244874cf4a9" + [[package]] name = "solana-native-token" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae8dd4c280dca9d046139eb5b7a5ac9ad10403fbd64964c7d7571214950d758f" +[[package]] +name = "solana-nonce" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703e22eb185537e06204a5bd9d509b948f0066f2d1d814a6f475dafb3ddf1325" +dependencies = [ + "serde", + "serde_derive", + "solana-fee-calculator 2.2.1", + "solana-hash 2.3.0", + "solana-pubkey 2.4.0", + "solana-sha256-hasher 2.3.0", +] + [[package]] name = "solana-nonce" version = "3.2.0" @@ -7059,7 +8554,7 @@ checksum = "d95dbc9f2e33b6c10e231df15cb2a3bff9ea7eab6347f9e316fe75c97fd67bbb" dependencies = [ "serde", "serde_derive", - "solana-fee-calculator", + "solana-fee-calculator 3.2.0", "solana-hash 4.3.0", "solana-pubkey 4.2.0", "solana-sha256-hasher 3.1.0", @@ -7071,10 +8566,19 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "805fd25b29e5a1a0e6c3dd6320c9da80f275fbe4ff6e392617c303a2085c435e" dependencies = [ - "solana-account", + "solana-account 3.4.0", "solana-hash 3.1.0", - "solana-nonce", - "solana-sdk-ids", + "solana-nonce 3.2.0", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-nostd-keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ced70920435b1baa58f76e6f84bbc1110ddd1d6161ec76b6d731ae8431e9c4" +dependencies = [ + "sha3", ] [[package]] @@ -7098,8 +8602,8 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", "solana-sha256-hasher 3.1.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", ] [[package]] @@ -7141,8 +8645,88 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f704eaf825be3180832445b9e4983b875340696e8e7239bf2d535b0f86c14a2" dependencies = [ "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", +] + +[[package]] +name = "solana-program" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98eca145bd3545e2fbb07166e895370576e47a00a7d824e325390d33bf467210" +dependencies = [ + "bincode", + "blake3", + "borsh 0.10.4", + "borsh 1.6.1", + "bs58", + "bytemuck", + "console_error_panic_hook", + "console_log", + "getrandom 0.2.17", + "lazy_static", + "log", + "memoffset", + "num-bigint 0.4.6", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info 2.3.0", + "solana-address-lookup-table-interface 2.2.2", + "solana-atomic-u64 2.2.1", + "solana-big-mod-exp 2.2.1", + "solana-bincode 2.2.1", + "solana-blake3-hasher 2.2.1", + "solana-borsh 2.2.1", + "solana-clock 2.2.3", + "solana-cpi 2.2.1", + "solana-decode-error", + "solana-define-syscall 2.3.0", + "solana-epoch-rewards 2.2.1", + "solana-epoch-schedule 2.2.1", + "solana-example-mocks 2.2.1", + "solana-feature-gate-interface 2.2.2", + "solana-fee-calculator 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-keccak-hasher 2.2.1", + "solana-last-restart-slot 2.2.1", + "solana-loader-v2-interface 2.2.1", + "solana-loader-v3-interface 5.0.0", + "solana-loader-v4-interface 2.2.1", + "solana-message 2.4.0", + "solana-msg 2.2.1", + "solana-native-token 2.3.0", + "solana-nonce 2.2.1", + "solana-program-entrypoint 2.3.0", + "solana-program-error 2.2.2", + "solana-program-memory 2.3.1", + "solana-program-option 2.2.1", + "solana-program-pack 2.2.1", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-secp256k1-recover 2.2.1", + "solana-serde-varint 2.2.2", + "solana-serialize-utils 2.2.1", + "solana-sha256-hasher 2.3.0", + "solana-short-vec 2.2.1", + "solana-slot-hashes 2.2.1", + "solana-slot-history 2.2.1", + "solana-stable-layout 2.2.1", + "solana-stake-interface 1.2.1", + "solana-system-interface 1.0.0", + "solana-sysvar 2.3.0", + "solana-sysvar-id 2.2.1", + "solana-vote-interface 2.2.6", + "thiserror 2.0.18", + "wasm-bindgen", ] [[package]] @@ -7152,44 +8736,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91b12305dd81045d705f427acd0435a2e46444b65367d7179d7bdcfc3bc5f5eb" dependencies = [ "memoffset", - "solana-account-info", - "solana-big-mod-exp", - "solana-blake3-hasher", - "solana-borsh", - "solana-clock", - "solana-cpi", + "solana-account-info 3.1.1", + "solana-big-mod-exp 3.0.0", + "solana-blake3-hasher 3.1.0", + "solana-borsh 3.0.2", + "solana-clock 3.0.1", + "solana-cpi 3.1.0", "solana-define-syscall 3.0.0", - "solana-epoch-rewards", - "solana-epoch-schedule", + "solana-epoch-rewards 3.0.1", + "solana-epoch-schedule 3.1.0", "solana-epoch-stake", - "solana-example-mocks", - "solana-fee-calculator", + "solana-example-mocks 3.0.0", + "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-instruction-error", - "solana-instructions-sysvar", - "solana-keccak-hasher", - "solana-last-restart-slot", - "solana-msg", - "solana-native-token", - "solana-program-entrypoint", - "solana-program-error", - "solana-program-memory", - "solana-program-option", - "solana-program-pack", + "solana-instructions-sysvar 3.0.0", + "solana-keccak-hasher 3.1.0", + "solana-last-restart-slot 3.0.0", + "solana-msg 3.1.0", + "solana-native-token 3.0.0", + "solana-program-entrypoint 3.1.1", + "solana-program-error 3.0.1", + "solana-program-memory 3.1.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-secp256k1-recover", - "solana-serde-varint", - "solana-serialize-utils", + "solana-sdk-ids 3.1.0", + "solana-secp256k1-recover 3.1.1", + "solana-serde-varint 3.0.1", + "solana-serialize-utils 3.1.1", "solana-sha256-hasher 3.1.0", - "solana-short-vec", - "solana-slot-hashes", - "solana-slot-history", - "solana-stable-layout", - "solana-sysvar", - "solana-sysvar-id", + "solana-short-vec 3.2.0", + "solana-slot-hashes 3.0.1", + "solana-slot-history 3.0.0", + "solana-stable-layout 3.0.1", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-program-entrypoint" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ce041b1a0ed275290a5008ee1a4a6c48f5054c8a3d78d313c08958a06aedbd" +dependencies = [ + "solana-account-info 2.3.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", ] [[package]] @@ -7198,23 +8794,48 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c9b0a1ff494e05f503a08b3d51150b73aa639544631e510279d6375f290997" dependencies = [ - "solana-account-info", + "solana-account-info 3.1.1", "solana-define-syscall 4.0.1", - "solana-program-error", + "solana-program-error 3.0.1", "solana-pubkey 4.2.0", ] +[[package]] +name = "solana-program-error" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" +dependencies = [ + "borsh 1.6.1", + "num-traits", + "serde", + "serde_derive", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-pubkey 2.4.0", +] + [[package]] name = "solana-program-error" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f04fa578707b3612b095f0c8e19b66a1233f7c42ca8082fcb3b745afcc0add6" dependencies = [ - "borsh", + "borsh 1.6.1", "serde", "serde_derive", ] +[[package]] +name = "solana-program-memory" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a5426090c6f3fd6cfdc10685322fede9ca8e5af43cd6a59e98bfe4e91671712" +dependencies = [ + "solana-define-syscall 2.3.0", +] + [[package]] name = "solana-program-memory" version = "3.1.0" @@ -7224,25 +8845,40 @@ dependencies = [ "solana-define-syscall 4.0.1", ] +[[package]] +name = "solana-program-option" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc677a2e9bc616eda6dbdab834d463372b92848b2bfe4a1ed4e4b4adba3397d0" + [[package]] name = "solana-program-option" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a88006a9b8594088cec9027ab77caaaa258a2aaa2083d3f086c44b42e50aeab" +[[package]] +name = "solana-program-pack" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "319f0ef15e6e12dc37c597faccb7d62525a509fec5f6975ecb9419efddeb277b" +dependencies = [ + "solana-program-error 2.2.2", +] + [[package]] name = "solana-program-pack" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7701cb15b90667ae1c89ef4ac35a59c61e66ce58ddee13d729472af7f41d59" dependencies = [ - "solana-program-error", + "solana-program-error 3.0.1", ] [[package]] name = "solana-program-runtime" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "base64 0.22.1", "bincode", @@ -7251,38 +8887,64 @@ dependencies = [ "percentage", "rand 0.8.5", "serde", - "solana-account", - "solana-account-info", - "solana-clock", - "solana-epoch-rewards", - "solana-epoch-schedule", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", + "solana-epoch-rewards 3.0.1", + "solana-epoch-schedule 3.1.0", "solana-fee-structure", "solana-hash 3.1.0", - "solana-instruction", - "solana-last-restart-slot", - "solana-loader-v3-interface", - "solana-program-entrypoint", + "solana-instruction 3.4.0", + "solana-last-restart-slot 3.0.0", + "solana-loader-v3-interface 6.1.1", + "solana-program-entrypoint 3.1.1", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", - "solana-sdk-ids", - "solana-slot-hashes", - "solana-stable-layout", - "solana-stake-interface", + "solana-sdk-ids 3.1.0", + "solana-slot-hashes 3.0.1", + "solana-stable-layout 3.0.1", + "solana-stake-interface 2.0.2", "solana-svm-callback", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-timings", "solana-svm-transaction", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-sysvar", - "solana-sysvar-id", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", ] +[[package]] +name = "solana-pubkey" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1" +dependencies = [ + "borsh 0.10.4", + "borsh 1.6.1", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "five8 0.2.1", + "five8_const 0.1.4", + "getrandom 0.2.17", + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-atomic-u64 2.2.1", + "solana-decode-error", + "solana-define-syscall 2.3.0", + "solana-sanitize 2.2.1", + "solana-sha256-hasher 2.3.0", + "wasm-bindgen", +] + [[package]] name = "solana-pubkey" version = "3.0.0" @@ -7315,11 +8977,11 @@ dependencies = [ "semver", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-clock", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.0.1", "solana-pubkey 3.0.0", - "solana-rpc-client-types", - "solana-signature", + "solana-rpc-client-types 3.1.12", + "solana-signature 3.4.0", "thiserror 2.0.18", "tokio", "tokio-stream", @@ -7328,6 +8990,19 @@ dependencies = [ "url", ] +[[package]] +name = "solana-rent" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1aea8fdea9de98ca6e8c2da5827707fb3842833521b528a713810ca685d2480" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", +] + [[package]] name = "solana-rent" version = "3.1.0" @@ -7336,9 +9011,9 @@ checksum = "e860d5499a705369778647e97d760f7670adfb6fc8419dd3d568deccd46d5487" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -7347,7 +9022,17 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9809b081e99bc142ce803bcd7ee18306759ce3b30a96a9da3f6f41c45e50ef0" dependencies = [ - "solana-sdk-macro", + "solana-sdk-macro 3.0.1", +] + +[[package]] +name = "solana-reward-info" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18205b69139b1ae0ab8f6e11cdcb627328c0814422ad2482000fa2ca54ae4a2f" +dependencies = [ + "serde", + "serde_derive", ] [[package]] @@ -7360,6 +9045,46 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-rpc-client" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d3161ac0918178e674c1f7f1bfac40de3e7ed0383bd65747d63113c156eaeb" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bincode", + "bs58", + "futures", + "indicatif 0.17.11", + "log", + "reqwest 0.12.28", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account 2.2.1", + "solana-account-decoder-client-types 2.3.13", + "solana-clock 2.2.3", + "solana-commitment-config 2.2.1", + "solana-epoch-info 2.2.1", + "solana-epoch-schedule 2.2.1", + "solana-feature-gate-interface 2.2.2", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-message 2.4.0", + "solana-pubkey 2.4.0", + "solana-rpc-client-api 2.3.13", + "solana-signature 2.3.0", + "solana-transaction 2.2.3", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "solana-version 2.3.13", + "solana-vote-interface 2.2.6", + "tokio", +] + [[package]] name = "solana-rpc-client" version = "3.1.12" @@ -7371,35 +9096,57 @@ dependencies = [ "bincode", "bs58", "futures", - "indicatif", + "indicatif 0.18.4", "log", "reqwest 0.12.28", "reqwest-middleware", "semver", "serde", "serde_json", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-account-decoder-client-types", - "solana-clock", - "solana-commitment-config", - "solana-epoch-info", - "solana-epoch-schedule", - "solana-feature-gate-interface", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-epoch-info 3.1.0", + "solana-epoch-schedule 3.1.0", + "solana-feature-gate-interface 3.1.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-message", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client-api", - "solana-signature", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", - "solana-version", - "solana-vote-interface", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", + "solana-version 3.1.12", + "solana-vote-interface 4.0.4", "tokio", ] +[[package]] +name = "solana-rpc-client-api" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dbc138685c79d88a766a8fd825057a74ea7a21e1dd7f8de275ada899540fff7" +dependencies = [ + "anyhow", + "jsonrpc-core", + "reqwest 0.12.28", + "reqwest-middleware", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types 2.3.13", + "solana-clock 2.2.3", + "solana-rpc-client-types 2.3.13", + "solana-signer 2.2.1", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "thiserror 2.0.18", +] + [[package]] name = "solana-rpc-client-api" version = "3.1.12" @@ -7412,12 +9159,38 @@ dependencies = [ "reqwest-middleware", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-clock", - "solana-rpc-client-types", - "solana-signer", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.0.1", + "solana-rpc-client-types 3.1.12", + "solana-signer 3.0.0", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-rpc-client-types" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea428a81729255d895ea47fba9b30fd4dacbfe571a080448121bd0592751676" +dependencies = [ + "base64 0.22.1", + "bs58", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account 2.2.1", + "solana-account-decoder-client-types 2.3.13", + "solana-clock 2.2.3", + "solana-commitment-config 2.2.1", + "solana-fee-calculator 2.2.1", + "solana-inflation 2.2.1", + "solana-pubkey 2.4.0", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "solana-version 2.3.13", + "spl-generic-token 1.0.1", "thiserror 2.0.18", ] @@ -7432,19 +9205,19 @@ dependencies = [ "semver", "serde", "serde_json", - "solana-account", - "solana-account-decoder-client-types", + "solana-account 3.4.0", + "solana-account-decoder-client-types 3.1.12", "solana-address 1.1.0", - "solana-clock", - "solana-commitment-config", - "solana-fee-calculator", - "solana-inflation", - "solana-reward-info", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", - "solana-version", - "spl-generic-token", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-fee-calculator 3.2.0", + "solana-inflation 3.1.0", + "solana-reward-info 3.0.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", + "solana-version 3.1.12", + "spl-generic-token 2.0.1", "thiserror 2.0.18", ] @@ -7467,7 +9240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15b079e08471a9dbfe1e48b2c7439c85aa2a055cbd54eddd8bd257b0a7dbb29" dependencies = [ "byteorder", - "combine", + "combine 3.8.1", "hash32", "libc", "log", @@ -7486,35 +9259,44 @@ dependencies = [ "bincode", "bs58", "serde", - "solana-account", - "solana-epoch-info", + "solana-account 3.4.0", + "solana-epoch-info 3.1.0", "solana-epoch-rewards-hasher", "solana-fee-structure", - "solana-inflation", - "solana-keypair", - "solana-message", + "solana-inflation 3.1.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-offchain-message", "solana-presigner", - "solana-program", - "solana-program-memory", + "solana-program 3.0.0", + "solana-program-memory 3.1.0", "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-seed-derivable", - "solana-seed-phrase", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", "solana-serde", - "solana-serde-varint", - "solana-short-vec", + "solana-serde-varint 3.0.1", + "solana-short-vec 3.2.0", "solana-shred-version", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-time-utils 3.0.0", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] +[[package]] +name = "solana-sdk-ids" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5d8b9cc68d5c88b062a33e23a6466722467dde0035152d8fb1afbcdf350a5f" +dependencies = [ + "solana-pubkey 2.4.0", +] + [[package]] name = "solana-sdk-ids" version = "3.1.0" @@ -7524,6 +9306,18 @@ dependencies = [ "solana-address 2.6.0", ] +[[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", + "quote", + "syn 2.0.117", +] + [[package]] name = "solana-sdk-macro" version = "3.0.1" @@ -7547,7 +9341,18 @@ dependencies = [ "serde", "serde_derive", "sha3", - "solana-signature", + "solana-signature 3.4.0", +] + +[[package]] +name = "solana-secp256k1-recover" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" +dependencies = [ + "libsecp256k1", + "solana-define-syscall 2.3.0", + "thiserror 2.0.18", ] [[package]] @@ -7569,8 +9374,26 @@ checksum = "445d8e12592631d76fc4dc57858bae66c9fd7cc838c306c62a472547fc9d0ce6" dependencies = [ "bytemuck", "openssl", - "solana-instruction", - "solana-sdk-ids", + "solana-instruction 3.4.0", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-security-txt" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "156bb61a96c605fa124e052d630dba2f6fb57e08c7d15b757e1e958b3ed7b3fe" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "solana-seed-derivable" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beb82b5adb266c6ea90e5cf3967235644848eac476c5a1f2f9283a143b7c97f" +dependencies = [ + "solana-derivation-path 2.2.1", ] [[package]] @@ -7579,7 +9402,18 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff7bdb72758e3bec33ed0e2658a920f1f35dfb9ed576b951d20d63cb61ecd95c" dependencies = [ - "solana-derivation-path", + "solana-derivation-path 3.0.0", +] + +[[package]] +name = "solana-seed-phrase" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36187af2324f079f65a675ec22b31c24919cb4ac22c79472e85d819db9bbbc15" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "sha2 0.10.9", ] [[package]] @@ -7602,6 +9436,15 @@ dependencies = [ "serde", ] +[[package]] +name = "solana-serde-varint" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7e155eba458ecfb0107b98236088c3764a09ddf0201ec29e52a0be40857113" +dependencies = [ + "serde", +] + [[package]] name = "solana-serde-varint" version = "3.0.1" @@ -7611,6 +9454,17 @@ dependencies = [ "serde", ] +[[package]] +name = "solana-serialize-utils" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "817a284b63197d2b27afdba829c5ab34231da4a9b4e763466a003c40ca4f535e" +dependencies = [ + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", +] + [[package]] name = "solana-serialize-utils" version = "3.1.1" @@ -7644,6 +9498,15 @@ dependencies = [ "solana-hash 4.3.0", ] +[[package]] +name = "solana-short-vec" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c54c66f19b9766a56fa0057d060de8378676cb64987533fa088861858fc5a69" +dependencies = [ + "serde", +] + [[package]] name = "solana-short-vec" version = "3.2.0" @@ -7664,6 +9527,20 @@ dependencies = [ "solana-sha256-hasher 3.1.0", ] +[[package]] +name = "solana-signature" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c" +dependencies = [ + "ed25519-dalek 1.0.1", + "five8 0.2.1", + "serde", + "serde-big-array", + "serde_derive", + "solana-sanitize 2.2.1", +] + [[package]] name = "solana-signature" version = "3.4.0" @@ -7680,6 +9557,17 @@ dependencies = [ "wincode", ] +[[package]] +name = "solana-signer" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c41991508a4b02f021c1342ba00bcfa098630b213726ceadc7cb032e051975b" +dependencies = [ + "solana-pubkey 2.4.0", + "solana-signature 2.3.0", + "solana-transaction-error 2.2.1", +] + [[package]] name = "solana-signer" version = "3.0.0" @@ -7687,8 +9575,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bfea97951fee8bae0d6038f39a5efcb6230ecdfe33425ac75196d1a1e3e3235" dependencies = [ "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-transaction-error 3.2.0", +] + +[[package]] +name = "solana-slot-hashes" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce" +dependencies = [ + "serde", + "serde_derive", + "solana-hash 2.3.0", + "solana-sdk-ids 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -7700,8 +9601,21 @@ dependencies = [ "serde", "serde_derive", "solana-hash 4.3.0", - "solana-sdk-ids", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-slot-history" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ccc1b2067ca22754d5283afb2b0126d61eae734fc616d23871b0943b0d935e" +dependencies = [ + "bv", + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -7713,18 +9627,49 @@ dependencies = [ "bv", "serde", "serde_derive", - "solana-sdk-ids", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-stable-layout" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f14f7d02af8f2bc1b5efeeae71bc1c2b7f0f65cd75bcc7d8180f2c762a57f54" +dependencies = [ + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", +] + +[[package]] +name = "solana-stable-layout" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9f6a291ba063a37780af29e7db14bdd3dc447584d8ba5b3fc4b88e2bbc982fa" +dependencies = [ + "solana-instruction 3.4.0", + "solana-pubkey 4.2.0", ] [[package]] -name = "solana-stable-layout" -version = "3.0.1" +name = "solana-stake-interface" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9f6a291ba063a37780af29e7db14bdd3dc447584d8ba5b3fc4b88e2bbc982fa" +checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c" dependencies = [ - "solana-instruction", - "solana-pubkey 4.2.0", + "borsh 0.10.4", + "borsh 1.6.1", + "num-traits", + "serde", + "serde_derive", + "solana-clock 2.2.3", + "solana-cpi 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-system-interface 1.0.0", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -7736,14 +9681,14 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-clock", - "solana-cpi", - "solana-instruction", - "solana-program-error", + "solana-clock 3.0.1", + "solana-cpi 3.1.0", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "solana-system-interface 2.0.0", - "solana-sysvar", - "solana-sysvar-id", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -7758,12 +9703,12 @@ dependencies = [ "serde", "solana-account-decoder", "solana-hash 3.1.0", - "solana-instruction", - "solana-message", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status", "tonic-prost-build", ] @@ -7771,43 +9716,43 @@ dependencies = [ [[package]] name = "solana-svm" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "ahash 0.8.12", "log", "percentage", "qualifier_attr", "serde", - "solana-account", - "solana-clock", + "solana-account 3.4.0", + "solana-clock 3.0.1", "solana-fee-structure", "solana-hash 3.1.0", - "solana-instruction", - "solana-instructions-sysvar", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-instructions-sysvar 3.0.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-loader-v4-program", - "solana-message", - "solana-nonce", + "solana-message 3.1.0", + "solana-nonce 3.2.0", "solana-nonce-account", - "solana-program-entrypoint", - "solana-program-pack", + "solana-program-entrypoint 3.1.1", + "solana-program-pack 3.1.0", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-callback", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-timings", "solana-svm-transaction", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-sysvar-id", - "solana-transaction-context", - "solana-transaction-error", - "spl-generic-token", + "solana-sysvar-id 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.2.0", + "spl-generic-token 2.0.1", "thiserror 2.0.18", ] @@ -7817,12 +9762,18 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb521c7f62db21661267a933f0d311a76b2b744a766b46f5a9a9395ce70f687c" dependencies = [ - "solana-account", - "solana-clock", + "solana-account 3.4.0", + "solana-clock 3.0.1", "solana-precompile-error", "solana-pubkey 3.0.0", ] +[[package]] +name = "solana-svm-feature-set" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f24b836eb4d74ec255217bdbe0f24f64a07adeac31aca61f334f91cd4a3b1d5" + [[package]] name = "solana-svm-feature-set" version = "3.1.12" @@ -7862,11 +9813,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba32fc24c9dc52ebefb481f2c971149a9624fe071803e9e19fa3bebbc0971ce" dependencies = [ "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-signature", - "solana-transaction", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", ] [[package]] @@ -7878,6 +9829,22 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "solana-system-interface" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d7c18cb1a91c6be5f5a8ac9276a1d7c737e39a21beba9ea710ab4b9c63bc90" +dependencies = [ + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "wasm-bindgen", +] + [[package]] name = "solana-system-interface" version = "2.0.0" @@ -7887,9 +9854,9 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-instruction", - "solana-msg", - "solana-program-error", + "solana-instruction 3.4.0", + "solana-msg 3.1.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", ] @@ -7903,9 +9870,9 @@ dependencies = [ "serde", "serde_derive", "solana-address 2.6.0", - "solana-instruction", - "solana-msg", - "solana-program-error", + "solana-instruction 3.4.0", + "solana-msg 3.1.0", + "solana-program-error 3.0.1", ] [[package]] @@ -7917,21 +9884,21 @@ dependencies = [ "bincode", "log", "serde", - "solana-account", - "solana-bincode", - "solana-fee-calculator", - "solana-instruction", - "solana-nonce", + "solana-account 3.4.0", + "solana-bincode 3.1.0", + "solana-fee-calculator 3.2.0", + "solana-instruction 3.4.0", + "solana-nonce 3.2.0", "solana-nonce-account", "solana-packet", "solana-program-runtime", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-log-collector", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-sysvar", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-transaction-context 3.1.12", ] [[package]] @@ -7941,12 +9908,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31b5699ec533621515e714f1533ee6b3b0e71c463301d919eb59b8c1e249d30" dependencies = [ "solana-hash 3.1.0", - "solana-keypair", - "solana-message", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signer", + "solana-signer 3.0.0", "solana-system-interface 2.0.0", - "solana-transaction", + "solana-transaction 3.1.0", +] + +[[package]] +name = "solana-sysvar" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8c3595f95069f3d90f275bb9bd235a1973c4d059028b0a7f81baca2703815db" +dependencies = [ + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "lazy_static", + "serde", + "serde_derive", + "solana-account-info 2.3.0", + "solana-clock 2.2.3", + "solana-define-syscall 2.3.0", + "solana-epoch-rewards 2.2.1", + "solana-epoch-schedule 2.2.1", + "solana-fee-calculator 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-last-restart-slot 2.2.1", + "solana-program-entrypoint 2.3.0", + "solana-program-error 2.2.2", + "solana-program-memory 2.3.1", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-slot-hashes 2.2.1", + "solana-slot-history 2.2.1", + "solana-stake-interface 1.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -7962,25 +9966,35 @@ dependencies = [ "lazy_static", "serde", "serde_derive", - "solana-account-info", - "solana-clock", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", "solana-define-syscall 4.0.1", - "solana-epoch-rewards", - "solana-epoch-schedule", - "solana-fee-calculator", + "solana-epoch-rewards 3.0.1", + "solana-epoch-schedule 3.1.0", + "solana-fee-calculator 3.2.0", "solana-hash 4.3.0", - "solana-instruction", - "solana-last-restart-slot", - "solana-program-entrypoint", - "solana-program-error", - "solana-program-memory", + "solana-instruction 3.4.0", + "solana-last-restart-slot 3.0.0", + "solana-program-entrypoint 3.1.1", + "solana-program-error 3.0.1", + "solana-program-memory 3.1.0", "solana-pubkey 4.2.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-slot-hashes", - "solana-slot-history", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-slot-hashes 3.0.1", + "solana-slot-history 3.0.0", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-sysvar-id" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5762b273d3325b047cfda250787f8d796d781746860d5d0a746ee29f3e8812c1" +dependencies = [ + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", ] [[package]] @@ -7990,7 +10004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17358d1e9a13e5b9c2264d301102126cf11a47fd394cdf3dec174fe7bc96e1de" dependencies = [ "solana-address 2.6.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", ] [[package]] @@ -8005,6 +10019,31 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ced92c60aa76ec4780a9d93f3bd64dfa916e1b998eacc6f1c110f3f444f02c9" +[[package]] +name = "solana-transaction" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80657d6088f721148f5d889c828ca60c7daeedac9a8679f9ec215e0c42bcbf41" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-bincode 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-keypair 2.2.3", + "solana-message 2.4.0", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-short-vec 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "solana-system-interface 1.0.0", + "solana-transaction-error 2.2.1", + "wasm-bindgen", +] + [[package]] name = "solana-transaction" version = "3.1.0" @@ -8016,32 +10055,61 @@ dependencies = [ "serde_derive", "solana-address 2.6.0", "solana-hash 4.3.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-instruction-error", - "solana-message", + "solana-message 3.1.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-short-vec", - "solana-signature", - "solana-signer", - "solana-transaction-error", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction-error 3.2.0", +] + +[[package]] +name = "solana-transaction-context" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a312304361987a85b2ef2293920558e6612876a639dd1309daf6d0d59ef2fe" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account 2.2.1", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sdk-ids 2.2.1", ] [[package]] name = "solana-transaction-context" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "bincode", "qualifier_attr", "serde", - "solana-account", - "solana-instruction", - "solana-instructions-sysvar", + "solana-account 3.4.0", + "solana-instruction 3.4.0", + "solana-instructions-sysvar 3.0.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-transaction-error" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a9dc8fdb61c6088baab34fc3a8b8473a03a7a5fd404ed8dd502fa79b67cb1" +dependencies = [ + "serde", + "serde_derive", + "solana-instruction 2.3.3", + "solana-sanitize 2.2.1", ] [[package]] @@ -8066,36 +10134,59 @@ dependencies = [ "agave-reserved-account-keys", "base64 0.22.1", "bincode", - "borsh", + "borsh 1.6.1", "bs58", "log", "serde", "serde_json", "solana-account-decoder", - "solana-address-lookup-table-interface", - "solana-clock", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-loader-v2-interface", - "solana-loader-v3-interface", - "solana-message", - "solana-program-option", + "solana-instruction 3.4.0", + "solana-loader-v2-interface 3.0.0", + "solana-loader-v3-interface 6.1.1", + "solana-message 3.1.0", + "solana-program-option 3.1.0", "solana-pubkey 3.0.0", - "solana-reward-info", - "solana-sdk-ids", - "solana-signature", - "solana-stake-interface", + "solana-reward-info 3.0.0", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-stake-interface 2.0.2", "solana-system-interface 2.0.0", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", - "solana-vote-interface", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", + "solana-vote-interface 4.0.4", "spl-associated-token-account-interface", "spl-memo-interface", - "spl-token-2022-interface", - "spl-token-group-interface", + "spl-token-2022-interface 2.1.0", + "spl-token-group-interface 0.7.2", "spl-token-interface", - "spl-token-metadata-interface", + "spl-token-metadata-interface 0.8.0", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-transaction-status-client-types" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f1d7c2387c35850848212244d2b225847666cb52d3bd59a5c409d2c300303d" +dependencies = [ + "base64 0.22.1", + "bincode", + "bs58", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types 2.3.13", + "solana-commitment-config 2.2.1", + "solana-message 2.4.0", + "solana-reward-info 2.2.1", + "solana-signature 2.3.0", + "solana-transaction 2.2.3", + "solana-transaction-context 2.3.13", + "solana-transaction-error 2.2.1", "thiserror 2.0.18", ] @@ -8110,31 +10201,70 @@ dependencies = [ "bs58", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-commitment-config", - "solana-instruction", - "solana-message", + "solana-account-decoder-client-types 3.1.12", + "solana-commitment-config 3.1.1", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-reward-info", - "solana-signature", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-reward-info 3.0.0", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] +[[package]] +name = "solana-version" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3324d46c7f7b7f5d34bf7dc71a2883bdc072c7b28ca81d0b2167ecec4cf8da9f" +dependencies = [ + "agave-feature-set 2.3.13", + "rand 0.8.5", + "semver", + "serde", + "serde_derive", + "solana-sanitize 2.2.1", + "solana-serde-varint 2.2.2", +] + [[package]] name = "solana-version" version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f697aacc5aa4ac5534abdde8a91afdcf18c24d28bd52768e8001445dbda078db" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "rand 0.8.5", "semver", "serde", "solana-sanitize 3.0.1", - "solana-serde-varint", + "solana-serde-varint 3.0.1", +] + +[[package]] +name = "solana-vote-interface" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b80d57478d6599d30acc31cc5ae7f93ec2361a06aefe8ea79bc81739a08af4c3" +dependencies = [ + "bincode", + "num-derive", + "num-traits", + "serde", + "serde_derive", + "solana-clock 2.2.3", + "solana-decode-error", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-serde-varint 2.2.2", + "solana-serialize-utils 2.2.1", + "solana-short-vec 2.2.1", + "solana-system-interface 1.0.0", ] [[package]] @@ -8150,16 +10280,16 @@ dependencies = [ "serde", "serde_derive", "serde_with", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-instruction-error", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-serde-varint", - "solana-serialize-utils", - "solana-short-vec", + "solana-sdk-ids 3.1.0", + "solana-serde-varint 3.0.1", + "solana-serialize-utils 3.1.1", + "solana-short-vec 3.2.0", "solana-system-interface 2.0.0", ] @@ -8169,7 +10299,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5a91404c7de468dd80658cdb5d894ec803d1092ea6e2bfdf84eee6f07559c0d" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", ] @@ -8180,15 +10310,51 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cee65de587e6fe912668903e62f3f40c02a834f21967a18cc6c71f550c51a639" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "bytemuck", "num-derive", "num-traits", - "solana-instruction", + "solana-instruction 3.4.0", "solana-program-runtime", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-log-collector", - "solana-zk-sdk", + "solana-zk-sdk 4.0.0", +] + +[[package]] +name = "solana-zk-sdk" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b9fc6ec37d16d0dccff708ed1dd6ea9ba61796700c3bb7c3b401973f10f63b" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "js-sys", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-derivation-path 2.2.1", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-seed-derivable 2.2.1", + "solana-seed-phrase 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "subtle", + "thiserror 2.0.18", + "wasm-bindgen", + "zeroize", ] [[package]] @@ -8214,14 +10380,14 @@ dependencies = [ "serde_derive", "serde_json", "sha3", - "solana-derivation-path", - "solana-instruction", + "solana-derivation-path 3.0.0", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-signature", - "solana-signer", + "solana-sdk-ids 3.1.0", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "subtle", "thiserror 2.0.18", "wasm-bindgen", @@ -8292,84 +10458,273 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" dependencies = [ - "borsh", - "solana-instruction", + "borsh 1.6.1", + "solana-instruction 3.4.0", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "spl-discriminator" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" +dependencies = [ + "bytemuck", + "solana-program-error 2.2.2", + "solana-sha256-hasher 2.3.0", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e597c5ff9ed7c74a54dbc47bae2f06e4db8c98f4356ad280200dc11878266db1" +dependencies = [ + "bytemuck", + "solana-program-error 3.0.1", + "solana-sha256-hasher 3.1.0", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +dependencies = [ + "quote", + "spl-discriminator-syn", + "syn 2.0.117", +] + +[[package]] +name = "spl-discriminator-syn" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d1dbc82ab91422345b6df40a79e2b78c7bce1ebb366da323572dd60b7076b67" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.9", + "syn 2.0.117", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-elgamal-registry" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce0f668975d2b0536e8a8fd60e56a05c467f06021dae037f1d0cfed0de2e231d" +dependencies = [ + "bytemuck", + "solana-program 2.3.0", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", + "spl-token-confidential-transfer-proof-extraction 0.2.1", +] + +[[package]] +name = "spl-generic-token" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741a62a566d97c58d33f9ed32337ceedd4e35109a686e31b1866c5dfa56abddc" +dependencies = [ + "bytemuck", + "solana-pubkey 2.4.0", +] + +[[package]] +name = "spl-generic-token" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233df81b75ab99b42f002b5cdd6e65a7505ffa930624f7096a7580a56765e9cf" +dependencies = [ + "bytemuck", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "spl-memo" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f09647c0974e33366efeb83b8e2daebb329f0420149e74d3a4bd2c08cf9f7cb" +dependencies = [ + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-entrypoint 2.3.0", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", +] + +[[package]] +name = "spl-memo-interface" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4e2aedd58f858337fa609af5ad7100d4a243fdaf6a40d6eb4c28c5f19505d3" +dependencies = [ + "solana-instruction 3.4.0", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "spl-pod" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d994afaf86b779104b4a95ba9ca75b8ced3fdb17ee934e38cb69e72afbe17799" +dependencies = [ + "borsh 1.6.1", + "bytemuck", + "bytemuck_derive", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-program-option 2.2.1", + "solana-pubkey 2.4.0", + "solana-zk-sdk 2.3.13", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-pod" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f9c6e142cdf1e7e77f480053ec9f0ce989890768ddf91f619b50f39d1b456f5" +dependencies = [ + "borsh 1.6.1", + "bytemuck", + "bytemuck_derive", + "num-derive", + "num-traits", + "num_enum", + "solana-program-error 3.0.1", + "solana-program-option 3.1.0", "solana-pubkey 3.0.0", + "solana-zero-copy", + "solana-zk-sdk 4.0.0", + "thiserror 2.0.18", ] [[package]] -name = "spl-discriminator" -version = "0.5.2" +name = "spl-program-error" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e597c5ff9ed7c74a54dbc47bae2f06e4db8c98f4356ad280200dc11878266db1" +checksum = "9d39b5186f42b2b50168029d81e58e800b690877ef0b30580d107659250da1d1" dependencies = [ - "bytemuck", - "solana-program-error", - "solana-sha256-hasher 3.1.0", - "spl-discriminator-derive", + "num-derive", + "num-traits", + "solana-program 2.3.0", + "spl-program-error-derive", + "thiserror 1.0.69", ] [[package]] -name = "spl-discriminator-derive" -version = "0.2.0" +name = "spl-program-error-derive" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" dependencies = [ + "proc-macro2", "quote", - "spl-discriminator-syn", + "sha2 0.10.9", "syn 2.0.117", ] [[package]] -name = "spl-discriminator-syn" -version = "0.2.1" +name = "spl-tlv-account-resolution" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1dbc82ab91422345b6df40a79e2b78c7bce1ebb366da323572dd60b7076b67" +checksum = "cd99ff1e9ed2ab86e3fd582850d47a739fec1be9f4661cba1782d3a0f26805f3" dependencies = [ - "proc-macro2", - "quote", - "sha2 0.10.9", - "syn 2.0.117", + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-program-error", + "spl-type-length-value 0.7.0", "thiserror 1.0.69", ] [[package]] -name = "spl-generic-token" -version = "2.0.1" +name = "spl-token" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233df81b75ab99b42f002b5cdd6e65a7505ffa930624f7096a7580a56765e9cf" +checksum = "ed320a6c934128d4f7e54fe00e16b8aeaecf215799d060ae14f93378da6dc834" dependencies = [ + "arrayref", "bytemuck", - "solana-pubkey 3.0.0", + "num-derive", + "num-traits", + "num_enum", + "solana-program 2.3.0", + "thiserror 1.0.69", ] [[package]] -name = "spl-memo-interface" -version = "2.0.0" +name = "spl-token-2022" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4e2aedd58f858337fa609af5ad7100d4a243fdaf6a40d6eb4c28c5f19505d3" +checksum = "9048b26b0df0290f929ff91317c83db28b3ef99af2b3493dd35baa146774924c" dependencies = [ - "solana-instruction", - "solana-pubkey 3.0.0", + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program 2.3.0", + "solana-security-txt", + "solana-zk-sdk 2.3.13", + "spl-elgamal-registry", + "spl-memo", + "spl-pod 0.5.1", + "spl-token", + "spl-token-confidential-transfer-ciphertext-arithmetic", + "spl-token-confidential-transfer-proof-extraction 0.2.1", + "spl-token-confidential-transfer-proof-generation 0.3.0", + "spl-token-group-interface 0.5.0", + "spl-token-metadata-interface 0.6.0", + "spl-transfer-hook-interface", + "spl-type-length-value 0.7.0", + "thiserror 2.0.18", ] [[package]] -name = "spl-pod" -version = "0.7.3" +name = "spl-token-2022-interface" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f9c6e142cdf1e7e77f480053ec9f0ce989890768ddf91f619b50f39d1b456f5" +checksum = "62d7ae2ee6b856f8ddcbdc3b3a9f4d2141582bbe150f93e5298ee97e0251fa04" dependencies = [ - "borsh", + "arrayref", "bytemuck", - "bytemuck_derive", "num-derive", "num-traits", "num_enum", - "solana-program-error", - "solana-program-option", - "solana-pubkey 3.0.0", - "solana-zero-copy", - "solana-zk-sdk", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-program-option 2.2.1", + "solana-program-pack 2.2.1", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", + "spl-token-confidential-transfer-proof-extraction 0.4.1", + "spl-token-confidential-transfer-proof-generation 0.4.1", + "spl-token-group-interface 0.6.0", + "spl-token-metadata-interface 0.7.0", + "spl-type-length-value 0.8.0", "thiserror 2.0.18", ] @@ -8384,20 +10739,66 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-account-info", - "solana-instruction", - "solana-program-error", - "solana-program-option", - "solana-program-pack", + "solana-account-info 3.1.1", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-zk-sdk", - "spl-pod", - "spl-token-confidential-transfer-proof-extraction", - "spl-token-confidential-transfer-proof-generation", - "spl-token-group-interface", - "spl-token-metadata-interface", - "spl-type-length-value", + "solana-sdk-ids 3.1.0", + "solana-zk-sdk 4.0.0", + "spl-pod 0.7.3", + "spl-token-confidential-transfer-proof-extraction 0.5.1", + "spl-token-confidential-transfer-proof-generation 0.5.1", + "spl-token-group-interface 0.7.2", + "spl-token-metadata-interface 0.8.0", + "spl-type-length-value 0.9.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-ciphertext-arithmetic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170378693c5516090f6d37ae9bad2b9b6125069be68d9acd4865bbe9fc8499fd" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "solana-curve25519 2.3.13", + "solana-zk-sdk 2.3.13", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff2d6a445a147c9d6dd77b8301b1e116c8299601794b558eafa409b342faf96" +dependencies = [ + "bytemuck", + "solana-curve25519 2.3.13", + "solana-program 2.3.0", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512c85bdbbb4cbcc2038849a9e164c958b16541f252b53ea1a3933191c0a4a1a" +dependencies = [ + "bytemuck", + "solana-account-info 2.3.0", + "solana-curve25519 2.3.13", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", "thiserror 2.0.18", ] @@ -8408,16 +10809,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879a9ebad0d77383d3ea71e7de50503554961ff0f4ef6cbca39ad126e6f6da3a" dependencies = [ "bytemuck", - "solana-account-info", - "solana-curve25519", - "solana-instruction", - "solana-instructions-sysvar", - "solana-msg", - "solana-program-error", + "solana-account-info 3.1.1", + "solana-curve25519 3.1.12", + "solana-instruction 3.4.0", + "solana-instructions-sysvar 3.0.0", + "solana-msg 3.1.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-zk-sdk", - "spl-pod", + "solana-sdk-ids 3.1.0", + "solana-zk-sdk 4.0.0", + "spl-pod 0.7.3", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3597628b0d2fe94e7900fd17cdb4cfbb31ee35c66f82809d27d86e44b2848b" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk 2.3.13", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa27b9174bea869a7ebf31e0be6890bce90b1a4288bc2bbf24bd413f80ae3fde" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk 2.3.13", "thiserror 2.0.18", ] @@ -8428,7 +10851,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0cd59fce3dc00f563c6fa364d67c3f200d278eae681f4dc250240afcfe044b1" dependencies = [ "curve25519-dalek 4.1.3", - "solana-zk-sdk", + "solana-zk-sdk 4.0.0", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d595667ed72dbfed8c251708f406d7c2814a3fa6879893b323d56a10bedfc799" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5597b4cd76f85ce7cd206045b7dc22da8c25516573d42d267c8d1fd128db5129" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", "thiserror 2.0.18", ] @@ -8443,11 +10904,11 @@ dependencies = [ "num-traits", "num_enum", "solana-address 2.6.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-nullable", - "solana-program-error", + "solana-program-error 3.0.1", "solana-zero-copy", - "spl-discriminator", + "spl-discriminator 0.5.2", "thiserror 2.0.18", ] @@ -8462,12 +10923,54 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-instruction", - "solana-program-error", - "solana-program-option", - "solana-program-pack", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb9c89dbc877abd735f05547dcf9e6e12c00c11d6d74d8817506cab4c99fdbb" +dependencies = [ + "borsh 1.6.1", + "num-derive", + "num-traits", + "solana-borsh 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-type-length-value 0.7.0", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304d6e06f0de0c13a621464b1fd5d4b1bebf60d15ca71a44d3839958e0da16ee" +dependencies = [ + "borsh 1.6.1", + "num-derive", + "num-traits", + "solana-borsh 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-type-length-value 0.8.0", "thiserror 2.0.18", ] @@ -8477,16 +10980,77 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c467c7c3bd056f8fe60119e7ec34ddd6f23052c2fa8f1f51999098063b72676" dependencies = [ - "borsh", + "borsh 1.6.1", "num-derive", "num-traits", - "solana-borsh", - "solana-instruction", - "solana-program-error", + "solana-borsh 3.0.2", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", - "spl-discriminator", - "spl-pod", - "spl-type-length-value", + "spl-discriminator 0.5.2", + "spl-pod 0.7.3", + "spl-type-length-value 0.9.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa7503d52107c33c88e845e1351565050362c2314036ddf19a36cd25137c043" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-program-error", + "spl-tlv-account-resolution", + "spl-type-length-value 0.7.0", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-type-length-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba70ef09b13af616a4c987797870122863cba03acc4284f226a4473b043923f9" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-type-length-value" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d417eb548214fa822d93f84444024b4e57c13ed6719d4dcc68eec24fb481e9f5" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", "thiserror 2.0.18", ] @@ -8500,10 +11064,10 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-account-info", - "solana-program-error", + "solana-account-info 3.1.1", + "solana-program-error 3.0.1", "solana-zero-copy", - "spl-discriminator", + "spl-discriminator 0.5.2", "thiserror 2.0.18", ] @@ -8703,15 +11267,15 @@ dependencies = [ "magicblock-core", "magicblock-ledger", "magicblock-processor", - "solana-account", - "solana-instruction", - "solana-keypair", - "solana-program", - "solana-rpc-client", - "solana-signature", - "solana-signer", - "solana-transaction", - "solana-transaction-status-client-types", + "solana-account 3.4.0", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-program 3.0.0", + "solana-rpc-client 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", + "solana-transaction-status-client-types 3.1.12", "tempfile", "tokio", "tracing", @@ -8922,12 +11486,21 @@ dependencies = [ "futures-io", "futures-sink", "futures-util", - "hashbrown 0.15.5", + "hashbrown 0.15.2", "pin-project-lite", "slab", "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.23" @@ -9505,6 +12078,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -9621,6 +12204,19 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasmparser" version = "0.244.0" @@ -9628,7 +12224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags 2.11.0", - "hashbrown 0.15.5", + "hashbrown 0.15.2", "indexmap 2.14.0", "semver", ] @@ -9653,6 +12249,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -9693,6 +12298,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -9836,6 +12450,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -9881,6 +12504,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -9938,6 +12576,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -9956,6 +12600,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -9974,6 +12624,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -10004,6 +12660,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -10022,6 +12684,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -10040,6 +12708,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -10058,6 +12732,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" diff --git a/Cargo.toml b/Cargo.toml index 77c913027..7f4d1f91e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,8 @@ split-debuginfo = "packed" [workspace] members = [ + "compressed-delegation-api", + "compressed-delegation-client", "magicblock-account-cloner", "magicblock-accounts", "magicblock-accounts-db", @@ -32,7 +34,7 @@ members = [ "tools/genx", "tools/keypair-base58", "tools/ledger-stats", - "tools/magicblock-tui-client" + "tools/magicblock-tui-client", ] # This prevents a Travis CI error when building for Windows. @@ -58,10 +60,13 @@ async-trait = "0.1.77" base64 = "0.21.7" bincode = "1.3.3" borsh = { version = "1.5.1", features = ["derive", "unstable__schema"] } +borsh10 = { package = "borsh", version = "0.10.4" } bs58 = "0.5.1" byteorder = "1.5.0" chrono = "0.4" clap = "4.5.40" +compressed-delegation-api = { path = "./compressed-delegation-api" } +compressed-delegation-client = { path = "./compressed-delegation-client" } console-subscriber = "0.5.0" derive_more = "2.0" ed25519-dalek = "1.0.1" @@ -86,6 +91,11 @@ json = { package = "sonic-rs", version = "0.5.3" } lazy_static = "1.4.0" libc = "0.2.153" libloading = "0.8" +light-client = "0.23" +light-compressed-account = "0.11" +light-hasher = "5" +light-sdk = "0.23" +light-sdk-types = "0.23" # Only used in magicblock-ledger for solana_metrics::datapoint_info! log = { version = "0.4.20" } lru = "0.16.0" @@ -97,7 +107,7 @@ magicblock-aperture = { path = "./magicblock-aperture" } magicblock-api = { path = "./magicblock-api" } magicblock-chainlink = { path = "./magicblock-chainlink" } magicblock-committor-program = { path = "./magicblock-committor-program", features = [ - "no-entrypoint" + "no-entrypoint", ] } magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } @@ -139,7 +149,7 @@ serde_json = "1.0" serde_with = "3.16" serial_test = "3.2" sha3 = "0.10.8" -solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } +solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } solana-account-decoder = { version = "3.1" } solana-account-decoder-client-types = { version = "3.1" } solana-account-info = { version = "3.1" } @@ -150,6 +160,7 @@ solana-commitment-config = { version = "3.1" } solana-compute-budget = { version = "3.1" } solana-compute-budget-interface = { version = "3.0" } solana-compute-budget-program = { version = "3.1" } +solana-cpi = { version = "3.1" } solana-feature-gate-interface = { version = "3.1" } solana-feature-set = { package = "agave-feature-set", version = "3.1" } solana-fee-calculator = { version = "3.1" } @@ -168,9 +179,10 @@ solana-metrics = { version = "2.3.13" } solana-native-token = { version = "3.0" } solana-precompile-error = "3.0" solana-program = "3.0" +solana-program-error = { version = "3.0" } solana-program-option = { version = "3.0" } solana-program-pack = { version = "3.0" } -solana-program-runtime = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } +solana-program-runtime = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } solana-pubkey = { version = "3.0" } solana-pubsub-client = { version = "3.1" } solana-rent = { version = "3.0" } @@ -192,8 +204,8 @@ solana-system-transaction = { version = "3.0" } solana-sysvar = { version = "3.0" } solana-timings = { package = "solana-svm-timings", version = "3.1" } solana-transaction = { version = "3.0" } -solana-transaction-context = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3", features = [ - "dev-context-only-utils" +solana-transaction-context = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed", features = [ + "dev-context-only-utils", ] } solana-transaction-error = { version = "3.0" } solana-transaction-status = { version = "3.1" } @@ -212,7 +224,10 @@ tonic-prost-build = "0.14" tracing = "0.1" tracing-log = { version = "0.2", features = ["log-tracer"] } tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } -twox-hash = { version = "2.1", default-features = false, features = ["alloc", "xxhash3_64"] } +twox-hash = { version = "2.1", default-features = false, features = [ + "alloc", + "xxhash3_64", +] } url = "2.5.0" # SPL Token crates used across the workspace @@ -220,7 +235,7 @@ spl-token = { package = "spl-token-interface", version = "2.0" } spl-token-2022 = { package = "spl-token-2022-interface", version = "2.1" } [workspace.dependencies.solana-svm] -branch = "v3" +branch = "fix/v3-compressed" features = ["dev-context-only-utils"] git = "https://github.com/magicblock-labs/magicblock-svm.git" @@ -233,11 +248,11 @@ version = "0.22.0" # some solana dependencies have solana-storage-proto as dependency # we need to patch them with our version, because they use protobuf-src v1.1.0 # and we use protobuf-src v2.1.1. Otherwise compilation fails -solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } -solana-program-runtime = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } +solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } +solana-program-runtime = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } solana-storage-proto = { path = "./storage-proto" } -solana-svm = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } -solana-transaction-context = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } +solana-svm = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } +solana-transaction-context = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } # Fork is used to enable `disable_manual_compaction` usage # Fork is based on commit d4e9e16 of rocksdb (parent commit of 0.23.0 release) # without patching update isn't possible due to conflict with solana deps diff --git a/compressed-delegation-api/Cargo.toml b/compressed-delegation-api/Cargo.toml new file mode 100644 index 000000000..00dc3a37b --- /dev/null +++ b/compressed-delegation-api/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "compressed-delegation-api" +version = "0.1.0" +edition = "2021" +license-file = "../../LICENSE" +publish = false + +[dependencies] +borsh = { workspace = true, features = ["derive"] } +# borsh10 = { workspace = true } +light-compressed-account = { workspace = true } +light-hasher = { workspace = true, features = ["solana"] } +light-sdk = { workspace = true, features = ["v2"] } +solana-pubkey = { workspace = true, features = ["borsh"] } diff --git a/compressed-delegation-api/src/instruction.rs b/compressed-delegation-api/src/instruction.rs new file mode 100644 index 000000000..b56337796 --- /dev/null +++ b/compressed-delegation-api/src/instruction.rs @@ -0,0 +1,279 @@ +use std::io::{Read, Write}; + +use borsh::{BorshDeserialize, BorshSerialize}; +use light_sdk::instruction::{ + account_meta::CompressedAccountMeta, CompressedProof, + PackedAddressTreeInfo, PackedStateTreeInfo, ValidityProof, +}; +use solana_pubkey::Pubkey; + +use crate::state::CompressedDelegationRecord; + +/// Instruction discriminators for the compressed delegation program (`u64`). +#[repr(u64)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum CompressedDelegationInstructionDiscriminator { + InitDelegationRecord = 0, + Delegate = 1, + CommitAndFinalize = 2, + Undelegate = 3, +} + +impl CompressedDelegationInstructionDiscriminator { + pub fn from_u64(value: u64) -> Option { + match value { + 0 => Some(Self::InitDelegationRecord), + 1 => Some(Self::Delegate), + 2 => Some(Self::CommitAndFinalize), + 3 => Some(Self::Undelegate), + _ => None, + } + } +} + +#[derive(Clone, Debug)] +pub enum CompressedDelegationProgramInstruction { + /// Delegate the compressed account to a validator. + InitDelegationRecord { args: InitDelegationRecordArgs }, + + /// Delegate the compressed account to a validator. + Delegate { args: DelegateArgs }, + + /// Commit the compressed account. + CommitAndFinalize { args: CommitAndFinalizeArgs }, + + /// Undelegate the compressed account. + Undelegate { args: UndelegateArgs }, +} + +impl CompressedDelegationProgramInstruction { + /// Discriminator for this instruction (first `u64` in serialized form). + pub fn discriminator( + &self, + ) -> CompressedDelegationInstructionDiscriminator { + match self { + Self::InitDelegationRecord { .. } => { + CompressedDelegationInstructionDiscriminator::InitDelegationRecord + } + Self::Delegate { .. } => CompressedDelegationInstructionDiscriminator::Delegate, + Self::CommitAndFinalize { .. } => CompressedDelegationInstructionDiscriminator::CommitAndFinalize, + Self::Undelegate { .. } => CompressedDelegationInstructionDiscriminator::Undelegate, + } + } +} + +impl BorshSerialize for CompressedDelegationProgramInstruction { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + (self.discriminator() as u64).serialize(writer)?; + match self { + Self::InitDelegationRecord { args } => args.serialize(writer), + Self::Delegate { args } => args.serialize(writer), + Self::CommitAndFinalize { args } => args.serialize(writer), + Self::Undelegate { args } => args.serialize(writer), + } + } +} + +impl BorshDeserialize for CompressedDelegationProgramInstruction { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let raw = u64::deserialize_reader(reader)?; + let disc = CompressedDelegationInstructionDiscriminator::from_u64(raw) + .ok_or_else(|| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Invalid CompressedDelegationProgramInstruction discriminant", + ) + })?; + Ok(match disc { + CompressedDelegationInstructionDiscriminator::InitDelegationRecord => { + Self::InitDelegationRecord { + args: InitDelegationRecordArgs::deserialize_reader(reader)?, + } + } + CompressedDelegationInstructionDiscriminator::Delegate => Self::Delegate { + args: DelegateArgs::deserialize_reader(reader)?, + }, + CompressedDelegationInstructionDiscriminator::CommitAndFinalize => Self::CommitAndFinalize { + args: CommitAndFinalizeArgs::deserialize_reader(reader)?, + }, + CompressedDelegationInstructionDiscriminator::Undelegate => Self::Undelegate { + args: UndelegateArgs::deserialize_reader(reader)?, + }, + }) + } +} + +#[repr(C)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Default, Debug, PartialEq, +)] +pub struct InitDelegationRecordArgs { + /// The proof of the account data + pub validity_proof: CdpValidityProof, + /// Address tree info + pub address_tree_info: CdpPackedAddressTreeInfo, + /// Output state tree index + pub output_state_tree_index: u8, + /// Owner program id + pub owner_program_id: Pubkey, + /// PDA seeds + pub pda_seeds: Vec>, + /// Bump + pub bump: u8, +} + +#[repr(C)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Default, Debug, PartialEq, +)] +pub struct DelegateArgs { + /// The proof of the account data + pub validity_proof: CdpValidityProof, + /// Account meta + pub account_meta: CdpCompressedAccountMeta, + /// Owner program id + pub owner_program_id: Pubkey, + /// Validator + pub validator: Pubkey, + /// Original lamports of the account + pub lamports: u64, + /// Account data before delegation + pub account_data: Vec, + /// PDA seeds + pub pda_seeds: Vec>, + /// Bump + pub bump: u8, +} + +#[repr(C)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Default, Debug, PartialEq, +)] +pub struct CommitAndFinalizeArgs { + /// The current data of the compressed delegated account + pub current_compressed_delegated_account_data: Vec, + /// The new state of the compressed delegated account data + pub new_data: Vec, + /// Compressed account meta + pub account_meta: CdpCompressedAccountMeta, + /// Validity proof + pub validity_proof: CdpValidityProof, + /// Update nonce + pub update_nonce: u64, + /// Allow undelegation + pub allow_undelegation: bool, +} + +#[derive( + BorshSerialize, BorshDeserialize, Clone, Default, Debug, PartialEq, +)] +pub struct UndelegateArgs { + /// The proof of the account data + pub validity_proof: CdpValidityProof, + /// Delegation record account meta + pub delegation_record_account_meta: CdpCompressedAccountMeta, + /// Compressed delegated record + pub compressed_delegated_record: CompressedDelegationRecord, +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, PartialEq)] +pub struct ExternalUndelegateArgs { + /// The delegation record + pub delegation_record: CompressedDelegationRecord, +} + +/// Reimplementations of the types from light-sdk for borsh compatibility + +#[derive( + BorshSerialize, BorshDeserialize, Clone, Copy, Debug, Default, PartialEq, +)] +pub struct CdpValidityProof(pub Option<[u8; 128]>); + +impl From for ValidityProof { + fn from(cdp_validity_proof: CdpValidityProof) -> Self { + Self( + cdp_validity_proof + .0 + .and_then(|bytes| CompressedProof::try_from(&bytes[..]).ok()), + ) + } +} + +impl From for CdpValidityProof { + fn from(vp: ValidityProof) -> Self { + Self(vp.0.map(|proof| proof.to_array())) + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Copy, Debug, PartialEq)] +pub struct CdpCompressedAccountMeta(pub [u8; 42]); + +impl From for CdpCompressedAccountMeta { + fn from(cam: CompressedAccountMeta) -> Self { + let mut bytes = [0u8; 42]; + bytes[0..2].copy_from_slice(&cam.tree_info.root_index.to_le_bytes()); + bytes[2] = cam.tree_info.prove_by_index as u8; + bytes[3] = cam.tree_info.merkle_tree_pubkey_index; + bytes[4] = cam.tree_info.queue_pubkey_index; + bytes[5..9].copy_from_slice(&cam.tree_info.leaf_index.to_le_bytes()); + bytes[9..41].copy_from_slice(&cam.address); + bytes[41] = cam.output_state_tree_index; + Self(bytes) + } +} + +impl TryFrom for CompressedAccountMeta { + type Error = core::array::TryFromSliceError; + fn try_from(cam: CdpCompressedAccountMeta) -> Result { + Ok(Self { + tree_info: PackedStateTreeInfo { + root_index: u16::from_le_bytes(cam.0[0..2].try_into()?), + prove_by_index: cam.0[2] != 0, + merkle_tree_pubkey_index: cam.0[3], + queue_pubkey_index: cam.0[4], + leaf_index: u32::from_le_bytes(cam.0[5..9].try_into()?), + }, + address: cam.0[9..41].try_into()?, + output_state_tree_index: cam.0[41], + }) + } +} + +impl Default for CdpCompressedAccountMeta { + fn default() -> Self { + Self([0u8; 42]) + } +} + +#[derive( + BorshSerialize, BorshDeserialize, Clone, Copy, Debug, Default, PartialEq, +)] +pub struct CdpPackedAddressTreeInfo(pub [u8; 4]); + +impl From for CdpPackedAddressTreeInfo { + fn from(pati: PackedAddressTreeInfo) -> Self { + let mut bytes = [0u8; 4]; + bytes[0..1].copy_from_slice( + &pati.address_merkle_tree_pubkey_index.to_le_bytes(), + ); + bytes[1..2] + .copy_from_slice(&pati.address_queue_pubkey_index.to_le_bytes()); + bytes[2..4].copy_from_slice(&pati.root_index.to_le_bytes()); + Self(bytes) + } +} + +impl TryFrom for PackedAddressTreeInfo { + type Error = core::array::TryFromSliceError; + fn try_from( + cdp_packed_address_tree_info: CdpPackedAddressTreeInfo, + ) -> Result { + Ok(Self { + address_merkle_tree_pubkey_index: cdp_packed_address_tree_info.0[0], + address_queue_pubkey_index: cdp_packed_address_tree_info.0[1], + root_index: u16::from_le_bytes( + cdp_packed_address_tree_info.0[2..4].try_into()?, + ), + }) + } +} diff --git a/compressed-delegation-api/src/lib.rs b/compressed-delegation-api/src/lib.rs new file mode 100644 index 000000000..1f98f1935 --- /dev/null +++ b/compressed-delegation-api/src/lib.rs @@ -0,0 +1,19 @@ +//! Shared instruction layouts, discriminators, and account types for the +//! compressed delegation program. Used by the on-chain program and off-chain clients. + +pub mod instruction; +pub mod state; + +pub use instruction::{ + CommitAndFinalizeArgs, CompressedDelegationInstructionDiscriminator, + CompressedDelegationProgramInstruction, DelegateArgs, + ExternalUndelegateArgs, InitDelegationRecordArgs, UndelegateArgs, +}; +pub use state::{CompressedDelegationRecord, DCP_DISCRIMINATOR}; + +/// Discriminator for CPI into owner programs for external undelegate. +pub const EXTERNAL_UNDELEGATE_DISCRIMINATOR: [u8; 8] = + [0xD, 0x23, 0xB0, 0x7C, 0x70, 0x68, 0xFE, 0x73]; + +pub const EXTERNAL_UNDELEGATE_DISCRIMINATOR_U64: u64 = + u64::from_le_bytes(EXTERNAL_UNDELEGATE_DISCRIMINATOR); diff --git a/compressed-delegation-api/src/state.rs b/compressed-delegation-api/src/state.rs new file mode 100644 index 000000000..292d8dd15 --- /dev/null +++ b/compressed-delegation-api/src/state.rs @@ -0,0 +1,51 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use light_hasher::{DataHasher, Hasher, HasherError, Sha256}; +use light_sdk::LightDiscriminator; +use solana_pubkey::Pubkey; + +pub const DCP_DISCRIMINATOR: [u8; 8] = + [0x4d, 0x41, 0x47, 0x49, 0x43, 0x42, 0x4c, 0x4b]; + +/// The Delegated Metadata includes Account Seeds, max delegation time, seeds +/// and other meta information about the delegated account. +/// * Everything necessary at cloning time is instead stored in the delegation record. +#[repr(C)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Debug, Default, PartialEq, +)] +pub struct CompressedDelegationRecord { + /// The PDA of the delegated account + pub pda: Pubkey, + /// The validator the account is delegated to + pub authority: Pubkey, + /// Last update nonce + pub last_update_nonce: u64, + /// Whether the account can be undelegated + pub is_undelegatable: bool, + /// The program that owns the delegated account + pub owner: Pubkey, + /// The slot at which the delegation was created + pub delegation_slot: u64, + /// Original lamports of the account + pub lamports: u64, + /// The original data of the delegated account + pub data: Vec, +} + +impl DataHasher for CompressedDelegationRecord { + fn hash(&self) -> Result<[u8; 32], HasherError> { + let bytes = borsh::to_vec(self).map_err(|_| HasherError::BorshError)?; + let mut hash = Sha256::hash(&bytes)?; + hash[0] = 0; + Ok(hash) + } +} + +impl LightDiscriminator for CompressedDelegationRecord { + const LIGHT_DISCRIMINATOR: [u8; 8] = DCP_DISCRIMINATOR; + const LIGHT_DISCRIMINATOR_SLICE: &'static [u8] = &Self::LIGHT_DISCRIMINATOR; + + fn discriminator() -> [u8; 8] { + Self::LIGHT_DISCRIMINATOR + } +} diff --git a/compressed-delegation-client/Cargo.toml b/compressed-delegation-client/Cargo.toml new file mode 100644 index 000000000..c399093d8 --- /dev/null +++ b/compressed-delegation-client/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "compressed-delegation-client" +description = "A new Solana program using the Metaplex Project Template" +version = "0.1.0" +edition = "2021" +readme = "README.md" +license-file = "../../LICENSE" +repository = "https://github.com/metaplex-foundation/compressed-delegation-program" + +[lib] +crate-type = ["lib"] + +[features] +test-sbf = [] +serde = ["dep:serde", "dep:serde_with"] +anchor = [] +anchor-idl-build = [] +fetch = [] + +[dependencies] +compressed-delegation-api = { workspace = true } +borsh = { workspace = true } +light-hasher = { workspace = true } +light-sdk = { workspace = true, features = ["v2"] } +light-sdk-types = { workspace = true } +light-compressed-account = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true, features = ["derive"], optional = true } +serde_with = { workspace = true, optional = true } +solana-account-info = { workspace = true } +solana-cpi = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true } +solana-instruction = { workspace = true } +thiserror = { workspace = true } diff --git a/compressed-delegation-client/src/builders/commit_finalize.rs b/compressed-delegation-client/src/builders/commit_finalize.rs new file mode 100644 index 000000000..0ef413dcd --- /dev/null +++ b/compressed-delegation-client/src/builders/commit_finalize.rs @@ -0,0 +1,40 @@ +use solana_instruction::{AccountMeta, Instruction}; +use solana_pubkey::Pubkey; + +use crate::{CommitAndFinalizeArgs, DelegationProgramDiscriminator}; + +/// Instruction builder for `Commit`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` validator +/// 1. `[]` delegated_account +#[derive(Clone, Debug, Default)] +pub struct CommitAndFinalizeBuilder { + pub validator: Pubkey, + pub delegated_account: Pubkey, + pub remaining_accounts: Vec, + pub args: CommitAndFinalizeArgs, +} + +impl CommitAndFinalizeBuilder { + pub fn instruction(&self) -> Result { + Ok(Instruction { + program_id: crate::COMPRESSED_DELEGATION_ID, + accounts: [ + &[ + AccountMeta::new(self.validator, true), + AccountMeta::new_readonly(self.delegated_account, false), + ], + self.remaining_accounts.as_slice(), + ] + .concat(), + data: [ + &(DelegationProgramDiscriminator::CommitAndFinalize as u64) + .to_le_bytes(), + borsh::to_vec(&self.args)?.as_slice(), + ] + .concat(), + }) + } +} diff --git a/compressed-delegation-client/src/builders/delegate.rs b/compressed-delegation-client/src/builders/delegate.rs new file mode 100644 index 000000000..479828792 --- /dev/null +++ b/compressed-delegation-client/src/builders/delegate.rs @@ -0,0 +1,40 @@ +use solana_instruction::{AccountMeta, Instruction}; +use solana_pubkey::Pubkey; + +use crate::{DelegateArgs, DelegationProgramDiscriminator}; + +/// Instruction builder for `Delegate`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[signer]` delegated_account +#[derive(Clone, Debug, Default)] +pub struct DelegateBuilder { + pub payer: Pubkey, + pub delegated_account: Pubkey, + pub remaining_accounts: Vec, + pub args: DelegateArgs, +} + +impl DelegateBuilder { + pub fn instruction(&self) -> Result { + Ok(Instruction { + program_id: crate::COMPRESSED_DELEGATION_ID, + accounts: [ + &[ + AccountMeta::new(self.payer, true), + AccountMeta::new_readonly(self.delegated_account, true), + ], + self.remaining_accounts.as_slice(), + ] + .concat(), + data: [ + &(DelegationProgramDiscriminator::Delegate as u64) + .to_le_bytes(), + borsh::to_vec(&self.args)?.as_slice(), + ] + .concat(), + }) + } +} diff --git a/compressed-delegation-client/src/builders/init_delegation_record.rs b/compressed-delegation-client/src/builders/init_delegation_record.rs new file mode 100644 index 000000000..76f56d044 --- /dev/null +++ b/compressed-delegation-client/src/builders/init_delegation_record.rs @@ -0,0 +1,40 @@ +use solana_instruction::{AccountMeta, Instruction}; +use solana_pubkey::Pubkey; + +use crate::{DelegationProgramDiscriminator, InitDelegationRecordArgs}; + +/// Instruction builder for `InitDelegationRecord`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[signer]` delegated_account +#[derive(Clone, Debug)] +pub struct InitDelegationRecordBuilder { + pub payer: Pubkey, + pub delegated_account: Pubkey, + pub remaining_accounts: Vec, + pub args: InitDelegationRecordArgs, +} + +impl InitDelegationRecordBuilder { + pub fn instruction(&self) -> Result { + Ok(Instruction { + program_id: crate::COMPRESSED_DELEGATION_ID, + accounts: [ + &[ + AccountMeta::new(self.payer, true), + AccountMeta::new_readonly(self.delegated_account, true), + ], + self.remaining_accounts.as_slice(), + ] + .concat(), + data: [ + &(DelegationProgramDiscriminator::InitDelegationRecord as u64) + .to_le_bytes(), + borsh::to_vec(&self.args)?.as_slice(), + ] + .concat(), + }) + } +} diff --git a/compressed-delegation-client/src/builders/mod.rs b/compressed-delegation-client/src/builders/mod.rs new file mode 100644 index 000000000..89accb2d0 --- /dev/null +++ b/compressed-delegation-client/src/builders/mod.rs @@ -0,0 +1,8 @@ +pub(crate) mod commit_finalize; +pub(crate) mod delegate; +pub(crate) mod init_delegation_record; +pub(crate) mod undelegate; + +pub use self::{ + commit_finalize::*, delegate::*, init_delegation_record::*, undelegate::*, +}; diff --git a/compressed-delegation-client/src/builders/undelegate.rs b/compressed-delegation-client/src/builders/undelegate.rs new file mode 100644 index 000000000..8c1a53830 --- /dev/null +++ b/compressed-delegation-client/src/builders/undelegate.rs @@ -0,0 +1,46 @@ +use solana_instruction::{AccountMeta, Instruction}; +use solana_pubkey::Pubkey; + +use crate::{DelegationProgramDiscriminator, UndelegateArgs}; + +/// Instruction builder for `Undelegate`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[writable]` delegated_account +/// 2. `[]` owner_program +/// 3. `[]` system_program +#[derive(Clone, Debug, Default)] +pub struct UndelegateBuilder { + pub payer: Pubkey, + pub delegated_account: Pubkey, + pub owner_program: Pubkey, + pub system_program: Pubkey, + pub remaining_accounts: Vec, + pub args: UndelegateArgs, +} + +impl UndelegateBuilder { + pub fn instruction(&self) -> Result { + Ok(Instruction { + program_id: crate::COMPRESSED_DELEGATION_ID, + accounts: [ + &[ + AccountMeta::new(self.payer, true), + AccountMeta::new(self.delegated_account, false), + AccountMeta::new_readonly(self.owner_program, false), + AccountMeta::new_readonly(self.system_program, false), + ], + self.remaining_accounts.as_slice(), + ] + .concat(), + data: [ + &(DelegationProgramDiscriminator::Undelegate as u64) + .to_le_bytes(), + borsh::to_vec(&self.args)?.as_slice(), + ] + .concat(), + }) + } +} diff --git a/compressed-delegation-client/src/cpi/commit_finalize.rs b/compressed-delegation-client/src/cpi/commit_finalize.rs new file mode 100644 index 000000000..51ebcfde7 --- /dev/null +++ b/compressed-delegation-client/src/cpi/commit_finalize.rs @@ -0,0 +1,43 @@ +use solana_account_info::AccountInfo; +use solana_cpi::invoke_signed; +use solana_program_error::ProgramResult; + +use crate::{ + cpi::helpers::{collect_account_infos, remaining_to_metas}, + CommitAndFinalizeArgs, +}; + +/// CPI helper for `CommitAndFinalize` (on-chain callers). +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` validator +/// 1. `[]` delegated_account +#[derive(Clone, Debug)] +pub struct CommitAndFinalizeCpi<'a> { + pub validator: AccountInfo<'a>, + pub delegated_account: AccountInfo<'a>, + pub remaining_accounts: Vec<(AccountInfo<'a>, bool, bool)>, + pub args: CommitAndFinalizeArgs, +} + +impl<'a> CommitAndFinalizeCpi<'a> { + pub fn invoke(&self) -> ProgramResult { + self.invoke_signed(&[]) + } + + pub fn invoke_signed(&self, signers: &[&[&[u8]]]) -> ProgramResult { + let ix = crate::builders::CommitAndFinalizeBuilder { + validator: *self.validator.key, + delegated_account: *self.delegated_account.key, + remaining_accounts: remaining_to_metas(&self.remaining_accounts), + args: self.args.clone(), + } + .instruction()?; + let infos = collect_account_infos( + &[self.validator.clone(), self.delegated_account.clone()], + &self.remaining_accounts, + ); + invoke_signed(&ix, &infos, signers) + } +} diff --git a/compressed-delegation-client/src/cpi/delegate.rs b/compressed-delegation-client/src/cpi/delegate.rs new file mode 100644 index 000000000..35dd91fb3 --- /dev/null +++ b/compressed-delegation-client/src/cpi/delegate.rs @@ -0,0 +1,43 @@ +use solana_account_info::AccountInfo; +use solana_cpi::invoke_signed; +use solana_program_error::ProgramResult; + +use crate::{ + cpi::helpers::{collect_account_infos, remaining_to_metas}, + DelegateArgs, +}; + +/// CPI helper for `Delegate` (on-chain callers). +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[signer]` delegated_account +#[derive(Clone, Debug)] +pub struct DelegateCpi<'a> { + pub payer: AccountInfo<'a>, + pub delegated_account: AccountInfo<'a>, + pub remaining_accounts: Vec<(AccountInfo<'a>, bool, bool)>, + pub args: DelegateArgs, +} + +impl<'a> DelegateCpi<'a> { + pub fn invoke(&self) -> ProgramResult { + self.invoke_signed(&[]) + } + + pub fn invoke_signed(&self, signers: &[&[&[u8]]]) -> ProgramResult { + let ix = crate::builders::DelegateBuilder { + payer: *self.payer.key, + delegated_account: *self.delegated_account.key, + remaining_accounts: remaining_to_metas(&self.remaining_accounts), + args: self.args.clone(), + } + .instruction()?; + let infos = collect_account_infos( + &[self.payer.clone(), self.delegated_account.clone()], + &self.remaining_accounts, + ); + invoke_signed(&ix, &infos, signers) + } +} diff --git a/compressed-delegation-client/src/cpi/helpers.rs b/compressed-delegation-client/src/cpi/helpers.rs new file mode 100644 index 000000000..88545e74b --- /dev/null +++ b/compressed-delegation-client/src/cpi/helpers.rs @@ -0,0 +1,24 @@ +use solana_account_info::AccountInfo; +use solana_instruction::AccountMeta; + +pub(crate) fn remaining_to_metas<'a>( + remaining: &[(AccountInfo<'a>, bool, bool)], +) -> Vec { + remaining + .iter() + .map(|(ai, is_signer, is_writable)| AccountMeta { + pubkey: *ai.key, + is_signer: *is_signer, + is_writable: *is_writable, + }) + .collect() +} + +pub(crate) fn collect_account_infos<'a>( + prefix: &[AccountInfo<'a>], + remaining: &[(AccountInfo<'a>, bool, bool)], +) -> Vec> { + let mut out = prefix.to_vec(); + out.extend(remaining.iter().map(|(ai, _, _)| ai.clone())); + out +} diff --git a/compressed-delegation-client/src/cpi/init_delegation_record.rs b/compressed-delegation-client/src/cpi/init_delegation_record.rs new file mode 100644 index 000000000..bdc5f27ba --- /dev/null +++ b/compressed-delegation-client/src/cpi/init_delegation_record.rs @@ -0,0 +1,43 @@ +use solana_account_info::AccountInfo; +use solana_cpi::invoke_signed; +use solana_program_error::ProgramResult; + +use crate::{ + cpi::helpers::{collect_account_infos, remaining_to_metas}, + InitDelegationRecordArgs, +}; + +/// CPI helper for `InitDelegationRecord` (on-chain callers). +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[signer]` delegated_account +#[derive(Clone, Debug)] +pub struct InitDelegationRecordCpi<'a> { + pub payer: AccountInfo<'a>, + pub delegated_account: AccountInfo<'a>, + pub remaining_accounts: Vec<(AccountInfo<'a>, bool, bool)>, + pub args: InitDelegationRecordArgs, +} + +impl<'a> InitDelegationRecordCpi<'a> { + pub fn invoke(&self) -> ProgramResult { + self.invoke_signed(&[]) + } + + pub fn invoke_signed(&self, signers: &[&[&[u8]]]) -> ProgramResult { + let ix = crate::builders::InitDelegationRecordBuilder { + payer: *self.payer.key, + delegated_account: *self.delegated_account.key, + remaining_accounts: remaining_to_metas(&self.remaining_accounts), + args: self.args.clone(), + } + .instruction()?; + let infos = collect_account_infos( + &[self.payer.clone(), self.delegated_account.clone()], + &self.remaining_accounts, + ); + invoke_signed(&ix, &infos, signers) + } +} diff --git a/compressed-delegation-client/src/cpi/mod.rs b/compressed-delegation-client/src/cpi/mod.rs new file mode 100644 index 000000000..d3b89833b --- /dev/null +++ b/compressed-delegation-client/src/cpi/mod.rs @@ -0,0 +1,10 @@ +mod helpers; + +pub(crate) mod commit_finalize; +pub(crate) mod delegate; +pub(crate) mod init_delegation_record; +pub(crate) mod undelegate; + +pub use self::{ + commit_finalize::*, delegate::*, init_delegation_record::*, undelegate::*, +}; diff --git a/compressed-delegation-client/src/cpi/undelegate.rs b/compressed-delegation-client/src/cpi/undelegate.rs new file mode 100644 index 000000000..2fc5a332f --- /dev/null +++ b/compressed-delegation-client/src/cpi/undelegate.rs @@ -0,0 +1,54 @@ +use solana_account_info::AccountInfo; +use solana_cpi::invoke_signed; +use solana_program_error::ProgramResult; + +use crate::{ + cpi::helpers::{collect_account_infos, remaining_to_metas}, + UndelegateArgs, +}; + +/// CPI helper for `Undelegate` (on-chain callers). +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[writable]` delegated_account +/// 2. `[]` owner_program +/// 3. `[]` system_program +#[derive(Clone, Debug)] +pub struct UndelegateCpi<'a> { + pub payer: AccountInfo<'a>, + pub delegated_account: AccountInfo<'a>, + pub owner_program: AccountInfo<'a>, + pub system_program: AccountInfo<'a>, + pub remaining_accounts: Vec<(AccountInfo<'a>, bool, bool)>, + pub args: UndelegateArgs, +} + +impl<'a> UndelegateCpi<'a> { + pub fn invoke(&self) -> ProgramResult { + self.invoke_signed(&[]) + } + + pub fn invoke_signed(&self, signers: &[&[&[u8]]]) -> ProgramResult { + let ix = crate::builders::UndelegateBuilder { + payer: *self.payer.key, + delegated_account: *self.delegated_account.key, + owner_program: *self.owner_program.key, + system_program: *self.system_program.key, + remaining_accounts: remaining_to_metas(&self.remaining_accounts), + args: self.args.clone(), + } + .instruction()?; + let infos = collect_account_infos( + &[ + self.payer.clone(), + self.delegated_account.clone(), + self.owner_program.clone(), + self.system_program.clone(), + ], + &self.remaining_accounts, + ); + invoke_signed(&ix, &infos, signers) + } +} diff --git a/compressed-delegation-client/src/lib.rs b/compressed-delegation-client/src/lib.rs new file mode 100644 index 000000000..3921c44b3 --- /dev/null +++ b/compressed-delegation-client/src/lib.rs @@ -0,0 +1,26 @@ +pub mod builders; +pub mod cpi; +mod programs; + +pub use compressed_delegation_api::{ + CommitAndFinalizeArgs, CompressedDelegationInstructionDiscriminator, + CompressedDelegationProgramInstruction, CompressedDelegationRecord, + DelegateArgs, ExternalUndelegateArgs, InitDelegationRecordArgs, + UndelegateArgs, DCP_DISCRIMINATOR, EXTERNAL_UNDELEGATE_DISCRIMINATOR, + EXTERNAL_UNDELEGATE_DISCRIMINATOR_U64, +}; +use light_sdk::derive_light_cpi_signer; +use light_sdk_types::CpiSigner; +pub use programs::{COMPRESSED_DELEGATION_ID, COMPRESSED_DELEGATION_ID as ID}; +use solana_pubkey::Pubkey; + +/// Backwards-compatible name for [`CompressedDelegationInstructionDiscriminator`]. +pub type DelegationProgramDiscriminator = + CompressedDelegationInstructionDiscriminator; + +pub const COMPRESSED_DELEGATION_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT"); + +pub const fn id() -> Pubkey { + ID +} diff --git a/compressed-delegation-client/src/mod.rs b/compressed-delegation-client/src/mod.rs new file mode 100644 index 000000000..500c4f924 --- /dev/null +++ b/compressed-delegation-client/src/mod.rs @@ -0,0 +1,9 @@ +//! Legacy client module layout (`accounts`, `instructions`, `types`). + +pub mod accounts; +pub mod instructions; +pub mod programs; +pub mod shared; +pub mod types; + +pub(crate) use programs::*; diff --git a/compressed-delegation-client/src/programs.rs b/compressed-delegation-client/src/programs.rs new file mode 100644 index 000000000..f68e7d375 --- /dev/null +++ b/compressed-delegation-client/src/programs.rs @@ -0,0 +1,7 @@ +//! Program IDs for on-chain programs in this workspace. + +use solana_pubkey::{pubkey, Pubkey}; + +/// `compressed_delegation` program ID. +pub const COMPRESSED_DELEGATION_ID: Pubkey = + pubkey!("DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT"); diff --git a/compressed-delegation-client/src/shared.rs b/compressed-delegation-client/src/shared.rs new file mode 100644 index 000000000..69c049e3d --- /dev/null +++ b/compressed-delegation-client/src/shared.rs @@ -0,0 +1,16 @@ +//! Shared account decoding helpers for optional `fetch` integration. + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub struct DecodedAccount { + pub address: solana_pubkey::Pubkey, + pub account: solana_account::Account, + pub data: T, +} + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub enum MaybeAccount { + Exists(DecodedAccount), + NotFound(solana_pubkey::Pubkey), +} diff --git a/config.example.toml b/config.example.toml index 82f9e75b0..83d6b300a 100644 --- a/config.example.toml +++ b/config.example.toml @@ -279,6 +279,15 @@ reset = false # Env: MBV_TASK_SCHEDULER__MIN_INTERVAL min-interval = "10ms" +# ============================================================================== +# Compression +# ============================================================================== +[compression] +# The URL of the Photon indexer. +# Default: http://localhost:8784 +# Env: MBV_COMPRESSION__PHOTON_URL +photon-url = "http://localhost:8784" + # ============================================================================== # Pre-loaded Programs # ============================================================================== diff --git a/magicblock-accounts/src/scheduled_commits_processor.rs b/magicblock-accounts/src/scheduled_commits_processor.rs index 820bf1fab..f09a0260f 100644 --- a/magicblock-accounts/src/scheduled_commits_processor.rs +++ b/magicblock-accounts/src/scheduled_commits_processor.rs @@ -10,6 +10,7 @@ use magicblock_chainlink::{ remote_account_provider::{ chain_rpc_client::ChainRpcClientImpl, chain_updates_client::ChainUpdatesClient, + photon_client::PhotonClientImpl, }, submux::SubMuxClient, Chainlink, @@ -48,6 +49,7 @@ pub type ChainlinkImpl = Chainlink< SubMuxClient, AccountsDb, ChainlinkCloner, + PhotonClientImpl, >; pub struct ScheduledCommitsProcessorImpl { diff --git a/magicblock-aperture/src/state/mod.rs b/magicblock-aperture/src/state/mod.rs index 8e1263562..4d77ad7cb 100644 --- a/magicblock-aperture/src/state/mod.rs +++ b/magicblock-aperture/src/state/mod.rs @@ -8,6 +8,7 @@ use magicblock_chainlink::{ remote_account_provider::{ chain_rpc_client::ChainRpcClientImpl, chain_updates_client::ChainUpdatesClient, + photon_client::PhotonClientImpl, }, submux::SubMuxClient, Chainlink, @@ -24,6 +25,7 @@ pub type ChainlinkImpl = Chainlink< SubMuxClient, AccountsDb, ChainlinkCloner, + PhotonClientImpl, >; /// A container for the shared, global state of the RPC service. diff --git a/magicblock-api/Cargo.toml b/magicblock-api/Cargo.toml index ba314a6ce..0131db9aa 100644 --- a/magicblock-api/Cargo.toml +++ b/magicblock-api/Cargo.toml @@ -32,6 +32,7 @@ magicblock-services = { workspace = true } magicblock-task-scheduler = { workspace = true } magicblock-validator-admin = { workspace = true } +light-client = { workspace = true, features = ["v2"] } num_cpus = { workspace = true } paste = { workspace = true } solana-account = { workspace = true } diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 95f91a345..77baed302 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -24,7 +24,8 @@ use magicblock_chainlink::{ config::ChainlinkConfig, remote_account_provider::{ chain_rpc_client::ChainRpcClientImpl, - chain_updates_client::ChainUpdatesClient, Endpoints, + chain_updates_client::ChainUpdatesClient, + photon_client::PhotonClientImpl, Endpoint, Endpoints, }, submux::SubMuxClient, Chainlink, @@ -109,6 +110,7 @@ type ChainlinkImpl = Chainlink< SubMuxClient, AccountsDb, ChainlinkCloner, + PhotonClientImpl, >; // ----------------- @@ -471,13 +473,18 @@ impl MagicValidator { accountsdb: &Arc, faucet_pubkey: Pubkey, ) -> ApiResult { - let endpoints = Endpoints::try_from(config.remotes.as_slice()) + let mut endpoints = Endpoints::try_from(config.remotes.as_slice()) .map_err(|e| { ApiError::from( magicblock_chainlink::errors::ChainlinkError::from(e), ) })?; + endpoints.push(Endpoint::Compression { + label: "photon".to_string(), + url: config.compression.photon_url.clone(), + }); + let cloner = ChainlinkCloner::new( committor_service, config.chainlink.clone(), diff --git a/magicblock-chainlink/Cargo.toml b/magicblock-chainlink/Cargo.toml index b3276a98f..eb7081456 100644 --- a/magicblock-chainlink/Cargo.toml +++ b/magicblock-chainlink/Cargo.toml @@ -8,9 +8,11 @@ arc-swap = "1.7" async-trait = { workspace = true } bincode = { workspace = true } borsh = { workspace = true } +compressed-delegation-client = { workspace = true } futures-util = { workspace = true } helius-laserstream = { workspace = true } lru = { workspace = true } +light-client = { workspace = true } magicblock-accounts-db = { workspace = true } magicblock-config = { workspace = true } magicblock-core = { workspace = true } diff --git a/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs b/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs index 1f4d135ec..cd3b99c12 100644 --- a/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs +++ b/magicblock-chainlink/src/chainlink/account_still_undelegating_on_chain.rs @@ -18,6 +18,8 @@ use tracing::*; /// of the account in our bank /// - `delegation_record`: the delegation record associated with the account in our bank, if found /// - `validator_auth`: the validator authority pubkey +/// - `compressed_delegation_slot`: for compressed (no DLP) accounts, the slot from the +/// borsh record; `None` when the classic DLP is used /// - returns `true` if the account is still undelegating, `false` otherwise. pub(crate) fn account_still_undelegating_on_chain( pubkey: &Pubkey, @@ -25,6 +27,7 @@ pub(crate) fn account_still_undelegating_on_chain( remote_slot_in_bank: u64, deleg_record: Option, validator_auth: &Pubkey, + compressed_delegation_slot: Option, ) -> bool { // In the case of a subscription update for an account that was undelegating // we know that the undelegation or associated commit or possibly a previous @@ -54,6 +57,7 @@ pub(crate) fn account_still_undelegating_on_chain( let delegation_slot = deleg_record .as_ref() .map(|d| d.delegation_slot) + .or(compressed_delegation_slot) .unwrap_or_default(); if delegation_slot <= remote_slot_in_bank { // The last update of the account was after the last delegation @@ -117,6 +121,7 @@ mod tests { remote_slot, deleg_record, &Pubkey::default(), + None, )); } @@ -144,6 +149,7 @@ mod tests { remote_slot, deleg_record, &Pubkey::default(), + None, )); */ @@ -156,6 +162,7 @@ mod tests { remote_slot, deleg_record, &Pubkey::default(), + None, )); } @@ -180,6 +187,7 @@ mod tests { remote_slot, deleg_record, &Pubkey::default(), + None, )); } @@ -203,6 +211,33 @@ mod tests { remote_slot, deleg_record, &Pubkey::default(), + None, + )); + } + + #[test] + fn test_compressed_redelegation_slot_when_no_dlp() { + let pubkey = Pubkey::default(); + let is_delegated = true; + let remote_slot = 100; + // No classic delegation record: without `compressed_delegation_slot`, `delegation_slot` + // defaults to 0 and is treated as case D (commit still behind bank). + assert!(account_still_undelegating_on_chain( + &pubkey, + is_delegated, + remote_slot, + None, + &Pubkey::default(), + None, + )); + // Borsh `delegation_slot` for compressed accounts disambiguates redelegation to us. + assert!(!account_still_undelegating_on_chain( + &pubkey, + is_delegated, + remote_slot, + None, + &Pubkey::default(), + Some(101), )); } } diff --git a/magicblock-chainlink/src/chainlink/errors.rs b/magicblock-chainlink/src/chainlink/errors.rs index 8f25487c5..a9a086b61 100644 --- a/magicblock-chainlink/src/chainlink/errors.rs +++ b/magicblock-chainlink/src/chainlink/errors.rs @@ -47,4 +47,10 @@ pub enum ChainlinkError { #[error("Missing accounts required by delegation actions: {0:?}")] MissingDelegationActionAccounts(Vec), + + #[error("Failed to deserialize compressed delegation record: {0}")] + FailedToDeserializeCompressedDelegationRecord(#[from] std::io::Error), + + #[error("Photon client error: {0}")] + PhotonClientError(#[from] magicblock_core::traits::PhotonClientError), } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs index 03175a2a0..a6273b5a3 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs @@ -3,9 +3,12 @@ use std::collections::HashSet; use dlp_api::state::DelegationRecord; use futures_util::future::join_all; use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::token_programs::{ - is_ata, try_derive_ata_address_and_bump, try_derive_eata_address_and_bump, - AtaInfo, +use magicblock_core::{ + token_programs::{ + is_ata, try_derive_ata_address_and_bump, + try_derive_eata_address_and_bump, AtaInfo, + }, + traits::PhotonClient, }; use magicblock_metrics::metrics; use solana_account::{AccountSharedData, ReadableAccount}; @@ -69,8 +72,8 @@ fn ata_info_from_layout( /// and, if the ATA is delegated to us and the eATA exists, we clone the eATA data /// into the ATA in the bank. #[instrument(skip(this, atas))] -pub(crate) async fn resolve_ata_with_eata_projection( - this: &FetchCloner, +pub(crate) async fn resolve_ata_with_eata_projection( + this: &FetchCloner, atas: Vec<( Pubkey, AccountSharedData, @@ -85,6 +88,7 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { if atas.is_empty() { return vec![]; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs new file mode 100644 index 000000000..a22d14cf3 --- /dev/null +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs @@ -0,0 +1,113 @@ +use borsh::BorshDeserialize; +use compressed_delegation_client::CompressedDelegationRecord; +use magicblock_accounts_db::traits::AccountsBank; +use magicblock_core::traits::PhotonClient; +use solana_account::{AccountSharedData, ReadableAccount}; +use solana_pubkey::Pubkey; +use tracing::*; + +use super::FetchCloner; +use crate::{ + cloner::{AccountCloneRequest, Cloner, DelegationActions}, + remote_account_provider::{ChainPubsubClient, ChainRpcClient}, +}; + +/// Expand a [`CompressedDelegationRecord`] from `data` into the logical owner, payload, and +/// delegation flags. +/// +/// Returns `None` when `data` is not a valid borsh record (including when the account is already +/// expanded and `data` holds only the program payload). +pub(crate) fn try_decompress_compressed_delegation( + this: &FetchCloner, + account: &AccountSharedData, + min_context_slot: u64, +) -> Option<(AccountSharedData, u64)> +where + T: ChainRpcClient, + U: ChainPubsubClient, + V: AccountsBank, + C: Cloner, + P: PhotonClient, +{ + let Ok(compressed_delegation_record) = + CompressedDelegationRecord::try_from_slice(account.data()) + else { + return None; + }; + let effective_slot = min_context_slot.max(account.remote_slot()); + let delegation_slot = compressed_delegation_record.delegation_slot; + let mut out = AccountSharedData::new( + compressed_delegation_record.lamports, + compressed_delegation_record.data.len(), + &compressed_delegation_record.owner, + ); + out.set_data(compressed_delegation_record.data); + out.set_compressed(true); + out.set_remote_slot(effective_slot); + out.set_delegated( + compressed_delegation_record.authority == this.validator_pubkey, + ); + Some((out, delegation_slot)) +} + +#[instrument(skip(this, compressed_accounts))] +pub(crate) fn resolve_compressed_accounts( + this: &FetchCloner, + compressed_accounts: Vec<(Pubkey, AccountSharedData, u64)>, + min_context_slot: Option, +) -> Vec +where + T: ChainRpcClient, + U: ChainPubsubClient, + V: AccountsBank, + C: Cloner, + P: PhotonClient, +{ + if compressed_accounts.is_empty() { + return vec![]; + } + + let mut accounts_to_clone = Vec::with_capacity(compressed_accounts.len()); + + for (pubkey, account_shared_data, slot) in compressed_accounts { + let effective_slot = if let Some(min_slot) = min_context_slot { + min_slot.max(slot) + } else { + slot + }; + + let Ok(compressed_delegation_record) = + CompressedDelegationRecord::try_from_slice( + account_shared_data.data(), + ) + else { + warn!( + pubkey = %pubkey, + "Failed to deserialize compressed delegation record" + ); + continue; + }; + + let mut account = AccountSharedData::new( + compressed_delegation_record.lamports, + compressed_delegation_record.data.len(), + &compressed_delegation_record.owner, + ); + account.set_data(compressed_delegation_record.data); + account.set_compressed(true); + account.set_remote_slot(effective_slot); + account.set_delegated( + compressed_delegation_record.authority == this.validator_pubkey, + ); + + accounts_to_clone.push(AccountCloneRequest { + pubkey, + account, + commit_frequency_ms: None, + delegation_actions: DelegationActions::default(), + delegated_to_other: None, + }); + } + + accounts_to_clone +} diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 9e726915c..e03686a04 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -3,7 +3,10 @@ use dlp_api::{ pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::token_programs::{derive_eata, EATA_PROGRAM_ID}; +use magicblock_core::{ + token_programs::{derive_eata, EATA_PROGRAM_ID}, + traits::PhotonClient, +}; use magicblock_metrics::metrics; use solana_account::ReadableAccount; use solana_keypair::Keypair; @@ -89,8 +92,8 @@ fn parse_post_delegation_actions( Ok(instructions.into()) } -pub(crate) fn apply_delegation_record_to_account( - this: &FetchCloner, +pub(crate) fn apply_delegation_record_to_account( + this: &FetchCloner, account_pubkey: Pubkey, account: &mut ResolvedAccountSharedData, delegation_record: &DelegationRecord, @@ -100,6 +103,7 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { let is_confined = delegation_record.authority.eq(&Pubkey::default()); let is_delegated_to_us = @@ -143,8 +147,8 @@ pub(crate) fn parse_raw_eata_pda( .then_some((wallet_owner, mint)) } -pub(crate) fn get_delegated_to_other( - this: &FetchCloner, +pub(crate) fn get_delegated_to_other( + this: &FetchCloner, delegation_record: &DelegationRecord, ) -> Option where @@ -152,6 +156,7 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { let is_delegated_to_us = delegation_record.authority.eq(&this.validator_pubkey) @@ -161,8 +166,8 @@ where } #[instrument(skip(this))] -pub(crate) async fn fetch_and_parse_delegation_record( - this: &FetchCloner, +pub(crate) async fn fetch_and_parse_delegation_record( + this: &FetchCloner, account_pubkey: Pubkey, min_context_slot: u64, fetch_origin: metrics::AccountFetchOrigin, @@ -172,6 +177,7 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { let delegation_record_pubkey = delegation_record_pda_from_delegated_account(&account_pubkey); diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 0bb02fb1a..2a16dd48a 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -12,9 +12,12 @@ use dlp_api::{ }; use magicblock_accounts_db::traits::AccountsBank; use magicblock_config::config::AllowedProgram; -use magicblock_core::token_programs::{ - is_ata, try_derive_ata_address_and_bump, try_derive_eata_address_and_bump, - MaybeIntoAta, EATA_PROGRAM_ID, +use magicblock_core::{ + token_programs::{ + is_ata, try_derive_ata_address_and_bump, + try_derive_eata_address_and_bump, MaybeIntoAta, EATA_PROGRAM_ID, + }, + traits::PhotonClient, }; use magicblock_metrics::metrics::{self, AccountFetchOrigin}; use scc::{hash_map::Entry, HashMap}; @@ -32,6 +35,7 @@ use tokio::{ use tracing::*; mod ata_projection; +mod compression; mod delegation; mod pending_clone_guard; mod pipeline; @@ -71,15 +75,16 @@ use self::pending_clone_guard::{ CloneClaim, CloneCompletion, CloneKey, PendingCloneGuard, }; -pub struct FetchCloner +pub struct FetchCloner where T: ChainRpcClient, U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { /// The RemoteAccountProvider to fetch accounts from - remote_account_provider: Arc>, + remote_account_provider: Arc>, /// Tracks pending account fetch requests to avoid duplicate fetches in parallel /// Once an account is fetched and cloned into the bank, it's removed from here pending_requests: Arc>, @@ -109,17 +114,24 @@ where hash_map::HashMap>>, >, >, + + /// Pubkeys for which the committor called `undelegation_requested`. Until the + /// bank reflects delegated+compressed (or a newer merged view), we must not short-circuit + /// in [`FetchCloner::fetch_and_clone_accounts_with_dedup`]: RPC may be up to date while + /// Photon has the compressed redelegation. + post_undelegation_photon_merge_pending: Arc>>, } /// Manual Clone impl: `#[derive(Clone)]` would add `V: Clone, C: Clone` /// bounds that are not satisfied (`AccountsBank` and `Cloner` don't /// require `Clone`). All fields are behind `Arc` so Clone is not needed. -impl Clone for FetchCloner +impl Clone for FetchCloner where T: ChainRpcClient, U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { fn clone(&self) -> Self { Self { @@ -133,21 +145,48 @@ where blacklisted_accounts: self.blacklisted_accounts.clone(), allowed_programs: self.allowed_programs.clone(), pending_clones: self.pending_clones.clone(), + post_undelegation_photon_merge_pending: self + .post_undelegation_photon_merge_pending + .clone(), } } } -impl FetchCloner +/// `mark_empty_if_not_found` can materialize a 0-lamport, no-data account. That entry must not +/// short-circuit [`FetchCloner::fetch_and_clone_accounts_with_dedup`], or a later run might skip +/// [`RemoteAccountProvider`]'s merged RPC+Photon path and never observe compressed state. +fn bank_entry_is_tentative_empty_for_refetch( + account: &AccountSharedData, +) -> bool { + if account.lamports() != 0 + || !account.data().is_empty() + || account.executable() + || account.delegated() + || account.undelegating() + { + return false; + } + if account.compressed() { + // Placeholder that already came from the compressed fetch path; both sides may agree on + // not found — nothing further to resolve here. + return false; + } + let owner = account.owner(); + owner == &Pubkey::default() || owner == &system_program::id() +} + +impl FetchCloner where T: ChainRpcClient, U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { /// Create FetchCloner with subscription updates properly connected #[allow(clippy::too_many_arguments)] pub fn new( - remote_account_provider: &Arc>, + remote_account_provider: &Arc>, accounts_bank: &Arc, cloner: &Arc, validator_keypair: Keypair, @@ -172,6 +211,9 @@ where blacklisted_accounts, allowed_programs, pending_clones: Arc::new(Mutex::new(hash_map::HashMap::new())), + post_undelegation_photon_merge_pending: Arc::new(Mutex::new( + HashSet::new(), + )), }); me.clone() @@ -185,6 +227,15 @@ where self.fetch_count.load(Ordering::Relaxed) } + /// Mark an account as needing a merged RPC+Photon refetch after the committor has run + /// `undelegation_requested` for this pubkey. + pub fn mark_post_undelegation_photon_merge_pending(&self, pubkey: Pubkey) { + self.post_undelegation_photon_merge_pending + .lock() + .expect("post_undelegation_photon_merge_pending lock poisoned") + .insert(pubkey); + } + pub fn cloner(&self) -> &Arc { &self.cloner } @@ -390,7 +441,12 @@ where return; } - let (resolved_account, deleg_record, delegation_actions) = self + let ( + resolved_account, + deleg_record, + delegation_actions, + compressed_delegation_slot, + ) = self .resolve_account_to_clone_from_forwarded_sub_with_unsubscribe( update, ) @@ -493,6 +549,7 @@ where in_bank.remote_slot(), deleg_record, &self.validator_pubkey, + compressed_delegation_slot, ) { return; } @@ -834,6 +891,60 @@ where } } + /// If `data` holds a borsh [`CompressedDelegationRecord`], expand to logical owner and + /// payload like `resolve_compressed_accounts`. Fetched Photon accounts may already list the + /// logical owner; we only require valid record bytes in `data`. + /// If the notification has no `data` (e.g. truncated), refetch merged RPC+Photon and retry. + /// Second return: [`CompressedDelegationRecord::delegation_slot`] when expanded (see + /// [`account_still_undelegating_on_chain`]). + async fn decompress_or_refetch_compressed_account( + &self, + pubkey: Pubkey, + account: AccountSharedData, + ) -> (AccountSharedData, Option) { + let min_slot = account.remote_slot(); + if let Some((out, delegation_slot)) = + compression::try_decompress_compressed_delegation( + self, &account, min_slot, + ) + { + return (out, Some(delegation_slot)); + } + if !account.data().is_empty() { + return (account, None); + } + if let Ok(fetched) = self + .remote_account_provider + .try_get_multi( + &[pubkey], + None, + AccountFetchOrigin::GetAccount, + None, + Some(min_slot), + ) + .await + { + if let Some(ra) = fetched.into_iter().next() { + if let Some(fresh) = ra.fresh_account() { + if let Some((out, delegation_slot)) = + compression::try_decompress_compressed_delegation( + self, + &fresh, + min_slot.max(fresh.remote_slot()), + ) + { + return (out, Some(delegation_slot)); + } + } + } + } else { + warn!(pubkey = %pubkey, "Refetch for compressed subscription account failed"); + } + (account, None) + } + + // Fourth return value: `CompressedDelegationRecord::delegation_slot` for compressed (no DLP) + // accounts, used in `account_still_undelegating_on_chain`. async fn resolve_account_to_clone_from_forwarded_sub_with_unsubscribe( &self, update: ForwardedSubscriptionUpdate, @@ -841,6 +952,7 @@ where Option, Option, DelegationActions, + Option, ) { let ForwardedSubscriptionUpdate { pubkey, account } = update; let owned_by_delegation_program = @@ -950,12 +1062,13 @@ where Some(account.into_account_shared_data()), Some(delegation_record), delegation_actions.unwrap_or_default(), + None, ) } else { // If the delegation record is invalid we cannot clone the account // since something is corrupt and we wouldn't know what owner to // use, etc. - (None, None, DelegationActions::default()) + (None, None, DelegationActions::default(), None) } } else { // If no delegation record exists we must assume the account itself is @@ -964,6 +1077,7 @@ where Some(account.into_account_shared_data()), None, DelegationActions::default(), + None, ) }; @@ -983,7 +1097,7 @@ where error = ?err, "Failed to fetch delegation record" ); - (None, None, DelegationActions::default()) + (None, None, DelegationActions::default(), None) } Err(err) => { warn!( @@ -991,10 +1105,13 @@ where error = ?err, "Failed to fetch delegation record" ); - (None, None, DelegationActions::default()) + (None, None, DelegationActions::default(), None) } } } else { + let (account, compressed_delegation_slot) = self + .decompress_or_refetch_compressed_account(pubkey, account) + .await; let (account, deleg_record) = self .maybe_project_ata_from_subscription_update(pubkey, account) .await; @@ -1003,16 +1120,22 @@ where Some(account), Some(deleg_record), actions.unwrap_or_default(), + compressed_delegation_slot, ) } else { - (Some(account), None, DelegationActions::default()) + ( + Some(account), + None, + DelegationActions::default(), + compressed_delegation_slot, + ) } } } else { // This should not happen since we call this method with sub updates which always hold // a fresh remote account error!(pubkey = %pubkey, account = ?account, "BUG: Received subscription update without fresh account"); - (None, None, DelegationActions::default()) + (None, None, DelegationActions::default(), None) } } @@ -1290,6 +1413,7 @@ where not_found, plain, owned_by_deleg, + compressed, programs, atas, } = pipeline::classify_remote_accounts(accs, pubkeys); @@ -1307,6 +1431,10 @@ where .iter() .map(|(pubkey, _, slot)| (pubkey.to_string(), *slot)) .collect::>(); + let compressed = compressed + .iter() + .map(|(pubkey, _, slot)| (pubkey.to_string(), *slot)) + .collect::>(); let programs = programs .iter() .map(|(p, _, _)| p.to_string()) @@ -1316,7 +1444,7 @@ where .map(|(a, _, _, _)| a.to_string()) .collect::>(); trace!( - "Fetched accounts: \nnot_found: {not_found:?} \nplain: {plain:?} \nowned_by_deleg: {owned_by_deleg:?}\nprograms: {programs:?} \natas: {atas:?}", + "Fetched accounts: \nnot_found: {not_found:?} \nplain: {plain:?} \nowned_by_deleg: {owned_by_deleg:?}\ncompressed: {compressed:?}\nprograms: {programs:?} \natas: {atas:?}", ); } @@ -1404,6 +1532,13 @@ where .await; accounts_to_clone.extend(ata_accounts); + let compressed_accounts = compression::resolve_compressed_accounts( + self, + compressed, + min_context_slot, + ); + accounts_to_clone.extend(compressed_accounts); + // Ensure all accounts referenced by delegation actions exist and are // cloned before we execute those actions as part of account cloning. let action_dependencies = @@ -1458,6 +1593,7 @@ where not_found, plain, owned_by_deleg, + compressed, programs, atas, } = pipeline::classify_remote_accounts( @@ -1525,8 +1661,16 @@ where ) .await; + let action_dep_compressed_accounts = + compression::resolve_compressed_accounts( + self, + compressed, + min_context_slot, + ); + accounts_to_clone.extend(action_dep_accounts_to_clone); accounts_to_clone.extend(action_dep_ata_accounts); + accounts_to_clone.extend(action_dep_compressed_accounts); loaded_programs.extend(action_dep_loaded_programs); all_requested_pubkeys.extend(action_dependencies_to_fetch); } @@ -1577,6 +1721,12 @@ where "Fetching undelegating account" ); + if in_bank.compressed() { + // We must refetch so RPC+Photon see the latest compressed record. + debug!(pubkey = %pubkey, "Undelegating compressed account: refresh from chain"); + return RefreshDecision::Yes; + } + if let Some(eata_pubkey) = ata_projection::derive_eata_pubkey_from_ata_layout( pubkey, in_bank, @@ -1629,6 +1779,7 @@ where in_bank.remote_slot(), deleg_record, &self.validator_pubkey, + None, ) { debug!( "Account {pubkey} marked as undelegating will be overridden since undelegation completed" @@ -1689,25 +1840,67 @@ where { if account_in_bank.undelegating() { undelegating_checks.push((**pubkey, account_in_bank)); + } else if bank_entry_is_tentative_empty_for_refetch( + &account_in_bank, + ) { + // `mark_empty_if_not_found` (RPC/Photon) stores a 0-lamport empty account. If + // the first attempt only had the RPC side, the bank can hold that placeholder + // even when Photon later has the real compressed state — and we would skip + // `try_get_multi` and never merge. Refetch to let consolidation run again. + debug!( + pubkey = %pubkey, + "Tentative empty account in bank; not treating as fetch-complete" + ); } else { - if account_in_bank.owner().eq(&dlp_api::id()) { - debug!( - pubkey = %pubkey, - "Account owned by deleg program not marked as undelegating" - ); + { + let mut pending = self + .post_undelegation_photon_merge_pending + .lock() + .expect("post_undelegation_photon_merge_pending lock poisoned"); + if account_in_bank.delegated() + || account_in_bank.compressed() + { + pending.remove(*pubkey); + } } - if tracing::enabled!(tracing::Level::TRACE) { - let delegated = account_in_bank.delegated(); - let owner = account_in_bank.owner(); - trace!( + // After undelegation the bank can hold a plain (non-compressed) undelegated + // view while a newer compressed redelegation exists only in Photon. If we + // short-circuited here, we would never run RPC+Photon merge and would miss + // redelegation. `undelegation_requested` marks the pubkey; we refetch until + // the bank shows merged delegated/compressed state. + let may_have_newer_photon = { + self.post_undelegation_photon_merge_pending + .lock() + .expect("post_undelegation_photon_merge_pending lock poisoned") + .contains(*pubkey) + } && self.is_watching(pubkey) + && !account_in_bank.delegated() + && !account_in_bank.compressed(); + if may_have_newer_photon { + debug!( pubkey = %pubkey, - undelegating = false, - delegated, - owner = %owner, - "Account found in bank in valid state, no fetch needed" + "Post-undelegation, non-delegated, non-compressed in bank; refetching to merge possible Photon state" ); + } else { + if account_in_bank.owner().eq(&dlp_api::id()) { + debug!( + pubkey = %pubkey, + "Account owned by deleg program not marked as undelegating" + ); + } + if tracing::enabled!(tracing::Level::TRACE) { + let delegated = account_in_bank.delegated(); + let owner = account_in_bank.owner(); + trace!( + pubkey = %pubkey, + undelegating = false, + delegated, + owner = %owner, + "Account found in bank in valid state, no fetch needed" + ); + } + in_bank.insert(**pubkey); } - in_bank.insert(**pubkey); } } } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index f1f1efdf8..c439943f1 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -2,7 +2,7 @@ use std::{collections::HashSet, sync::atomic::Ordering}; use dlp_api::pda::delegation_record_pda_from_delegated_account; use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::token_programs::is_ata; +use magicblock_core::{token_programs::is_ata, traits::PhotonClient}; use magicblock_metrics::metrics::AccountFetchOrigin; use solana_account::{AccountSharedData, ReadableAccount}; use solana_pubkey::Pubkey; @@ -28,12 +28,12 @@ use crate::{ LOADER_V3, }, ChainPubsubClient, ChainRpcClient, MatchSlotsConfig, RemoteAccount, - ResolvedAccount, + RemoteAccountUpdateSource, ResolvedAccount, }, }; -pub(crate) fn build_existing_subs( - this: &FetchCloner, +pub(crate) fn build_existing_subs( + this: &FetchCloner, pubkeys: &[Pubkey], ) -> ExistingSubs where @@ -41,6 +41,7 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { let delegation_records = pubkeys .iter() @@ -84,6 +85,7 @@ pub(crate) fn classify_remote_accounts( let mut not_found = Vec::new(); let mut plain = Vec::new(); let mut owned_by_deleg = Vec::new(); + let mut compressed = Vec::new(); let mut programs = Vec::new(); let mut atas = Vec::new(); @@ -94,6 +96,7 @@ pub(crate) fn classify_remote_accounts( &mut not_found, &mut plain, &mut owned_by_deleg, + &mut compressed, &mut programs, &mut atas, ); @@ -103,6 +106,7 @@ pub(crate) fn classify_remote_accounts( not_found, plain, owned_by_deleg, + compressed, programs, atas, } @@ -110,12 +114,14 @@ pub(crate) fn classify_remote_accounts( /// Helper function to classify a single remote account #[inline] +#[allow(clippy::too_many_arguments)] fn classify_single_account( acc: RemoteAccount, pubkey: Pubkey, not_found: &mut Vec<(Pubkey, u64)>, plain: &mut Vec, owned_by_deleg: &mut Vec<(Pubkey, AccountSharedData, u64)>, + compressed: &mut Vec<(Pubkey, AccountSharedData, u64)>, programs: &mut Vec<(Pubkey, AccountSharedData, u64)>, atas: &mut Vec<( Pubkey, @@ -154,6 +160,11 @@ fn classify_single_account( { // Associated Token Account atas.push((pubkey, account_shared_data, ata, slot)); + } else if remote_account_state.source + == RemoteAccountUpdateSource::Compressed + { + // Compressed account + compressed.push((pubkey, account_shared_data, slot)); } else { // Plain account plain.push(AccountCloneRequest { @@ -219,8 +230,8 @@ pub(crate) fn partition_not_found( /// Resolves delegated accounts by fetching their delegation records #[instrument(skip(this, owned_by_deleg, plain, pubkeys, existing_subs), fields(pubkey_count = pubkeys.len()))] -pub(crate) async fn resolve_delegated_accounts( - this: &FetchCloner, +pub(crate) async fn resolve_delegated_accounts( + this: &FetchCloner, owned_by_deleg: Vec<(Pubkey, AccountSharedData, u64)>, plain: Vec, min_context_slot: Option, @@ -233,6 +244,7 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { // For potentially delegated accounts we update the owner and delegation state first let mut fetch_with_delegation_record_join_set = JoinSet::new(); @@ -413,8 +425,8 @@ where /// Resolves program accounts, fetching program data accounts for LoaderV3 programs #[instrument(skip(this, programs, pubkeys, existing_subs), fields(pubkey_count = pubkeys.len()))] -pub(crate) async fn resolve_programs_with_program_data( - this: &FetchCloner, +pub(crate) async fn resolve_programs_with_program_data( + this: &FetchCloner, programs: Vec<(Pubkey, AccountSharedData, u64)>, min_context_slot: Option, fetch_origin: AccountFetchOrigin, @@ -426,6 +438,7 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { // For LoaderV3 accounts we fetch the program data account let (loaderv3_programs, single_account_programs): (Vec<_>, Vec<_>) = @@ -504,7 +517,7 @@ where let account_program = account_pair[0].clone(); let account_data = account_pair[1].clone(); - let result = FetchCloner::::resolve_account_with_companion( + let result = FetchCloner::::resolve_account_with_companion( &this.accounts_bank, pubkey, program_data_pubkey, @@ -663,10 +676,41 @@ pub(crate) fn compute_cancel_strategy( } } +/// While the bank still marks a compressed account as `undelegating`, a refetch can return the +/// prior on-chain/Photon state (still delegated to us at the same or older slot). Cloning that +/// would clear `undelegating` early. Skip only for that stale same-slot (or older) view; a fetch +/// with a **newer** `remote_slot` is fresh (e.g. redelegation after undelegation) and must be +/// applied. +fn skip_clone_while_compressed_undelegation_not_on_chain_yet( + in_bank: Option, + request: &AccountCloneRequest, +) -> bool { + let Some(in_bank) = in_bank else { + return false; + }; + if !in_bank.undelegating() || !in_bank.compressed() { + return false; + } + if !request.account.compressed() { + return false; + } + if !request.account.delegated() { + return false; + } + if request.account.remote_slot() > in_bank.remote_slot() { + return false; + } + trace!( + pubkey = %request.pubkey, + "Skipping clone: merged fetch still shows delegation to us at a stale slot while bank is undelegating" + ); + true +} + /// Clones accounts and programs into the bank #[instrument(skip(this, accounts_to_clone, loaded_programs))] -pub(crate) async fn clone_accounts_and_programs( - this: &FetchCloner, +pub(crate) async fn clone_accounts_and_programs( + this: &FetchCloner, accounts_to_clone: Vec, loaded_programs: Vec< crate::remote_account_provider::program_account::LoadedProgram, @@ -677,7 +721,18 @@ where U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { + let accounts_to_clone = accounts_to_clone + .into_iter() + .filter(|request| { + !skip_clone_while_compressed_undelegation_not_on_chain_yet( + this.accounts_bank.get_account(&request.pubkey), + request, + ) + }) + .collect::>(); + // 1) Clone programs first so post-delegation action instructions can load // their program accounts when action txs are sent during account cloning. let mut program_join_set = JoinSet::new(); diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs index ffdf3774b..a7238563b 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs @@ -1,4 +1,5 @@ use magicblock_accounts_db::traits::AccountsBank; +use magicblock_core::traits::PhotonClient; use magicblock_metrics::metrics::AccountFetchOrigin; use solana_account::{AccountSharedData, ReadableAccount}; use solana_pubkey::Pubkey; @@ -13,8 +14,8 @@ use crate::{ }, }; -pub(crate) async fn handle_executable_sub_update( - this: &FetchCloner, +pub(crate) async fn handle_executable_sub_update( + this: &FetchCloner, pubkey: Pubkey, account: AccountSharedData, ) where @@ -22,6 +23,7 @@ pub(crate) async fn handle_executable_sub_update( U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, { if !this.is_program_allowed(&pubkey) { debug!(pubkey = %pubkey, "Skipping clone of program, not in allowed_programs"); diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs index a6037e13d..263e04673 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs @@ -1,5 +1,6 @@ use std::{collections::HashSet, fmt, sync::Arc}; +use magicblock_core::traits::PhotonClient; use solana_pubkey::Pubkey; use tokio::task::JoinSet; use tracing::*; @@ -102,8 +103,12 @@ impl fmt::Display for CancelStrategy { } #[instrument(skip(provider, strategy))] -pub(crate) async fn cancel_subs( - provider: &Arc>, +pub(crate) async fn cancel_subs< + T: ChainRpcClient, + U: ChainPubsubClient, + P: PhotonClient, +>( + provider: &Arc>, strategy: CancelStrategy, ) { if strategy.is_empty() { diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index d99202421..b208153f1 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -31,6 +31,7 @@ use crate::{ EATA_PROGRAM_ID, }, init_logger, + photon_client_mock::PhotonClientMock, rpc_client_mock::{ChainRpcClientMock, ChainRpcClientMockBuilder}, utils::{create_test_lru_cache, random_pubkey}, }, @@ -43,6 +44,7 @@ type TestFetchClonerResult = ( ChainPubsubClientMock, AccountsBankStub, ClonerStub, + PhotonClientMock, >, >, mpsc::Sender, @@ -96,8 +98,13 @@ macro_rules! assert_cloned_undelegated_account { } struct FetcherTestCtx { - remote_account_provider: - Arc>, + remote_account_provider: Arc< + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, + >, accounts_bank: Arc, rpc_client: crate::testing::rpc_client_mock::ChainRpcClientMock, #[allow(unused)] @@ -108,6 +115,7 @@ struct FetcherTestCtx { ChainPubsubClientMock, AccountsBankStub, ClonerStub, + PhotonClientMock, >, >, #[allow(unused)] @@ -138,6 +146,7 @@ where let (updates_sender, updates_receiver) = mpsc::channel(1_000); let pubsub_client = ChainPubsubClientMock::new(updates_sender, updates_receiver); + let photon_client = PhotonClientMock::default(); let accounts_bank = Arc::new(AccountsBankStub::default()); let rpc_client_clone = rpc_client.clone(); @@ -149,6 +158,7 @@ where RemoteAccountProvider::new( rpc_client, pubsub_client, + photon_client, forward_tx, &config, subscribed_accounts, @@ -235,7 +245,11 @@ fn add_delegation_record_with_slot_for( /// Returns (FetchCloner, subscription_sender) for simulating subscription updates in tests fn init_fetch_cloner( remote_account_provider: Arc< - RemoteAccountProvider, + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, >, bank: &Arc, validator_keypair: Keypair, @@ -991,7 +1005,7 @@ async fn test_delegation_record_unsub_race_condition_prevention() { // Use a shared FetchCloner to test deduplication // Helper function to spawn a fetch_and_clone task with shared FetchCloner - let spawn_fetch_task = |fetch_cloner: &Arc>| { + let spawn_fetch_task = |fetch_cloner: &Arc>| { let fetch_cloner = fetch_cloner.clone(); tokio::spawn(async move { fetch_cloner @@ -2083,7 +2097,11 @@ async fn test_no_program_subscription_for_undelegated_account() { #[allow(clippy::too_many_arguments)] async fn send_subscription_update_and_get_subscribed_programs( remote_account_provider: &Arc< - RemoteAccountProvider, + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, >, accounts_bank: &Arc, subscription_tx: &mpsc::Sender, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs index e7ddbeb2b..b43445419 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs @@ -32,6 +32,7 @@ pub(crate) struct ClassifiedAccounts { pub(crate) not_found: Vec<(Pubkey, u64)>, pub(crate) plain: Vec, pub(crate) owned_by_deleg: Vec<(Pubkey, AccountSharedData, u64)>, + pub(crate) compressed: Vec<(Pubkey, AccountSharedData, u64)>, pub(crate) programs: Vec<(Pubkey, AccountSharedData, u64)>, pub(crate) atas: Vec<( Pubkey, diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index 2fe098d41..ba4e52e77 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -11,6 +11,7 @@ use errors::ChainlinkResult; use fetch_cloner::FetchCloner; use magicblock_accounts_db::{traits::AccountsBank, AccountsDbResult}; use magicblock_config::config::ChainLinkConfig; +use magicblock_core::traits::PhotonClient; use magicblock_metrics::metrics::AccountFetchOrigin; use solana_account::{AccountSharedData, ReadableAccount}; use solana_commitment_config::CommitmentConfig; @@ -28,8 +29,9 @@ use crate::{ fetch_cloner::FetchAndCloneResult, filters::is_noop_system_transfer, remote_account_provider::{ - chain_updates_client::ChainUpdatesClient, ChainPubsubClient, - ChainRpcClient, ChainRpcClientImpl, Endpoints, RemoteAccountProvider, + chain_updates_client::ChainUpdatesClient, + photon_client::PhotonClientImpl, ChainPubsubClient, ChainRpcClient, + ChainRpcClientImpl, Endpoints, RemoteAccountProvider, }, submux::SubMuxClient, }; @@ -42,6 +44,11 @@ pub mod fetch_cloner; pub use blacklisted_accounts::*; +type OptionalFetchCloner = + Option>>; +type OptionalFetchClonerRef<'a, T, U, V, C, P> = + Option<&'a Arc>>; + // ----------------- // Chainlink // ----------------- @@ -50,9 +57,10 @@ pub struct Chainlink< U: ChainPubsubClient, V: AccountsBank, C: Cloner, + P: PhotonClient, > { accounts_bank: Arc, - fetch_cloner: Option>>, + fetch_cloner: OptionalFetchCloner, /// The subscription to events for each account that is removed from /// the accounts tracked by the provider. /// In that case we also remove it from the bank since it is no longer @@ -67,12 +75,17 @@ pub struct Chainlink< remove_confined_accounts: bool, } -impl - Chainlink +impl< + T: ChainRpcClient, + U: ChainPubsubClient, + V: AccountsBank, + C: Cloner, + P: PhotonClient, + > Chainlink { pub fn try_new( accounts_bank: &Arc, - fetch_cloner: Option>>, + fetch_cloner: OptionalFetchCloner, validator_pubkey: Pubkey, faucet_pubkey: Pubkey, config: &ChainLinkConfig, @@ -117,7 +130,13 @@ impl config: ChainlinkConfig, chainlink_config: &ChainLinkConfig, ) -> ChainlinkResult< - Chainlink, V, C>, + Chainlink< + ChainRpcClientImpl, + SubMuxClient, + V, + C, + PhotonClientImpl, + >, > { let validator_pubkey = validator_keypair.pubkey(); // Extract accounts provider and create fetch cloner while connecting @@ -288,7 +307,7 @@ impl /// does nothing as only existing accounts are affected. /// See [lru::LruCache::promote] fn promote_accounts( - fetch_cloner: &FetchCloner, + fetch_cloner: &FetchCloner, pubkeys: &[&Pubkey], ) { fetch_cloner.promote_accounts(pubkeys); @@ -427,7 +446,7 @@ impl ))] async fn fetch_accounts_common( &self, - fetch_cloner: &FetchCloner, + fetch_cloner: &FetchCloner, pubkeys: &[Pubkey], mark_empty_if_not_found: Option<&[Pubkey]>, fetch_origin: AccountFetchOrigin, @@ -478,12 +497,15 @@ impl // Subscribe to updates for this account so we can track changes // once it's undelegated fetch_cloner.subscribe_to_account(&pubkey).await?; + fetch_cloner.mark_post_undelegation_photon_merge_pending(pubkey); debug!(pubkey = %pubkey, "Successfully subscribed for undelegation tracking"); Ok(()) } - pub fn fetch_cloner(&self) -> Option<&Arc>> { + pub fn fetch_cloner<'a>( + &'a self, + ) -> OptionalFetchClonerRef<'a, T, U, V, C, P> { self.fetch_cloner.as_ref() } diff --git a/magicblock-chainlink/src/remote_account_provider/chain_updates_client.rs b/magicblock-chainlink/src/remote_account_provider/chain_updates_client.rs index 1294a2933..8784c3d8d 100644 --- a/magicblock-chainlink/src/remote_account_provider/chain_updates_client.rs +++ b/magicblock-chainlink/src/remote_account_provider/chain_updates_client.rs @@ -92,6 +92,11 @@ impl ChainUpdatesClient { "{endpoint:?}" ))) } + Compression { .. } => { + Err(RemoteAccountProviderError::InvalidPubsubEndpoint(format!( + "{endpoint:?}" + ))) + } } } } diff --git a/magicblock-chainlink/src/remote_account_provider/endpoint.rs b/magicblock-chainlink/src/remote_account_provider/endpoint.rs index 7ee300ceb..84df22de5 100644 --- a/magicblock-chainlink/src/remote_account_provider/endpoint.rs +++ b/magicblock-chainlink/src/remote_account_provider/endpoint.rs @@ -1,4 +1,4 @@ -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; use magicblock_config::types::network::Remote; use url::Url; @@ -21,6 +21,10 @@ pub enum Endpoint { supports_backfill: bool, api_key: String, }, + Compression { + label: String, + url: String, + }, } impl Endpoint { @@ -28,7 +32,8 @@ impl Endpoint { match self { Endpoint::Rpc { label, .. } | Endpoint::WebSocket { label, .. } - | Endpoint::Grpc { label, .. } => label, + | Endpoint::Grpc { label, .. } + | Endpoint::Compression { label, .. } => label, } } } @@ -53,6 +58,16 @@ impl Endpoints { }) .collect() } + + pub fn photon_url(&self) -> Option { + self.iter().find_map(|ep| { + if let Endpoint::Compression { url, .. } = ep { + Some(url.clone()) + } else { + None + } + }) + } } impl TryFrom<&[Remote]> for Endpoints { @@ -131,6 +146,12 @@ impl Deref for Endpoints { } } +impl DerefMut for Endpoints { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + impl<'a> IntoIterator for &'a Endpoints { type Item = &'a Endpoint; type IntoIter = std::slice::Iter<'a, Endpoint>; diff --git a/magicblock-chainlink/src/remote_account_provider/errors.rs b/magicblock-chainlink/src/remote_account_provider/errors.rs index 18a1efe0e..dda18bc61 100644 --- a/magicblock-chainlink/src/remote_account_provider/errors.rs +++ b/magicblock-chainlink/src/remote_account_provider/errors.rs @@ -122,6 +122,9 @@ pub enum RemoteAccountProviderError { "Failed to update gRPC subscription to {0} after {1} retries: {2}" )] GrpcSubscriptionUpdateFailed(String, usize, String), + + #[error("Photon indexer error: {0}")] + PhotonIndexerError(#[from] light_client::indexer::IndexerError), } impl From for RemoteAccountProviderError diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index a6ec4d314..5a47ac787 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -18,6 +18,7 @@ pub(crate) use errors::{ }; use futures_util::future::{join_all, try_join_all}; pub use lru_cache::AccountsLruCache; +use magicblock_core::traits::PhotonClient; pub(crate) use remote_account::RemoteAccount; pub use remote_account::RemoteAccountUpdateSource; use solana_account::Account; @@ -50,6 +51,7 @@ pub mod config; pub mod endpoint; pub mod errors; mod lru_cache; +pub mod photon_client; pub mod program_account; pub mod pubsub_common; pub mod pubsub_connection; @@ -58,22 +60,23 @@ mod remote_account; mod subscription_reconciler; pub use endpoint::{Endpoint, Endpoints}; -use magicblock_metrics::{ - metrics, - metrics::{ - inc_account_fetches_failed, inc_account_fetches_found, - inc_account_fetches_not_found, inc_account_fetches_success, - inc_per_program_account_fetch_stats, set_monitored_accounts_count, - AccountFetchOrigin, ProgramFetchResult, - }, +use magicblock_metrics::metrics::{ + self, inc_account_fetches_found, inc_account_fetches_not_found, + inc_account_fetches_success, inc_compressed_account_fetches_found, + inc_compressed_account_fetches_not_found, + inc_compressed_account_fetches_success, + inc_per_program_account_fetch_stats, set_monitored_accounts_count, + AccountFetchOrigin, ProgramFetchResult, }; +use remote_account::is_synthetic_mark_empty_fresh; pub use remote_account::{ResolvedAccount, ResolvedAccountSharedData}; use crate::{ errors::ChainlinkResult, remote_account_provider::{ chain_updates_client::ChainUpdatesClient, - pubsub_common::SubscriptionUpdate, + photon_client::PhotonClientImpl, pubsub_common::SubscriptionUpdate, + remote_account::FetchedRemoteAccounts, }, submux::SubMuxClient, }; @@ -96,13 +99,19 @@ unsafe impl Sync for ForwardedSubscriptionUpdate {} // Not sure why helius uses a different code for this error const HELIUS_CONTEXT_SLOT_NOT_REACHED: i64 = -32603; -pub struct RemoteAccountProvider { +pub struct RemoteAccountProvider< + T: ChainRpcClient, + U: ChainPubsubClient, + P: PhotonClient, +> { /// The RPC client to fetch accounts from chain the first time we receive /// a request for them rpc_client: T, /// The pubsub client to listen for updates on chain and keep the account /// states up to date pubsub_client: U, + /// The photon client to fetch compressed accounts from + photon_client: P, /// Minimal tracking of accounts currently being fetched to handle race conditions /// between fetch and subscription updates. Only used during active fetch operations. fetching_accounts: Arc, @@ -164,7 +173,11 @@ impl Default for MatchSlotsConfig { } impl - RemoteAccountProvider> + RemoteAccountProvider< + ChainRpcClientImpl, + SubMuxClient, + PhotonClientImpl, + > { pub async fn try_from_urls_and_config( endpoints: &Endpoints, @@ -176,6 +189,7 @@ impl RemoteAccountProvider< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, >, >, > { @@ -185,6 +199,7 @@ impl let provider = RemoteAccountProvider::< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, >::try_new_from_endpoints( endpoints, commitment, @@ -199,21 +214,25 @@ impl } } -impl RemoteAccountProvider { +impl + RemoteAccountProvider +{ pub async fn try_from_clients_and_mode( rpc_client: T, pubsub_client: U, + photon_client: P, subscription_forwarder: mpsc::Sender, config: &RemoteAccountProviderConfig, lrucache_subscribed_accounts: Arc, chain_slot: Arc, - ) -> ChainlinkResult>> { + ) -> ChainlinkResult>> { let chain_slot = ChainSlot::new(chain_slot); if config.lifecycle_mode().needs_remote_account_provider() { Ok(Some( Self::new( rpc_client, pubsub_client, + photon_client, subscription_forwarder, config, lrucache_subscribed_accounts, @@ -261,6 +280,7 @@ impl RemoteAccountProvider { pub(crate) async fn new( rpc_client: T, pubsub_client: U, + photon_client: P, subscription_forwarder: mpsc::Sender, config: &RemoteAccountProviderConfig, lrucache_subscribed_accounts: Arc, @@ -284,6 +304,7 @@ impl RemoteAccountProvider { fetching_accounts: Arc::::default(), rpc_client, pubsub_client, + photon_client, chain_slot, last_update_slot: Arc::::default(), received_updates_count: Arc::::default(), @@ -321,6 +342,7 @@ impl RemoteAccountProvider { RemoteAccountProvider< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, >, > { if endpoints.is_empty() { @@ -340,6 +362,13 @@ impl RemoteAccountProvider { let rpc_client = ChainRpcClientImpl::new_from_url(rpc_url.as_str(), commitment); + let photon_url = endpoints.photon_url().ok_or_else(|| { + RemoteAccountProviderError::AccountSubscriptionsTaskFailed( + "No compression endpoint found".to_string(), + ) + })?; + let photon_client = PhotonClientImpl::new_from_url(photon_url); + // Create chain_slot to be shared with all pubsub clients let chain_slot = Arc::::default(); @@ -409,9 +438,11 @@ impl RemoteAccountProvider { let provider = RemoteAccountProvider::< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, >::new( rpc_client, submux, + photon_client, subscription_forwarder, config, subscribed_accounts, @@ -1057,12 +1088,6 @@ impl RemoteAccountProvider { Ok(()) } - /// Tries to fetch the given accounts from RPC. - /// NOTE: if we get an RPC error we just log it and give up since there is no - /// obvious way how to handle this even if we were to bubble the error up. - /// Any action that depends on those accounts to be there will fail. - /// NOTE: this is not used during subscription updates since we receive the data - /// as part of that update, thus we won't have stale data issues. fn fetch( &self, pubkeys: Vec, @@ -1071,104 +1096,227 @@ impl RemoteAccountProvider { fetch_origin: AccountFetchOrigin, program_ids: Option<&[Pubkey]>, ) { - const MAX_RETRIES: u64 = 10; - const RPC_CALL_TIMEOUT: Duration = Duration::from_secs(2); - let rpc_client = self.rpc_client.clone(); + let photon_client = self.photon_client.clone(); let fetching_accounts = self.fetching_accounts.clone(); - let commitment = self.rpc_client.commitment(); let mark_empty_if_not_found = mark_empty_if_not_found.unwrap_or(&[]).to_vec(); let program_ids = program_ids.map(|ids| ids.to_vec()); tokio::spawn(async move { - use RemoteAccount::*; - - // Helper to notify all pending requests of fetch failure - let notify_error = |error_msg: &str| { - let mut fetching = fetching_accounts.lock().unwrap(); - warn!("{error_msg}"); - inc_account_fetches_failed(pubkeys.len() as u64); - if let Some(program_ids) = &program_ids { - for program_id in program_ids { + // Fetch accounts from RPC + // If any are owned by the compressed delegation program then we also fetch from Photon with retries + let (rpc_accounts, photon_accounts) = tokio::join!( + Self::fetch_from_rpc( + rpc_client, + pubkeys.clone(), + &mark_empty_if_not_found, + min_context_slot, + ), + Self::fetch_from_photon( + photon_client, + pubkeys.clone(), + &mark_empty_if_not_found, + min_context_slot, + ) + ); + debug!(rpc_accounts = ?rpc_accounts, photon_accounts = ?photon_accounts, "Fetched accounts from RPC and Photon"); + + let mut remote_accounts_results = Vec::with_capacity(2); + let mut found_cnt = 0; + let mut not_found_cnt = 0; + let mut compressed_found_count = 0; + let mut compressed_not_found_count = 0; + + let results = vec![rpc_accounts, photon_accounts]; + + for result in results { + match result { + Ok((FetchedRemoteAccounts::Rpc(accs), fc, nfc)) => { + remote_accounts_results + .push(FetchedRemoteAccounts::Rpc(accs)); + found_cnt += fc; + not_found_cnt += nfc; + } + Ok((FetchedRemoteAccounts::Compressed(accs), fc, nfc)) => { + remote_accounts_results + .push(FetchedRemoteAccounts::Compressed(accs)); + compressed_found_count += fc; + compressed_not_found_count += nfc; + } + Err(err) => { + error!("Failed to fetch accounts: {err:?}"); + } + } + } + let remote_accounts = Self::consolidate_fetched_remote_accounts( + &pubkeys, + remote_accounts_results, + ); + + // Update metrics for successful RPC fetch + inc_account_fetches_success(pubkeys.len() as u64); + inc_account_fetches_found(fetch_origin, found_cnt); + inc_account_fetches_not_found(fetch_origin, not_found_cnt); + + let compressed_total = + compressed_found_count + compressed_not_found_count; + if compressed_total > 0 { + // Update metrics for successful compressed fetch + inc_compressed_account_fetches_success(pubkeys.len() as u64); + inc_compressed_account_fetches_found( + fetch_origin, + compressed_found_count, + ); + inc_compressed_account_fetches_not_found( + fetch_origin, + compressed_not_found_count, + ); + } + + // Record per-program metrics if programs were provided + if let Some(program_ids) = &program_ids { + for program_id in program_ids { + if found_cnt > 0 { + inc_per_program_account_fetch_stats( + &program_id.to_string(), + ProgramFetchResult::Found, + found_cnt, + ); + } + if not_found_cnt > 0 { inc_per_program_account_fetch_stats( &program_id.to_string(), - ProgramFetchResult::Failed, - pubkeys.len() as u64, + ProgramFetchResult::NotFound, + not_found_cnt, ); } } + } + + if tracing::enabled!(tracing::Level::TRACE) { + trace!( + pubkeys = pubkeys_str(&pubkeys), + remote_accounts = %format!("{:?}", remote_accounts), + "Fetched accounts, notifying pending requests", + ); + } - for pubkey in &pubkeys { - // Update metrics - // Remove pending requests and send error + // Notify all pending requests with fetch results (unless subscription override occurred) + for (pubkey, remote_account) in + pubkeys.iter().zip(remote_accounts.iter()) + { + let requests = { + let mut fetching = match fetching_accounts.lock() { + Ok(guard) => guard, + Err(poisoned) => { + error!( + "fetching_accounts lock poisoned; continuing with inner state: {poisoned:?}" + ); + poisoned.into_inner() + } + }; + // Remove from fetching and get pending requests + // Note: the account might have been resolved by subscription update already if let Some((_, requests)) = fetching.remove(pubkey) { - for sender in requests { - let error = RemoteAccountProviderError::AccountResolutionsFailed( - format!("{}: {}", pubkey, error_msg) + requests + } else { + // Account was resolved by subscription update, skipExpand commentComment on lines R1093 to R1108Resolved + if tracing::enabled!(tracing::Level::TRACE) { + trace!( + pubkey = %pubkey, + "Account was already resolved by subscription update" ); - let _ = sender.send(Err(error)); } + continue; } + }; + + // Send the fetch result to all waiting requests + for request in requests { + let _ = request.send(Ok(remote_account.clone())); } - }; + } + Ok::<(), RemoteAccountProviderError>(()) + }); + } - let mut remaining_retries: u64 = MAX_RETRIES; + /// Tries to fetch the given accounts from RPC. + /// NOTE: if we get an RPC error we just log it and give up since there is no + /// obvious way how to handle this even if we were to bubble the error up. + /// Any action that depends on those accounts to be there will fail. + /// NOTE: this is not used during subscription updates since we receive the data + /// as part of that update, thus we won't have stale data issues. + async fn fetch_from_rpc( + rpc_client: T, + pubkeys: Vec, + mark_empty_if_not_found: &[Pubkey], + min_context_slot: u64, + ) -> ChainlinkResult<(FetchedRemoteAccounts, u64, u64)> { + const MAX_RETRIES: u64 = 10; + const RPC_CALL_TIMEOUT: Duration = Duration::from_secs(2); - if tracing::enabled!(tracing::Level::TRACE) { - trace!(pubkeys = pubkeys_str(&pubkeys), "Fetching accounts"); - } + let commitment = rpc_client.commitment(); + let mut remaining_retries: u64 = MAX_RETRIES; + + if tracing::enabled!(tracing::Level::TRACE) { + trace!( + pubkeys = pubkeys_str(&pubkeys), + "Fetching accounts from RPC" + ); + } - macro_rules! retry { + macro_rules! retry { ($msg:expr) => {{ trace!($msg); remaining_retries -= 1; if remaining_retries <= 0 { let err_msg = format!("Max retries {MAX_RETRIES} reached, giving up on fetching accounts: {pubkeys:?}"); - notify_error(&err_msg); - return; + return Err(RemoteAccountProviderError::AccountResolutionsFailed( + err_msg + ).into()); } tokio::time::sleep(Duration::from_millis(400)).await; continue; }}; } - let response = loop { - // We provide the min_context slot in order to _force_ the RPC to update - // its account cache. Otherwise we could just keep fetching the accounts - // until the context slot is high enough. - metrics::inc_remote_account_provider_a_count(); - match tokio::time::timeout(RPC_CALL_TIMEOUT, async { - let config = RpcAccountInfoConfig { - commitment: Some(commitment), - min_context_slot: Some(min_context_slot), - encoding: Some(UiAccountEncoding::Base64Zstd), - data_slice: None, - }; + let response = loop { + // We provide the min_context slot in order to _force_ the RPC to update + // its account cache. Otherwise we could just keep fetching the accounts + // until the context slot is high enough. + metrics::inc_remote_account_provider_a_count(); + match tokio::time::timeout(RPC_CALL_TIMEOUT, async { + let config = RpcAccountInfoConfig { + commitment: Some(commitment), + min_context_slot: Some(min_context_slot), + encoding: Some(UiAccountEncoding::Base64Zstd), + data_slice: None, + }; - if pubkeys.len() == 1 { - rpc_client - .get_account_with_config(&pubkeys[0], config) - .await - .map(|res| (res.context.slot, vec![res.value])) + if pubkeys.len() == 1 { + rpc_client + .get_account_with_config(&pubkeys[0], config) + .await + .map(|res| (res.context.slot, vec![res.value])) + } else { + rpc_client + .get_multiple_accounts_with_config(&pubkeys, config) + .await + .map(|res| (res.context.slot, res.value)) + } + }) + .await + { + Ok(Ok(res)) => { + let (slot, value) = res; + if slot < min_context_slot { + retry!("Response slot {slot} < {min_context_slot}. Retrying..."); } else { - rpc_client - .get_multiple_accounts_with_config(&pubkeys, config) - .await - .map(|res| (res.context.slot, res.value)) + break (slot, value); } - }) - .await - { - Ok(Ok(res)) => { - let (slot, value) = res; - if slot < min_context_slot { - retry!("Response slot {slot} < {min_context_slot}. Retrying..."); - } else { - break (slot, value); - } - } - Ok(Err(err)) => match *err.kind { - ErrorKind::RpcError(rpc_err) => { - match rpc_err { + } + Ok(Err(err)) => match *err.kind { + ErrorKind::RpcError(rpc_err) => { + match rpc_err { RpcError::ForUser(ref rpc_user_err) => { // When an account is not present for the desired // min-context slot then we normally get the below @@ -1186,7 +1334,7 @@ impl RemoteAccountProvider { // ) // ``` retry!("Fetching accounts failed: {rpc_user_err:?}"); - } + } RpcError::RpcResponseError { code, message, @@ -1203,149 +1351,276 @@ impl RemoteAccountProvider { let err_msg = format!( "RpcError fetching accounts {}: {err:?}", pubkeys_str(&pubkeys) ); - notify_error(&err_msg); - return; + return Err(RemoteAccountProviderError::AccountResolutionsFailed( + err_msg + ).into()); } } err => { let err_msg = format!( "RpcError fetching accounts {}: {err:?}", pubkeys_str(&pubkeys) ); - notify_error(&err_msg); - return; + return Err(RemoteAccountProviderError::AccountResolutionsFailed( + err_msg + ).into()); } } - } - _ => { - let err_msg = format!( - "RpcError fetching accounts {}: {err:?}", - pubkeys_str(&pubkeys) - ); - notify_error(&err_msg); - return; - } - }, - Err(_) => { - warn!("RPC call timeout. Retrying..."); - remaining_retries -= 1; - if remaining_retries == 0 { - let err_msg = format!("Max retries {MAX_RETRIES} reached, giving up on fetching accounts: {pubkeys:?}"); - notify_error(&err_msg); - return; - } - tokio::time::sleep(Duration::from_millis(400)).await; - continue; } - }; + _ => { + let err_msg = format!( + "RpcError fetching accounts {}: {err:?}", + pubkeys_str(&pubkeys) + ); + return Err(RemoteAccountProviderError::AccountResolutionsFailed( + err_msg + ).into()); + } + }, + Err(_) => { + warn!("RPC call timeout. Retrying..."); + remaining_retries -= 1; + if remaining_retries == 0 { + let err_msg = format!("Max retries {MAX_RETRIES} reached, giving up on fetching accounts: {pubkeys:?}"); + return Err(RemoteAccountProviderError::AccountResolutionsFailed( + err_msg + ).into()); + } + tokio::time::sleep(Duration::from_millis(400)).await; + continue; + } }; + }; - // TODO: should we retry if not or respond with an error? - let (response_slot, response_value) = response; - assert!(response_slot >= min_context_slot); + // TODO: should we retry if not or respond with an error? + let (response_slot, response_value) = response; + assert!(response_slot >= min_context_slot); + + let mut found_count = 0u64; + let mut not_found_count = 0u64; + + let remote_accounts: Vec = pubkeys + .iter() + .zip(response_value) + .map(|(pubkey, acc)| match acc { + Some(value) => { + found_count += 1; + RemoteAccount::from_fresh_account( + value, + response_slot, + RemoteAccountUpdateSource::Fetch, + ) + } + None if mark_empty_if_not_found.contains(pubkey) => { + not_found_count += 1; + RemoteAccount::from_fresh_account( + Account { + lamports: 0, + data: vec![], + owner: Pubkey::default(), + executable: false, + rent_epoch: 0, + }, + response_slot, + RemoteAccountUpdateSource::Fetch, + ) + } + None => { + not_found_count += 1; + RemoteAccount::NotFound(response_slot) + } + }) + .collect(); - let mut found_count = 0u64; - let mut not_found_count = 0u64; + Ok(( + FetchedRemoteAccounts::Rpc(remote_accounts), + found_count, + not_found_count, + )) + } - let remote_accounts: Vec = pubkeys - .iter() - .zip(response_value) - .map(|(pubkey, acc)| match acc { - Some(value) => { - found_count += 1; - RemoteAccount::from_fresh_account( - value, - response_slot, - RemoteAccountUpdateSource::Fetch, - ) - } - None if mark_empty_if_not_found.contains(pubkey) => { - not_found_count += 1; - RemoteAccount::from_fresh_account( - Account { - lamports: 0, - data: vec![], - owner: Pubkey::default(), - executable: false, - rent_epoch: 0, - }, - response_slot, - RemoteAccountUpdateSource::Fetch, - ) - } - None => { - not_found_count += 1; - NotFound(response_slot) - } - }) - .collect(); + async fn fetch_from_photon( + photon_client: P, + pubkeys: Vec, + mark_empty_if_not_found: &[Pubkey], + min_context_slot: u64, + ) -> ChainlinkResult<(FetchedRemoteAccounts, u64, u64)> { + if tracing::enabled!(tracing::Level::TRACE) { + trace!( + pubkeys = pubkeys_str(&pubkeys), + "Fetching accounts from photon" + ); + } - // Update metrics for successful RPC fetch - inc_account_fetches_success(pubkeys.len() as u64); - inc_account_fetches_found(fetch_origin, found_count); - inc_account_fetches_not_found(fetch_origin, not_found_count); + // The photon client already handles the retry logic + let response = if pubkeys.len() == 1 { + match photon_client + .get_account(&pubkeys[0], Some(min_context_slot)) + .await? + { + Some((acc, slot)) => (slot, vec![Some(acc)]), + None => (min_context_slot, vec![None]), + } + } else { + photon_client + .get_multiple_accounts(&pubkeys, Some(min_context_slot)) + .await + .map(|(accs, slot)| (slot, accs))? + }; - // Record per-program metrics if programs were provided - if let Some(program_ids) = &program_ids { - for program_id in program_ids { - if found_count > 0 { - inc_per_program_account_fetch_stats( - &program_id.to_string(), - ProgramFetchResult::Found, - found_count, - ); + // TODO: should we retry if not or respond with an error? + let (response_slot, response_value) = response; + assert!(response_slot >= min_context_slot); + + let mut found_count = 0u64; + let mut not_found_count = 0u64; + + let remote_accounts: Vec = pubkeys + .iter() + .zip(response_value) + .map(|(pubkey, acc)| match acc { + Some(value) => { + found_count += 1; + RemoteAccount::from_fresh_account( + value, + response_slot, + RemoteAccountUpdateSource::Compressed, + ) + } + None if mark_empty_if_not_found.contains(pubkey) => { + not_found_count += 1; + RemoteAccount::from_fresh_account( + Account { + lamports: 0, + data: vec![], + owner: Pubkey::default(), + executable: false, + rent_epoch: 0, + }, + response_slot, + RemoteAccountUpdateSource::Compressed, + ) + } + None => { + not_found_count += 1; + RemoteAccount::NotFound(response_slot) + } + }) + .collect(); + + Ok(( + FetchedRemoteAccounts::Compressed(remote_accounts), + found_count, + not_found_count, + )) + } + + fn consolidate_fetched_remote_accounts( + pubkeys: &[Pubkey], + remote_accounts_results: Vec, + ) -> Vec { + const STALE_SLOT_THRESHOLD: u64 = 100; + let (rpc_accounts, compressed_accounts) = { + if remote_accounts_results.is_empty() { + return vec![]; + } + if remote_accounts_results.len() == 1 { + match &remote_accounts_results[0] { + FetchedRemoteAccounts::Rpc(rpc_accounts) => { + return rpc_accounts.clone(); } - if not_found_count > 0 { - inc_per_program_account_fetch_stats( - &program_id.to_string(), - ProgramFetchResult::NotFound, - not_found_count, - ); + FetchedRemoteAccounts::Compressed(compressed_accounts) => { + return compressed_accounts.clone(); } } } - - if tracing::enabled!(tracing::Level::TRACE) { - let pubkeys = pubkeys - .iter() - .map(|pk| pk.to_string()) - .collect::>() - .join(", "); - trace!( - pubkeys = %pubkeys, remote_accounts = ?remote_accounts, "Fetched, notifying pending requests" - ); - } - - // Notify all pending requests with fetch results (unless subscription override occurred) - for (pubkey, remote_account) in - pubkeys.iter().zip(remote_accounts.iter()) - { - let requests = { - let mut fetching = fetching_accounts.lock().unwrap(); - // Remove from fetching and get pending requests - // Note: the account might have been resolved by subscription update already - if let Some((_, requests)) = fetching.remove(pubkey) { - requests - } else { - // Account was resolved by subscription update, skip - if tracing::enabled!(tracing::Level::TRACE) { - trace!( - "Account {pubkey} was already resolved by subscription update" - ); + if remote_accounts_results.len() == 2 { + let mut rpc_accounts = None; + let mut compressed_accounts = None; + for res in remote_accounts_results { + match res { + FetchedRemoteAccounts::Rpc(rpc_accs) => { + rpc_accounts.replace(rpc_accs); + } + FetchedRemoteAccounts::Compressed(comp_accs) => { + compressed_accounts.replace(comp_accs); } - continue; } - }; - - // Send the fetch result to all waiting requests - for request in requests { - let _ = request.send(Ok(remote_account.clone())); } + (rpc_accounts.unwrap_or_default(), compressed_accounts) + } else { + error!("BUG: More than 2 fetch results found"); + return vec![]; + } + }; + + debug_assert_eq!(rpc_accounts.len(), pubkeys.len()); + debug_assert!(compressed_accounts + .as_ref() + .is_none_or(|comp_accs| comp_accs.len() == pubkeys.len())); + + let all_lens_match = pubkeys.len() == rpc_accounts.len() + && pubkeys.len() + == compressed_accounts + .as_ref() + .map_or(rpc_accounts.len(), |comp_accs| comp_accs.len()); + if !all_lens_match { + error!("BUG: Fetched accounts length mismatch: pubkeys {}, rpc {}, compressed {:?}", + pubkeys.len(), rpc_accounts.len(), + compressed_accounts.as_ref().map(|c| c.len())); + return rpc_accounts; + } + + use RemoteAccount::*; + match compressed_accounts { + Some(compressed_accounts) => + pubkeys.iter().zip( + rpc_accounts + .into_iter() + .zip(compressed_accounts)) + .map(|(pubkey, (rpc_acc, comp_acc))| match (rpc_acc, comp_acc) { + (Found(rpc_state), Found(comp_state)) => { + if is_synthetic_mark_empty_fresh(&rpc_state.account) + && is_synthetic_mark_empty_fresh( + &comp_state.account, + ) + { + // Both sides materialized the same not-found + + // `mark_empty_if_not_found` placeholder. Prefer + // the RPC `Fresh` (not marked compressed) so + // classification and cloning do not run empty + // data through the compressed delegation path. + Found(rpc_state) + } else { + debug!("Both RPC and Compressed account found for pubkey {}. Using Compressed account.", pubkey); + if rpc_state.account.slot() > comp_state.account.slot() + STALE_SLOT_THRESHOLD { + warn!("Compressed account is stale. rpc_slot={}, comp_slot={}", rpc_state.account.slot(), comp_state.account.slot()); + } + Found(comp_state) + } + } + (Found(rpc_state), NotFound(_)) => Found(rpc_state), + (NotFound(_), Found(comp_state)) => Found(comp_state), + (NotFound(rpc_slot), NotFound(comp_slot)) => { + if rpc_slot >= comp_slot { + NotFound(rpc_slot) + } else { + NotFound(comp_slot) + } + } + }) + .collect(), + None => rpc_accounts, } - }); } } -impl RemoteAccountProvider { +impl + RemoteAccountProvider< + ChainRpcClientImpl, + ChainPubsubClientImpl, + PhotonClientImpl, + > +{ #[cfg(any(test, feature = "dev-context"))] pub fn rpc_client(&self) -> &RpcClient { &self.rpc_client.rpc_client @@ -1356,6 +1631,7 @@ impl RemoteAccountProvider< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, > { #[cfg(any(test, feature = "dev-context"))] @@ -1365,7 +1641,11 @@ impl } impl - RemoteAccountProvider> + RemoteAccountProvider< + ChainRpcClientImpl, + SubMuxClient, + PhotonClientImpl, + > { #[cfg(any(test, feature = "dev-context"))] pub fn rpc_client(&self) -> &RpcClient { @@ -1430,6 +1710,7 @@ mod test { remote_account_provider::chain_pubsub_client::mock::ChainPubsubClientMock, testing::{ init_logger, + photon_client_mock::PhotonClientMock, rpc_client_mock::{ AccountAtSlot, ChainRpcClientMock, ChainRpcClientMockBuilder, }, @@ -1449,6 +1730,7 @@ mod test { .build(); let pubsub_client = chain_pubsub_client::mock::ChainPubsubClientMock::new(tx, rx); + let photon_client = PhotonClientMock::default(); let (fwd_tx, _fwd_rx) = mpsc::channel(100); let (subscribed_accounts, config) = create_test_lru_cache(1000); let chain_slot = Arc::::default(); @@ -1456,6 +1738,7 @@ mod test { RemoteAccountProvider::new( rpc_client, pubsub_client, + photon_client, fwd_tx, &config, subscribed_accounts, @@ -1498,6 +1781,7 @@ mod test { let (tx, rx) = mpsc::channel(1); let pubsub_client = chain_pubsub_client::mock::ChainPubsubClientMock::new(tx, rx); + let photon_client = PhotonClientMock::default(); ( { let (fwd_tx, _fwd_rx) = mpsc::channel(100); @@ -1508,6 +1792,7 @@ mod test { RemoteAccountProvider::new( rpc_client.clone(), pubsub_client, + photon_client, fwd_tx, &config, subscribed_accounts, @@ -1549,7 +1834,11 @@ mod test { pubkey1: Pubkey, pubkey2: Pubkey, ) -> ( - RemoteAccountProvider, + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, mpsc::Receiver, ) { init_logger(); @@ -1581,6 +1870,7 @@ mod test { .build(); let (tx, rx) = mpsc::channel(1); let pubsub_client = ChainPubsubClientMock::new(tx, rx); + let photon_client = PhotonClientMock::default(); let (forward_tx, forward_rx) = mpsc::channel(100); let (subscribed_accounts, config) = create_test_lru_cache(1000); @@ -1590,6 +1880,7 @@ mod test { RemoteAccountProvider::new( rpc_client, pubsub_client, + photon_client, forward_tx, &config, subscribed_accounts, @@ -1763,7 +2054,11 @@ mod test { pubkeys: &[Pubkey], accounts_capacity: usize, ) -> ( - RemoteAccountProvider, + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, mpsc::Receiver, mpsc::Receiver, ) { @@ -1787,6 +2082,7 @@ mod test { let (tx, rx) = mpsc::channel(1); let pubsub_client = ChainPubsubClientMock::new(tx, rx); + let photon_client = PhotonClientMock::default(); let (forward_tx, forward_rx) = mpsc::channel(100); let (subscribed_accounts, config) = @@ -1796,6 +2092,7 @@ mod test { let provider = RemoteAccountProvider::new( rpc_client, pubsub_client, + photon_client, forward_tx, &config, subscribed_accounts, diff --git a/magicblock-chainlink/src/remote_account_provider/photon_client.rs b/magicblock-chainlink/src/remote_account_provider/photon_client.rs new file mode 100644 index 000000000..63bfee3e1 --- /dev/null +++ b/magicblock-chainlink/src/remote_account_provider/photon_client.rs @@ -0,0 +1,116 @@ +use std::{ops::Deref, sync::Arc}; + +use async_trait::async_trait; +use light_client::indexer::{ + photon_indexer::PhotonIndexer, CompressedAccount, Context, Indexer, + IndexerRpcConfig, Response, +}; +use magicblock_core::{ + compression::derive_cda_from_pda, + traits::{PhotonClient, PhotonClientResult}, +}; +use solana_account::Account; +use solana_clock::Slot; +use solana_pubkey::Pubkey; +use tracing::*; + +#[derive(Clone)] +pub struct PhotonClientImpl(Arc); + +impl Deref for PhotonClientImpl { + type Target = Arc; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl PhotonClientImpl { + pub(crate) fn new(photon_indexer: Arc) -> Self { + Self(photon_indexer) + } + pub(crate) fn new_from_url(url: String) -> Self { + debug!(url = %url, "Creating PhotonClient"); + Self::new(Arc::new(PhotonIndexer::new(url))) + } +} + +#[async_trait] +impl PhotonClient for PhotonClientImpl { + async fn get_account( + &self, + pubkey: &Pubkey, + min_context_slot: Option, + ) -> PhotonClientResult> { + let config = min_context_slot.map(|slot| IndexerRpcConfig { + slot, + ..Default::default() + }); + let cda = derive_cda_from_pda(pubkey); + let Response { + value: compressed_acc, + context: Context { slot, .. }, + } = self.get_compressed_account(cda.to_bytes(), config).await?; + let account = account_from_compressed_account(compressed_acc); + Ok(account.map(|acc| (acc, slot))) + } + + async fn get_multiple_accounts( + &self, + pubkeys: &[Pubkey], + min_context_slot: Option, + ) -> PhotonClientResult<(Vec>, Slot)> { + let config = min_context_slot.map(|slot| IndexerRpcConfig { + slot, + ..Default::default() + }); + let cdas: Vec<_> = pubkeys + .iter() + .map(|pk| derive_cda_from_pda(pk).to_bytes()) + .collect(); + + if tracing::enabled!(tracing::Level::DEBUG) { + let pks_cdas = pubkeys + .iter() + .zip(cdas.iter()) + .map(|(pk, cda)| { + format!("({}: {})", pk, Pubkey::new_from_array(*cda)) + }) + .collect::>() + .join(", "); + debug!(cdas = %pks_cdas, "Fetching multiple accounts"); + } + + let Response { + value: compressed_accs, + context: Context { slot, .. }, + } = self + .get_multiple_compressed_accounts(Some(cdas), None, config) + .await?; + + let accounts = compressed_accs + .items + .into_iter() + .map(account_from_compressed_account) + .collect(); + Ok((accounts, slot)) + } +} + +// ----------------- +// Helpers +// ----------------- + +fn account_from_compressed_account( + compressed_acc: Option, +) -> Option { + let compressed_acc = compressed_acc?; + // NOTE: delegated compressed accounts are set to zero lamports when cloned + // Actual lamports have to be paid back when undelegating + Some(Account { + lamports: 0, + data: compressed_acc.data.unwrap_or_default().data, + owner: compressed_acc.owner.to_bytes().into(), + executable: false, + rent_epoch: 0, + }) +} diff --git a/magicblock-chainlink/src/remote_account_provider/remote_account.rs b/magicblock-chainlink/src/remote_account_provider/remote_account.rs index fd79aea26..2a03b87ca 100644 --- a/magicblock-chainlink/src/remote_account_provider/remote_account.rs +++ b/magicblock-chainlink/src/remote_account_provider/remote_account.rs @@ -9,6 +9,7 @@ use solana_pubkey::Pubkey; pub enum RemoteAccountUpdateSource { Fetch, Subscription, + Compressed, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -27,6 +28,23 @@ pub enum ResolvedAccount { Bank((Pubkey, Slot)), } +/// The placeholder produced when a pubkey is not on chain but the caller set +/// `mark_empty_if_not_found` (see [`super::RemoteAccountProvider::fetch_from_rpc`]). The same +/// structure is used for both RPC and Photon; if both are present, the merged result must not +/// always be treated as a compressed account or empty bytes may be run through +/// decompression. +pub(crate) fn is_synthetic_mark_empty_fresh(resolved: &ResolvedAccount) -> bool { + match resolved { + ResolvedAccount::Fresh(acc) => { + acc.lamports() == 0 + && acc.data().is_empty() + && !acc.executable() + && *acc.owner() == Pubkey::default() + } + ResolvedAccount::Bank(_) => false, + } +} + impl ResolvedAccount { pub fn resolved_account_shared_data( &self, @@ -41,6 +59,13 @@ impl ResolvedAccount { .map(ResolvedAccountSharedData::Bank), } } + + pub fn slot(&self) -> u64 { + match self { + ResolvedAccount::Fresh(account) => account.remote_slot(), + ResolvedAccount::Bank((_, slot)) => *slot, + } + } } /// Same as [ResolvedAccount], but with the account data fetched from the bank. @@ -166,6 +191,10 @@ impl ResolvedAccountSharedData { Bank(account) => account.remote_slot(), } } + + pub fn compressed(&self) -> bool { + self.account_shared_data().compressed() + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -188,6 +217,8 @@ impl RemoteAccount { ) -> Self { let mut account_shared_data = AccountSharedData::from(account); account_shared_data.set_remote_slot(slot); + account_shared_data + .set_compressed(source == RemoteAccountUpdateSource::Compressed); RemoteAccount::Found(RemoteAccountState { account: ResolvedAccount::Fresh(account_shared_data), source, @@ -265,3 +296,9 @@ impl RemoteAccount { self.owner().is_some_and(|owner| owner.eq(&dlp_api::id())) } } + +#[derive(Clone, Debug)] +pub enum FetchedRemoteAccounts { + Rpc(Vec), + Compressed(Vec), +} diff --git a/magicblock-chainlink/src/testing/accounts.rs b/magicblock-chainlink/src/testing/accounts.rs index 88b19c991..3338c11f1 100644 --- a/magicblock-chainlink/src/testing/accounts.rs +++ b/magicblock-chainlink/src/testing/accounts.rs @@ -1,3 +1,4 @@ +use compressed_delegation_client::CompressedDelegationRecord; use solana_account::{Account, AccountSharedData, WritableAccount}; use solana_pubkey::Pubkey; @@ -34,3 +35,31 @@ pub fn delegated_account_shared_with_owner_and_slot( acc.set_remote_slot(remote_slot); acc } + +pub fn compressed_account_shared_with_owner_and_slot( + pda: Pubkey, + authority: Pubkey, + delegation_slot: u64, + account: Account, +) -> AccountSharedData { + let delegation_record_bytes = borsh::to_vec(&CompressedDelegationRecord { + pda, + authority, + last_update_nonce: 0, + is_undelegatable: false, + owner: account.owner, + delegation_slot, + lamports: account.lamports, + data: account.data, + }) + .unwrap(); + let mut acc = Account::new( + 0, + delegation_record_bytes.len(), + &compressed_delegation_client::ID, + ); + acc.data = delegation_record_bytes; + let mut acc = AccountSharedData::from(acc); + acc.set_remote_slot(delegation_slot); + acc +} diff --git a/magicblock-chainlink/src/testing/mod.rs b/magicblock-chainlink/src/testing/mod.rs index 4d5696938..e061ff190 100644 --- a/magicblock-chainlink/src/testing/mod.rs +++ b/magicblock-chainlink/src/testing/mod.rs @@ -9,6 +9,8 @@ pub mod deleg; #[cfg(any(test, feature = "dev-context"))] pub mod eatas; #[cfg(any(test, feature = "dev-context"))] +pub mod photon_client_mock; +#[cfg(any(test, feature = "dev-context"))] pub mod rpc_client_mock; #[cfg(any(test, feature = "dev-context"))] pub mod utils; diff --git a/magicblock-chainlink/src/testing/photon_client_mock.rs b/magicblock-chainlink/src/testing/photon_client_mock.rs new file mode 100644 index 000000000..e341bf84d --- /dev/null +++ b/magicblock-chainlink/src/testing/photon_client_mock.rs @@ -0,0 +1,69 @@ +use std::{collections::HashMap, sync::Arc}; + +use magicblock_core::{ + compression::derive_cda_from_pda, + traits::{PhotonClient, PhotonClientResult}, + Slot, +}; +use parking_lot::Mutex; +use solana_account::Account; +use solana_pubkey::Pubkey; +use tonic::async_trait; + +#[derive(Clone, Default)] +pub struct PhotonClientMock { + accounts: Arc>>, +} + +impl PhotonClientMock { + pub fn add_account(&self, pubkey: Pubkey, account: Account, slot: Slot) { + let cda = derive_cda_from_pda(&pubkey); + self.accounts.lock().insert(cda, (account, slot)); + } + + pub fn remove_account(&self, pubkey: &Pubkey) { + let cda = derive_cda_from_pda(pubkey); + self.accounts.lock().remove(&cda); + } +} + +#[async_trait] +impl PhotonClient for PhotonClientMock { + async fn get_account( + &self, + pubkey: &Pubkey, + min_context_slot: Option, + ) -> PhotonClientResult> { + let cda = derive_cda_from_pda(pubkey); + if let Some((account, slot)) = self.accounts.lock().get(&cda) { + if let Some(min_slot) = min_context_slot { + if *slot < min_slot { + return Ok(None); + } + } + return Ok(Some((account.clone(), *slot))); + } + Ok(None) + } + + async fn get_multiple_accounts( + &self, + pubkeys: &[Pubkey], + min_context_slot: Option, + ) -> PhotonClientResult<(Vec>, Slot)> { + let mut accs = Vec::with_capacity(pubkeys.len()); + // Seed with min_context_slot if present to better approximate the + // "context slot" semantics of the real Photon client. + let mut slot = min_context_slot.unwrap_or(0); + for pubkey in pubkeys { + let account = self.get_account(pubkey, min_context_slot).await?; + if let Some((ref _acc, acc_slot)) = account { + if acc_slot > slot { + slot = acc_slot; + } + } + accs.push(account.map(|(acc, _)| acc)); + } + Ok((accs, slot)) + } +} diff --git a/magicblock-chainlink/tests/01_ensure-accounts.rs b/magicblock-chainlink/tests/01_ensure-accounts.rs index ada3afe24..754e583c7 100644 --- a/magicblock-chainlink/tests/01_ensure-accounts.rs +++ b/magicblock-chainlink/tests/01_ensure-accounts.rs @@ -1,11 +1,16 @@ use assert_matches::assert_matches; +use compressed_delegation_client::CompressedDelegationRecord; use dlp_api::pda::delegation_record_pda_from_delegated_account; use magicblock_chainlink::{ assert_cloned_as_delegated, assert_cloned_as_undelegated, assert_not_cloned, assert_not_found, assert_not_subscribed, assert_not_undelegating, assert_remain_undelegating, assert_subscribed_without_delegation_record, - testing::deleg::add_delegation_record_for, AccountFetchOrigin, + testing::{ + accounts::compressed_account_shared_with_owner_and_slot, + deleg::add_delegation_record_for, + }, + AccountFetchOrigin, }; use solana_account::{Account, AccountSharedData}; use solana_program::clock::Slot; @@ -357,3 +362,132 @@ async fn test_write_existing_account_invalid_delegation_record() { assert_not_subscribed!(chainlink, &[&deleg_record_pubkey, &pubkey]); } + +// ----------------- +// Compressed delegation record is initialized and delegated to us +// ----------------- +#[tokio::test] +async fn test_compressed_delegation_record_delegated() { + let TestContext { + chainlink, + photon_client, + cloner, + validator_pubkey, + .. + } = setup(CURRENT_SLOT).await; + + let pubkey = Pubkey::new_unique(); + let owner = Pubkey::new_unique(); + let account = Account::new(0, 0, &owner); + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + validator_pubkey, + CURRENT_SLOT, + account, + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + CURRENT_SLOT, + ); + + let pubkeys = [pubkey]; + let res = chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + debug!("res: {res:?}"); + + assert_cloned_as_delegated!(cloner, &pubkeys, CURRENT_SLOT, owner); + assert_not_subscribed!(chainlink, &[&pubkey]); +} + +// ----------------- +// Compressed delegation record is initialized and delegated to another authority +// ----------------- +#[tokio::test] +async fn test_compressed_delegation_record_delegated_to_other() { + let TestContext { + chainlink, + photon_client, + cloner, + .. + } = setup(CURRENT_SLOT).await; + + let pubkey = Pubkey::new_unique(); + let authority = Pubkey::new_unique(); + let owner = Pubkey::new_unique(); + let account = Account::new(0, 0, &owner); + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + authority, + CURRENT_SLOT, + account, + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + CURRENT_SLOT, + ); + + let pubkeys = [pubkey]; + let res = chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + debug!("res: {res:?}"); + + assert_cloned_as_undelegated!(cloner, &pubkeys, CURRENT_SLOT, owner); + assert_subscribed_without_delegation_record!(chainlink, &[&pubkey]); +} + +// ----------------- +// Compressed delegation record is initialized and empty (undelegated) +// ----------------- +#[tokio::test] +async fn test_compressed_account_undelegated() { + let TestContext { + chainlink, + photon_client, + rpc_client, + cloner, + .. + } = setup(CURRENT_SLOT).await; + + let pubkey = Pubkey::new_unique(); + rpc_client.add_account(pubkey, Account::default()); + photon_client.add_account( + pubkey, + Account { + data: borsh::to_vec(&CompressedDelegationRecord::default()) + .unwrap(), + ..Account::default() + }, + CURRENT_SLOT, + ); + + let pubkeys = [pubkey]; + let res = chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + debug!("res: {res:?}"); + + assert_cloned_as_undelegated!(cloner, &pubkeys, CURRENT_SLOT); + assert_subscribed_without_delegation_record!(chainlink, &[&pubkey]); +} diff --git a/magicblock-chainlink/tests/03_deleg_after_sub.rs b/magicblock-chainlink/tests/03_deleg_after_sub.rs index 81baba293..7f58a2825 100644 --- a/magicblock-chainlink/tests/03_deleg_after_sub.rs +++ b/magicblock-chainlink/tests/03_deleg_after_sub.rs @@ -2,7 +2,10 @@ use magicblock_chainlink::{ assert_cloned_as_delegated, assert_cloned_as_undelegated, assert_not_cloned, assert_not_subscribed, assert_subscribed_without_delegation_record, - testing::{deleg::add_delegation_record_for, init_logger}, + testing::{ + accounts::compressed_account_shared_with_owner_and_slot, + deleg::add_delegation_record_for, init_logger, + }, AccountFetchOrigin, }; use solana_account::Account; @@ -119,3 +122,122 @@ async fn test_deleg_after_subscribe_case2() { assert_not_subscribed!(&chainlink, &[&pubkey, &delegation_record]); } } + +// NOTE: Flow "Account created then fetched, then delegated" +#[tokio::test] +async fn test_deleg_after_subscribe_case2_compressed() { + let mut slot: u64 = 11; + + let ctx = setup(slot).await; + let TestContext { + chainlink, + cloner, + rpc_client, + photon_client, + validator_pubkey, + .. + } = ctx.clone(); + + let pubkey = Pubkey::new_unique(); + let program_pubkey = Pubkey::new_unique(); + let acc = Account { + lamports: 1_000, + owner: program_pubkey, + ..Default::default() + }; + + // 1. Initially the account does not exist + // - readable: OK (non existing account) + // - writable: NO + { + info!("1. Initially the account does not exist"); + assert_not_cloned!(cloner, &[pubkey]); + + chainlink + .ensure_accounts( + &[pubkey], + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + assert_not_cloned!(cloner, &[pubkey]); + } + + // 2. Account created with original owner + // + // Now we can ensure it as readonly and it will be cloned + // - readable: OK + // - writable: NO + { + info!("2. Create account owned by program {program_pubkey}"); + + slot = rpc_client.set_slot(slot + 11); + let acc = + account_shared_with_owner_and_slot(&acc, program_pubkey, slot); + + // When the account is created we do not receive any update since we do not sub to a non-existing account + let updated = ctx + .send_and_receive_account_update(pubkey, acc.clone(), Some(400)) + .await; + assert!(!updated); + + chainlink + .ensure_accounts( + &[pubkey], + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + assert_cloned_as_undelegated!(cloner, &[pubkey], slot, program_pubkey); + assert_subscribed_without_delegation_record!(&chainlink, &[&pubkey]); + } + + // 3. Account delegated to us + // + // Delegate account to us and the sub update should be received + // even before the ensure_writable request + { + info!("3. Delegate account {pubkey} to us"); + + slot = rpc_client.set_slot(slot + 11); + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + validator_pubkey, + slot, + acc, + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + // Compressed accounts don't need the PDA to exist + rpc_client.remove_account(&pubkey); + let updated = ctx + .send_and_receive_account_update( + pubkey, + Account::default(), + Some(400), + ) + .await; + + // Needs to ensure accounts for compressed accounts + chainlink + .ensure_accounts( + &[pubkey], + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + + assert!(updated); + assert_cloned_as_delegated!(cloner, &[pubkey], slot, program_pubkey); + assert_not_subscribed!(&chainlink, &[&pubkey]); + } +} diff --git a/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs b/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs index 835726338..27a8155c9 100644 --- a/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs +++ b/magicblock-chainlink/tests/04_redeleg_other_separate_slots.rs @@ -7,7 +7,10 @@ use magicblock_chainlink::{ assert_cloned_as_delegated, assert_cloned_as_undelegated, assert_not_subscribed, assert_remain_undelegating, assert_subscribed_without_delegation_record, - testing::{deleg::add_delegation_record_for, init_logger}, + testing::{ + accounts::compressed_account_shared_with_owner_and_slot, + deleg::add_delegation_record_for, init_logger, + }, }; use solana_account::Account; use solana_program::clock::Slot; @@ -127,3 +130,120 @@ async fn test_undelegate_redelegate_to_other_in_separate_slot() { assert_subscribed_without_delegation_record!(&chainlink, &[&pubkey]); } } + +#[tokio::test] +async fn test_undelegate_redelegate_to_other_in_separate_slot_compressed() { + let mut slot: u64 = 11; + + let ctx = setup(slot).await; + let TestContext { + chainlink, + cloner, + rpc_client, + photon_client, + validator_pubkey, + .. + } = ctx.clone(); + + let pubkey = Pubkey::new_unique(); + let program_pubkey = Pubkey::new_unique(); + let other_authority = Pubkey::new_unique(); + let acc = Account::new(0, 0, &program_pubkey); + + // 1. Account delegated to us + // Initial state: Account is delegated to us and we can read/write to it + { + info!("1. Account delegated to us"); + + slot = rpc_client.set_slot(slot + 11); + let mut compressed_account = + compressed_account_shared_with_owner_and_slot( + pubkey, + validator_pubkey, + slot, + acc.clone(), + ); + compressed_account.set_remote_slot(slot); + photon_client.add_account(pubkey, compressed_account.into(), slot); + + // Transaction to read + // Fetch account - see it's owned by DP, fetch compressed account, clone account as delegated + ctx.ensure_account(&pubkey).await.unwrap(); + assert_cloned_as_delegated!(cloner, &[pubkey], slot, program_pubkey); + assert_not_subscribed!(&chainlink, &[&pubkey]); + }; + + // 2. Account is undelegated + // Undelegation requested, setup subscription, writes refused + { + info!("2.1. Account is undelegated - Undelegation requested (account owner set to DP in Ephem)"); + + ctx.force_undelegation(&pubkey); + + info!("2.2. Would refuse write (account still owned by DP in Ephem)"); + ctx.ensure_account(&pubkey).await.unwrap(); + assert_remain_undelegating!(cloner, &[pubkey], slot); + + slot = rpc_client.set_slot(slot + 11); + + info!("2.3. Account is undelegated on chain"); + // For compressed accounts, undelegation means the compressed account is emptied. + let undelegated_acc = ctx + .commit_and_undelegate_compressed(&pubkey, &program_pubkey) + .await + .unwrap(); + + // Account should be empty onchain + assert_eq!(cloner.get_account(&pubkey).unwrap(), undelegated_acc); + + info!("2.4. Would refuse write (undelegated on chain)"); + ctx.ensure_account(&pubkey).await.unwrap(); + assert_cloned_as_undelegated!(cloner, &[pubkey], slot, program_pubkey); + assert_subscribed_without_delegation_record!(&chainlink, &[&pubkey]); + } + + // 4. Account redelegated to another authority + // Delegate to other, subscription update, writes refused + { + info!("4.1. Account redelegated to another authority - Delegate account to other"); + slot = rpc_client.set_slot(slot + 2); + + // Create compressed delegation record + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + other_authority, + slot, + acc, + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + + // Compressed accounts don't send notifications when they are undelegated. + let acc = rpc_client.get_account_at_slot(&pubkey).unwrap(); + let updated = ctx + .send_and_receive_account_update( + pubkey, + acc.account.clone(), + Some(400), + ) + .await; + assert!(updated, "Failed to receive delegation update"); + + // Logical state matches; `compressed` stays set (expanded from `CompressedDelegationRecord`). + let mut acc_redeleg_expected = account_shared_with_owner_and_slot( + &acc.account, + program_pubkey, + slot, + ); + acc_redeleg_expected.set_compressed(true); + assert_eq!(cloner.get_account(&pubkey).unwrap(), acc_redeleg_expected); + + info!("4.2. Would refuse write (delegated to other)"); + ctx.ensure_account(&pubkey).await.unwrap(); + assert_cloned_as_undelegated!(cloner, &[pubkey], slot, program_pubkey); + assert_subscribed_without_delegation_record!(&chainlink, &[&pubkey]); + } +} diff --git a/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs b/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs index 664c9e940..b6c6ca214 100644 --- a/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs +++ b/magicblock-chainlink/tests/05_redeleg_other_same_slot.rs @@ -7,7 +7,11 @@ use magicblock_chainlink::{ assert_cloned_as_delegated, assert_cloned_as_undelegated, assert_not_subscribed, assert_remain_undelegating, assert_subscribed_without_delegation_record, - testing::{deleg::add_delegation_record_for, init_logger}, + testing::{ + accounts::compressed_account_shared_with_owner_and_slot, + deleg::add_delegation_record_for, init_logger, + }, + AccountFetchOrigin, }; use solana_account::Account; use solana_program::clock::Slot; @@ -99,3 +103,92 @@ async fn test_undelegate_redelegate_to_other_in_same_slot() { assert_subscribed_without_delegation_record!(&chainlink, &[&pubkey]); } } + +#[tokio::test] +async fn test_undelegate_redelegate_to_other_in_same_slot_compressed() { + let mut slot: u64 = 11; + + let ctx = setup(slot).await; + let TestContext { + chainlink, + cloner, + rpc_client, + photon_client, + .. + } = ctx.clone(); + + let pubkey = Pubkey::new_unique(); + let program_pubkey = Pubkey::new_unique(); + let other_authority = Pubkey::new_unique(); + let acc = Account::new(0, 0, &program_pubkey); + + // 1. Account delegated to us + // Initial state: Account is delegated to us and we can read/write to it + { + info!("1. Account delegated to us"); + + slot = rpc_client.set_slot(slot + 11); + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + ctx.validator_pubkey, + slot, + acc.clone(), + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + + // Transaction to read/write would be ok + // Fetch account - see it's owned by DP, fetch delegation record, clone account as delegated + ctx.ensure_account(&pubkey).await.unwrap(); + assert_cloned_as_delegated!(cloner, &[pubkey], slot, program_pubkey); + assert_not_subscribed!(&chainlink, &[&pubkey]); + }; + + // 2. Account is undelegated and redelegated to another authority (same slot) + // Undelegation requested, setup subscription, writes refused + { + info!("2.1. Account is undelegated - Undelegation requested (account owner set to DP in Ephem)"); + + ctx.force_undelegation(&pubkey); + + info!("2.2. Would refuse write (account still owned by DP in Ephem)"); + assert_remain_undelegating!(cloner, &[pubkey], slot); + + slot = rpc_client.set_slot(slot + 1); + + info!("2.3. Account is undelegated and redelegated to other authority in same slot"); + + // Compressed accounts don't send notifications when they are undelegated. + + // Then immediately delegate to other authority (simulating same slot operation) + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + other_authority, + slot, + acc.clone(), + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + + ctx.chainlink + .ensure_accounts( + &[pubkey], + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + + // Account should be cloned as delegated to other (flagged as undelegated) + info!("2.4. Would refuse write (delegated to other)"); + assert_cloned_as_undelegated!(cloner, &[pubkey], slot, program_pubkey); + assert_subscribed_without_delegation_record!(&chainlink, &[&pubkey]); + } +} diff --git a/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs b/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs index e26956f1b..0f38c51ab 100644 --- a/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs +++ b/magicblock-chainlink/tests/06_redeleg_us_separate_slots.rs @@ -7,7 +7,11 @@ use magicblock_chainlink::{ assert_cloned_as_delegated, assert_cloned_as_undelegated, assert_not_subscribed, assert_remain_undelegating, assert_subscribed_without_delegation_record, - testing::{deleg::add_delegation_record_for, init_logger}, + testing::{ + accounts::compressed_account_shared_with_owner_and_slot, + deleg::add_delegation_record_for, init_logger, + }, + AccountFetchOrigin, }; use solana_account::Account; use solana_program::clock::Slot; @@ -113,3 +117,109 @@ async fn test_undelegate_redelegate_to_us_in_separate_slots() { assert_not_subscribed!(chainlink, &[&pubkey, &deleg_record_pubkey]); } } + +#[tokio::test] +async fn test_undelegate_redelegate_to_us_in_separate_slots_compressed() { + let mut slot: u64 = 11; + + let ctx = setup(slot).await; + let TestContext { + chainlink, + cloner, + rpc_client, + photon_client, + .. + } = ctx.clone(); + + let pubkey = Pubkey::new_unique(); + let program_pubkey = Pubkey::new_unique(); + + // 1. Account delegated to us + // Initial state: Account is delegated to us and we can read/write to it + { + info!("1. Account delegated to us"); + + slot = rpc_client.set_slot(slot + 11); + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + ctx.validator_pubkey, + slot, + Account::new(0, 0, &program_pubkey), + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + + // Fetch account - see it's owned by DP, fetch delegation record, clone account as delegated + ctx.ensure_account(&pubkey).await.unwrap(); + assert_cloned_as_delegated!(cloner, &[pubkey], slot, program_pubkey); + assert_not_subscribed!(&chainlink, &[&pubkey]); + }; + + // 2. Account is undelegated + // Undelegation requested, setup subscription, writes would be refused + { + info!("2.1. Account is undelegated - Undelegation requested (account owner set to DP in Ephem)"); + + ctx.force_undelegation(&pubkey); + + info!("2.2. Would refuse write (account still owned by DP in Ephem)"); + assert_remain_undelegating!(cloner, &[pubkey], slot); + + slot = rpc_client.set_slot(slot + 11); + + info!("2.3. Account is undelegated on chain"); + // Committor service calls this to trigger subscription + chainlink.undelegation_requested(pubkey).await.unwrap(); + + // Committor service then requests undelegation on chain + let undelegated_acc = ctx + .commit_and_undelegate_compressed(&pubkey, &program_pubkey) + .await + .unwrap(); + assert_eq!(cloner.get_account(&pubkey).unwrap(), undelegated_acc); + + // Account should be cloned as undelegated + info!("2.4. Write would be refused (undelegated on chain)"); + assert_cloned_as_undelegated!(cloner, &[pubkey], slot, program_pubkey); + assert_subscribed_without_delegation_record!(&chainlink, &[&pubkey]); + } + + // 3. Account redelegated to us (separate slot) + // Delegate back to us, subscription update, writes allowed + { + info!("3.1. Account redelegated to us - Delegate account back to us"); + slot = rpc_client.set_slot(slot + 11); + + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + ctx.validator_pubkey, + slot, + Account::new(0, 0, &program_pubkey), + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + + chainlink + .ensure_accounts( + &[pubkey], + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + + // Account should be cloned as delegated back to us + info!("3.2. Would allow write (delegated to us again)"); + assert_cloned_as_delegated!(cloner, &[pubkey], slot, program_pubkey); + + // Account is delegated to us, so we don't subscribe to it nor its delegation record + assert_not_subscribed!(chainlink, &[&pubkey]); + } +} diff --git a/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs b/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs index 911dd3004..49f2a688e 100644 --- a/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs +++ b/magicblock-chainlink/tests/07_redeleg_us_same_slot.rs @@ -6,7 +6,11 @@ use magicblock_chainlink::{ assert_cloned_as_delegated, assert_not_subscribed, assert_remain_undelegating, - testing::{deleg::add_delegation_record_for, init_logger}, + testing::{ + accounts::compressed_account_shared_with_owner_and_slot, + deleg::add_delegation_record_for, init_logger, + }, + AccountFetchOrigin, }; use solana_account::Account; use solana_program::clock::Slot; @@ -108,3 +112,95 @@ async fn test_undelegate_redelegate_to_us_in_same_slot() { assert_not_subscribed!(chainlink, &[&pubkey, &deleg_record_pubkey]); } } + +#[tokio::test] +async fn test_undelegate_redelegate_to_us_in_same_slot_compressed() { + let mut slot: u64 = 11; + + let ctx = setup(slot).await; + let TestContext { + chainlink, + cloner, + rpc_client, + photon_client, + .. + } = ctx.clone(); + + let pubkey = Pubkey::new_unique(); + let program_pubkey = Pubkey::new_unique(); + + // 1. Account delegated to us + // Initial state: Account is delegated to us and we can read/write to it + { + info!("1. Account delegated to us"); + + slot = rpc_client.set_slot(slot + 11); + + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + ctx.validator_pubkey, + slot, + Account::new(0, 0, &program_pubkey), + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + + // Transaction to read + // Fetch account - see it's owned by DP, fetch delegation record, clone account as delegated + ctx.ensure_account(&pubkey).await.unwrap(); + assert_cloned_as_delegated!(cloner, &[pubkey], slot, program_pubkey); + assert_not_subscribed!(&chainlink, &[&pubkey]); + } + + // 2. Account is undelegated and redelegated to us (same slot) + // Undelegation requested, setup subscription, writes refused until redelegation + { + info!("2.1. Account is undelegated - Undelegation requested (account owner set to DP in Ephem)"); + + ctx.force_undelegation(&pubkey); + + info!("2.2. Would refuse write (account still owned by DP in Ephem)"); + assert_remain_undelegating!(cloner, &[pubkey], slot); + + slot = rpc_client.set_slot(slot + 1); + + info!("2.3. Account is undelegated and redelegated to us in same slot"); + + // First trigger undelegation subscription + ctx.chainlink.undelegation_requested(pubkey).await.unwrap(); + + // Update account to be delegated on chain and send a sub update + let compressed_account = compressed_account_shared_with_owner_and_slot( + pubkey, + ctx.validator_pubkey, + slot, + Account::new(0, 0, &program_pubkey), + ); + photon_client.add_account( + pubkey, + compressed_account.clone().into(), + slot, + ); + + // Then immediately delegate back to us (simulating same slot operation) + chainlink + .ensure_accounts( + &[pubkey], + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + + // Account should be cloned as delegated back to us + info!("2.4. Would allow write (delegated to us again)"); + assert_cloned_as_delegated!(cloner, &[pubkey], slot, program_pubkey); + + // Account is delegated to us, so we don't subscribe to it nor its delegation record + assert_not_subscribed!(chainlink, &[&pubkey]); + } +} diff --git a/magicblock-chainlink/tests/utils/test_context.rs b/magicblock-chainlink/tests/utils/test_context.rs index f89f8ba24..c6a8e783b 100644 --- a/magicblock-chainlink/tests/utils/test_context.rs +++ b/magicblock-chainlink/tests/utils/test_context.rs @@ -18,12 +18,14 @@ use magicblock_chainlink::{ accounts::account_shared_with_owner, cloner_stub::ClonerStub, deleg::add_delegation_record_for, + photon_client_mock::PhotonClientMock, rpc_client_mock::{ChainRpcClientMock, ChainRpcClientMockBuilder}, utils::{create_test_lru_cache, create_test_lru_cache_with_config}, }, AccountFetchOrigin, Chainlink, }; use magicblock_config::config::{ChainLinkConfig, LifecycleMode}; +use magicblock_core::traits::PhotonClient; use solana_account::{Account, AccountSharedData}; use solana_keypair::Keypair; use solana_program::{clock::Slot, sysvar::clock}; @@ -38,16 +40,24 @@ pub type TestChainlink = Chainlink< ChainPubsubClientMock, AccountsBankStub, ClonerStub, + PhotonClientMock, >; #[derive(Clone)] pub struct TestContext { pub rpc_client: ChainRpcClientMock, pub pubsub_client: ChainPubsubClientMock, + pub photon_client: PhotonClientMock, pub chainlink: Arc, pub bank: Arc, pub remote_account_provider: Option< - Arc>, + Arc< + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, + >, >, pub cloner: Arc, pub validator_pubkey: Pubkey, @@ -55,13 +65,14 @@ pub struct TestContext { impl TestContext { pub async fn init(slot: Slot) -> Self { - let (rpc_client, pubsub_client) = { + let (rpc_client, pubsub_client, photon_client) = { let rpc_client = ChainRpcClientMockBuilder::new().slot(slot).build(); let (updates_sndr, updates_rcvr) = mpsc::channel(100); let pubsub_client = ChainPubsubClientMock::new(updates_sndr, updates_rcvr); - (rpc_client, pubsub_client) + let photon_client = PhotonClientMock::default(); + (rpc_client, pubsub_client, photon_client) }; let lifecycle_mode = LifecycleMode::Ephemeral; @@ -83,6 +94,7 @@ impl TestContext { RemoteAccountProvider::try_from_clients_and_mode( rpc_client.clone(), pubsub_client.clone(), + photon_client.clone(), tx, &config, subscribed_accounts, @@ -124,6 +136,7 @@ impl TestContext { Self { rpc_client, pubsub_client, + photon_client, chainlink: Arc::new(chainlink), bank, cloner, @@ -263,6 +276,39 @@ impl TestContext { Ok(undelegated_acc) } + /// Assumes that account was already marked as undelegate in the bank + /// see [`force_undelegation`](Self::force_undelegation) + #[allow(dead_code)] + pub async fn commit_and_undelegate_compressed( + &self, + pubkey: &Pubkey, + owner: &Pubkey, + ) -> ChainlinkResult { + // For compressed accounts, undelegation means the compressed account is emptied. + let acc = self.bank.get(pubkey).unwrap(); + self.rpc_client.add_account(*pubkey, acc.clone().into()); + self.photon_client.remove_account(pubkey); + // Committor service calls this to trigger subscription + self.chainlink.undelegation_requested(*pubkey).await?; + + // Committor service then requests undelegation on chain + let undelegated_acc = account_shared_with_owner_and_slot( + &acc.into(), + *owner, + self.rpc_client.get_slot(), + ); + let updated = self + .send_and_receive_account_update( + *pubkey, + undelegated_acc.clone(), + Some(400), + ) + .await; + assert!(updated, "Failed to receive undelegation update"); + + Ok(undelegated_acc) + } + #[allow(dead_code)] pub async fn delegate_existing_account_to( &self, diff --git a/magicblock-config/README.md b/magicblock-config/README.md index 79b88c99d..b1504d703 100644 --- a/magicblock-config/README.md +++ b/magicblock-config/README.md @@ -53,10 +53,10 @@ Environment variables are mapped using the `figment` provider. ### Examples -| Struct Field | Config Section | Environment Variable | -| :--- | :--- | :--- | -| `validator.basefee` | `[validator]` | `MBV_VALIDATOR__BASEFEE` | -| `ledger.block_time` | `[ledger]` | `MBV_LEDGER__BLOCK_TIME` | +| Struct Field | Config Section | Environment Variable | +| :----------------------------- | :------------------ | :---------------------------------- | +| `validator.basefee` | `[validator]` | `MBV_VALIDATOR__BASEFEE` | +| `ledger.block_time` | `[ledger]` | `MBV_LEDGER__BLOCK_TIME` | | `chain_operation.country_code` | `[chain-operation]` | `MBV_CHAIN_OPERATION__COUNTRY_CODE` | ## Configuration File @@ -93,6 +93,7 @@ The configuration is split into domain-specific structs available in `src/config * **`ChainLinkConfig`**: Account cloning settings. * **`CommitStrategy`**: Compute unit pricing for base chain commits. * **`TaskSchedulerConfig`**: Task scheduling settings. + * **`CompressionConfig`**: Compression settings. ## Testing diff --git a/magicblock-config/src/config/compression.rs b/magicblock-config/src/config/compression.rs new file mode 100644 index 000000000..3c32a75f7 --- /dev/null +++ b/magicblock-config/src/config/compression.rs @@ -0,0 +1,19 @@ +use serde::{Deserialize, Serialize}; + +use crate::consts; + +/// Configuration for the compression service. +#[derive(Deserialize, Serialize, Debug, Clone)] +#[serde(rename_all = "kebab-case", deny_unknown_fields, default)] +pub struct CompressionConfig { + /// The URL of the Photon indexer. + pub photon_url: String, +} + +impl Default for CompressionConfig { + fn default() -> Self { + Self { + photon_url: consts::DEFAULT_PHOTON_URL.to_string(), + } + } +} diff --git a/magicblock-config/src/config/mod.rs b/magicblock-config/src/config/mod.rs index 64802b702..0a5b719e1 100644 --- a/magicblock-config/src/config/mod.rs +++ b/magicblock-config/src/config/mod.rs @@ -2,6 +2,7 @@ pub mod accounts; pub mod aperture; pub mod chain; pub mod cli; +pub mod compression; pub mod grpc; pub mod ledger; pub mod lifecycle; @@ -16,6 +17,7 @@ pub use aperture::ApertureConfig; pub use chain::{ AllowedProgram, ChainLinkConfig, ChainOperationConfig, CommittorConfig, }; +pub use compression::CompressionConfig; pub use grpc::GrpcConfig; pub use ledger::LedgerConfig; pub use lifecycle::LifecycleMode; diff --git a/magicblock-config/src/consts.rs b/magicblock-config/src/consts.rs index e164d8485..952a29c18 100644 --- a/magicblock-config/src/consts.rs +++ b/magicblock-config/src/consts.rs @@ -73,3 +73,7 @@ pub const DEFAULT_RESUBSCRIPTION_DELAY_MS: u64 = 50; /// Default capacity for the LRU cache of subscribed accounts pub const DEFAULT_MAX_MONITORED_ACCOUNTS: usize = 5_000; + +// Compression Defaults +/// Default URL of the Photon indexer +pub const DEFAULT_PHOTON_URL: &str = "http://localhost:8784"; diff --git a/magicblock-config/src/lib.rs b/magicblock-config/src/lib.rs index 2f19e7511..12807aabe 100644 --- a/magicblock-config/src/lib.rs +++ b/magicblock-config/src/lib.rs @@ -22,8 +22,8 @@ pub mod types; use crate::{ config::{ AccountsDbConfig, ChainLinkConfig, ChainOperationConfig, - CommittorConfig, LedgerConfig, LoadableProgram, TaskSchedulerConfig, - ValidatorConfig, + CommittorConfig, CompressionConfig, LedgerConfig, LoadableProgram, + TaskSchedulerConfig, ValidatorConfig, }, types::Remote, }; @@ -64,6 +64,7 @@ pub struct ValidatorParams { pub chainlink: ChainLinkConfig, pub chain_operation: Option, pub task_scheduler: TaskSchedulerConfig, + pub compression: CompressionConfig, pub programs: Vec, } diff --git a/magicblock-config/src/tests.rs b/magicblock-config/src/tests.rs index 067c786b7..d666fa310 100644 --- a/magicblock-config/src/tests.rs +++ b/magicblock-config/src/tests.rs @@ -282,6 +282,22 @@ fn test_chainlink_config() { ); } +#[test] +#[parallel] +fn test_compression_config() { + // Verify compression config is loaded correctly + let (_dir, config_path) = create_temp_config( + r#" + [compression] + photon-url = "http://localhost:8784" + "#, + ); + + let config = run_cli(vec![config_path.to_str().unwrap()]); + + assert_eq!(config.compression.photon_url, "http://localhost:8784"); +} + // ============================================================================ // 6. Type Parsing & Validation // ============================================================================ @@ -451,6 +467,9 @@ fn test_example_config_full_coverage() { Duration::from_millis(10) ); + // Compression config is present + assert_eq!(config.compression.photon_url, "http://localhost:8784"); + // The example file has the programs section with 2 entries assert_eq!( config.programs.len(), diff --git a/magicblock-core/Cargo.toml b/magicblock-core/Cargo.toml index eda52b85a..ce1450cf2 100644 --- a/magicblock-core/Cargo.toml +++ b/magicblock-core/Cargo.toml @@ -8,9 +8,14 @@ license.workspace = true edition.workspace = true [dependencies] - +async-trait = { workspace = true } +light-client = { workspace = true } +light-compressed-account = { workspace = true } +light-sdk = { workspace = true, features = ["v2"] } +compressed-delegation-client = { workspace = true } console-subscriber = { workspace = true, optional = true } tokio = { workspace = true, features = ["sync"] } +thiserror = { workspace = true } flume = { workspace = true } bincode = { workspace = true } diff --git a/magicblock-core/src/compression.rs b/magicblock-core/src/compression.rs new file mode 100644 index 000000000..3af81d64b --- /dev/null +++ b/magicblock-core/src/compression.rs @@ -0,0 +1,44 @@ +use light_compressed_account::address::derive_address; +use light_sdk::light_hasher::hash_to_field_size::hashv_to_bn254_field_size_be_const_array; +use solana_pubkey::Pubkey; + +// Light protocol V2 accounts: +// https://www.zkcompression.com/resources/addresses-and-urls#v2-2 +pub const ADDRESS_TREE: Pubkey = + Pubkey::from_str_const("amt2kaJA14v3urZbZvnc5v2np8jqvc4Z8zDep5wbtzx"); +pub const OUTPUT_QUEUE: Pubkey = + Pubkey::from_str_const("oq1na8gojfdUhsfCpyjNt6h4JaDWtHf1yQj4koBWfto"); + +/// Derives a CDA (Compressed derived Address) from a PDA (Program derived Address) +/// of a compressed account we want to use in our validator in uncompressed form. +pub fn derive_cda_from_pda(pda: &Pubkey) -> Pubkey { + // Since the PDA is already unique we use the delegation program's id + // as a program id. + // SAFETY: BN254 hash of PDA must succeed for a 32-byte PDA seed + let seed = + hashv_to_bn254_field_size_be_const_array::<3>(&[&pda.to_bytes()]) + .expect("BN254 hash of PDA must succeed for a 32-byte PDA seed"); + let address = derive_address( + &seed, + &ADDRESS_TREE.to_bytes(), + &compressed_delegation_client::ID.to_bytes(), + ); + Pubkey::new_from_array(address) +} + +#[cfg(test)] +mod tests { + use solana_pubkey::pubkey; + + use super::*; + + #[test] + fn test_derive_cda_from_pda() { + let pda = pubkey!("6pyGAQnqveUcHJ4iT1B6N72iJSBWcb6KRht315Fo7mLX"); + let cda = derive_cda_from_pda(&pda); + assert_eq!( + cda, + pubkey!("13CJjg6sMzZ8Lsn1oyQggzcyq5nFHYt97i7bhMu7BNu9") + ); + } +} diff --git a/magicblock-core/src/lib.rs b/magicblock-core/src/lib.rs index cbe515ada..1776c199d 100644 --- a/magicblock-core/src/lib.rs +++ b/magicblock-core/src/lib.rs @@ -13,6 +13,7 @@ macro_rules! debug_panic { ) } +pub mod compression; pub mod coordination_mode; pub mod intent; pub mod link; diff --git a/magicblock-core/src/traits.rs b/magicblock-core/src/traits.rs index 7ccc27bae..c9733b108 100644 --- a/magicblock-core/src/traits.rs +++ b/magicblock-core/src/traits.rs @@ -1,11 +1,14 @@ use std::{collections::HashMap, fmt}; +use async_trait::async_trait; +use solana_account::Account; use solana_clock::Clock; use solana_hash::Hash; use solana_program::instruction::InstructionError; use solana_pubkey::Pubkey; use solana_signature::Signature; use solana_transaction_error::TransactionError; +use thiserror::Error; use crate::{ intent::{BaseActionCallback, CommittedAccount}, @@ -104,3 +107,26 @@ impl std::error::Error for ActionError { } pub type ActionResult = Result<(), ActionError>; + +#[derive(Debug, Clone, Error)] +pub enum PhotonClientError { + #[error("Indexer error: {0}")] + IndexerError(#[from] light_client::indexer::IndexerError), +} + +pub type PhotonClientResult = Result; + +#[async_trait] +pub trait PhotonClient: Send + Sync + Clone + 'static { + async fn get_account( + &self, + pubkey: &Pubkey, + min_context_slot: Option, + ) -> PhotonClientResult>; + + async fn get_multiple_accounts( + &self, + pubkeys: &[Pubkey], + min_context_slot: Option, + ) -> PhotonClientResult<(Vec>, Slot)>; +} diff --git a/magicblock-magic-program-api/src/instruction.rs b/magicblock-magic-program-api/src/instruction.rs index 6efc57abf..1456ff3a4 100644 --- a/magicblock-magic-program-api/src/instruction.rs +++ b/magicblock-magic-program-api/src/instruction.rs @@ -311,6 +311,38 @@ pub enum MagicBlockInstruction { /// - **1.** `[]` Crank signer PDA /// - **2..n** `[]` Accounts required by the embedded instructions ExecuteCrank { instructions: Vec }, + + /// Schedules the accounts provided at end of accounts Vec to be committed using compression. + /// It should be invoked from the program whose PDA accounts are to be + /// committed. + /// + /// This is the first part of scheduling a commit. + /// A second transaction [MagicBlockInstruction::AcceptScheduleCommits] has to run in order + /// to finish scheduling the commit. + /// + /// # Account references + /// - **0.** `[WRITE, SIGNER]` Payer requesting the commit to be scheduled + /// - **1.** `[WRITE]` Magic Context Account containing to which we store + /// the scheduled commits + /// - **2..n** `[]` Accounts to be committed + ScheduleCommitCompressed, + + /// This is the exact same instruction as [MagicBlockInstruction::ScheduleCommitCompressed] except + /// that the [ScheduledCommit] is flagged such that when accounts are committed, + /// they can later be undelegated. + /// Additionally the validator will refuse anymore transactions for the specific account + /// since they are no longer considered delegated to it. + /// + /// This is the first part of scheduling a commit. + /// A second transaction [MagicBlockInstruction::AcceptScheduleCommits] has to run in order + /// to finish scheduling the commit. + /// + /// # Account references + /// - **0.** `[WRITE, SIGNER]` Payer requesting the commit to be scheduled + /// - **1.** `[WRITE]` Magic Context Account containing to which we store + /// the scheduled commits + /// - **2..n** `[]` Accounts to be committed and undelegated + ScheduleCommitAndUndelegateCompressed, } impl MagicBlockInstruction { @@ -327,6 +359,7 @@ pub struct AccountModification { pub executable: Option, pub data: Option>, pub delegated: Option, + pub compressed: Option, pub confined: Option, pub remote_slot: Option, } @@ -338,6 +371,7 @@ pub struct AccountModificationForInstruction { pub executable: Option, pub data: Option>, pub delegated: Option, + pub compressed: Option, pub confined: Option, pub remote_slot: Option, } diff --git a/magicblock-metrics/src/metrics/mod.rs b/magicblock-metrics/src/metrics/mod.rs index f776e1447..6edcd45f3 100644 --- a/magicblock-metrics/src/metrics/mod.rs +++ b/magicblock-metrics/src/metrics/mod.rs @@ -286,6 +286,41 @@ lazy_static::lazy_static! { ) .unwrap(); + // Account fetch results from network (Photon) + pub static ref COMPRESSED_ACCOUNT_FETCHES_SUCCESS_COUNT: IntCounter = + IntCounter::new( + "compressed_account_fetches_success_count", + "Total number of successful network \ + account fetches", + ) + .unwrap(); + + pub static ref COMPRESSED_ACCOUNT_FETCHES_FAILED_COUNT: IntCounter = + IntCounter::new( + "compressed_account_fetches_failed_count", + "Total number of failed network account fetches \ + (RPC errors)", + ) + .unwrap(); + + pub static ref COMPRESSED_ACCOUNT_FETCHES_FOUND_COUNT: IntCounterVec = IntCounterVec::new( + Opts::new( + "compressed_account_fetches_found_count", + "Total number of network account fetches that found an account", + ), + &["origin"], + ) + .unwrap(); + + pub static ref COMPRESSED_ACCOUNT_FETCHES_NOT_FOUND_COUNT: IntCounterVec = IntCounterVec::new( + Opts::new( + "compressed_account_fetches_not_found_count", + "Total number of network account fetches where account was not found", + ), + &["origin"], + ) + .unwrap(); + pub static ref PER_PROGRAM_ACCOUNT_FETCH_STATS: IntCounterVec = IntCounterVec::new( Opts::new( "per_program_account_fetch_stats", @@ -817,6 +852,32 @@ pub fn inc_account_fetches_found(fetch_origin: AccountFetchOrigin, count: u64) { .inc_by(count); } +pub fn inc_compressed_account_fetches_success(count: u64) { + COMPRESSED_ACCOUNT_FETCHES_SUCCESS_COUNT.inc_by(count); +} + +pub fn inc_compressed_account_fetches_found( + fetch_origin: AccountFetchOrigin, + count: u64, +) { + COMPRESSED_ACCOUNT_FETCHES_FOUND_COUNT + .with_label_values(&[fetch_origin.value()]) + .inc_by(count); +} + +pub fn inc_compressed_account_fetches_not_found( + fetch_origin: AccountFetchOrigin, + count: u64, +) { + COMPRESSED_ACCOUNT_FETCHES_NOT_FOUND_COUNT + .with_label_values(&[fetch_origin.value()]) + .inc_by(count); +} + +pub fn inc_compressed_account_fetches_failed(count: u64) { + COMPRESSED_ACCOUNT_FETCHES_FAILED_COUNT.inc_by(count); +} + pub fn inc_account_fetches_not_found( fetch_origin: AccountFetchOrigin, count: u64, diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index e05827bb3..5243d3367 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -206,6 +206,8 @@ pub enum MagicBaseIntent { CommitAndUndelegate(CommitAndUndelegate), CommitFinalize(CommitType), CommitFinalizeAndUndelegate(CommitAndUndelegate), + CommitFinalizeCompressed(CommitType), + CommitFinalizeAndUndelegateCompressed(CommitAndUndelegate), } // Bundle of BaseIntents @@ -235,6 +237,12 @@ impl From for MagicIntentBundle { MagicBaseIntent::CommitFinalizeAndUndelegate(value) => { this.commit_finalize_and_undelegate = Some(value) } + MagicBaseIntent::CommitFinalizeCompressed(value) => { + this.commit_finalize = Some(value) + } + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed(value) => { + this.commit_finalize_and_undelegate = Some(value) + } } this @@ -633,6 +641,8 @@ impl MagicBaseIntent { MagicBaseIntent::CommitAndUndelegate(_) => true, MagicBaseIntent::CommitFinalize(_) => false, MagicBaseIntent::CommitFinalizeAndUndelegate(_) => true, + MagicBaseIntent::CommitFinalizeCompressed(_) => false, + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed(_) => true, } } @@ -643,6 +653,8 @@ impl MagicBaseIntent { MagicBaseIntent::CommitAndUndelegate(_) => false, MagicBaseIntent::CommitFinalize(_) => true, MagicBaseIntent::CommitFinalizeAndUndelegate(_) => true, + MagicBaseIntent::CommitFinalizeCompressed(_) => true, + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed(_) => true, } } @@ -659,6 +671,12 @@ impl MagicBaseIntent { MagicBaseIntent::CommitFinalizeAndUndelegate(t) => { Some(t.get_committed_accounts()) } + MagicBaseIntent::CommitFinalizeCompressed(t) => { + Some(t.get_committed_accounts()) + } + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed(t) => { + Some(t.get_committed_accounts()) + } } } @@ -677,6 +695,12 @@ impl MagicBaseIntent { MagicBaseIntent::CommitFinalizeAndUndelegate(t) => { Some(t.get_committed_accounts_mut()) } + MagicBaseIntent::CommitFinalizeCompressed(t) => { + Some(t.get_committed_accounts_mut()) + } + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed(t) => { + Some(t.get_committed_accounts_mut()) + } } } @@ -693,6 +717,10 @@ impl MagicBaseIntent { MagicBaseIntent::CommitAndUndelegate(t) => t.is_empty(), MagicBaseIntent::CommitFinalize(t) => t.is_empty(), MagicBaseIntent::CommitFinalizeAndUndelegate(t) => t.is_empty(), + MagicBaseIntent::CommitFinalizeCompressed(t) => t.is_empty(), + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed(t) => { + t.is_empty() + } } } } diff --git a/programs/magicblock/src/magicblock_processor.rs b/programs/magicblock/src/magicblock_processor.rs index f5575ad8a..2664906e8 100644 --- a/programs/magicblock/src/magicblock_processor.rs +++ b/programs/magicblock/src/magicblock_processor.rs @@ -67,6 +67,7 @@ declare_process_instruction!( invoke_context, ProcessScheduleCommitOptions { request_undelegation: false, + compressed: false, }, ), ScheduleCommitAndUndelegate => process_schedule_commit( @@ -74,6 +75,7 @@ declare_process_instruction!( invoke_context, ProcessScheduleCommitOptions { request_undelegation: true, + compressed: false, }, ), ScheduleCommitFinalize { @@ -83,6 +85,7 @@ declare_process_instruction!( invoke_context, ProcessScheduleCommitOptions { request_undelegation, + compressed: false, }, ), AcceptScheduleCommits => { @@ -221,6 +224,24 @@ declare_process_instruction!( ExecuteCrank { instructions } => { process_execute_crank(signers, invoke_context, instructions) } + ScheduleCommitCompressed => process_schedule_commit_finalize( + signers, + invoke_context, + ProcessScheduleCommitOptions { + request_undelegation: false, + compressed: true, + }, + ), + ScheduleCommitAndUndelegateCompressed => { + process_schedule_commit_finalize( + signers, + invoke_context, + ProcessScheduleCommitOptions { + request_undelegation: true, + compressed: true, + }, + ) + } } } ); diff --git a/programs/magicblock/src/mutate_accounts/process_mutate_accounts.rs b/programs/magicblock/src/mutate_accounts/process_mutate_accounts.rs index 2ebdbd42a..782b6d020 100644 --- a/programs/magicblock/src/mutate_accounts/process_mutate_accounts.rs +++ b/programs/magicblock/src/mutate_accounts/process_mutate_accounts.rs @@ -198,6 +198,14 @@ pub(crate) fn process_mutate_accounts( ); account.set_delegated(delegated); } + if let Some(compressed) = modification.compressed { + ic_msg!( + invoke_context, + "MutateAccounts: setting compressed to {}", + compressed + ); + account.set_compressed(compressed); + } if let Some(confined) = modification.confined { ic_msg!( invoke_context, @@ -299,6 +307,7 @@ mod tests { executable: Some(true), data: Some(vec![1, 2, 3, 4, 5]), delegated: Some(true), + compressed: Some(true), confined: Some(true), remote_slot: None, }; @@ -328,6 +337,7 @@ mod tests { let account_authority: AccountSharedData = accounts.drain(0..1).next().unwrap(); assert!(!account_authority.delegated()); + assert!(!account_authority.compressed()); assert!(!account_authority.confined()); assert_matches!( account_authority.into(), @@ -346,6 +356,7 @@ mod tests { let modified_account: AccountSharedData = accounts.drain(0..1).next().unwrap(); assert!(modified_account.delegated()); + assert!(modified_account.compressed()); assert!(modified_account.confined()); assert_matches!( modified_account.into(), diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs index 76a6f222f..2f97a217d 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs @@ -32,6 +32,7 @@ use crate::{ #[derive(Default)] pub(crate) struct ProcessScheduleCommitOptions { pub request_undelegation: bool, + pub compressed: bool, } pub(crate) fn process_schedule_commit( diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs index 6afde0630..034e42c54 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs @@ -288,15 +288,25 @@ pub(crate) fn process_schedule_commit_finalize( InstructionUtils::scheduled_commit_sent(intent_id, blockhash); let commit_sent_sig = action_sent_transaction.signatures[0]; - let base_intent = if opts.request_undelegation { - MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { - commit_action: CommitType::Standalone(committed_accounts), - undelegate_action: UndelegateType::Standalone, - }) - } else { - MagicBaseIntent::CommitFinalize(CommitType::Standalone( - committed_accounts, - )) + let base_intent = match (opts.request_undelegation, opts.compressed) { + (true, true) => MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( + CommitAndUndelegate { + commit_action: CommitType::Standalone(committed_accounts), + undelegate_action: UndelegateType::Standalone, + }, + ), + (true, false) => { + MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(committed_accounts), + undelegate_action: UndelegateType::Standalone, + }) + } + (false, true) => MagicBaseIntent::CommitFinalizeCompressed( + CommitType::Standalone(committed_accounts), + ), + (false, false) => MagicBaseIntent::CommitFinalize( + CommitType::Standalone(committed_accounts), + ), }; let scheduled_base_intent = ScheduledIntentBundle { diff --git a/programs/magicblock/src/utils/instruction_utils.rs b/programs/magicblock/src/utils/instruction_utils.rs index b712ddbca..bd80e3e70 100644 --- a/programs/magicblock/src/utils/instruction_utils.rs +++ b/programs/magicblock/src/utils/instruction_utils.rs @@ -112,6 +112,76 @@ impl InstructionUtils { ) } + // ----------------- + // Schedule Commit and Undelegate Compressed + // ----------------- + #[cfg(test)] + pub fn schedule_commit_and_undelegate_compressed( + payer: &Keypair, + pubkeys: Vec, + recent_blockhash: Hash, + ) -> Transaction { + let ix = Self::schedule_commit_and_undelegate_compressed_instruction( + &payer.pubkey(), + pubkeys, + ); + Self::into_transaction(payer, ix, recent_blockhash) + } + + #[cfg(test)] + pub(crate) fn schedule_commit_and_undelegate_compressed_instruction( + payer: &Pubkey, + pdas: Vec, + ) -> Instruction { + let mut account_metas = vec![ + AccountMeta::new(*payer, true), + AccountMeta::new(MAGIC_CONTEXT_PUBKEY, false), + ]; + for pubkey in &pdas { + account_metas.push(AccountMeta::new(*pubkey, true)); + } + Instruction::new_with_bincode( + crate::id(), + &MagicBlockInstruction::ScheduleCommitAndUndelegateCompressed, + account_metas, + ) + } + + // ----------------- + // Schedule Commit Compressed + // ----------------- + #[cfg(test)] + pub fn schedule_commit_compressed( + payer: &Keypair, + pubkeys: Vec, + recent_blockhash: Hash, + ) -> Transaction { + let ix = Self::schedule_commit_compressed_instruction( + &payer.pubkey(), + pubkeys, + ); + Self::into_transaction(payer, ix, recent_blockhash) + } + + #[cfg(test)] + pub(crate) fn schedule_commit_compressed_instruction( + payer: &Pubkey, + pdas: Vec, + ) -> Instruction { + let mut account_metas = vec![ + AccountMeta::new(*payer, true), + AccountMeta::new(MAGIC_CONTEXT_PUBKEY, false), + ]; + for pubkey in &pdas { + account_metas.push(AccountMeta::new_readonly(*pubkey, true)); + } + Instruction::new_with_bincode( + crate::id(), + &MagicBlockInstruction::ScheduleCommitCompressed, + account_metas, + ) + } + // ----------------- // Scheduled Commit Sent // ----------------- @@ -200,6 +270,7 @@ impl InstructionUtils { executable: account_modification.executable, data: account_modification.data, delegated: account_modification.delegated, + compressed: account_modification.compressed, confined: account_modification.confined, remote_slot: account_modification.remote_slot, }; diff --git a/test-integration/programs/compressed_delegation/compressed_delegation.so b/test-integration/programs/compressed_delegation/compressed_delegation.so new file mode 100755 index 0000000000000000000000000000000000000000..0bbaa5f117a83e3d1f3830ff6acaed8c54f26a44 GIT binary patch literal 172744 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 literal 0 HcmV?d00001 From b8556f82deffa81e9bfa04f65b9607ed8ad7a75b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 27 Apr 2026 00:36:31 +0200 Subject: [PATCH 002/110] fix: chainlink integration tests --- .github/workflows/ci-test-integration.yml | 4 +- Cargo.lock | 4 + compressed-delegation-api/src/lib.rs | 9 +- compressed-delegation-client/src/lib.rs | 5 +- magicblock-api/src/magic_sys_adapter.rs | 8 +- magicblock-api/src/magic_validator.rs | 1 + .../src/remote_account_provider/mod.rs | 13 +- .../remote_account_provider/photon_client.rs | 4 +- .../remote_account_provider/remote_account.rs | 26 +- magicblock-chainlink/src/testing/utils.rs | 1 + magicblock-committor-service/Cargo.toml | 4 + .../src/committor_processor.rs | 14 +- magicblock-committor-service/src/config.rs | 4 + .../src/intent_executor/task_info_fetcher.rs | 399 +- .../src/intent_executor/utils.rs | 24 +- .../src/persist/commit_persister.rs | 4 + magicblock-committor-service/src/service.rs | 21 +- .../src/service_ext.rs | 8 +- .../src/stubs/changeset_committor_stub.rs | 1 + .../tasks/commit_finalize_compressed_task.rs | 89 + magicblock-committor-service/src/tasks/mod.rs | 31 +- .../src/tasks/task_builder.rs | 93 +- .../src/tasks/task_strategist.rs | 12 +- magicblock-core/src/traits.rs | 1 + magicblock-magic-program-api/src/args.rs | 5 + .../src/magic_scheduled_base_intent.rs | 31 + programs/magicblock/src/magic_sys.rs | 3 +- .../src/schedule_transactions/mod.rs | 3 +- .../process_schedule_commit.rs | 21 +- .../process_schedule_commit_finalize.rs | 9 +- .../process_schedule_commit_tests.rs | 1 + .../process_schedule_intent_bundle.rs | 4 +- programs/magicblock/src/test_utils/mod.rs | 1 + test-integration/Cargo.lock | 4646 +++++++++++++---- test-integration/Cargo.toml | 32 +- .../configs/chainlink-conf.devnet.toml | 4 + .../configs/committor-conf.devnet.toml | 4 + .../compressed_delegation.so | Bin 172744 -> 172232 bytes .../programs/flexi-counter/Cargo.toml | 5 + .../programs/flexi-counter/src/instruction.rs | 104 + .../programs/flexi-counter/src/processor.rs | 260 +- .../src/processor/schedule_intent.rs | 1 + .../programs/flexi-counter/src/state.rs | 12 +- test-integration/test-chainlink/Cargo.toml | 13 +- .../test-chainlink/src/ixtest_context.rs | 419 +- .../test-chainlink/src/test_context.rs | 16 +- .../tests/ix_01_ensure-accounts.rs | 41 + .../tests/ix_03_deleg_after_sub.rs | 87 + .../tests/ix_06_redeleg_us_separate_slots.rs | 105 +- .../tests/ix_07_redeleg_us_same_slot.rs | 71 + .../tests/ix_remote_account_provider.rs | 19 +- .../test-committor-service/Cargo.toml | 6 + .../test-committor-service/tests/common.rs | 23 +- .../tests/test_intent_executor.rs | 31 +- .../tests/utils/instructions.rs | 173 + .../tests/utils/transactions.rs | 100 +- test-integration/test-runner/bin/run_tests.rs | 70 +- test-integration/test-runner/src/cleanup.rs | 23 + test-integration/test-runner/src/signal.rs | 6 +- test-integration/test-tools/Cargo.toml | 5 +- test-integration/test-tools/src/validator.rs | 175 +- 61 files changed, 6029 insertions(+), 1280 deletions(-) create mode 100644 magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index 54afcc86b..3eed205c9 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -75,7 +75,7 @@ jobs: shell: bash env: RUSTFLAGS: "-A dead-code" - run: cargo install --git https://github.com/lightprotocol/photon.git --rev ac7df6c388db847b7693a7a1cb766a7c9d7809b5 --locked --forceExpand commentComment on lines R74 to R79Resolved + run: cargo install --git https://github.com/lightprotocol/photon.git --rev 3f82b926be6717a07bd41aedb84b4d9e6b0ab0d3 --locked --force - name: Setup Node.js if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' @@ -86,7 +86,7 @@ jobs: - name: Install zk-compression CLI if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' run: | - npm i -g @lightprotocol/zk-compression-cli@0.27.1-alpha.10 + npm i -g @lightprotocol/zk-compression-cli@0.28.3 shell: bash - name: Run integration tests - ${{ matrix.batch_tests }} diff --git a/Cargo.lock b/Cargo.lock index b0caec379..2f50eaf50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4665,8 +4665,12 @@ dependencies = [ "base64 0.21.7", "bincode", "borsh 1.6.1", + "compressed-delegation-api", + "compressed-delegation-client", "futures-util", "lazy_static", + "light-client", + "light-sdk", "lru 0.16.3", "magicblock-committor-program", "magicblock-core", diff --git a/compressed-delegation-api/src/lib.rs b/compressed-delegation-api/src/lib.rs index 1f98f1935..eb128b81c 100644 --- a/compressed-delegation-api/src/lib.rs +++ b/compressed-delegation-api/src/lib.rs @@ -9,11 +9,14 @@ pub use instruction::{ CompressedDelegationProgramInstruction, DelegateArgs, ExternalUndelegateArgs, InitDelegationRecordArgs, UndelegateArgs, }; +use solana_pubkey::declare_id; pub use state::{CompressedDelegationRecord, DCP_DISCRIMINATOR}; /// Discriminator for CPI into owner programs for external undelegate. -pub const EXTERNAL_UNDELEGATE_DISCRIMINATOR: [u8; 8] = +pub const EXTERNAL_UNDELEGATE_DISCRIMINATOR_COMPRESSED: [u8; 8] = [0xD, 0x23, 0xB0, 0x7C, 0x70, 0x68, 0xFE, 0x73]; -pub const EXTERNAL_UNDELEGATE_DISCRIMINATOR_U64: u64 = - u64::from_le_bytes(EXTERNAL_UNDELEGATE_DISCRIMINATOR); +pub const EXTERNAL_UNDELEGATE_DISCRIMINATOR_U64_COMPRESSED: u64 = + u64::from_le_bytes(EXTERNAL_UNDELEGATE_DISCRIMINATOR_COMPRESSED); + +declare_id!("DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT"); diff --git a/compressed-delegation-client/src/lib.rs b/compressed-delegation-client/src/lib.rs index 3921c44b3..091b37362 100644 --- a/compressed-delegation-client/src/lib.rs +++ b/compressed-delegation-client/src/lib.rs @@ -6,8 +6,9 @@ pub use compressed_delegation_api::{ CommitAndFinalizeArgs, CompressedDelegationInstructionDiscriminator, CompressedDelegationProgramInstruction, CompressedDelegationRecord, DelegateArgs, ExternalUndelegateArgs, InitDelegationRecordArgs, - UndelegateArgs, DCP_DISCRIMINATOR, EXTERNAL_UNDELEGATE_DISCRIMINATOR, - EXTERNAL_UNDELEGATE_DISCRIMINATOR_U64, + UndelegateArgs, DCP_DISCRIMINATOR, + EXTERNAL_UNDELEGATE_DISCRIMINATOR_COMPRESSED, + EXTERNAL_UNDELEGATE_DISCRIMINATOR_U64_COMPRESSED, }; use light_sdk::derive_light_cpi_signer; use light_sdk_types::CpiSigner; diff --git a/magicblock-api/src/magic_sys_adapter.rs b/magicblock-api/src/magic_sys_adapter.rs index 1e13b44a7..c0beb482f 100644 --- a/magicblock-api/src/magic_sys_adapter.rs +++ b/magicblock-api/src/magic_sys_adapter.rs @@ -33,6 +33,7 @@ impl MagicSys for MagicSysAdapter { fn fetch_current_commit_nonces( &self, commits: &[CommittedAccount], + compressed: bool, ) -> Result, InstructionError> { if commits.is_empty() { return Ok(HashMap::new()); @@ -53,8 +54,11 @@ impl MagicSys for MagicSysAdapter { commits.iter().map(|account| account.pubkey).collect(); let _timer = metrics::start_fetch_commit_nonces_wait_timer(); - let receiver = committor_service - .fetch_current_commit_nonces_sync(&pubkeys, min_context_slot); + let receiver = committor_service.fetch_current_commit_nonces_sync( + &pubkeys, + compressed, + min_context_slot, + ); receiver .recv_timeout(Self::FETCH_TIMEOUT) .map_err(|err| match err { diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 77baed302..7e8d0e146 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -435,6 +435,7 @@ impl MagicValidator { committor_persist_path, ChainConfig { rpc_uri: config.rpc_url().to_owned(), + photon_uri: config.compression.photon_url.clone(), commitment: CommitmentConfig::confirmed(), compute_budget_config: ComputeBudgetConfig::new( config.commit.compute_unit_price, diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 5a47ac787..a61c4f2eb 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -68,7 +68,9 @@ use magicblock_metrics::metrics::{ inc_per_program_account_fetch_stats, set_monitored_accounts_count, AccountFetchOrigin, ProgramFetchResult, }; -use remote_account::is_synthetic_mark_empty_fresh; +use remote_account::{ + is_synthetic_mark_empty_fresh, should_prefer_rpc_over_photon_compressed_shell, +}; pub use remote_account::{ResolvedAccount, ResolvedAccountSharedData}; use crate::{ @@ -1590,6 +1592,15 @@ impl // classification and cloning do not run empty // data through the compressed delegation path. Found(rpc_state) + } else if should_prefer_rpc_over_photon_compressed_shell( + &rpc_state, + &comp_state, + ) { + trace!( + pubkey = %pubkey, + "Photon compressed account has no payload; using RPC ledger account" + ); + Found(rpc_state) } else { debug!("Both RPC and Compressed account found for pubkey {}. Using Compressed account.", pubkey); if rpc_state.account.slot() > comp_state.account.slot() + STALE_SLOT_THRESHOLD { diff --git a/magicblock-chainlink/src/remote_account_provider/photon_client.rs b/magicblock-chainlink/src/remote_account_provider/photon_client.rs index 63bfee3e1..1b522d4c3 100644 --- a/magicblock-chainlink/src/remote_account_provider/photon_client.rs +++ b/magicblock-chainlink/src/remote_account_provider/photon_client.rs @@ -25,10 +25,10 @@ impl Deref for PhotonClientImpl { } impl PhotonClientImpl { - pub(crate) fn new(photon_indexer: Arc) -> Self { + pub fn new(photon_indexer: Arc) -> Self { Self(photon_indexer) } - pub(crate) fn new_from_url(url: String) -> Self { + pub fn new_from_url(url: String) -> Self { debug!(url = %url, "Creating PhotonClient"); Self::new(Arc::new(PhotonIndexer::new(url))) } diff --git a/magicblock-chainlink/src/remote_account_provider/remote_account.rs b/magicblock-chainlink/src/remote_account_provider/remote_account.rs index 2a03b87ca..d194bf500 100644 --- a/magicblock-chainlink/src/remote_account_provider/remote_account.rs +++ b/magicblock-chainlink/src/remote_account_provider/remote_account.rs @@ -33,7 +33,9 @@ pub enum ResolvedAccount { /// structure is used for both RPC and Photon; if both are present, the merged result must not /// always be treated as a compressed account or empty bytes may be run through /// decompression. -pub(crate) fn is_synthetic_mark_empty_fresh(resolved: &ResolvedAccount) -> bool { +pub(crate) fn is_synthetic_mark_empty_fresh( + resolved: &ResolvedAccount, +) -> bool { match resolved { ResolvedAccount::Fresh(acc) => { acc.lamports() == 0 @@ -203,6 +205,28 @@ pub struct RemoteAccountState { pub source: RemoteAccountUpdateSource, } +/// Prefer RPC when Photon returns a compressed-account shell with no payload while RPC has +/// real ledger state. Empty account data cannot deserialize as a compressed delegation record; +/// without this, merge would pick Photon and the fetch cloner would drop the account. +pub(crate) fn should_prefer_rpc_over_photon_compressed_shell( + rpc: &RemoteAccountState, + photon: &RemoteAccountState, +) -> bool { + if photon.source != RemoteAccountUpdateSource::Compressed { + return false; + } + let ResolvedAccount::Fresh(photon_acc) = &photon.account else { + return false; + }; + if !photon_acc.data().is_empty() { + return false; + } + let ResolvedAccount::Fresh(rpc_acc) = &rpc.account else { + return false; + }; + rpc_acc.lamports() > 0 || !rpc_acc.data().is_empty() +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum RemoteAccount { NotFound(Slot), diff --git a/magicblock-chainlink/src/testing/utils.rs b/magicblock-chainlink/src/testing/utils.rs index 4f1bc4503..a276829c6 100644 --- a/magicblock-chainlink/src/testing/utils.rs +++ b/magicblock-chainlink/src/testing/utils.rs @@ -18,6 +18,7 @@ use crate::{ pub const PUBSUB_URL: &str = "ws://localhost:7800"; pub const RPC_URL: &str = "http://localhost:7799"; +pub const COMPRESSION_URL: &str = "http://localhost:8784"; pub fn random_pubkey() -> Pubkey { Keypair::new().pubkey() diff --git a/magicblock-committor-service/Cargo.toml b/magicblock-committor-service/Cargo.toml index 11eec877e..d61d2e9ba 100644 --- a/magicblock-committor-service/Cargo.toml +++ b/magicblock-committor-service/Cargo.toml @@ -15,8 +15,12 @@ async-trait = { workspace = true } base64 = { workspace = true } bincode = { workspace = true } borsh = { workspace = true } +compressed-delegation-api = { workspace = true } +compressed-delegation-client = { workspace = true } futures-util = { workspace = true } tracing = { workspace = true } +light-client = { workspace = true } +light-sdk = { workspace = true, features = ["v2"] } lru = { workspace = true } magicblock-committor-program = { workspace = true, features = [ "no-entrypoint", diff --git a/magicblock-committor-service/src/committor_processor.rs b/magicblock-committor-service/src/committor_processor.rs index 5439037d8..42c3e30c7 100644 --- a/magicblock-committor-service/src/committor_processor.rs +++ b/magicblock-committor-service/src/committor_processor.rs @@ -4,6 +4,7 @@ use std::{ sync::Arc, }; +use light_client::indexer::photon_indexer::PhotonIndexer; use magicblock_core::traits::ActionsCallbackScheduler; use magicblock_program::magic_scheduled_base_intent::ScheduledIntentBundle; use magicblock_rpc_client::MagicblockRpcClient; @@ -60,6 +61,8 @@ impl CommittorProcessor { ); let rpc_client = Arc::new(rpc_client); let magic_block_rpc_client = MagicblockRpcClient::new(rpc_client); + let photon_client = + Arc::new(PhotonIndexer::new(chain_config.photon_uri.to_string())); // Create TableMania let gc_config = GarbageCollectorConfig::default(); @@ -73,9 +76,11 @@ impl CommittorProcessor { let persister = IntentPersisterImpl::try_new(persist_file)?; // Create commit scheduler - let task_info_fetcher = Arc::new(CacheTaskInfoFetcher::new( - RpcTaskInfoFetcher::new(magic_block_rpc_client.clone()), - )); + let task_info_fetcher = + Arc::new(CacheTaskInfoFetcher::new(RpcTaskInfoFetcher::new( + magic_block_rpc_client.clone(), + photon_client, + ))); let commits_scheduler = IntentExecutionManager::new( magic_block_rpc_client.clone(), DummyDB::new(), @@ -180,10 +185,11 @@ impl CommittorProcessor { pub async fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult> { self.task_info_fetcher - .fetch_current_commit_nonces(pubkeys, min_context_slot) + .fetch_current_commit_nonces(pubkeys, compressed, min_context_slot) .await } } diff --git a/magicblock-committor-service/src/config.rs b/magicblock-committor-service/src/config.rs index fc231b07f..116b0e274 100644 --- a/magicblock-committor-service/src/config.rs +++ b/magicblock-committor-service/src/config.rs @@ -9,6 +9,7 @@ pub const DEFAULT_ACTIONS_TIMEOUT: Duration = Duration::from_secs(60); #[derive(Debug, Clone)] pub struct ChainConfig { pub rpc_uri: String, + pub photon_uri: String, pub commitment: CommitmentConfig, pub compute_budget_config: ComputeBudgetConfig, pub actions_timeout: Duration, @@ -18,6 +19,7 @@ impl ChainConfig { pub fn devnet(compute_budget_config: ComputeBudgetConfig) -> Self { Self { rpc_uri: "https://api.devnet.solana.com".to_string(), + photon_uri: "http://localhost:8784".to_string(), commitment: CommitmentConfig::confirmed(), compute_budget_config, actions_timeout: DEFAULT_ACTIONS_TIMEOUT, @@ -27,6 +29,7 @@ impl ChainConfig { pub fn mainnet(compute_budget_config: ComputeBudgetConfig) -> Self { Self { rpc_uri: "https://api.mainnet-beta.solana.com".to_string(), + photon_uri: "http://localhost:8784".to_string(), commitment: CommitmentConfig::confirmed(), compute_budget_config, actions_timeout: DEFAULT_ACTIONS_TIMEOUT, @@ -36,6 +39,7 @@ impl ChainConfig { pub fn local(compute_budget_config: ComputeBudgetConfig) -> Self { Self { rpc_uri: "http://localhost:7799".to_string(), + photon_uri: "http://localhost:8784".to_string(), commitment: CommitmentConfig::processed(), compute_budget_config, actions_timeout: DEFAULT_ACTIONS_TIMEOUT, diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 25c93d79f..4e5d4a47a 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -7,14 +7,29 @@ use std::{ }; use async_trait::async_trait; +use borsh::BorshDeserialize; +use compressed_delegation_api::{ + instruction::{CdpCompressedAccountMeta, CdpValidityProof}, + CompressedDelegationRecord, +}; use dlp_api::{ delegation_metadata_seeds_from_delegated_account, state::DelegationMetadata, }; +use futures_util::future::try_join_all; +use light_client::indexer::{ + photon_indexer::PhotonIndexer, Indexer, IndexerRpcConfig, RetryConfig, +}; +use light_sdk::instruction::{ + account_meta::CompressedAccountMeta, PackedAccounts, + SystemAccountMetaConfig, +}; use lru::LruCache; +use magicblock_core::compression::derive_cda_from_pda; use magicblock_metrics::metrics; use magicblock_rpc_client::{MagicBlockRpcClientError, MagicblockRpcClient}; use solana_account::Account; use solana_account_decoder::UiAccountEncoding; +use solana_instruction::AccountMeta; use solana_pubkey::Pubkey; use solana_rpc_client_api::{ client_error::ErrorKind, config::RpcAccountInfoConfig, @@ -28,6 +43,15 @@ use tracing::{error, info, warn}; const NUM_FETCH_RETRIES: NonZeroUsize = NonZeroUsize::new(5).unwrap(); const MUTEX_POISONED_MSG: &str = "CacheTaskInfoFetcher mutex poisoned!"; +#[derive(Clone, Debug, Default, PartialEq)] +pub struct CompressedData { + pub hash: [u8; 32], + pub compressed_delegation_record_bytes: Vec, + pub remaining_accounts: Vec, + pub account_meta: CdpCompressedAccountMeta, + pub proof: CdpValidityProof, +} + #[async_trait] pub trait TaskInfoFetcher: Send + Sync + 'static { /// Fetches correct commit nonces for pubkeys @@ -35,6 +59,7 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { async fn fetch_next_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult>; @@ -43,6 +68,7 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { async fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult>; @@ -58,6 +84,25 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { pubkeys: &[Pubkey], min_context_slot: u64, ) -> TaskInfoFetcherResult>; + + async fn get_compressed_data( + &self, + pubkey: &Pubkey, + min_context_slot: Option, + ) -> TaskInfoFetcherResult; + + async fn get_compressed_data_for_accounts( + &self, + pubkeys: &[Pubkey], + min_context_slot: Option, + ) -> TaskInfoFetcherResult>> { + try_join_all(pubkeys.iter().map(|pubkey| async move { + Ok(Some( + self.get_compressed_data(pubkey, min_context_slot).await?, + )) + })) + .await + } } // --------------------------------------------------------------------------- @@ -67,11 +112,18 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { /// Pure RPC implementation of [`TaskInfoFetcher`] — no caching. pub struct RpcTaskInfoFetcher { rpc_client: MagicblockRpcClient, + photon_client: Arc, } impl RpcTaskInfoFetcher { - pub fn new(rpc_client: MagicblockRpcClient) -> Self { - Self { rpc_client } + pub fn new( + rpc_client: MagicblockRpcClient, + photon_client: Arc, + ) -> Self { + Self { + rpc_client, + photon_client, + } } /// Fetches [`DelegationMetadata`]s with some num of retries @@ -162,6 +214,27 @@ impl RpcTaskInfoFetcher { TaskInfoFetcherError::MagicBlockRpcClientError(ref err) => { warn!(error = ?err, attempt = i, "Fetch account error"); } + TaskInfoFetcherError::IndexerError(_) => { + break Err(err); + } + TaskInfoFetcherError::CompressedAccountNotFound(_) => { + break Err(err); + } + TaskInfoFetcherError::EmptyCompressedAccount => { + break Err(err); + } + TaskInfoFetcherError::MissingStateTrees => { + break Err(err); + } + TaskInfoFetcherError::MissingAddress => { + break Err(err); + } + TaskInfoFetcherError::MissingCompressedData => { + break Err(err); + } + TaskInfoFetcherError::LightSdkError(_) => { + break Err(err); + } } if i >= max_retries.get() { @@ -228,41 +301,97 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { async fn fetch_next_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult> { if pubkeys.is_empty() { return Ok(HashMap::new()); } - let nonces = Self::fetch_metadata_with_retries( - &self.rpc_client, - pubkeys, - min_context_slot, - NUM_FETCH_RETRIES, - ) - .await? - .into_iter() - .map(|m| m.last_update_nonce + 1); - Ok(pubkeys.iter().copied().zip(nonces).collect()) + if !compressed { + let nonces = Self::fetch_metadata_with_retries( + &self.rpc_client, + pubkeys, + min_context_slot, + NUM_FETCH_RETRIES, + ) + .await? + .into_iter() + .map(|m| m.last_update_nonce + 1); + Ok(pubkeys.iter().copied().zip(nonces).collect()) + } else { + let cdas = pubkeys + .iter() + .map(|pubkey| derive_cda_from_pda(pubkey).to_bytes()) + .collect::>(); + + let nonces = self + .photon_client + .get_multiple_compressed_accounts(Some(cdas), None, None) + .await? + .value + .items + .into_iter() + .filter_map(|compressed_account| { + let record = compressed_account + .and_then(|acc| acc.data) + .and_then(|compressed_account| { + CompressedDelegationRecord::try_from_slice( + &compressed_account.data, + ) + .ok() + })?; + Some(record.last_update_nonce + 1) + }); + Ok(pubkeys.iter().copied().zip(nonces).collect()) + } } async fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult> { if pubkeys.is_empty() { return Ok(HashMap::new()); } - let nonces = Self::fetch_metadata_with_retries( - &self.rpc_client, - pubkeys, - min_context_slot, - NUM_FETCH_RETRIES, - ) - .await? - .into_iter() - .map(|m| m.last_update_nonce); - Ok(pubkeys.iter().copied().zip(nonces).collect()) + if !compressed { + let nonces = Self::fetch_metadata_with_retries( + &self.rpc_client, + pubkeys, + min_context_slot, + NUM_FETCH_RETRIES, + ) + .await? + .into_iter() + .map(|m| m.last_update_nonce); + Ok(pubkeys.iter().copied().zip(nonces).collect()) + } else { + let cdas = pubkeys + .iter() + .map(|pubkey| derive_cda_from_pda(pubkey).to_bytes()) + .collect::>(); + + let nonces = self + .photon_client + .get_multiple_compressed_accounts(Some(cdas), None, None) + .await? + .value + .items + .into_iter() + .filter_map(|compressed_account| { + let record = compressed_account + .and_then(|acc| acc.data) + .and_then(|compressed_account| { + CompressedDelegationRecord::try_from_slice( + &compressed_account.data, + ) + .ok() + })?; + Some(record.last_update_nonce) + }); + Ok(pubkeys.iter().copied().zip(nonces).collect()) + } } async fn fetch_rent_reimbursements( @@ -296,6 +425,87 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .await?; Ok(pubkeys.iter().copied().zip(accounts).collect()) } + + async fn get_compressed_data( + &self, + pubkey: &Pubkey, + min_context_slot: Option, + ) -> TaskInfoFetcherResult { + let cda = derive_cda_from_pda(pubkey); + let compressed_delegation_record = self + .photon_client + .get_compressed_account( + cda.to_bytes(), + min_context_slot.map(|slot| IndexerRpcConfig { + slot, + retry_config: RetryConfig::default(), + }), + ) + .await? + .value + .ok_or(TaskInfoFetcherError::EmptyCompressedAccount)?; + let proof_result = self + .photon_client + .get_validity_proof( + vec![compressed_delegation_record.hash], + vec![], + min_context_slot.map(|slot| IndexerRpcConfig { + slot, + retry_config: RetryConfig::default(), + }), + ) + .await? + .value; + + let system_account_meta_config = SystemAccountMetaConfig::new( + compressed_delegation_client::ID.to_bytes().into(), + ); + let mut remaining_accounts = PackedAccounts::default(); + remaining_accounts + .add_system_accounts_v2(system_account_meta_config) + .map_err(|err| { + TaskInfoFetcherError::LightSdkError(Box::new(err)) + })?; + let packed_tree_accounts = proof_result + .pack_tree_infos(&mut remaining_accounts) + .state_trees + .ok_or(TaskInfoFetcherError::MissingStateTrees)?; + + let tree_info = packed_tree_accounts + .packed_tree_infos + .first() + .copied() + .ok_or(TaskInfoFetcherError::MissingStateTrees)?; + + let account_meta = CompressedAccountMeta { + tree_info, + address: compressed_delegation_record + .address + .ok_or(TaskInfoFetcherError::MissingAddress)?, + output_state_tree_index: packed_tree_accounts.output_tree_index, + } + .into(); + + Ok(CompressedData { + hash: compressed_delegation_record.hash, + compressed_delegation_record_bytes: compressed_delegation_record + .data + .ok_or(TaskInfoFetcherError::MissingCompressedData)? + .data, + remaining_accounts: remaining_accounts + .to_account_metas() + .0 + .iter() + .map(|meta| AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect(), + account_meta, + proof: proof_result.proof.into(), + }) + } } /// Per-account async mutex protecting the cached nonce value. @@ -500,6 +710,7 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { async fn fetch_next_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult> { if pubkeys.is_empty() { @@ -537,7 +748,11 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { let missing_pubkeys: Vec<_> = missing.iter().map(|(pubkey, _)| **pubkey).collect(); self.inner - .fetch_current_commit_nonces(&missing_pubkeys, min_context_slot) + .fetch_current_commit_nonces( + &missing_pubkeys, + compressed, + min_context_slot, + ) .await? }; @@ -563,6 +778,7 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { async fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult> { if pubkeys.is_empty() { @@ -593,7 +809,11 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { let missing_pubkeys: Vec<_> = missing.iter().map(|(pubkey, _)| **pubkey).collect(); self.inner - .fetch_current_commit_nonces(&missing_pubkeys, min_context_slot) + .fetch_current_commit_nonces( + &missing_pubkeys, + compressed, + min_context_slot, + ) .await? }; @@ -632,6 +852,16 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { .get_base_accounts(pubkeys, min_context_slot) .await } + + async fn get_compressed_data( + &self, + pubkey: &Pubkey, + min_context_slot: Option, + ) -> TaskInfoFetcherResult { + self.inner + .get_compressed_data(pubkey, min_context_slot) + .await + } } pub enum ResetType<'a> { @@ -649,6 +879,20 @@ pub enum TaskInfoFetcherError { MinContextSlotNotReachedError(u64, Box), #[error("MagicBlockRpcClientError: {0}")] MagicBlockRpcClientError(Box), + #[error("Indexer error: {0}")] + IndexerError(#[from] light_client::indexer::IndexerError), + #[error("Compressed account not found for: {0}")] + CompressedAccountNotFound(Pubkey), + #[error("Empty compressed account")] + EmptyCompressedAccount, + #[error("Missing state trees")] + MissingStateTrees, + #[error("Missing address")] + MissingAddress, + #[error("Missing compressed data")] + MissingCompressedData, + #[error("LightSdkError: {0}")] + LightSdkError(Box), } impl TaskInfoFetcherError { @@ -699,6 +943,13 @@ impl TaskInfoFetcherError { Self::InvalidAccountDataError(_) => None, Self::MinContextSlotNotReachedError(_, err) => err.signature(), Self::MagicBlockRpcClientError(err) => err.signature(), + Self::IndexerError(_) => None, + Self::CompressedAccountNotFound(_) => None, + Self::EmptyCompressedAccount => None, + Self::LightSdkError(_) => None, + Self::MissingStateTrees => None, + Self::MissingAddress => None, + Self::MissingCompressedData => None, } } } @@ -720,11 +971,17 @@ mod tests { let pk = Pubkey::new_unique(); let fetcher = FetcherBuilder::new(vec![10]).build(); - let r1 = fetcher.fetch_next_commit_nonces(&[pk], 0).await.unwrap(); + let r1 = fetcher + .fetch_next_commit_nonces(&[pk], false, 0) + .await + .unwrap(); assert_eq!(r1[&pk], 11); // Cache hit: no RPC (only 1 response queued), increments - let r2 = fetcher.fetch_next_commit_nonces(&[pk], 0).await.unwrap(); + let r2 = fetcher + .fetch_next_commit_nonces(&[pk], false, 0) + .await + .unwrap(); assert_eq!(r2[&pk], 12); } @@ -735,9 +992,12 @@ mod tests { // prime pk1 (nonce 5), then mixed call fetches only cold pk2 (nonce 20) let fetcher = FetcherBuilder::new(vec![5, 20]).build(); - fetcher.fetch_next_commit_nonces(&[pk1], 0).await.unwrap(); // pk1 = 6 + fetcher + .fetch_next_commit_nonces(&[pk1], false, 0) + .await + .unwrap(); // pk1 = 6 let r = fetcher - .fetch_next_commit_nonces(&[pk1, pk2], 0) + .fetch_next_commit_nonces(&[pk1, pk2], false, 0) .await .unwrap(); assert_eq!(r[&pk1], 7); // cached, incremented @@ -751,12 +1011,21 @@ mod tests { // pk1 initial, pk2 evicts pk1, pk1 re-fetch after eviction let fetcher = FetcherBuilder::new(vec![1, 2, 10]).capacity(1).build(); - fetcher.fetch_next_commit_nonces(&[pk1], 0).await.unwrap(); // pk1 cached = 2 - fetcher.fetch_next_commit_nonces(&[pk2], 0).await.unwrap(); // pk2 cached = 3, pk1 evicted + fetcher + .fetch_next_commit_nonces(&[pk1], false, 0) + .await + .unwrap(); // pk1 cached = 2 + fetcher + .fetch_next_commit_nonces(&[pk2], false, 0) + .await + .unwrap(); // pk2 cached = 3, pk1 evicted assert!(fetcher.peek_commit_nonce(&pk1).await.is_none()); // evicted - let r = fetcher.fetch_next_commit_nonces(&[pk1], 0).await.unwrap(); + let r = fetcher + .fetch_next_commit_nonces(&[pk1], false, 0) + .await + .unwrap(); assert_eq!(r[&pk1], 11); // re-fetched (10 + 1) // Sequential eviction: pk1's guard was dropped before pk2 evicted it, @@ -776,17 +1045,26 @@ mod tests { iters: usize, ) { for pk in &phase1_keys { - fetcher.fetch_next_commit_nonces(&[*pk], 0).await.unwrap(); + fetcher + .fetch_next_commit_nonces(&[*pk], false, 0) + .await + .unwrap(); } barrier.wait().await; // signal phase 1 done barrier.wait().await; // wait for outer verification for _ in 0..iters { for pk in &phase2_keys { - fetcher.fetch_next_commit_nonces(&[*pk], 0).await.unwrap(); + fetcher + .fetch_next_commit_nonces(&[*pk], false, 0) + .await + .unwrap(); } } for chunk in shared_b.chunks(2) { - fetcher.fetch_next_commit_nonces(chunk, 0).await.unwrap(); + fetcher + .fetch_next_commit_nonces(chunk, false, 0) + .await + .unwrap(); } } @@ -885,11 +1163,17 @@ mod tests { let pk = Pubkey::new_unique(); let fetcher = FetcherBuilder::new(vec![10]).build(); - let r1 = fetcher.fetch_current_commit_nonces(&[pk], 0).await.unwrap(); + let r1 = fetcher + .fetch_current_commit_nonces(&[pk], false, 0) + .await + .unwrap(); assert_eq!(r1[&pk], 10); // stored as-is // Cache hit: still 10, fetch_current never increments - let r2 = fetcher.fetch_current_commit_nonces(&[pk], 0).await.unwrap(); + let r2 = fetcher + .fetch_current_commit_nonces(&[pk], false, 0) + .await + .unwrap(); assert_eq!(r2[&pk], 10); } @@ -900,14 +1184,23 @@ mod tests { // pk1 initial, pk2 initial, pk1 after reset let fetcher = FetcherBuilder::new(vec![1, 2, 50]).build(); - fetcher.fetch_next_commit_nonces(&[pk1], 0).await.unwrap(); // pk1 cached = 2 - fetcher.fetch_next_commit_nonces(&[pk2], 0).await.unwrap(); // pk2 cached = 3 + fetcher + .fetch_next_commit_nonces(&[pk1], false, 0) + .await + .unwrap(); // pk1 cached = 2 + fetcher + .fetch_next_commit_nonces(&[pk2], false, 0) + .await + .unwrap(); // pk2 cached = 3 fetcher.reset(ResetType::Specific(&[pk1])); assert!(fetcher.peek_commit_nonce(&pk1).await.is_none()); // cleared assert_eq!(fetcher.peek_commit_nonce(&pk2).await, Some(3)); // still cached - let r1 = fetcher.fetch_next_commit_nonces(&[pk1], 0).await.unwrap(); + let r1 = fetcher + .fetch_next_commit_nonces(&[pk1], false, 0) + .await + .unwrap(); assert_eq!(r1[&pk1], 51); // re-fetched (50 + 1) } @@ -927,7 +1220,10 @@ mod tests { // Spawn Task A: slow fetch for pk1 acquires its nonce lock and sleeps. let fetcher2 = fetcher.clone(); let task_a = tokio::spawn(async move { - fetcher2.fetch_next_commit_nonces(&[pk1], 0).await.unwrap(); + fetcher2 + .fetch_next_commit_nonces(&[pk1], false, 0) + .await + .unwrap(); }); // Let Task A acquire pk1's nonce lock and start the slow fetch. @@ -937,7 +1233,10 @@ mod tests { // because Task A's guard still holds a clone of pk1's Arc. let fetcher3 = fetcher.clone(); let task_b = tokio::spawn(async move { - fetcher3.fetch_next_commit_nonces(&[pk2], 0).await.unwrap(); + fetcher3 + .fetch_next_commit_nonces(&[pk2], false, 0) + .await + .unwrap(); }); // Let Task B run through acquire_nonce_locks (eviction happens here). @@ -982,15 +1281,21 @@ mod tests { async fn fetch_next_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> TaskInfoFetcherResult> { - self.fetch_current_commit_nonces(pubkeys, min_context_slot) - .await + self.fetch_current_commit_nonces( + pubkeys, + compressed, + min_context_slot, + ) + .await } async fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + _: bool, _: u64, ) -> TaskInfoFetcherResult> { if let Some(delay) = self.delay { @@ -1022,6 +1327,14 @@ mod tests { ) -> TaskInfoFetcherResult> { unimplemented!() } + + async fn get_compressed_data( + &self, + _: &Pubkey, + _: Option, + ) -> TaskInfoFetcherResult { + unimplemented!() + } } struct FetcherBuilder { diff --git a/magicblock-committor-service/src/intent_executor/utils.rs b/magicblock-committor-service/src/intent_executor/utils.rs index a32976696..c0f09464b 100644 --- a/magicblock-committor-service/src/intent_executor/utils.rs +++ b/magicblock-committor-service/src/intent_executor/utils.rs @@ -1,4 +1,4 @@ -use std::time::Duration; +use std::{collections::HashMap, time::Duration}; use async_trait::async_trait; use magicblock_core::traits::{ @@ -90,10 +90,24 @@ pub(in crate::intent_executor) async fn handle_commit_id_error< // We reset TaskInfoFetcher for all committed accounts // We re-fetch them to fix out of sync tasks task_info_fetcher.reset(ResetType::Specific(committed_pubkeys)); - let commit_ids = task_info_fetcher - .fetch_next_commit_nonces(committed_pubkeys, min_context_slot) - .await - .map_err(TaskBuilderError::CommitTasksBuildError)?; + let commit_ids = { + let regular_nonces = task_info_fetcher + .fetch_next_commit_nonces( + committed_pubkeys, + false, + min_context_slot, + ) + .await + .map_err(TaskBuilderError::CommitTasksBuildError)?; + let compressed_nonces = task_info_fetcher + .fetch_next_commit_nonces(committed_pubkeys, true, min_context_slot) + .await + .map_err(TaskBuilderError::CommitTasksBuildError)?; + regular_nonces + .into_iter() + .chain(compressed_nonces.into_iter()) + .collect::>() + }; // Here we find the broken tasks and reset them // Broken tasks are prepared incorrectly so they have to be cleaned up diff --git a/magicblock-committor-service/src/persist/commit_persister.rs b/magicblock-committor-service/src/persist/commit_persister.rs index 2fc1598c1..9a40183d8 100644 --- a/magicblock-committor-service/src/persist/commit_persister.rs +++ b/magicblock-committor-service/src/persist/commit_persister.rs @@ -501,6 +501,7 @@ mod tests { commit_and_undelegate: None, commit_finalize: None, commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, standalone_actions: vec![], } } @@ -514,6 +515,7 @@ mod tests { }), commit_finalize: None, commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, standalone_actions: vec![], } } @@ -527,6 +529,7 @@ mod tests { }), commit_finalize: None, commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, standalone_actions: vec![], } } @@ -537,6 +540,7 @@ mod tests { commit_and_undelegate: None, commit_finalize: None, commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, standalone_actions: vec![], } } diff --git a/magicblock-committor-service/src/service.rs b/magicblock-committor-service/src/service.rs index bbec9d805..34dad6d52 100644 --- a/magicblock-committor-service/src/service.rs +++ b/magicblock-committor-service/src/service.rs @@ -88,6 +88,7 @@ pub enum CommittorMessage { respond_to: oneshot::Sender>>, pubkeys: Vec, + compressed: bool, min_context_slot: u64, }, FetchCurrentCommitNoncesSync { @@ -95,6 +96,7 @@ pub enum CommittorMessage { CommittorServiceResult>, >, pubkeys: Vec, + compressed: bool, min_context_slot: u64, }, } @@ -248,12 +250,17 @@ impl CommittorActor { FetchCurrentCommitNonces { respond_to, pubkeys, + compressed, min_context_slot, } => { let processor = self.processor.clone(); tokio::spawn(async move { let result = processor - .fetch_current_commit_nonces(&pubkeys, min_context_slot) + .fetch_current_commit_nonces( + &pubkeys, + compressed, + min_context_slot, + ) .await; if let Err(err) = respond_to .send(result.map_err(CommittorServiceError::from)) @@ -265,12 +272,17 @@ impl CommittorActor { FetchCurrentCommitNoncesSync { respond_to, pubkeys, + compressed, min_context_slot, } => { let processor = self.processor.clone(); tokio::spawn(async move { let result = processor - .fetch_current_commit_nonces(&pubkeys, min_context_slot) + .fetch_current_commit_nonces( + &pubkeys, + compressed, + min_context_slot, + ) .await; if let Err(err) = respond_to .send(result.map_err(CommittorServiceError::from)) @@ -386,6 +398,7 @@ impl CommittorService { pub fn fetch_current_commit_nonces_sync( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> std::sync::mpsc::Receiver>> { @@ -393,6 +406,7 @@ impl CommittorService { self.try_send(CommittorMessage::FetchCurrentCommitNoncesSync { respond_to: tx, pubkeys: pubkeys.to_vec(), + compressed, min_context_slot, }); rx @@ -496,12 +510,14 @@ impl BaseIntentCommittor for CommittorService { fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> oneshot::Receiver>> { let (tx, rx) = oneshot::channel(); self.try_send(CommittorMessage::FetchCurrentCommitNonces { respond_to: tx, pubkeys: pubkeys.to_vec(), + compressed, min_context_slot, }); @@ -559,6 +575,7 @@ pub trait BaseIntentCommittor: Send + Sync + 'static { fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> oneshot::Receiver>>; diff --git a/magicblock-committor-service/src/service_ext.rs b/magicblock-committor-service/src/service_ext.rs index 024d0423e..b40f19a92 100644 --- a/magicblock-committor-service/src/service_ext.rs +++ b/magicblock-committor-service/src/service_ext.rs @@ -210,10 +210,14 @@ impl BaseIntentCommittor for CommittorServiceExt { fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + compressed: bool, min_context_slot: u64, ) -> oneshot::Receiver>> { - self.inner - .fetch_current_commit_nonces(pubkeys, min_context_slot) + self.inner.fetch_current_commit_nonces( + pubkeys, + compressed, + min_context_slot, + ) } fn stop(&self) { diff --git a/magicblock-committor-service/src/stubs/changeset_committor_stub.rs b/magicblock-committor-service/src/stubs/changeset_committor_stub.rs index 0b417db47..ac9f79d4c 100644 --- a/magicblock-committor-service/src/stubs/changeset_committor_stub.rs +++ b/magicblock-committor-service/src/stubs/changeset_committor_stub.rs @@ -195,6 +195,7 @@ impl BaseIntentCommittor for ChangesetCommittorStub { fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + _compressed: bool, _min_context_slot: u64, ) -> oneshot::Receiver>> { let (tx, rx) = oneshot::channel(); diff --git a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs new file mode 100644 index 000000000..6947d2eef --- /dev/null +++ b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs @@ -0,0 +1,89 @@ +use borsh::BorshDeserialize; +use compressed_delegation_api::{ + CommitAndFinalizeArgs, CompressedDelegationRecord, +}; +use magicblock_committor_program::Chunks; +use magicblock_core::intent::CommittedAccount; +use solana_instruction::Instruction; +use solana_pubkey::Pubkey; + +use crate::{ + consts::MAX_WRITE_CHUNK_SIZE, + intent_executor::task_info_fetcher::CompressedData, + tasks::{commit_task::CommitBufferStage, BaseTaskImpl, PreparationTask}, +}; + +/// A task that commits a delegated account's state to the base layer and finalizes it in the same +/// instruction, using compressed data. +/// +/// The delivery strategy ([`CommitDelivery`]) determines how the data reaches +/// the chain (inline args vs buffer, full state vs diff). +#[derive(Clone, Debug)] +pub struct CommitFinalizeCompressedTask { + pub commit_id: u64, + pub allow_undelegation: bool, + pub committed_account: CommittedAccount, + pub compressed_data: CompressedData, +} + +impl CommitFinalizeCompressedTask { + #[inline(always)] + pub fn instruction(&self, validator: &Pubkey) -> Instruction { + let old_record = CompressedDelegationRecord::try_from_slice( + &self.compressed_data.compressed_delegation_record_bytes, + ).expect("The record should have been valid because it was already used to clone the account"); + let new_record = CompressedDelegationRecord { + pda: self.committed_account.pubkey, + authority: *validator, + last_update_nonce: self.commit_id + 1, + is_undelegatable: self.allow_undelegation, + owner: old_record.owner, + delegation_slot: old_record.delegation_slot, + lamports: self.committed_account.account.lamports, + data: self.committed_account.account.data.clone(), + }; + let args = CommitAndFinalizeArgs { + current_compressed_delegated_account_data: self + .compressed_data + .compressed_delegation_record_bytes + .clone(), + new_data: borsh::to_vec(&new_record) + .expect("The serializing the new record should not fail"), + account_meta: self.compressed_data.account_meta, + validity_proof: self.compressed_data.proof, + update_nonce: self.commit_id, + allow_undelegation: self.allow_undelegation, + }; + + compressed_delegation_client::builders::CommitAndFinalizeBuilder { + validator: *validator, + delegated_account: self.committed_account.pubkey, + remaining_accounts: self.compressed_data.remaining_accounts.clone(), + args, + } + .instruction() + .expect("The serializing the args should not fail") + } + + pub fn state_preparation_stage(&self) -> CommitBufferStage { + let data = self.committed_account.account.data.clone(); + self.preparation_stage(data) + } + + fn preparation_stage(&self, buffer_data: Vec) -> CommitBufferStage { + let chunks = + Chunks::from_data_length(buffer_data.len(), MAX_WRITE_CHUNK_SIZE); + CommitBufferStage::Preparation(PreparationTask { + commit_id: self.commit_id, + pubkey: self.committed_account.pubkey, + buffer_data, + chunks, + }) + } +} + +impl From for BaseTaskImpl { + fn from(value: CommitFinalizeCompressedTask) -> Self { + Self::CommitFinalizeCompressed(value) + } +} diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 033877bdd..fc81dce0e 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -16,6 +16,7 @@ use magicblock_program::magic_scheduled_base_intent::BaseAction; use solana_instruction::{AccountMeta, Instruction}; use solana_pubkey::Pubkey; +pub mod commit_finalize_compressed_task; pub mod commit_finalize_task; pub mod commit_task; pub mod task_builder; @@ -25,18 +26,10 @@ pub mod utils; pub use task_builder::TaskBuilderImpl; use crate::tasks::{ + commit_finalize_compressed_task::CommitFinalizeCompressedTask, commit_finalize_task::CommitFinalizeTask, commit_task::CommitTask, }; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum TaskType { - Commit, - CommitFinalize, - Finalize, - Undelegate, - Action, -} - #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TaskStrategy { Args, @@ -50,6 +43,7 @@ pub enum BaseTaskImpl { Finalize(FinalizeTask), Undelegate(UndelegateTask), BaseAction(BaseActionTask), + CommitFinalizeCompressed(CommitFinalizeCompressedTask), } impl BaseTask for BaseTaskImpl { @@ -64,6 +58,9 @@ impl BaseTask for BaseTaskImpl { Self::Finalize(value) => value.instruction(validator), Self::Undelegate(value) => value.instruction(validator), Self::BaseAction(value) => value.instruction(validator), + Self::CommitFinalizeCompressed(value) => { + value.instruction(validator) + } } } @@ -82,6 +79,7 @@ impl BaseTask for BaseTaskImpl { Self::BaseAction(value) => value.compute_units(), Self::Finalize(_) => 70_000, Self::Undelegate(_) => 70_000, + Self::CommitFinalizeCompressed(_) => 250_000, } } @@ -89,6 +87,11 @@ impl BaseTask for BaseTaskImpl { match self { Self::Commit(value) => value.accounts_size_budget(), Self::CommitFinalize(value) => value.accounts_size_budget(), + Self::CommitFinalizeCompressed(_) => { + dlp_api::instruction_builder::finalize_size_budget( + AccountSizeClass::Huge, + ) + } Self::BaseAction(value) => value.accounts_size_budget(), Self::Finalize(_) => { dlp_api::instruction_builder::finalize_size_budget( @@ -111,7 +114,12 @@ impl BaseTaskImpl { Self::CommitFinalize(task) if task.is_buffer() => { TaskStrategy::Buffer } - _ => TaskStrategy::Args, + Self::Commit(_) + | Self::CommitFinalize(_) + | Self::Finalize(_) + | Self::Undelegate(_) + | Self::BaseAction(_) + | Self::CommitFinalizeCompressed(_) => TaskStrategy::Args, } } } @@ -137,6 +145,9 @@ impl LabelValue for BaseTaskImpl { Self::Undelegate(_) => "args_undelegate", Self::BaseAction(BaseActionTask::V1(_)) => "args_action", Self::BaseAction(BaseActionTask::V2(_)) => "args_action_v2", + Self::CommitFinalizeCompressed(_) => { + "args_commit_finalize_compressed" + } } } } diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 55e7051e7..dfd294c6c 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -99,30 +99,50 @@ impl TaskBuilderImpl { async fn fetch_commit_nonces( task_info_fetcher: &Arc, - accounts: &[(bool, bool, CommittedAccount)], + accounts: &[(bool, bool, bool, CommittedAccount)], min_context_slot: u64, ) -> TaskInfoFetcherResult> { - let committed_pubkeys = accounts - .iter() - .map(|(_, _, account)| account.pubkey) + let (regular_accounts, compressed_accounts): (Vec<_>, Vec<_>) = + accounts + .iter() + .partition(|(_, _, compressed, _)| !compressed); + let regular_pubkeys = regular_accounts + .into_iter() + .map(|(_, _, _, account)| account.pubkey) + .collect::>(); + let compressed_pubkeys = compressed_accounts + .into_iter() + .map(|(_, _, _, account)| account.pubkey) .collect::>(); - task_info_fetcher - .fetch_next_commit_nonces(&committed_pubkeys, min_context_slot) - .await + let regular_nonces = task_info_fetcher + .fetch_next_commit_nonces(®ular_pubkeys, false, min_context_slot) + .await?; + let compressed_nonces = task_info_fetcher + .fetch_next_commit_nonces( + &compressed_pubkeys, + true, + min_context_slot, + ) + .await?; + Ok(regular_nonces + .into_iter() + .chain(compressed_nonces.into_iter()) + .collect::>()) } async fn fetch_diffable_accounts( task_info_fetcher: &Arc, - accounts: &[(bool, bool, CommittedAccount)], + accounts: &[(bool, bool, bool, CommittedAccount)], min_context_slot: u64, ) -> TaskInfoFetcherResult> { let diffable_pubkeys = accounts .iter() - .filter(|(_, _, account)| { + .filter(|(_, _, compressed, account)| { account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD + && !compressed }) - .map(|(_, _, account)| account.pubkey) + .map(|(_, _, _, account)| account.pubkey) .collect::>(); task_info_fetcher @@ -156,6 +176,19 @@ impl TaskBuilderImpl { delivery: delivery_details, } } + + pub fn create_commit_finalize_compressed_task( + commit_id: u64, + allow_undelegation: bool, + account: CommittedAccount, + ) -> CommitFinalizeTask { + CommitFinalizeTask { + commit_id, + allow_undelegation, + committed_account: account, + delivery: CommitDelivery::StateInArgs, + } + } } #[async_trait] @@ -180,26 +213,29 @@ impl TasksBuilder for TaskBuilderImpl { let commit_finalize_and_undelegate_accounts = intent_bundle .get_commit_finalize_and_undelegate_intent_accounts() .cloned(); + let commit_finalize_compressed_accounts = intent_bundle + .get_commit_finalize_compressed_intent_accounts() + .cloned(); let flagged_accounts: Vec<_> = [ - (false, false, committed_accounts), - (true, false, undelegated_accounts), - (false, true, commit_finalize_accounts), - (true, true, commit_finalize_and_undelegate_accounts), + (false, false, false, committed_accounts), + (true, false, false, undelegated_accounts), + (false, true, false, commit_finalize_accounts), + (true, true, false, commit_finalize_and_undelegate_accounts), + (false, true, true, commit_finalize_compressed_accounts), ] .into_iter() - .flat_map(|(allow_undelegation, finalize, accounts)| { - accounts - .into_iter() - .flatten() - .map(move |account| (allow_undelegation, finalize, account)) + .flat_map(|(allow_undelegation, finalize, compressed, accounts)| { + accounts.into_iter().flatten().map(move |account| { + (allow_undelegation, finalize, compressed, account) + }) }) .collect(); // Get commit nonces and base accounts let min_context_slot = flagged_accounts .iter() - .map(|(_, _, account)| account.remote_slot) + .map(|(_, _, _, account)| account.remote_slot) .max() .unwrap_or(0); let (commit_ids, base_accounts) = tokio::join!( @@ -232,7 +268,7 @@ impl TasksBuilder for TaskBuilderImpl { // Create commit tasks let commit_tasks_iter = flagged_accounts.into_iter().map( - |(allow_undelegation, finalize, account)| { + |(allow_undelegation, finalize, compressed, account)| { let commit_id = commit_ids .get(&account.pubkey) .copied() @@ -245,11 +281,13 @@ impl TasksBuilder for TaskBuilderImpl { }); let base_account = base_accounts.remove(&account.pubkey); - if finalize { - Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account).into() - } else { - Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account).into() - } + if compressed { + Self::create_commit_finalize_compressed_task(commit_id, allow_undelegation, account.clone()).into() + } else if finalize { + Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account).into() + } else { + Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account).into() + } }, ); tasks.extend(commit_tasks_iter); @@ -372,6 +410,8 @@ pub enum TaskBuilderError { CommitTasksBuildError(#[source] TaskInfoFetcherError), #[error("FinalizedTasksBuildError: {0}")] FinalizedTasksBuildError(#[source] TaskInfoFetcherError), + #[error("CommitFinalizeCompressedTasksBuildError: {0}")] + CommitFinalizeCompressedTasksBuildError(#[from] std::io::Error), } impl TaskBuilderError { @@ -379,6 +419,7 @@ impl TaskBuilderError { match self { Self::CommitTasksBuildError(err) => err.signature(), Self::FinalizedTasksBuildError(err) => err.signature(), + Self::CommitFinalizeCompressedTasksBuildError(_) => None, } } } diff --git a/magicblock-committor-service/src/tasks/task_strategist.rs b/magicblock-committor-service/src/tasks/task_strategist.rs index eeba22ac5..59a77403d 100644 --- a/magicblock-committor-service/src/tasks/task_strategist.rs +++ b/magicblock-committor-service/src/tasks/task_strategist.rs @@ -479,7 +479,7 @@ mod tests { use crate::{ intent_execution_manager::intent_scheduler::create_test_intent, intent_executor::task_info_fetcher::{ - TaskInfoFetcher, TaskInfoFetcherResult, + CompressedData, TaskInfoFetcher, TaskInfoFetcherResult, }, persist::IntentPersisterImpl, tasks::{ @@ -500,6 +500,7 @@ mod tests { async fn fetch_next_commit_nonces( &self, pubkeys: &[Pubkey], + _: bool, _: u64, ) -> TaskInfoFetcherResult> { Ok(pubkeys.iter().map(|pubkey| (*pubkey, 0)).collect()) @@ -508,6 +509,7 @@ mod tests { async fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + _: bool, _: u64, ) -> TaskInfoFetcherResult> { Ok(pubkeys.iter().map(|pubkey| (*pubkey, 0)).collect()) @@ -528,6 +530,14 @@ mod tests { ) -> TaskInfoFetcherResult> { Ok(Default::default()) } + + async fn get_compressed_data( + &self, + _: &Pubkey, + _: Option, + ) -> TaskInfoFetcherResult { + Ok(Default::default()) + } } // Helper to create a simple commit task diff --git a/magicblock-core/src/traits.rs b/magicblock-core/src/traits.rs index c9733b108..3bd6e215c 100644 --- a/magicblock-core/src/traits.rs +++ b/magicblock-core/src/traits.rs @@ -21,6 +21,7 @@ pub trait MagicSys: Sync + Send + 'static { fn fetch_current_commit_nonces( &self, commits: &[CommittedAccount], + compressed: bool, ) -> Result, InstructionError>; } diff --git a/magicblock-magic-program-api/src/args.rs b/magicblock-magic-program-api/src/args.rs index 1a08580ee..759f8f678 100644 --- a/magicblock-magic-program-api/src/args.rs +++ b/magicblock-magic-program-api/src/args.rs @@ -87,6 +87,7 @@ pub enum MagicBaseIntentArgs { CommitAndUndelegate(CommitAndUndelegateArgs), CommitFinalize(CommitTypeArgs), CommitFinalizeAndUndelegate(CommitAndUndelegateArgs), + CommitFinalizeCompressed(CommitTypeArgs), } #[derive(Clone, Default, Serialize, Deserialize, Debug, PartialEq, Eq)] @@ -95,6 +96,7 @@ pub struct MagicIntentBundleArgs { pub commit_and_undelegate: Option, pub commit_finalize: Option, pub commit_finalize_and_undelegate: Option, + pub commit_finalize_compressed: Option, pub standalone_actions: Vec, } @@ -115,6 +117,9 @@ impl From for MagicIntentBundleArgs { MagicBaseIntentArgs::CommitFinalizeAndUndelegate(value) => { this.commit_finalize_and_undelegate = Some(value) } + MagicBaseIntentArgs::CommitFinalizeCompressed(value) => { + this.commit_finalize_compressed = Some(value) + } } this diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 5243d3367..4c3d10dbb 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -165,6 +165,14 @@ impl ScheduledIntentBundle { self.intent_bundle.get_commit_finalize_intent_accounts() } + /// Returns `CommitFinalizeCompressed` intent's accounts + pub fn get_commit_finalize_compressed_intent_accounts( + &self, + ) -> Option<&Vec> { + self.intent_bundle + .get_commit_finalize_compressed_intent_accounts() + } + /// Returns `Commit` intent's accounts pub fn get_commit_intent_accounts_mut( &mut self, @@ -217,6 +225,7 @@ pub struct MagicIntentBundle { pub commit_and_undelegate: Option, pub commit_finalize: Option, pub commit_finalize_and_undelegate: Option, + pub commit_finalize_compressed: Option, pub standalone_actions: Vec, } @@ -276,6 +285,11 @@ impl MagicIntentBundle { .map(|value| CommitAndUndelegate::try_from_args(value, context)) .transpose()?; + let commit_finalize_compressed = args + .commit_finalize_compressed + .map(|value| CommitType::try_from_args(value, context)) + .transpose()?; + let actions = args .standalone_actions .into_iter() @@ -287,6 +301,7 @@ impl MagicIntentBundle { commit_and_undelegate, commit_finalize, commit_finalize_and_undelegate, + commit_finalize_compressed, standalone_actions: actions, }; this.post_validation(context)?; @@ -450,6 +465,17 @@ impl MagicIntentBundle { ) } + /// Returns `[CommitType]` intent's accounts + pub fn get_commit_finalize_compressed_intent_accounts( + &self, + ) -> Option<&Vec> { + Some( + self.commit_finalize_compressed + .as_ref()? + .get_committed_accounts(), + ) + } + /// Returns `Commit` intent's accounts pub fn get_commit_finalize_intent_accounts( &self, @@ -631,6 +657,10 @@ impl MagicBaseIntent { commit_and_undelegate, )) } + MagicBaseIntentArgs::CommitFinalizeCompressed(type_) => { + let commit = CommitType::try_from_args(type_, context)?; + Ok(MagicBaseIntent::CommitFinalizeCompressed(commit)) + } } } @@ -1402,6 +1432,7 @@ mod tests { }), commit_finalize: None, commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, standalone_actions: vec![make_base_action(50_000)], }, }; diff --git a/programs/magicblock/src/magic_sys.rs b/programs/magicblock/src/magic_sys.rs index 0fda01653..233d0a19e 100644 --- a/programs/magicblock/src/magic_sys.rs +++ b/programs/magicblock/src/magic_sys.rs @@ -31,11 +31,12 @@ pub fn init_magic_sys(magic_sys: Arc) { pub(crate) fn fetch_current_commit_nonces( commits: &[CommittedAccount], + compressed: bool, ) -> Result, InstructionError> { MAGIC_SYS .read() .expect(MAGIC_SYS_POISONED_MSG) .as_ref() .ok_or(InstructionError::UninitializedAccount)? - .fetch_current_commit_nonces(commits) + .fetch_current_commit_nonces(commits, compressed) } diff --git a/programs/magicblock/src/schedule_transactions/mod.rs b/programs/magicblock/src/schedule_transactions/mod.rs index dbef40e0b..35956bd75 100644 --- a/programs/magicblock/src/schedule_transactions/mod.rs +++ b/programs/magicblock/src/schedule_transactions/mod.rs @@ -123,9 +123,10 @@ pub fn check_magic_context_id( pub(crate) fn check_commit_limits( commits: &[CommittedAccount], + compressed: bool, invoke_context: &InvokeContext, ) -> Result<(), InstructionError> { - let mut nonces = fetch_current_commit_nonces(commits)?; + let mut nonces = fetch_current_commit_nonces(commits, compressed)?; let mut limit_exceeded = false; for account in commits { let nonce = nonces diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs index 2f97a217d..fbb675940 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs @@ -228,6 +228,18 @@ pub(crate) fn process_schedule_commit( committed_accounts.push(committed); } + if opts.compressed + && committed_accounts + .iter() + .any(|acc| acc.account.lamports > 0) + { + ic_msg!( + invoke_context, + "ScheduleCommit: compressed accounts with lamports > 0 are not supported", + ); + return Err(InstructionError::InvalidAccountData); + } + if opts.request_undelegation { // If the account is scheduled to be undelegated then we need to lock it // immediately in order to prevent the following actions: @@ -252,13 +264,18 @@ pub(crate) fn process_schedule_commit( } if let Some(fee_vault) = magic_fee_vault { - let nonces = fetch_current_commit_nonces(&committed_accounts)?; + let nonces = + fetch_current_commit_nonces(&committed_accounts, opts.compressed)?; let fee = calculate_commit_fee(&committed_accounts, &nonces)?; charge_delegated_payer(&payer_account, &fee_vault, fee)?; } else if !opts.request_undelegation { // We validate commit nonces only for plain commits. // If accounts are undelegated we don't want to fail. - check_commit_limits(&committed_accounts, invoke_context)?; + check_commit_limits( + &committed_accounts, + opts.compressed, + invoke_context, + )?; } // NOTE: this is only protected by all the above checks however if the diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs index 034e42c54..389fc73c5 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs @@ -244,13 +244,18 @@ pub(crate) fn process_schedule_commit_finalize( } if let Some(fee_vault) = magic_fee_vault { - let nonces = fetch_current_commit_nonces(&committed_accounts)?; + let nonces = + fetch_current_commit_nonces(&committed_accounts, opts.compressed)?; let fee = calculate_commit_fee(&committed_accounts, &nonces)?; charge_delegated_payer(&payer_account, &fee_vault, fee)?; } else if !opts.request_undelegation { // We validate commit nonces only for plain commits. // If accounts are undelegated we don't want to fail. - check_commit_limits(&committed_accounts, invoke_context)?; + check_commit_limits( + &committed_accounts, + opts.compressed, + invoke_context, + )?; } // NOTE: this is only protected by all the above checks however if the diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs index 67168f3de..5e5baa951 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs @@ -417,6 +417,7 @@ mod tests { commit_and_undelegate: None, commit_finalize: None, commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, standalone_actions: vec![BaseActionArgs { args: ActionArgs::new(vec![1, 2, 3]).with_escrow_index(0), compute_units: 100_000, diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index 5210e36f6..9aade2143 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -144,13 +144,13 @@ pub(crate) fn process_schedule_intent_bundle( )?; if let Some(magic_fee_vault) = magic_fee_vault { let chargable_accounts = scheduled_intent.get_all_committed_accounts(); - let nonces = fetch_current_commit_nonces(&chargable_accounts)?; + let nonces = fetch_current_commit_nonces(&chargable_accounts, false)?; let fee = scheduled_intent.calculate_fee(&nonces)?; charge_delegated_payer(&payer_account, &magic_fee_vault, fee)?; } else if let Some(commit_accounts) = scheduled_intent.get_commit_intent_accounts() { - check_commit_limits(commit_accounts, invoke_context)?; + check_commit_limits(commit_accounts, false, invoke_context)?; } let action_sent_signature = scheduled_intent.sent_transaction.signatures[0]; diff --git a/programs/magicblock/src/test_utils/mod.rs b/programs/magicblock/src/test_utils/mod.rs index 7a7eda903..b92350b4e 100644 --- a/programs/magicblock/src/test_utils/mod.rs +++ b/programs/magicblock/src/test_utils/mod.rs @@ -143,6 +143,7 @@ impl MagicSys for MagicSysStub { fn fetch_current_commit_nonces( &self, commits: &[CommittedAccount], + _compressed: bool, ) -> Result, InstructionError> { match &self.nonces { StubNonces::Global(nonce) => { diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index bd479e24c..215db9f62 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -69,6 +69,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "agave-feature-set" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a2c365c0245cbb8959de725fc2b44c754b673fdf34c9a7f9d4a25c35a7bf1" +dependencies = [ + "ahash 0.8.12", + "solana-epoch-schedule 2.2.1", + "solana-hash 2.3.0", + "solana-pubkey 2.4.0", + "solana-sha256-hasher 2.2.1", + "solana-svm-feature-set 2.3.13", +] + [[package]] name = "agave-feature-set" version = "3.1.12" @@ -76,11 +90,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6200f3b8cfbe5992fde00d443f60e62a79d2d8f6a658af1ffb7c4f0baa3c7028" dependencies = [ "ahash 0.8.12", - "solana-epoch-schedule", + "solana-epoch-schedule 3.1.0", "solana-hash 3.1.0", "solana-pubkey 3.0.0", "solana-sha256-hasher 3.1.0", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", ] [[package]] @@ -104,10 +118,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d93caf9e6dd35ba4193fe778c1e52ee69433ba53b9eaeebc00c7bcd4d699081" dependencies = [ "log", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-signature", - "solana-transaction", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", "solana-transaction-status", "thiserror 2.0.18", ] @@ -143,7 +157,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c0fa80ea1037091eff64931fc53b6a89f153f5a88c33035cedfa79265b985cb" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "bincode", "digest 0.10.7", "ed25519-dalek 1.0.1", @@ -151,10 +165,10 @@ dependencies = [ "openssl", "sha3", "solana-ed25519-program", - "solana-message", + "solana-message 3.1.0", "solana-precompile-error", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-secp256k1-program", "solana-secp256r1-program", ] @@ -165,9 +179,9 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c3998a6ec388df954d8f78eeaf73ff487b50a8bdaebd48c8573af22c7b6db72" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", ] [[package]] @@ -186,7 +200,7 @@ dependencies = [ "regex", "semver", "solana-accounts-db", - "solana-clock", + "solana-clock 3.0.1", "solana-genesis-config", "solana-hash 3.1.0", "solana-lattice-hash", @@ -209,37 +223,37 @@ dependencies = [ "bincode", "libsecp256k1", "num-traits", - "solana-account", - "solana-account-info", - "solana-big-mod-exp", - "solana-blake3-hasher", - "solana-bn254", - "solana-clock", - "solana-cpi", - "solana-curve25519", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-big-mod-exp 3.0.0", + "solana-blake3-hasher 3.1.0", + "solana-bn254 3.2.1", + "solana-clock 3.0.1", + "solana-cpi 3.1.0", + "solana-curve25519 3.1.12", "solana-hash 3.1.0", - "solana-instruction", - "solana-keccak-hasher", - "solana-loader-v3-interface", + "solana-instruction 3.4.0", + "solana-keccak-hasher 3.1.0", + "solana-loader-v3-interface 6.1.1", "solana-poseidon", - "solana-program-entrypoint", + "solana-program-entrypoint 3.1.1", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-sbpf", - "solana-sdk-ids", - "solana-secp256k1-recover", + "solana-sdk-ids 3.1.0", + "solana-secp256k1-recover 3.1.1", "solana-sha256-hasher 3.1.0", - "solana-stable-layout", - "solana-stake-interface", + "solana-stable-layout 3.0.1", + "solana-stake-interface 2.0.2", "solana-svm-callback", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-timings", "solana-svm-type-overrides", - "solana-sysvar", - "solana-sysvar-id", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", ] @@ -250,14 +264,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9b36ce7792c4e48140ee2f9ef4eaa289fab1c383a0670588a6c7c755947608c" dependencies = [ "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-packet", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-short-vec", - "solana-signature", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", + "solana-signature 3.4.0", "solana-svm-transaction", - "solana-transaction-context", + "solana-transaction-context 3.1.12", ] [[package]] @@ -269,7 +283,7 @@ dependencies = [ "agave-logger", "serde", "solana-bls-signatures", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", ] @@ -306,6 +320,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-sized" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48a526ec4434d531d488af59fe866f36b310fe8906691c75dffa664450a3800a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -718,6 +743,7 @@ checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ "num-traits", "rand 0.8.5", + "rayon", ] [[package]] @@ -870,6 +896,28 @@ dependencies = [ "cc", ] +[[package]] +name = "aws-lc-rs" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.7.9" @@ -1163,16 +1211,39 @@ dependencies = [ "subtle", ] +[[package]] +name = "borsh" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" +dependencies = [ + "borsh-derive 0.10.4", + "hashbrown 0.13.2", +] + [[package]] name = "borsh" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" dependencies = [ - "borsh-derive", + "borsh-derive 1.6.0", "cfg_aliases", ] +[[package]] +name = "borsh-derive" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "borsh-derive" version = "1.6.0" @@ -1180,12 +1251,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" dependencies = [ "once_cell", - "proc-macro-crate", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", "syn 2.0.117", ] +[[package]] +name = "borsh-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "brotli" version = "8.0.2" @@ -1464,6 +1557,15 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "009067b02b9284528f9f01e3b35ebcd6b545666d15fb74fd9fa30222de89da8e" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "color-backtrace" version = "0.7.2" @@ -1503,6 +1605,37 @@ dependencies = [ "memchr", ] +[[package]] +name = "compressed-delegation-api" +version = "0.1.0" +dependencies = [ + "borsh 1.6.0", + "light-compressed-account", + "light-hasher", + "light-sdk", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "compressed-delegation-client" +version = "0.1.0" +dependencies = [ + "borsh 1.6.0", + "compressed-delegation-api", + "light-compressed-account", + "light-hasher", + "light-sdk", + "light-sdk-types", + "num-derive", + "num-traits", + "solana-account-info 3.1.1", + "solana-cpi 3.1.0", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", + "solana-pubkey 3.0.0", + "thiserror 2.0.18", +] + [[package]] name = "compression-codecs" version = "0.4.35" @@ -1530,6 +1663,19 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + [[package]] name = "console" version = "0.16.3" @@ -1542,6 +1688,26 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + [[package]] name = "const-crypto" version = "0.3.0" @@ -2022,6 +2188,12 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -2255,7 +2427,7 @@ source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=c dependencies = [ "base64ct", "bincode", - "borsh", + "borsh 1.6.0", "ephemeral-rollups-sdk-attribute-action", "ephemeral-rollups-sdk-attribute-commit", "ephemeral-rollups-sdk-attribute-delegate", @@ -2264,15 +2436,15 @@ dependencies = [ "getrandom 0.2.16", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade)", "magicblock-magic-program-api 0.9.0 (git+https://github.com/magicblock-labs/magicblock-validator.git?branch=bmuddha%2Fepic%2Fmigration-solana-v3)", - "solana-account", - "solana-account-info", - "solana-cpi", - "solana-instruction", - "solana-program-error", - "solana-program-memory", + "solana-account 2.2.1", + "solana-account-info 3.1.1", + "solana-cpi 3.1.0", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", + "solana-program-memory 3.1.0", "solana-pubkey 3.0.0", "solana-system-interface 3.2.0", - "solana-sysvar", + "solana-sysvar 3.1.1", ] [[package]] @@ -2465,7 +2637,7 @@ dependencies = [ "atomic", "pear", "serde", - "toml", + "toml 0.8.23", "uncased", "version_check", ] @@ -2856,6 +3028,21 @@ dependencies = [ "spinning_top", ] +[[package]] +name = "groth16-solana" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6d1ffb18dbf5cfc60b11bd7da88474c672870247c1e5b498619bcb6ba3d8f5" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "num-bigint 0.4.6", + "solana-bn254 2.2.2", + "thiserror 1.0.69", +] + [[package]] name = "group" version = "0.13.0" @@ -2876,7 +3063,7 @@ dependencies = [ "bincode", "magicblock-magic-program-api 0.9.0", "serde", - "solana-program", + "solana-program 3.0.0", ] [[package]] @@ -2957,6 +3144,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", + "equivalent", "foldhash 0.1.5", ] @@ -3257,6 +3445,22 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.19" @@ -3276,9 +3480,11 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2 0.6.1", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -3471,13 +3677,26 @@ dependencies = [ "serde_core", ] +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console 0.15.11", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + [[package]] name = "indicatif" version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ - "console", + "console 0.16.3", "portable-atomic", "unicode-width", "unit-prefix", @@ -3504,22 +3723,23 @@ name = "integration-test-tools" version = "0.0.0" dependencies = [ "anyhow", - "borsh", + "borsh 1.6.0", "color-backtrace", "magicblock-config", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "rand 0.8.5", "rayon", "serde", - "solana-commitment-config", + "shlex", + "solana-commitment-config 3.1.1", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk", "solana-system-interface 3.2.0", "solana-transaction-status", "tempfile", - "toml", + "toml 0.8.23", "tracing", "ureq 2.12.1", "url", @@ -3659,10 +3879,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -3736,16 +3958,16 @@ dependencies = [ "prost 0.14.3", "prost-types 0.14.3", "protobuf-src", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "solana-transaction-status", "tonic 0.14.5", "tonic-build 0.14.5", @@ -3948,100 +4170,680 @@ dependencies = [ ] [[package]] -name = "light-poseidon" -version = "0.2.0" +name = "light-account" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +checksum = "ec4f3acf8345ca221e4c7a7d277924ca52daea0dea5d5cf8c8f0951a3cad60dc" dependencies = [ - "ark-bn254 0.4.0", - "ark-ff 0.4.2", - "num-bigint 0.4.6", - "thiserror 1.0.69", + "light-account-checks", + "light-compressed-account", + "light-compressible", + "light-hasher", + "light-macros", + "light-sdk-macros", + "light-sdk-types", + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", ] [[package]] -name = "light-poseidon" -version = "0.4.0" +name = "light-account-checks" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a1ccadd0bb5a32c196da536fd72c59183de24a055f6bf0513bf845fefab862" +checksum = "34d74dd13535c6014abb4cac694e14083b206a7f6cf1bbbc9611aa5c2e11cdd1" dependencies = [ - "ark-bn254 0.5.0", - "ark-ff 0.5.0", - "num-bigint 0.4.6", - "thiserror 1.0.69", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-system-interface 1.0.0", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", ] [[package]] -name = "linux-raw-sys" -version = "0.11.0" +name = "light-array-map" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "9bdd13b18028ac9d80d0a987551c0dad7fe81be8140e87cc9d568b80f3728203" +dependencies = [ + "tinyvec", +] [[package]] -name = "litemap" -version = "0.8.1" +name = "light-batched-merkle-tree" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "3702b96798a1cc93c9d4b0d9eb6ee980481beb147ab663cfd260c71ec258c5f0" +dependencies = [ + "aligned-sized", + "borsh 0.10.4", + "light-account-checks", + "light-bloom-filter", + "light-compressed-account", + "light-hasher", + "light-macros", + "light-merkle-tree-metadata", + "light-verifier", + "light-zero-copy", + "solana-account-info 2.3.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", + "zerocopy", +] [[package]] -name = "lmdb-rkv" -version = "0.14.0" +name = "light-bloom-filter" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447a296f7aca299cfbb50f4e4f3d49451549af655fb7215d7f8c0c3d64bad42b" +checksum = "380b8cf734ccf5fbc1f5fed8e5308b57ebde6774d9304c167bcb0de2854412d8" dependencies = [ - "bitflags 1.3.2", - "byteorder", - "libc", - "lmdb-rkv-sys", + "bitvec", + "num-bigint 0.4.6", + "solana-nostd-keccak", + "solana-program-error 2.2.2", + "thiserror 2.0.18", ] [[package]] -name = "lmdb-rkv-sys" -version = "0.11.2" +name = "light-bounded-vec" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b9ce6b3be08acefa3003c57b7565377432a89ec24476bbe72e11d101f852fe" +checksum = "58cfa375d028164719e3ffef93d2e5c27855cc8a5bb5bf257b868d17c12a3e66" dependencies = [ - "cc", - "libc", - "pkg-config", + "bytemuck", + "memoffset", + "solana-program-error 2.2.2", + "thiserror 1.0.69", ] [[package]] -name = "lock_api" -version = "0.4.14" +name = "light-client" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +checksum = "4830579bed474120d4c8b79be18ecd7443ed62bf2d692fdfc591ef7cdee3f3de" dependencies = [ - "scopeguard", + "async-trait", + "base64 0.13.1", + "borsh 0.10.4", + "bs58", + "futures", + "lazy_static", + "light-account", + "light-compressed-account", + "light-compressed-token-sdk", + "light-compressible", + "light-concurrent-merkle-tree", + "light-event", + "light-hasher", + "light-indexed-merkle-tree", + "light-merkle-tree-metadata", + "light-prover-client", + "light-sdk", + "light-sdk-types", + "light-token", + "light-token-interface", + "num-bigint 0.4.6", + "photon-api", + "rand 0.8.5", + "reqwest 0.12.28", + "serde_json", + "smallvec", + "solana-account 2.2.1", + "solana-account-decoder-client-types 2.3.13", + "solana-address-lookup-table-interface 2.2.2", + "solana-clock 2.2.3", + "solana-commitment-config 2.2.1", + "solana-compute-budget-interface 2.2.2", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-keypair 2.2.3", + "solana-message 2.4.0", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-rpc-client 2.3.13", + "solana-rpc-client-api 2.3.13", + "solana-signature 2.3.0", + "solana-transaction 2.2.3", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "spl-pod 0.5.1", + "spl-token-2022-interface 1.0.0", + "thiserror 2.0.18", + "tokio", + "tracing", ] [[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "lru" -version = "0.7.8" +name = "light-compressed-account" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +checksum = "c2ce168f42dab1a4c01ad83993d68b17cd2dc1bb31ced8ab4edecaf5b666a8ad" dependencies = [ - "hashbrown 0.12.3", + "borsh 0.10.4", + "bytemuck", + "light-hasher", + "light-macros", + "light-poseidon 0.3.0", + "light-program-profiler", + "light-zero-copy", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "thiserror 2.0.18", + "tinyvec", + "zerocopy", ] [[package]] -name = "lru" -version = "0.16.2" +name = "light-compressed-token-sdk" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +checksum = "af361443099082c3f7b0e8afe18a770512c494b25219aad951c80daba76beb86" dependencies = [ - "hashbrown 0.16.1", + "arrayvec", + "borsh 0.10.4", + "light-account", + "light-account-checks", + "light-compressed-account", + "light-program-profiler", + "light-sdk", + "light-sdk-types", + "light-token-interface", + "light-token-types", + "light-zero-copy", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "thiserror 2.0.18", ] [[package]] -name = "lru-slab" -version = "0.1.2" +name = "light-compressible" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54745d82dab271a4178b48c48d5768ff54af0a6e01aae62425003c25ed394fc5" +dependencies = [ + "aligned-sized", + "borsh 0.10.4", + "bytemuck", + "light-account-checks", + "light-compressed-account", + "light-hasher", + "light-macros", + "light-program-profiler", + "light-zero-copy", + "pinocchio-pubkey", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "thiserror 2.0.18", + "zerocopy", +] + +[[package]] +name = "light-concurrent-merkle-tree" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db96f47253a0907aaa46dac15cecb27b5510130e48da0b36690dcd2e99a6d558" +dependencies = [ + "borsh 0.10.4", + "light-bounded-vec", + "light-hasher", + "memoffset", + "solana-program-error 2.2.2", + "thiserror 2.0.18", +] + +[[package]] +name = "light-event" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0c2e68b31f5fc890eb0e0c43bc7d5007cd2e02f4b46f3d601f3a91b4c7262c" +dependencies = [ + "borsh 0.10.4", + "light-compressed-account", + "light-hasher", + "light-token-interface", + "light-zero-copy", + "thiserror 2.0.18", +] + +[[package]] +name = "light-hasher" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c822662e6e109bac0e132a43fd52a4ef684811245a794e048cf9cda001e934c8" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "borsh 0.10.4", + "light-poseidon 0.3.0", + "num-bigint 0.4.6", + "sha2 0.10.9", + "sha3", + "solana-program-error 2.2.2", + "thiserror 2.0.18", + "tinyvec", +] + +[[package]] +name = "light-indexed-array" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f14f984030d86b6f07bd8f5ae04e2c40fcd0c3bdfcc7a291fff1ed59c9e6554" +dependencies = [ + "light-hasher", + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.18", +] + +[[package]] +name = "light-indexed-merkle-tree" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0824755289075f28de2820fc7d4ec4e6b9e99d404e033c07338b91cce8c71fb8" +dependencies = [ + "light-bounded-vec", + "light-concurrent-merkle-tree", + "light-hasher", + "light-merkle-tree-reference", + "num-bigint 0.4.6", + "num-traits", + "solana-program-error 2.2.2", + "thiserror 2.0.18", +] + +[[package]] +name = "light-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "179ac51cadc1d0ca047b4d6265a7cc245ca3affc16a20a2749585aa6464d39c2" +dependencies = [ + "bs58", + "proc-macro2", + "quote", + "solana-pubkey 2.4.0", + "syn 2.0.117", +] + +[[package]] +name = "light-merkle-tree-metadata" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2ef127f8b968a22203515fca1822cb54bb8f0bd84de392fcb9fb0b77855393" +dependencies = [ + "borsh 0.10.4", + "bytemuck", + "light-compressed-account", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", + "zerocopy", +] + +[[package]] +name = "light-merkle-tree-reference" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8d480f62ca32b38a6231bbc5310d693f91d6b5bdcc18bb13c2d9aab7a1c90e8" +dependencies = [ + "light-hasher", + "light-indexed-array", + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.18", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254 0.4.0", + "ark-ff 0.4.2", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "light-poseidon" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3d87542063daaccbfecd78b60f988079b6ec4e089249658b9455075c78d42" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "light-poseidon" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47a1ccadd0bb5a32c196da536fd72c59183de24a055f6bf0513bf845fefab862" +dependencies = [ + "ark-bn254 0.5.0", + "ark-ff 0.5.0", + "num-bigint 0.4.6", + "thiserror 1.0.69", +] + +[[package]] +name = "light-profiler-macro" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a8be18fe4de58a6f754caa74a3fbc6d8a758a26f1f3c24d5b0f5b55df5f5408" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "light-program-profiler" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1d345871581aebd8825868a3f08410290aa1cdddcb189ca7f7e588f61d79fcf" +dependencies = [ + "light-profiler-macro", +] + +[[package]] +name = "light-prover-client" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9b434c4819c575c53b439a04cef23e14a7359728d9438a10e6de3641a6d3ba" +dependencies = [ + "ark-bn254 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "light-compressed-account", + "light-hasher", + "light-indexed-array", + "light-sparse-merkle-tree", + "num-bigint 0.4.6", + "num-traits", + "reqwest 0.11.27", + "serde", + "serde_json", + "solana-bn254 2.2.2", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "light-sdk" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f982db1ecc2998f3f9af539f282a355582f094036024918627e468e9e29ab418" +dependencies = [ + "bincode", + "borsh 0.10.4", + "bytemuck", + "light-account-checks", + "light-compressed-account", + "light-hasher", + "light-macros", + "light-program-profiler", + "light-sdk-macros", + "light-sdk-types", + "light-token-interface", + "light-zero-copy", + "num-bigint 0.4.6", + "solana-account-info 2.3.0", + "solana-clock 2.2.3", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-loader-v3-interface 5.0.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-system-interface 1.0.0", + "solana-sysvar 2.3.0", + "thiserror 2.0.18", +] + +[[package]] +name = "light-sdk-macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2160586e2b381827d1ca921b5b9e3383e65c013e2c32e8c14a09d913ca7e1312" +dependencies = [ + "darling", + "light-hasher", + "light-sdk-types", + "proc-macro2", + "quote", + "solana-pubkey 2.4.0", + "syn 2.0.117", +] + +[[package]] +name = "light-sdk-types" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbd944a80033d928d0abf6152595d2e69aa1af07a3dd0e5b86f0b7e4fc9f484" +dependencies = [ + "borsh 0.10.4", + "bytemuck", + "light-account-checks", + "light-compressed-account", + "light-compressible", + "light-hasher", + "light-macros", + "light-token-interface", + "solana-msg 2.2.1", + "thiserror 2.0.18", +] + +[[package]] +name = "light-sparse-merkle-tree" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4251e79b6c63f4946572dcfd7623680ad0f9e0efe1a761a944733333c5645063" +dependencies = [ + "light-hasher", + "light-indexed-array", + "num-bigint 0.4.6", + "num-traits", + "thiserror 2.0.18", +] + +[[package]] +name = "light-token" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "962fc0c26808f218cd4fb782a15adc24a2163e2e64cacd74c9ca86540cf9afb3" +dependencies = [ + "arrayvec", + "borsh 0.10.4", + "light-account", + "light-account-checks", + "light-batched-merkle-tree", + "light-compressed-account", + "light-compressed-token-sdk", + "light-compressible", + "light-macros", + "light-program-profiler", + "light-sdk", + "light-sdk-types", + "light-token-interface", + "light-token-types", + "light-zero-copy", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-pod 0.5.1", + "thiserror 2.0.18", +] + +[[package]] +name = "light-token-interface" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b14661b6592711d90b1cac2402fa10310d90e0517e035c6b1f47c30a14883461" +dependencies = [ + "aligned-sized", + "borsh 0.10.4", + "bytemuck", + "light-array-map", + "light-compressed-account", + "light-compressible", + "light-hasher", + "light-macros", + "light-program-profiler", + "light-zero-copy", + "pinocchio 0.9.2", + "pinocchio-pubkey", + "solana-account-info 2.3.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sysvar 2.3.0", + "spl-pod 0.5.1", + "spl-token-2022", + "thiserror 2.0.18", + "tinyvec", + "zerocopy", +] + +[[package]] +name = "light-token-types" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e5a8ab668ed571a98a01b4eb4df1e671386e89dc0075e614ede972e34c22742" +dependencies = [ + "borsh 0.10.4", + "light-account-checks", + "light-compressed-account", + "light-macros", + "light-sdk-types", + "solana-msg 2.2.1", + "thiserror 2.0.18", +] + +[[package]] +name = "light-verifier" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d829f997b17c7c65198bb93f0d645a4b2818aed2bd14bf2716e36171d4a9f3f" +dependencies = [ + "groth16-solana", + "light-compressed-account", + "thiserror 2.0.18", +] + +[[package]] +name = "light-zero-copy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5621fb515e14af46148699c0b65334aabe230a1d2cbd06736ccc7a408c8a4af" +dependencies = [ + "light-zero-copy-derive", + "solana-program-error 2.2.2", + "zerocopy", +] + +[[package]] +name = "light-zero-copy-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c46425e5c7ab5203ff5c86ae2615b169cca55f9283f5f60f5dd74143be6934" +dependencies = [ + "lazy_static", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lmdb-rkv" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447a296f7aca299cfbb50f4e4f3d49451549af655fb7215d7f8c0c3d64bad42b" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "libc", + "lmdb-rkv-sys", +] + +[[package]] +name = "lmdb-rkv-sys" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b9ce6b3be08acefa3003c57b7565377432a89ec24476bbe72e11d101f852fe" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "lru" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +dependencies = [ + "hashbrown 0.12.3", +] + +[[package]] +name = "lru" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" @@ -4069,9 +4871,9 @@ name = "magic-domain-program" version = "0.3.0" source = "git+https://github.com/magicblock-labs/magic-domain-program.git?rev=335a22#335a22ba5aa7b8c4bc84d5053444c74c3b05cdac" dependencies = [ - "borsh", + "borsh 1.6.0", "bytemuck_derive", - "solana-program", + "solana-program 3.0.0", "solana-system-interface 3.2.0", ] @@ -4092,17 +4894,17 @@ dependencies = [ "magicblock-program", "magicblock-rpc-client", "rand 0.9.2", - "solana-account", + "solana-account 3.4.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-signature", - "solana-signer", - "solana-sysvar", - "solana-transaction", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -4122,8 +4924,8 @@ dependencies = [ "magicblock-program", "solana-hash 3.1.0", "solana-pubkey 3.0.0", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", "tokio-util 0.7.17", @@ -4140,7 +4942,7 @@ dependencies = [ "memmap2 0.9.9", "parking_lot", "reflink-copy", - "solana-account", + "solana-account 3.4.0", "solana-pubkey 3.0.0", "thiserror 2.0.18", "tracing", @@ -4151,7 +4953,7 @@ dependencies = [ name = "magicblock-aperture" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "agave-geyser-plugin-interface", "arc-swap", "base64 0.21.7", @@ -4174,17 +4976,17 @@ dependencies = [ "parking_lot", "scc", "serde", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", "solana-fee-structure", - "solana-keypair", - "solana-message", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client-api", - "solana-signature", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", "solana-system-transaction", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "solana-transaction-status", "sonic-rs", "thiserror 2.0.18", @@ -4197,10 +4999,11 @@ dependencies = [ name = "magicblock-api" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "anyhow", - "borsh", + "borsh 1.6.0", "fd-lock", + "light-client", "magic-domain-program", "magicblock-account-cloner", "magicblock-accounts", @@ -4221,30 +5024,30 @@ dependencies = [ "magicblock-validator-admin", "num_cpus", "paste", - "solana-account", - "solana-clock", - "solana-commitment-config", - "solana-feature-gate-interface", - "solana-fee-calculator", + "solana-account 3.4.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-feature-gate-interface 3.1.0", + "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-message", - "solana-native-token", - "solana-program", - "solana-program-option", - "solana-program-pack", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", + "solana-native-token 3.0.0", + "solana-program 3.0.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-rpc-client", - "solana-sdk-ids", + "solana-rpc-client 3.1.12", + "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-system-program", - "solana-sysvar", - "solana-transaction", - "solana-transaction-error", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "spl-token-interface", "thiserror 2.0.18", "tokio", @@ -4256,13 +5059,15 @@ dependencies = [ name = "magicblock-chainlink" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "arc-swap", "async-trait", "bincode", - "borsh", + "borsh 1.6.0", + "compressed-delegation-client", "futures-util", "helius-laserstream", + "light-client", "lru 0.16.2", "magicblock-accounts-db", "magicblock-config", @@ -4272,31 +5077,31 @@ dependencies = [ "magicblock-metrics", "parking_lot", "scc", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-account-decoder-client-types", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-commitment-config", + "solana-account-decoder-client-types 3.1.12", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-loader-v3-interface", - "solana-loader-v4-interface", - "solana-message", - "solana-program", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", + "solana-message 3.1.0", + "solana-program 3.0.0", "solana-pubkey 3.0.0", "solana-pubsub-client", "solana-rent 3.1.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-sdk-ids", - "solana-signature", - "solana-signer", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-system-interface 3.2.0", - "solana-transaction", - "solana-transaction-error", - "spl-token-2022-interface", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", + "spl-token-2022-interface 2.1.0", "spl-token-interface", "thiserror 2.0.18", "tokio", @@ -4311,13 +5116,13 @@ dependencies = [ name = "magicblock-committor-program" version = "0.9.0" dependencies = [ - "borsh", + "borsh 1.6.0", "paste", - "solana-account", - "solana-account-info", - "solana-program", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-program 3.0.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", "thiserror 2.0.18", ] @@ -4329,8 +5134,12 @@ dependencies = [ "async-trait", "base64 0.21.7", "bincode", - "borsh", + "borsh 1.6.0", + "compressed-delegation-api", + "compressed-delegation-client", "futures-util", + "light-client", + "light-sdk", "lru 0.16.2", "magicblock-committor-program", "magicblock-core", @@ -4340,25 +5149,25 @@ dependencies = [ "magicblock-rpc-client", "magicblock-table-mania", "rusqlite", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-address-lookup-table-interface", - "solana-commitment-config", - "solana-compute-budget-interface", + "solana-address-lookup-table-interface 3.1.0", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-message", - "solana-program", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", + "solana-program 3.0.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-signer", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-system-program", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", "static_assertions", "thiserror 2.0.18", "tokio", @@ -4377,10 +5186,10 @@ dependencies = [ "isocountry", "serde", "serde_with", - "solana-keypair", + "solana-keypair 3.1.2", "solana-pubkey 3.0.0", - "solana-signer", - "toml", + "solana-signer 3.0.0", + "toml 0.8.23", "url", ] @@ -4388,24 +5197,30 @@ dependencies = [ name = "magicblock-core" version = "0.9.0" dependencies = [ + "async-trait", "bincode", + "compressed-delegation-client", "flume", + "light-client", + "light-compressed-account", + "light-sdk", "magicblock-magic-program-api 0.9.0", "serde", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-message", - "solana-program", + "solana-message 3.1.0", + "solana-program 3.0.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", - "solana-transaction-status-client-types", - "spl-token-2022-interface", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", + "spl-token-2022-interface 2.1.0", "spl-token-interface", + "thiserror 2.0.18", "tokio", "tracing", "tracing-log", @@ -4418,7 +5233,7 @@ version = "0.3.0" source = "git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" dependencies = [ "bincode", - "borsh", + "borsh 1.6.0", "bytemuck", "const-crypto", "num_enum", @@ -4429,10 +5244,10 @@ dependencies = [ "rkyv 0.7.45", "serde", "solana-address 2.6.0", - "solana-instruction", - "solana-loader-v3-interface", - "solana-program", - "solana-sdk-ids", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-program 3.0.0", + "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-system-interface 2.0.0", "static_assertions", @@ -4446,7 +5261,7 @@ version = "0.3.0" source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" dependencies = [ "bincode", - "borsh", + "borsh 1.6.0", "bytemuck", "const-crypto", "libsodium-rs", @@ -4458,11 +5273,11 @@ dependencies = [ "rkyv 0.7.45", "serde", "solana-address 2.6.0", - "solana-instruction", - "solana-loader-v3-interface", - "solana-program", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-program 3.0.0", "solana-sdk", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-system-interface 2.0.0", "static_assertions", @@ -4488,19 +5303,19 @@ dependencies = [ "rocksdb", "serde", "solana-account-decoder", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-message", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-metrics 2.3.13", "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-storage-proto", "solana-svm-measure", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "solana-transaction-status", "thiserror 2.0.18", "tokio", @@ -4515,8 +5330,8 @@ dependencies = [ "bincode", "const-crypto", "serde", - "solana-program", - "solana-signature", + "solana-program 3.0.0", + "solana-signature 3.4.0", ] [[package]] @@ -4526,8 +5341,8 @@ source = "git+https://github.com/magicblock-labs/magicblock-validator.git?branch dependencies = [ "bincode", "serde", - "solana-program", - "solana-signature", + "solana-program 3.0.0", + "solana-signature 3.4.0", ] [[package]] @@ -4539,7 +5354,7 @@ dependencies = [ "hyper-util", "lazy_static", "prometheus", - "solana-signature", + "solana-signature 3.4.0", "tokio", "tokio-util 0.7.17", "tracing", @@ -4549,7 +5364,7 @@ dependencies = [ name = "magicblock-processor" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "agave-precompiles", "agave-syscalls", "bincode", @@ -4561,27 +5376,27 @@ dependencies = [ "parking_lot", "rustc-hash 2.1.1", "serde", - "solana-account", + "solana-account 3.4.0", "solana-bpf-loader-program", "solana-compute-budget", "solana-compute-budget-program", - "solana-feature-gate-interface", + "solana-feature-gate-interface 3.1.0", "solana-fee-structure", - "solana-instruction", - "solana-loader-v3-interface", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", "solana-loader-v4-program", "solana-precompile-error", - "solana-program", + "solana-program 3.0.0", "solana-program-runtime", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm", "solana-svm-callback", "solana-svm-transaction", "solana-system-program", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "solana-transaction-status", "solana-zk-elgamal-proof-program", "tokio", @@ -4601,25 +5416,25 @@ dependencies = [ "num-traits", "parking_lot", "serde", - "solana-account", - "solana-account-info", - "solana-clock", - "solana-fee-calculator", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", + "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-program-runtime", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-seed-derivable", - "solana-signature", - "solana-signer", + "solana-sdk-ids 3.1.0", + "solana-seed-derivable 3.0.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-svm-log-collector", - "solana-sysvar", - "solana-transaction", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", ] @@ -4627,19 +5442,19 @@ dependencies = [ name = "magicblock-rpc-client" version = "0.9.0" dependencies = [ - "solana-account", - "solana-account-decoder-client-types", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-commitment-config", + "solana-account 3.4.0", + "solana-account-decoder-client-types 3.1.12", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", "thiserror 2.0.18", "tokio", "tracing", @@ -4653,14 +5468,14 @@ dependencies = [ "futures-util", "magicblock-core", "magicblock-magic-program-api 0.9.0", - "solana-instruction", - "solana-keypair", - "solana-message", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-signature", - "solana-signer", - "solana-transaction", + "solana-rpc-client 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -4675,18 +5490,18 @@ dependencies = [ "magicblock-rpc-client", "rand 0.9.2", "sha3", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-commitment-config", - "solana-compute-budget-interface", - "solana-instruction", - "solana-keypair", - "solana-message", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", - "solana-slot-hashes", - "solana-transaction", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-slot-hashes 3.0.1", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -4704,14 +5519,14 @@ dependencies = [ "magicblock-ledger", "magicblock-program", "rusqlite", - "solana-instruction", - "solana-message", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-transaction", - "solana-transaction-error", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", "tokio-util 0.7.17", @@ -4725,11 +5540,11 @@ dependencies = [ "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "magicblock-program", "magicblock-rpc-client", - "solana-commitment-config", - "solana-rpc-client", - "solana-signature", - "solana-signer", - "solana-transaction", + "solana-commitment-config 3.1.1", + "solana-rpc-client 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", "tokio", "tokio-util 0.7.17", "tracing", @@ -4739,13 +5554,13 @@ dependencies = [ name = "magicblock-version" version = "0.9.0" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "git-version", "rustc_version", "semver", "serde", "solana-frozen-abi-macro", - "solana-rpc-client-api", + "solana-rpc-client-api 3.1.12", "solana-sanitize 3.0.1", ] @@ -5037,6 +5852,7 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "serde", ] [[package]] @@ -5143,12 +5959,18 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", "syn 2.0.117", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "objc2" version = "0.6.3" @@ -5400,6 +6222,18 @@ dependencies = [ "indexmap 2.12.1", ] +[[package]] +name = "photon-api" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95609d4f08f2cf86d6e41f5b483cfbbfd914099eb0f7c6ea15e98b358f4614f8" +dependencies = [ + "progenitor-client", + "reqwest 0.13.2", + "serde", + "serde_json", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -5448,7 +6282,7 @@ dependencies = [ "solana-address 2.6.0", "solana-define-syscall 4.0.1", "solana-instruction-view", - "solana-program-error", + "solana-program-error 3.0.0", ] [[package]] @@ -5599,6 +6433,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -5651,16 +6494,36 @@ dependencies = [ "yansi", ] +[[package]] +name = "progenitor-client" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffab7b358944dba033a7b324e7558e66e6bcb1fb4705cf57f26fd5092bcae630" +dependencies = [ + "bytes", + "futures-core", + "percent-encoding", + "reqwest 0.13.2", + "serde", + "serde_json", + "serde_urlencoded", +] + [[package]] name = "program-flexi-counter" version = "0.0.0" dependencies = [ "bincode", - "borsh", + "borsh 1.6.0", + "compressed-delegation-api", + "compressed-delegation-client", "ephemeral-rollups-sdk", + "light-hasher", + "light-sdk", + "light-sdk-types", "magicblock-magic-program-api 0.9.0", "serde", - "solana-program", + "solana-program 3.0.0", "solana-system-interface 3.2.0", ] @@ -5668,10 +6531,10 @@ dependencies = [ name = "program-mini" version = "0.0.0" dependencies = [ - "solana-program", + "solana-program 3.0.0", "solana-program-test", "solana-sdk", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", "tokio", ] @@ -5680,12 +6543,12 @@ dependencies = [ name = "program-schedulecommit" version = "0.0.0" dependencies = [ - "borsh", + "borsh 1.6.0", "ephemeral-rollups-sdk", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "magicblock-magic-program-api 0.9.0", "rkyv 0.7.45", - "solana-program", + "solana-program 3.0.0", "solana-system-interface 3.2.0", "static_assertions", ] @@ -5694,10 +6557,10 @@ dependencies = [ name = "program-schedulecommit-security" version = "0.0.0" dependencies = [ - "borsh", + "borsh 1.6.0", "ephemeral-rollups-sdk", "program-schedulecommit", - "solana-program", + "solana-program 3.0.0", ] [[package]] @@ -5966,6 +6829,7 @@ version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -6283,7 +7147,7 @@ dependencies = [ "http-body 0.4.6", "hyper 0.14.32", "hyper-rustls 0.24.2", - "hyper-tls", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -6320,17 +7184,22 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", "futures-channel", "futures-core", "futures-util", + "h2 0.4.12", "http 1.4.0", "http-body 1.0.1", "http-body-util", "hyper 1.8.1", "hyper-rustls 0.27.8", + "hyper-tls 0.6.0", "hyper-util", "js-sys", "log", + "mime", + "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -6341,6 +7210,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.2", "tokio", + "tokio-native-tls", "tokio-rustls 0.26.4", "tower 0.5.2", "tower-http", @@ -6352,6 +7222,47 @@ dependencies = [ "webpki-roots 1.0.4", ] +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls 0.27.8", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.35", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tokio-rustls 0.26.4", + "tokio-util 0.7.17", + "tower 0.5.2", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "reqwest-middleware" version = "0.4.2" @@ -6545,6 +7456,7 @@ version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -6637,6 +7549,7 @@ version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -6686,15 +7599,15 @@ name = "schedulecommit-client" version = "0.0.0" dependencies = [ "anyhow", - "borsh", + "borsh 1.6.0", "integration-test-tools", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "program-schedulecommit", - "solana-commitment-config", - "solana-compute-budget-interface", - "solana-program", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", + "solana-program 3.0.0", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk", "solana-system-interface 3.2.0", "tracing", @@ -6705,8 +7618,13 @@ name = "schedulecommit-committor-service" version = "0.0.0" dependencies = [ "async-trait", - "borsh", + "borsh 1.6.0", + "compressed-delegation-client", "futures", + "light-client", + "light-compressed-account", + "light-sdk", + "light-sdk-types", "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", @@ -6717,13 +7635,14 @@ dependencies = [ "program-flexi-counter", "program-schedulecommit", "rand 0.8.5", - "solana-account", - "solana-commitment-config", + "solana-account 3.4.0", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", "test-kit", "tokio", @@ -6734,7 +7653,7 @@ dependencies = [ name = "schedulecommit-test-scenarios" version = "0.0.0" dependencies = [ - "borsh", + "borsh 1.6.0", "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", @@ -6745,10 +7664,10 @@ dependencies = [ "rand 0.8.5", "schedulecommit-client", "serial_test", - "solana-commitment-config", - "solana-program", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-commitment-config 3.1.1", + "solana-program 3.0.0", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk", "test-kit", "tracing", @@ -6764,7 +7683,7 @@ dependencies = [ "program-schedulecommit", "program-schedulecommit-security", "schedulecommit-client", - "solana-rpc-client-api", + "solana-rpc-client-api 3.1.12", "solana-sdk", "solana-system-interface 3.2.0", ] @@ -6937,15 +7856,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -7193,21 +8112,39 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "solana-account" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f949fe4edaeaea78c844023bfc1c898e0b1f5a100f8a8d2d0f85d0a7b090258" +dependencies = [ + "bincode", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info 2.3.0", + "solana-clock 2.2.3", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-sysvar 2.3.0", +] + [[package]] name = "solana-account" version = "3.4.0" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "bincode", "qualifier_attr", "serde", "serde_bytes", - "solana-account-info", - "solana-clock", - "solana-instruction", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-sysvar", + "solana-sdk-ids 3.1.0", + "solana-sysvar 3.1.1", ] [[package]] @@ -7218,37 +8155,53 @@ checksum = "8dbde78ccf7c3e14bc5ab230da1dfadfc2dc84b860cd2ffa39d0fd3030f7df4a" dependencies = [ "Inflector", "base64 0.22.1", - "bincode", + "bincode", + "bs58", + "bv", + "serde", + "serde_json", + "solana-account 3.4.0", + "solana-account-decoder-client-types 3.1.12", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", + "solana-config-interface", + "solana-epoch-schedule 3.1.0", + "solana-fee-calculator 3.2.0", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-nonce 3.1.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", + "solana-pubkey 3.0.0", + "solana-rent 3.1.0", + "solana-sdk-ids 3.1.0", + "solana-slot-hashes 3.0.1", + "solana-slot-history 3.0.0", + "solana-stake-interface 2.0.2", + "solana-sysvar 3.1.1", + "solana-vote-interface 4.0.4", + "spl-generic-token 2.0.1", + "spl-token-2022-interface 2.1.0", + "spl-token-group-interface 0.7.2", + "spl-token-interface", + "spl-token-metadata-interface 0.8.0", + "thiserror 2.0.18", + "zstd", +] + +[[package]] +name = "solana-account-decoder-client-types" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5519e8343325b707f17fbed54fcefb325131b692506d0af9e08a539d15e4f8cf" +dependencies = [ + "base64 0.22.1", "bs58", - "bv", "serde", + "serde_derive", "serde_json", - "solana-account", - "solana-account-decoder-client-types", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-config-interface", - "solana-epoch-schedule", - "solana-fee-calculator", - "solana-instruction", - "solana-loader-v3-interface", - "solana-nonce", - "solana-program-option", - "solana-program-pack", - "solana-pubkey 3.0.0", - "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-slot-hashes", - "solana-slot-history", - "solana-stake-interface", - "solana-sysvar", - "solana-vote-interface", - "spl-generic-token", - "spl-token-2022-interface", - "spl-token-group-interface", - "spl-token-interface", - "spl-token-metadata-interface", - "thiserror 2.0.18", + "solana-account 2.2.1", + "solana-pubkey 2.4.0", "zstd", ] @@ -7262,11 +8215,24 @@ dependencies = [ "bs58", "serde", "serde_json", - "solana-account", + "solana-account 3.4.0", "solana-pubkey 3.0.0", "zstd", ] +[[package]] +name = "solana-account-info" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8f5152a288ef1912300fc6efa6c2d1f9bb55d9398eb6c72326360b8063987da" +dependencies = [ + "bincode", + "serde", + "solana-program-error 2.2.2", + "solana-program-memory 2.3.1", + "solana-pubkey 2.4.0", +] + [[package]] name = "solana-account-info" version = "3.1.1" @@ -7276,8 +8242,8 @@ dependencies = [ "bincode", "serde_core", "solana-address 2.6.0", - "solana-program-error", - "solana-program-memory", + "solana-program-error 3.0.0", + "solana-program-memory 3.1.0", ] [[package]] @@ -7287,7 +8253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37ca34c37f92ee341b73d5ce7c8ef5bb38e9a87955b4bd343c63fa18b149215" dependencies = [ "solana-address 2.6.0", - "solana-program-error", + "solana-program-error 3.0.0", ] [[package]] @@ -7318,32 +8284,32 @@ dependencies = [ "seqlock", "serde", "smallvec", - "solana-account", - "solana-address-lookup-table-interface", + "solana-account 3.4.0", + "solana-address-lookup-table-interface 3.1.0", "solana-bucket-map", - "solana-clock", - "solana-epoch-schedule", - "solana-fee-calculator", + "solana-clock 3.0.1", + "solana-epoch-schedule 3.1.0", + "solana-fee-calculator 3.2.0", "solana-genesis-config", "solana-hash 3.1.0", "solana-lattice-hash", "solana-measure", - "solana-message", + "solana-message 3.1.0", "solana-metrics 3.1.12", "solana-nohash-hasher", "solana-pubkey 3.0.0", "solana-rayon-threadlimit", - "solana-reward-info", + "solana-reward-info 3.0.0", "solana-sha256-hasher 3.1.0", - "solana-slot-hashes", + "solana-slot-hashes 3.0.1", "solana-svm-transaction", "solana-system-interface 2.0.0", - "solana-sysvar", + "solana-sysvar 3.1.1", "solana-time-utils 3.0.0", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", - "spl-generic-token", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", + "spl-generic-token 2.0.1", "static_assertions", "tempfile", "thiserror 2.0.18", @@ -7364,7 +8330,7 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1384b52c435a750cc9c538760fc7bb472fd78e65a9900a2d07312c5bb335b72" dependencies = [ - "borsh", + "borsh 1.6.0", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", @@ -7377,12 +8343,29 @@ dependencies = [ "solana-atomic-u64 3.0.1", "solana-define-syscall 5.0.0", "solana-nullable", - "solana-program-error", + "solana-program-error 3.0.0", "solana-sanitize 3.0.1", "solana-sha256-hasher 3.1.0", "wincode 0.5.1", ] +[[package]] +name = "solana-address-lookup-table-interface" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1673f67efe870b64a65cb39e6194be5b26527691ce5922909939961a6e6b395" +dependencies = [ + "bincode", + "bytemuck", + "serde", + "serde_derive", + "solana-clock 2.2.3", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-slot-hashes 2.2.1", +] + [[package]] name = "solana-address-lookup-table-interface" version = "3.1.0" @@ -7393,12 +8376,12 @@ dependencies = [ "bytemuck", "serde", "serde_derive", - "solana-clock", - "solana-instruction", + "solana-clock 3.0.1", + "solana-instruction 3.4.0", "solana-instruction-error", "solana-pubkey 4.2.0", - "solana-sdk-ids", - "solana-slot-hashes", + "solana-sdk-ids 3.1.0", + "solana-slot-hashes 3.0.1", ] [[package]] @@ -7425,22 +8408,22 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16034da9477c2ceb6bf03a04389d68f463fb9e09a7641b4517af4177976c5f59" dependencies = [ - "borsh", + "borsh 1.6.0", "futures", - "solana-account", + "solana-account 3.4.0", "solana-banks-interface", - "solana-clock", - "solana-commitment-config", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-message", - "solana-program-pack", + "solana-message 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-signature", - "solana-sysvar", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "tarpc", "thiserror 2.0.18", "tokio", @@ -7454,16 +8437,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aeed8b00c1b30e10cada0de485c4c7aa2805bc54587d7fbfd4c89b9a6a2b7bb5" dependencies = [ "serde", - "solana-account", - "solana-clock", - "solana-commitment-config", + "solana-account 3.4.0", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "tarpc", ] @@ -7473,30 +8456,41 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d24b007191bac5046513d8b642ff554a9413a270fbf78ab416e5ecc1b9eea11" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "bincode", "crossbeam-channel", "futures", - "solana-account", + "solana-account 3.4.0", "solana-banks-interface", "solana-client", - "solana-clock", - "solana-commitment-config", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-runtime", "solana-runtime-transaction", "solana-send-transaction-service", - "solana-signature", + "solana-signature 3.4.0", "solana-svm", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "tarpc", "tokio", "tokio-serde", ] +[[package]] +name = "solana-big-mod-exp" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "solana-define-syscall 2.3.0", +] + [[package]] name = "solana-big-mod-exp" version = "3.0.0" @@ -7508,6 +8502,17 @@ dependencies = [ "solana-define-syscall 3.0.0", ] +[[package]] +name = "solana-bincode" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a3787b8cf9c9fe3dd360800e8b70982b9e5a8af9e11c354b6665dd4a003adc" +dependencies = [ + "bincode", + "serde", + "solana-instruction 2.3.3", +] + [[package]] name = "solana-bincode" version = "3.1.0" @@ -7519,6 +8524,18 @@ dependencies = [ "solana-instruction-error", ] +[[package]] +name = "solana-blake3-hasher" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" +dependencies = [ + "blake3", + "solana-define-syscall 2.3.0", + "solana-hash 2.3.0", + "solana-sanitize 2.2.1", +] + [[package]] name = "solana-blake3-hasher" version = "3.1.0" @@ -7548,12 +8565,27 @@ dependencies = [ "serde", "serde_json", "serde_with", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "subtle", "thiserror 2.0.18", ] +[[package]] +name = "solana-bn254" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4420f125118732833f36facf96a27e7b78314b2d642ba07fa9ffdacd8d79e243" +dependencies = [ + "ark-bn254 0.4.0", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "bytemuck", + "solana-define-syscall 2.3.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-bn254" version = "3.2.1" @@ -7569,13 +8601,23 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "solana-borsh" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718333bcd0a1a7aed6655aa66bef8d7fb047944922b2d3a18f49cbc13e73d004" +dependencies = [ + "borsh 0.10.4", + "borsh 1.6.0", +] + [[package]] name = "solana-borsh" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c04abbae16f57178a163125805637b8a076175bb5c0002fb04f4792bea901cf7" dependencies = [ - "borsh", + "borsh 1.6.0", ] [[package]] @@ -7587,24 +8629,24 @@ dependencies = [ "agave-syscalls", "bincode", "qualifier_attr", - "solana-account", - "solana-bincode", - "solana-clock", - "solana-instruction", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-account 3.4.0", + "solana-bincode 3.1.0", + "solana-clock 3.0.1", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-packet", - "solana-program-entrypoint", + "solana-program-entrypoint 3.1.1", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-sbpf", - "solana-sdk-ids", - "solana-svm-feature-set", + "solana-sdk-ids 3.1.0", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-transaction-context", + "solana-transaction-context 3.1.12", ] [[package]] @@ -7620,7 +8662,7 @@ dependencies = [ "modular-bitfield", "num_enum", "rand 0.8.5", - "solana-clock", + "solana-clock 3.0.1", "solana-measure", "solana-pubkey 3.0.0", "tempfile", @@ -7632,14 +8674,14 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaf44075aa3dbe16ce0112314d0dfd2435a18ddfd96f53e5269879f4006eb60d" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "solana-bpf-loader-program", "solana-compute-budget-program", "solana-hash 3.1.0", "solana-loader-v4-program", "solana-program-runtime", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-program", "solana-vote-program", "solana-zk-elgamal-proof-program", @@ -7652,14 +8694,14 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cd4d41f391f427e64e03fb00fb0c93443f18464dafd71e06f996ac03a3982" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "ahash 0.8.12", "log", "solana-bpf-loader-program", "solana-compute-budget-program", "solana-loader-v4-program", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-program", "solana-vote-program", ] @@ -7677,35 +8719,35 @@ dependencies = [ "futures", "futures-util", "indexmap 2.12.1", - "indicatif", + "indicatif 0.18.4", "log", "rayon", - "solana-account", + "solana-account 3.4.0", "solana-client-traits", - "solana-commitment-config", + "solana-commitment-config 3.1.1", "solana-connection-cache", - "solana-epoch-info", + "solana-epoch-info 3.1.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", "solana-measure", - "solana-message", + "solana-message 3.1.0", "solana-net-utils", "solana-pubkey 3.0.0", "solana-pubsub-client", "solana-quic-client", "solana-quic-definitions", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-rpc-client-nonce-utils", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-streamer", "solana-time-utils 3.0.0", "solana-tpu-client", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", "solana-udp-client", "thiserror 2.0.18", "tokio", @@ -7718,19 +8760,32 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08618ed587e128105510c54ae3e456b9a06d674d8640db75afe66dad65cb4e02" dependencies = [ - "solana-account", - "solana-commitment-config", - "solana-epoch-info", + "solana-account 3.4.0", + "solana-commitment-config 3.1.1", + "solana-epoch-info 3.1.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-message", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-system-interface 2.0.0", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", +] + +[[package]] +name = "solana-clock" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8584296123df8fe229b95e2ebfd37ae637fe9db9b7d4dd677ac5a78e80dbfce" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -7741,9 +8796,9 @@ checksum = "95cf11109c3b6115cc510f1e31f06fdd52f504271bc24ef5f1249fbbcae5f9f3" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -7766,6 +8821,16 @@ dependencies = [ "solana-hash 4.2.0", ] +[[package]] +name = "solana-commitment-config" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac49c4dde3edfa832de1697e9bcdb7c3b3f7cb7a1981b7c62526c8bb6700fb73" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "solana-commitment-config" version = "3.1.1" @@ -7792,30 +8857,40 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bf47dcc57b770cee0432899ac89cd7e85896f9e28e3d5e5542a0b8a8f5839f" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "log", - "solana-borsh", + "solana-borsh 3.0.2", "solana-builtins-default-costs", "solana-compute-budget", - "solana-compute-budget-interface", - "solana-instruction", + "solana-compute-budget-interface 3.0.0", + "solana-instruction 3.4.0", "solana-packet", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-transaction", - "solana-transaction-error", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", ] +[[package]] +name = "solana-compute-budget-interface" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8432d2c4c22d0499aa06d62e4f7e333f81777b3d7c96050ae9e5cb71a8c3aee4" +dependencies = [ + "solana-instruction 2.3.3", + "solana-sdk-ids 2.2.1", +] + [[package]] name = "solana-compute-budget-interface" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8292c436b269ad23cecc8b24f7da3ab07ca111661e25e00ce0e1d22771951ab9" dependencies = [ - "borsh", - "solana-instruction", - "solana-sdk-ids", + "borsh 1.6.0", + "solana-instruction 3.4.0", + "solana-sdk-ids 3.1.0", ] [[package]] @@ -7836,11 +8911,11 @@ dependencies = [ "bincode", "serde", "serde_derive", - "solana-account", - "solana-instruction", + "solana-account 3.4.0", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-short-vec", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", "solana-system-interface 2.0.0", ] @@ -7858,11 +8933,11 @@ dependencies = [ "log", "rand 0.8.5", "rayon", - "solana-keypair", + "solana-keypair 3.1.2", "solana-measure", "solana-metrics 3.1.12", "solana-time-utils 3.0.0", - "solana-transaction-error", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", ] @@ -7873,40 +8948,68 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daa79df27ff7b933c4cb7612340d9af3b4f49b0219bec81ad6826e9352ad054f" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "ahash 0.8.12", "log", - "solana-bincode", - "solana-borsh", + "solana-bincode 3.1.0", + "solana-borsh 3.0.2", "solana-builtins-default-costs", - "solana-clock", + "solana-clock 3.0.1", "solana-compute-budget", "solana-compute-budget-instruction", - "solana-compute-budget-interface", + "solana-compute-budget-interface 3.0.0", "solana-fee-structure", "solana-metrics 3.1.12", "solana-packet", "solana-pubkey 3.0.0", "solana-runtime-transaction", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-transaction", "solana-system-interface 2.0.0", - "solana-transaction-error", + "solana-transaction-error 3.1.0", "solana-vote-program", ] +[[package]] +name = "solana-cpi" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11" +dependencies = [ + "solana-account-info 2.3.0", + "solana-define-syscall 2.3.0", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-stable-layout 2.2.1", +] + [[package]] name = "solana-cpi" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dea26709d867aada85d0d3617db0944215c8bb28d3745b912de7db13a23280c" dependencies = [ - "solana-account-info", + "solana-account-info 3.1.1", "solana-define-syscall 4.0.1", - "solana-instruction", - "solana-program-error", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", "solana-pubkey 4.2.0", - "solana-stable-layout", + "solana-stable-layout 3.0.1", +] + +[[package]] +name = "solana-curve25519" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae4261b9a8613d10e77ac831a8fa60b6fa52b9b103df46d641deff9f9812a23" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-define-syscall 2.3.0", + "subtle", + "thiserror 2.0.18", ] [[package]] @@ -7923,6 +9026,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "solana-decode-error" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c781686a18db2f942e70913f7ca15dc120ec38dcab42ff7557db2c70c625a35" +dependencies = [ + "num-traits", +] + [[package]] name = "solana-define-syscall" version = "2.3.0" @@ -7947,6 +9059,17 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03aacdd7a61e2109887a7a7f046caebafce97ddf1150f33722eeac04f9039c73" +[[package]] +name = "solana-derivation-path" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "939756d798b25c5ec3cca10e06212bdca3b1443cb9bb740a38124f58b258737b" +dependencies = [ + "derivation-path", + "qstring", + "uriparse", +] + [[package]] name = "solana-derivation-path" version = "3.0.0" @@ -7966,8 +9089,18 @@ checksum = "e1419197f1c06abf760043f6d64ba9d79a03ad5a43f18c7586471937122094da" dependencies = [ "bytemuck", "bytemuck_derive", - "solana-instruction", - "solana-sdk-ids", + "solana-instruction 3.4.0", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-epoch-info" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ef6f0b449290b0b9f32973eefd95af35b01c5c0c34c569f936c34c5b20d77b" +dependencies = [ + "serde", + "serde_derive", ] [[package]] @@ -7980,6 +9113,20 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-epoch-rewards" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" +dependencies = [ + "serde", + "serde_derive", + "solana-hash 2.3.0", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", +] + [[package]] name = "solana-epoch-rewards" version = "3.0.1" @@ -7989,9 +9136,9 @@ dependencies = [ "serde", "serde_derive", "solana-hash 4.2.0", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -8005,6 +9152,19 @@ dependencies = [ "solana-hash 4.2.0", ] +[[package]] +name = "solana-epoch-schedule" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fce071fbddecc55d727b1d7ed16a629afe4f6e4c217bc8d00af3b785f6f67ed" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", +] + [[package]] name = "solana-epoch-schedule" version = "3.1.0" @@ -8013,9 +9173,9 @@ checksum = "9ce264b7b42322325947c4136a09460bf5c73d9aa8262c9b0a2064be63ba8639" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -8028,6 +9188,27 @@ dependencies = [ "solana-pubkey 4.2.0", ] +[[package]] +name = "solana-example-mocks" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84461d56cbb8bb8d539347151e0525b53910102e4bced875d49d5139708e39d3" +dependencies = [ + "serde", + "serde_derive", + "solana-address-lookup-table-interface 2.2.2", + "solana-clock 2.2.3", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-keccak-hasher 2.2.1", + "solana-message 2.4.0", + "solana-nonce 2.2.1", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", + "thiserror 2.0.18", +] + [[package]] name = "solana-example-mocks" version = "3.0.0" @@ -8036,19 +9217,38 @@ checksum = "978855d164845c1b0235d4b4d101cadc55373fffaf0b5b6cfa2194d25b2ed658" dependencies = [ "serde", "serde_derive", - "solana-address-lookup-table-interface", - "solana-clock", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-keccak-hasher", - "solana-message", - "solana-nonce", + "solana-instruction 3.4.0", + "solana-keccak-hasher 3.1.0", + "solana-message 3.1.0", + "solana-nonce 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 2.0.0", "thiserror 2.0.18", ] +[[package]] +name = "solana-feature-gate-interface" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f5c5382b449e8e4e3016fb05e418c53d57782d8b5c30aa372fc265654b956d" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account 2.2.1", + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", +] + [[package]] name = "solana-feature-gate-interface" version = "3.1.0" @@ -8058,13 +9258,13 @@ dependencies = [ "bincode", "serde", "serde_derive", - "solana-account", - "solana-account-info", - "solana-instruction", - "solana-program-error", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", "solana-pubkey 4.2.0", "solana-rent 4.2.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", ] @@ -8074,11 +9274,22 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0c7ab7f31d404a130c78c29a7a845cd599b2623fa335e5fcaef2bd7b3be83e6" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "solana-fee-structure", "solana-svm-transaction", ] +[[package]] +name = "solana-fee-calculator" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89bc408da0fb3812bc3008189d148b4d3e08252c79ad810b245482a3f70cd8d" +dependencies = [ + "log", + "serde", + "serde_derive", +] + [[package]] name = "solana-fee-calculator" version = "3.2.0" @@ -8122,21 +9333,21 @@ dependencies = [ "memmap2 0.5.10", "serde", "serde_derive", - "solana-account", - "solana-clock", + "solana-account 3.4.0", + "solana-clock 3.0.1", "solana-cluster-type 3.1.0", - "solana-epoch-schedule", - "solana-fee-calculator", + "solana-epoch-schedule 3.1.0", + "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-inflation", - "solana-keypair", + "solana-inflation 3.1.0", + "solana-keypair 3.1.2", "solana-poh-config", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-shred-version", - "solana-signer", + "solana-signer 3.0.0", "solana-time-utils 3.0.0", ] @@ -8156,8 +9367,13 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63" dependencies = [ + "borsh 1.6.0", + "bytemuck", + "bytemuck_derive", "five8 0.2.1", "js-sys", + "serde", + "serde_derive", "solana-atomic-u64 2.2.1", "solana-sanitize 2.2.1", "wasm-bindgen", @@ -8178,7 +9394,7 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8064ea1d591ec791be95245058ca40f4f5345d390c200069d0f79bbf55bfae55" dependencies = [ - "borsh", + "borsh 1.6.0", "bytemuck", "bytemuck_derive", "five8 1.0.0", @@ -8189,6 +9405,12 @@ dependencies = [ "wincode 0.4.4", ] +[[package]] +name = "solana-inflation" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23eef6a09eb8e568ce6839573e4966850e85e9ce71e6ae1a6c930c1c43947de3" + [[package]] name = "solana-inflation" version = "3.1.0" @@ -8199,6 +9421,25 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-instruction" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab5682934bd1f65f8d2c16f21cb532526fcc1a09f796e2cacdb091eee5774ad" +dependencies = [ + "bincode", + "borsh 1.6.0", + "getrandom 0.2.16", + "js-sys", + "num-traits", + "serde", + "serde_derive", + "serde_json", + "solana-define-syscall 2.3.0", + "solana-pubkey 2.4.0", + "wasm-bindgen", +] + [[package]] name = "solana-instruction" version = "3.4.0" @@ -8206,7 +9447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ebb0ffd19263051bc3f683fcc086134b8ff23af894dcb63f7563c7137b42f1" dependencies = [ "bincode", - "borsh", + "borsh 1.6.0", "serde", "serde_derive", "solana-define-syscall 5.0.0", @@ -8223,7 +9464,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-program-error", + "solana-program-error 3.0.0", ] [[package]] @@ -8235,7 +9476,24 @@ dependencies = [ "solana-account-view", "solana-address 2.6.0", "solana-define-syscall 4.0.1", - "solana-program-error", + "solana-program-error 3.0.0", +] + +[[package]] +name = "solana-instructions-sysvar" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0e85a6fad5c2d0c4f5b91d34b8ca47118fc593af706e523cdbedf846a954f57" +dependencies = [ + "bitflags 2.10.0", + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-serialize-utils 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -8245,15 +9503,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf67876c541aa1e21ee1acae35c95c6fbc61119814bfef70579317a5e26955" dependencies = [ "bitflags 2.10.0", - "solana-account-info", - "solana-instruction", + "solana-account-info 3.1.1", + "solana-instruction 3.4.0", "solana-instruction-error", - "solana-program-error", + "solana-program-error 3.0.0", "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-serialize-utils", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-serialize-utils 3.1.1", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-keccak-hasher" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" +dependencies = [ + "sha3", + "solana-define-syscall 2.3.0", + "solana-hash 2.3.0", + "solana-sanitize 2.2.1", ] [[package]] @@ -8267,6 +9537,22 @@ dependencies = [ "solana-hash 4.2.0", ] +[[package]] +name = "solana-keypair" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd3f04aa1a05c535e93e121a95f66e7dcccf57e007282e8255535d24bf1e98bb" +dependencies = [ + "ed25519-dalek 1.0.1", + "five8 0.2.1", + "rand 0.7.3", + "solana-pubkey 2.4.0", + "solana-seed-phrase 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "wasm-bindgen", +] + [[package]] name = "solana-keypair" version = "3.1.2" @@ -8279,11 +9565,24 @@ dependencies = [ "five8_core 1.0.0", "rand 0.9.2", "solana-address 2.6.0", - "solana-derivation-path", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-signature", - "solana-signer", + "solana-derivation-path 3.0.0", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", +] + +[[package]] +name = "solana-last-restart-slot" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a6360ac2fdc72e7463565cd256eedcf10d7ef0c28a1249d261ec168c1b55cdd" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -8294,9 +9593,9 @@ checksum = "dcda154ec827f5fc1e4da0af3417951b7e9b8157540f81f936c4a8b1156134d0" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -8311,6 +9610,20 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "solana-loader-v2-interface" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ab08006dad78ae7cd30df8eea0539e207d08d91eaefb3e1d49a446e1c49654" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", +] + [[package]] name = "solana-loader-v2-interface" version = "3.0.0" @@ -8320,9 +9633,24 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-loader-v3-interface" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f7162a05b8b0773156b443bccd674ea78bb9aa406325b467ea78c06c99a63a2" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", ] [[package]] @@ -8334,12 +9662,27 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 4.2.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", ] +[[package]] +name = "solana-loader-v4-interface" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "706a777242f1f39a83e2a96a2a6cb034cb41169c6ecbee2cf09cb873d9659e7e" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-system-interface 1.0.0", +] + [[package]] name = "solana-loader-v4-interface" version = "3.1.0" @@ -8349,9 +9692,9 @@ dependencies = [ "serde", "serde_bytes", "serde_derive", - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 2.0.0", ] @@ -8362,21 +9705,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e88b98ba6b408fe6fcf180784fc378d07ae63100c7dd413ff97474b6de30c5d" dependencies = [ "log", - "solana-account", - "solana-bincode", + "solana-account 3.4.0", + "solana-bincode 3.1.0", "solana-bpf-loader-program", - "solana-instruction", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-packet", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-sbpf", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-type-overrides", - "solana-transaction-context", + "solana-transaction-context 3.1.12", ] [[package]] @@ -8385,6 +9728,29 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de496c3f0e0cee33abd4ae958a8703e04ae1011f3c3e73b641bf319a18301c01" +[[package]] +name = "solana-message" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b" +dependencies = [ + "bincode", + "blake3", + "lazy_static", + "serde", + "serde_derive", + "solana-bincode 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-short-vec 2.2.1", + "solana-system-interface 1.0.0", + "solana-transaction-error 2.2.1", + "wasm-bindgen", +] + [[package]] name = "solana-message" version = "3.1.0" @@ -8398,11 +9764,11 @@ dependencies = [ "serde_derive", "solana-address 2.6.0", "solana-hash 4.2.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-short-vec", - "solana-transaction-error", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", + "solana-transaction-error 3.1.0", ] [[package]] @@ -8437,6 +9803,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "solana-msg" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092" +dependencies = [ + "solana-define-syscall 2.3.0", +] + [[package]] name = "solana-msg" version = "3.1.0" @@ -8446,6 +9821,12 @@ dependencies = [ "solana-define-syscall 5.0.0", ] +[[package]] +name = "solana-native-token" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61515b880c36974053dd499c0510066783f0cc6ac17def0c7ef2a244874cf4a9" + [[package]] name = "solana-native-token" version = "3.0.0" @@ -8481,6 +9862,20 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b8a731ed60e89177c8a7ab05fe0f1511cedd3e70e773f288f9de33a9cfdc21e" +[[package]] +name = "solana-nonce" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703e22eb185537e06204a5bd9d509b948f0066f2d1d814a6f475dafb3ddf1325" +dependencies = [ + "serde", + "serde_derive", + "solana-fee-calculator 2.2.1", + "solana-hash 2.3.0", + "solana-pubkey 2.4.0", + "solana-sha256-hasher 2.2.1", +] + [[package]] name = "solana-nonce" version = "3.1.0" @@ -8489,7 +9884,7 @@ checksum = "cbc469152a63284ef959b80c59cda015262a021da55d3b8fe42171d89c4b64f8" dependencies = [ "serde", "serde_derive", - "solana-fee-calculator", + "solana-fee-calculator 3.2.0", "solana-hash 4.2.0", "solana-pubkey 4.2.0", "solana-sha256-hasher 3.1.0", @@ -8501,10 +9896,19 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "805fd25b29e5a1a0e6c3dd6320c9da80f275fbe4ff6e392617c303a2085c435e" dependencies = [ - "solana-account", + "solana-account 3.4.0", "solana-hash 3.1.0", - "solana-nonce", - "solana-sdk-ids", + "solana-nonce 3.1.0", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-nostd-keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ced70920435b1baa58f76e6f84bbc1110ddd1d6161ec76b6d731ae8431e9c4" +dependencies = [ + "sha3", ] [[package]] @@ -8528,8 +9932,8 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", "solana-sha256-hasher 3.1.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", ] [[package]] @@ -8567,16 +9971,16 @@ dependencies = [ "rayon", "serde", "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-metrics 3.1.12", "solana-packet", "solana-pubkey 3.0.0", "solana-rayon-threadlimit", - "solana-sdk-ids", - "solana-short-vec", - "solana-signature", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", + "solana-signature 3.4.0", "solana-time-utils 3.0.0", - "solana-transaction-context", + "solana-transaction-context 3.1.12", ] [[package]] @@ -8619,8 +10023,88 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f704eaf825be3180832445b9e4983b875340696e8e7239bf2d535b0f86c14a2" dependencies = [ "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", +] + +[[package]] +name = "solana-program" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98eca145bd3545e2fbb07166e895370576e47a00a7d824e325390d33bf467210" +dependencies = [ + "bincode", + "blake3", + "borsh 0.10.4", + "borsh 1.6.0", + "bs58", + "bytemuck", + "console_error_panic_hook", + "console_log", + "getrandom 0.2.16", + "lazy_static", + "log", + "memoffset", + "num-bigint 0.4.6", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info 2.3.0", + "solana-address-lookup-table-interface 2.2.2", + "solana-atomic-u64 2.2.1", + "solana-big-mod-exp 2.2.1", + "solana-bincode 2.2.1", + "solana-blake3-hasher 2.2.1", + "solana-borsh 2.2.1", + "solana-clock 2.2.3", + "solana-cpi 2.2.1", + "solana-decode-error", + "solana-define-syscall 2.3.0", + "solana-epoch-rewards 2.2.1", + "solana-epoch-schedule 2.2.1", + "solana-example-mocks 2.2.1", + "solana-feature-gate-interface 2.2.2", + "solana-fee-calculator 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-keccak-hasher 2.2.1", + "solana-last-restart-slot 2.2.1", + "solana-loader-v2-interface 2.2.1", + "solana-loader-v3-interface 5.0.0", + "solana-loader-v4-interface 2.2.1", + "solana-message 2.4.0", + "solana-msg 2.2.1", + "solana-native-token 2.3.0", + "solana-nonce 2.2.1", + "solana-program-entrypoint 2.3.0", + "solana-program-error 2.2.2", + "solana-program-memory 2.3.1", + "solana-program-option 2.2.1", + "solana-program-pack 2.2.1", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-secp256k1-recover 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-slot-hashes 2.2.1", + "solana-slot-history 2.2.1", + "solana-stable-layout 2.2.1", + "solana-stake-interface 1.2.1", + "solana-system-interface 1.0.0", + "solana-sysvar 2.3.0", + "solana-sysvar-id 2.2.1", + "solana-vote-interface 2.2.6", + "thiserror 2.0.18", + "wasm-bindgen", ] [[package]] @@ -8630,44 +10114,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91b12305dd81045d705f427acd0435a2e46444b65367d7179d7bdcfc3bc5f5eb" dependencies = [ "memoffset", - "solana-account-info", - "solana-big-mod-exp", - "solana-blake3-hasher", - "solana-borsh", - "solana-clock", - "solana-cpi", + "solana-account-info 3.1.1", + "solana-big-mod-exp 3.0.0", + "solana-blake3-hasher 3.1.0", + "solana-borsh 3.0.2", + "solana-clock 3.0.1", + "solana-cpi 3.1.0", "solana-define-syscall 3.0.0", - "solana-epoch-rewards", - "solana-epoch-schedule", + "solana-epoch-rewards 3.0.1", + "solana-epoch-schedule 3.1.0", "solana-epoch-stake", - "solana-example-mocks", - "solana-fee-calculator", + "solana-example-mocks 3.0.0", + "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-instruction-error", - "solana-instructions-sysvar", - "solana-keccak-hasher", - "solana-last-restart-slot", - "solana-msg", - "solana-native-token", - "solana-program-entrypoint", - "solana-program-error", - "solana-program-memory", - "solana-program-option", - "solana-program-pack", + "solana-instructions-sysvar 3.0.0", + "solana-keccak-hasher 3.1.0", + "solana-last-restart-slot 3.0.0", + "solana-msg 3.1.0", + "solana-native-token 3.0.0", + "solana-program-entrypoint 3.1.1", + "solana-program-error 3.0.0", + "solana-program-memory 3.1.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-secp256k1-recover", - "solana-serde-varint", - "solana-serialize-utils", + "solana-sdk-ids 3.1.0", + "solana-secp256k1-recover 3.1.1", + "solana-serde-varint 3.0.1", + "solana-serialize-utils 3.1.1", "solana-sha256-hasher 3.1.0", - "solana-short-vec", - "solana-slot-hashes", - "solana-slot-history", - "solana-stable-layout", - "solana-sysvar", - "solana-sysvar-id", + "solana-short-vec 3.2.0", + "solana-slot-hashes 3.0.1", + "solana-slot-history 3.0.0", + "solana-stable-layout 3.0.1", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -8678,12 +10162,24 @@ checksum = "68d372660fc5c61b691279bcecb4bf92fa1a7cba3b357ef209404f425dafd394" dependencies = [ "bincode", "serde", - "solana-account", - "solana-loader-v3-interface", + "solana-account 3.4.0", + "solana-loader-v3-interface 6.1.1", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "spl-generic-token", + "solana-sdk-ids 3.1.0", + "spl-generic-token 2.0.1", +] + +[[package]] +name = "solana-program-entrypoint" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ce041b1a0ed275290a5008ee1a4a6c48f5054c8a3d78d313c08958a06aedbd" +dependencies = [ + "solana-account-info 2.3.0", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", ] [[package]] @@ -8692,23 +10188,48 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c9b0a1ff494e05f503a08b3d51150b73aa639544631e510279d6375f290997" dependencies = [ - "solana-account-info", + "solana-account-info 3.1.1", "solana-define-syscall 4.0.1", - "solana-program-error", + "solana-program-error 3.0.0", "solana-pubkey 4.2.0", ] +[[package]] +name = "solana-program-error" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" +dependencies = [ + "borsh 1.6.0", + "num-traits", + "serde", + "serde_derive", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-pubkey 2.4.0", +] + [[package]] name = "solana-program-error" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1af32c995a7b692a915bb7414d5f8e838450cf7c70414e763d8abcae7b51f28" dependencies = [ - "borsh", + "borsh 1.6.0", "serde", "serde_derive", ] +[[package]] +name = "solana-program-memory" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a5426090c6f3fd6cfdc10685322fede9ca8e5af43cd6a59e98bfe4e91671712" +dependencies = [ + "solana-define-syscall 2.3.0", +] + [[package]] name = "solana-program-memory" version = "3.1.0" @@ -8718,25 +10239,40 @@ dependencies = [ "solana-define-syscall 4.0.1", ] +[[package]] +name = "solana-program-option" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc677a2e9bc616eda6dbdab834d463372b92848b2bfe4a1ed4e4b4adba3397d0" + [[package]] name = "solana-program-option" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a88006a9b8594088cec9027ab77caaaa258a2aaa2083d3f086c44b42e50aeab" +[[package]] +name = "solana-program-pack" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "319f0ef15e6e12dc37c597faccb7d62525a509fec5f6975ecb9419efddeb277b" +dependencies = [ + "solana-program-error 2.2.2", +] + [[package]] name = "solana-program-pack" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7701cb15b90667ae1c89ef4ac35a59c61e66ce58ddee13d729472af7f41d59" dependencies = [ - "solana-program-error", + "solana-program-error 3.0.0", ] [[package]] name = "solana-program-runtime" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "base64 0.22.1", "bincode", @@ -8745,35 +10281,35 @@ dependencies = [ "percentage", "rand 0.8.5", "serde", - "solana-account", - "solana-account-info", - "solana-clock", - "solana-epoch-rewards", - "solana-epoch-schedule", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", + "solana-epoch-rewards 3.0.1", + "solana-epoch-schedule 3.1.0", "solana-fee-structure", "solana-hash 3.1.0", - "solana-instruction", - "solana-last-restart-slot", - "solana-loader-v3-interface", - "solana-program-entrypoint", + "solana-instruction 3.4.0", + "solana-last-restart-slot 3.0.0", + "solana-loader-v3-interface 6.1.1", + "solana-program-entrypoint 3.1.1", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", - "solana-sdk-ids", - "solana-slot-hashes", - "solana-stable-layout", - "solana-stake-interface", + "solana-sdk-ids 3.1.0", + "solana-slot-hashes 3.0.1", + "solana-stable-layout 3.0.1", + "solana-stake-interface 2.0.2", "solana-svm-callback", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-timings", "solana-svm-transaction", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-sysvar", - "solana-sysvar-id", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", ] @@ -8783,7 +10319,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3848324dae946ff709b78cf5599fc5fa17fb1877cf5c98e8167e2e0fd9e1990f" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "agave-logger", "assert_matches", "async-trait", @@ -8793,55 +10329,81 @@ dependencies = [ "crossbeam-channel", "log", "serde", - "solana-account", - "solana-account-info", + "solana-account 3.4.0", + "solana-account-info 3.1.1", "solana-accounts-db", "solana-banks-client", "solana-banks-interface", "solana-banks-server", - "solana-clock", + "solana-clock 3.0.1", "solana-cluster-type 3.1.0", - "solana-commitment-config", + "solana-commitment-config 3.1.1", "solana-compute-budget", - "solana-epoch-rewards", - "solana-epoch-schedule", - "solana-fee-calculator", + "solana-epoch-rewards 3.0.1", + "solana-epoch-schedule 3.1.0", + "solana-fee-calculator 3.2.0", "solana-genesis-config", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", - "solana-loader-v3-interface", - "solana-message", - "solana-msg", - "solana-native-token", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-loader-v3-interface 6.1.1", + "solana-message 3.1.0", + "solana-msg 3.1.0", + "solana-native-token 3.0.0", "solana-poh-config", "solana-program-binaries", - "solana-program-entrypoint", - "solana-program-error", + "solana-program-entrypoint 3.1.1", + "solana-program-error 3.0.0", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-runtime", "solana-sbpf", - "solana-sdk-ids", - "solana-signer", - "solana-stable-layout", - "solana-stake-interface", + "solana-sdk-ids 3.1.0", + "solana-signer 3.0.0", + "solana-stable-layout 3.0.1", + "solana-stake-interface 2.0.2", "solana-svm", "solana-svm-log-collector", "solana-svm-timings", "solana-system-interface 2.0.0", - "solana-sysvar", - "solana-sysvar-id", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "solana-vote-program", - "spl-generic-token", + "spl-generic-token 2.0.1", "thiserror 2.0.18", "tokio", ] +[[package]] +name = "solana-pubkey" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1" +dependencies = [ + "borsh 0.10.4", + "borsh 1.6.0", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "five8 0.2.1", + "five8_const 0.1.4", + "getrandom 0.2.16", + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-atomic-u64 2.2.1", + "solana-decode-error", + "solana-define-syscall 2.3.0", + "solana-sanitize 2.2.1", + "solana-sha256-hasher 2.2.1", + "wasm-bindgen", +] + [[package]] name = "solana-pubkey" version = "3.0.0" @@ -8874,11 +10436,11 @@ dependencies = [ "semver", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-clock", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.0.1", "solana-pubkey 3.0.0", - "solana-rpc-client-types", - "solana-signature", + "solana-rpc-client-types 3.1.12", + "solana-signature 3.4.0", "thiserror 2.0.18", "tokio", "tokio-stream", @@ -8902,17 +10464,17 @@ dependencies = [ "log", "rustls 0.23.35", "solana-connection-cache", - "solana-keypair", + "solana-keypair 3.1.2", "solana-measure", "solana-metrics 3.1.12", "solana-net-utils", "solana-pubkey 3.0.0", "solana-quic-definitions", - "solana-rpc-client-api", - "solana-signer", + "solana-rpc-client-api 3.1.12", + "solana-signer 3.0.0", "solana-streamer", "solana-tls-utils", - "solana-transaction-error", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", ] @@ -8923,7 +10485,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15319accf7d3afd845817aeffa6edd8cc185f135cefbc6b985df29cfd8c09609" dependencies = [ - "solana-keypair", + "solana-keypair 3.1.2", ] [[package]] @@ -8936,6 +10498,19 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "solana-rent" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1aea8fdea9de98ca6e8c2da5827707fb3842833521b528a713810ca685d2480" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-sysvar-id 2.2.1", +] + [[package]] name = "solana-rent" version = "3.1.0" @@ -8944,9 +10519,9 @@ checksum = "e860d5499a705369778647e97d760f7670adfb6fc8419dd3d568deccd46d5487" dependencies = [ "serde", "serde_derive", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -8955,7 +10530,17 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9809b081e99bc142ce803bcd7ee18306759ce3b30a96a9da3f6f41c45e50ef0" dependencies = [ - "solana-sdk-macro", + "solana-sdk-macro 3.0.1", +] + +[[package]] +name = "solana-reward-info" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18205b69139b1ae0ab8f6e11cdcb627328c0814422ad2482000fa2ca54ae4a2f" +dependencies = [ + "serde", + "serde_derive", ] [[package]] @@ -8968,6 +10553,46 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-rpc-client" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d3161ac0918178e674c1f7f1bfac40de3e7ed0383bd65747d63113c156eaeb" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bincode", + "bs58", + "futures", + "indicatif 0.17.11", + "log", + "reqwest 0.12.28", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account 2.2.1", + "solana-account-decoder-client-types 2.3.13", + "solana-clock 2.2.3", + "solana-commitment-config 2.2.1", + "solana-epoch-info 2.2.1", + "solana-epoch-schedule 2.2.1", + "solana-feature-gate-interface 2.2.2", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-message 2.4.0", + "solana-pubkey 2.4.0", + "solana-rpc-client-api 2.3.13", + "solana-signature 2.3.0", + "solana-transaction 2.2.3", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "solana-version 2.3.13", + "solana-vote-interface 2.2.6", + "tokio", +] + [[package]] name = "solana-rpc-client" version = "3.1.12" @@ -8979,35 +10604,57 @@ dependencies = [ "bincode", "bs58", "futures", - "indicatif", + "indicatif 0.18.4", "log", "reqwest 0.12.28", "reqwest-middleware", "semver", "serde", "serde_json", - "solana-account", + "solana-account 3.4.0", "solana-account-decoder", - "solana-account-decoder-client-types", - "solana-clock", - "solana-commitment-config", - "solana-epoch-info", - "solana-epoch-schedule", - "solana-feature-gate-interface", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-epoch-info 3.1.0", + "solana-epoch-schedule 3.1.0", + "solana-feature-gate-interface 3.1.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-message", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client-api", - "solana-signature", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", - "solana-version", - "solana-vote-interface", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", + "solana-version 3.1.12", + "solana-vote-interface 4.0.4", "tokio", ] +[[package]] +name = "solana-rpc-client-api" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dbc138685c79d88a766a8fd825057a74ea7a21e1dd7f8de275ada899540fff7" +dependencies = [ + "anyhow", + "jsonrpc-core", + "reqwest 0.12.28", + "reqwest-middleware", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types 2.3.13", + "solana-clock 2.2.3", + "solana-rpc-client-types 2.3.13", + "solana-signer 2.2.1", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "thiserror 2.0.18", +] + [[package]] name = "solana-rpc-client-api" version = "3.1.12" @@ -9020,12 +10667,12 @@ dependencies = [ "reqwest-middleware", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-clock", - "solana-rpc-client-types", - "solana-signer", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.0.1", + "solana-rpc-client-types 3.1.12", + "solana-signer 3.0.0", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", "thiserror 2.0.18", ] @@ -9035,14 +10682,40 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1fc7c6ad3eb7df35a1f97c820003439334ee0d5944b155e9cb78bf9e0ecce36" dependencies = [ - "solana-account", - "solana-commitment-config", + "solana-account 3.4.0", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", - "solana-message", - "solana-nonce", + "solana-message 3.1.0", + "solana-nonce 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-sdk-ids", + "solana-rpc-client 3.1.12", + "solana-sdk-ids 3.1.0", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-rpc-client-types" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea428a81729255d895ea47fba9b30fd4dacbfe571a080448121bd0592751676" +dependencies = [ + "base64 0.22.1", + "bs58", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account 2.2.1", + "solana-account-decoder-client-types 2.3.13", + "solana-clock 2.2.3", + "solana-commitment-config 2.2.1", + "solana-fee-calculator 2.2.1", + "solana-inflation 2.2.1", + "solana-pubkey 2.4.0", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "solana-version 2.3.13", + "spl-generic-token 1.0.1", "thiserror 2.0.18", ] @@ -9057,19 +10730,19 @@ dependencies = [ "semver", "serde", "serde_json", - "solana-account", - "solana-account-decoder-client-types", + "solana-account 3.4.0", + "solana-account-decoder-client-types 3.1.12", "solana-address 1.1.0", - "solana-clock", - "solana-commitment-config", - "solana-fee-calculator", - "solana-inflation", - "solana-reward-info", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", - "solana-version", - "spl-generic-token", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", + "solana-fee-calculator 3.2.0", + "solana-inflation 3.1.0", + "solana-reward-info 3.0.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", + "solana-version 3.1.12", + "spl-generic-token 2.0.1", "thiserror 2.0.18", ] @@ -9079,7 +10752,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eb482d0c82ee826621758e7fdba331cd78857a94107247a2674216abb4ff808" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "agave-fs", "agave-precompiles", "agave-reserved-account-keys", @@ -9121,47 +10794,47 @@ dependencies = [ "serde", "serde_json", "serde_with", - "solana-account", - "solana-account-info", + "solana-account 3.4.0", + "solana-account-info 3.1.1", "solana-accounts-db", - "solana-address-lookup-table-interface", + "solana-address-lookup-table-interface 3.1.0", "solana-bls-signatures", "solana-bpf-loader-program", "solana-bucket-map", "solana-builtins", "solana-client-traits", - "solana-clock", + "solana-clock 3.0.1", "solana-cluster-type 3.1.0", - "solana-commitment-config", + "solana-commitment-config 3.1.1", "solana-compute-budget", "solana-compute-budget-instruction", - "solana-compute-budget-interface", + "solana-compute-budget-interface 3.0.0", "solana-config-interface", "solana-cost-model", - "solana-cpi", + "solana-cpi 3.1.0", "solana-ed25519-program", - "solana-epoch-info", + "solana-epoch-info 3.1.0", "solana-epoch-rewards-hasher", - "solana-epoch-schedule", - "solana-feature-gate-interface", + "solana-epoch-schedule 3.1.0", + "solana-feature-gate-interface 3.1.0", "solana-fee", - "solana-fee-calculator", + "solana-fee-calculator 3.2.0", "solana-fee-structure", "solana-genesis-config", "solana-hard-forks", "solana-hash 3.1.0", - "solana-inflation", - "solana-instruction", - "solana-keypair", + "solana-inflation 3.1.0", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", "solana-lattice-hash", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-measure", - "solana-message", + "solana-message 3.1.0", "solana-metrics 3.1.12", - "solana-native-token", + "solana-native-token 3.0.0", "solana-nohash-hasher", - "solana-nonce", + "solana-nonce 3.1.0", "solana-nonce-account", "solana-packet", "solana-perf", @@ -9171,37 +10844,37 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-rayon-threadlimit", "solana-rent 3.1.0", - "solana-reward-info", + "solana-reward-info 3.0.0", "solana-runtime-transaction", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-secp256k1-program", - "solana-seed-derivable", + "solana-seed-derivable 3.0.0", "solana-serde", "solana-sha256-hasher 3.1.0", - "solana-signature", - "solana-signer", - "solana-slot-hashes", - "solana-slot-history", - "solana-stake-interface", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-slot-hashes 3.0.1", + "solana-slot-history 3.0.0", + "solana-stake-interface 2.0.2", "solana-svm", "solana-svm-callback", "solana-svm-timings", "solana-svm-transaction", "solana-system-interface 2.0.0", "solana-system-transaction", - "solana-sysvar", - "solana-sysvar-id", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", "solana-time-utils 3.0.0", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", "solana-unified-scheduler-logic", - "solana-version", + "solana-version 3.1.12", "solana-vote", - "solana-vote-interface", + "solana-vote-interface 4.0.4", "solana-vote-program", - "spl-generic-token", + "spl-generic-token 2.0.1", "static_assertions", "strum 0.24.1", "strum_macros 0.24.3", @@ -9221,14 +10894,14 @@ dependencies = [ "solana-compute-budget", "solana-compute-budget-instruction", "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-signature", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", "solana-svm-transaction", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", ] @@ -9270,35 +10943,44 @@ dependencies = [ "bincode", "bs58", "serde", - "solana-account", - "solana-epoch-info", + "solana-account 3.4.0", + "solana-epoch-info 3.1.0", "solana-epoch-rewards-hasher", "solana-fee-structure", - "solana-inflation", - "solana-keypair", - "solana-message", + "solana-inflation 3.1.0", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-offchain-message", "solana-presigner", - "solana-program", - "solana-program-memory", + "solana-program 3.0.0", + "solana-program-memory 3.1.0", "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-seed-derivable", - "solana-seed-phrase", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", "solana-serde", - "solana-serde-varint", - "solana-short-vec", + "solana-serde-varint 3.0.1", + "solana-short-vec 3.2.0", "solana-shred-version", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-time-utils 3.0.0", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", ] +[[package]] +name = "solana-sdk-ids" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5d8b9cc68d5c88b062a33e23a6466722467dde0035152d8fb1afbcdf350a5f" +dependencies = [ + "solana-pubkey 2.4.0", +] + [[package]] name = "solana-sdk-ids" version = "3.1.0" @@ -9308,6 +10990,18 @@ dependencies = [ "solana-address 2.6.0", ] +[[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", + "quote", + "syn 2.0.117", +] + [[package]] name = "solana-sdk-macro" version = "3.0.1" @@ -9331,7 +11025,18 @@ dependencies = [ "serde", "serde_derive", "sha3", - "solana-signature", + "solana-signature 3.4.0", +] + +[[package]] +name = "solana-secp256k1-recover" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" +dependencies = [ + "libsecp256k1", + "solana-define-syscall 2.3.0", + "thiserror 2.0.18", ] [[package]] @@ -9353,8 +11058,26 @@ checksum = "445d8e12592631d76fc4dc57858bae66c9fd7cc838c306c62a472547fc9d0ce6" dependencies = [ "bytemuck", "openssl", - "solana-instruction", - "solana-sdk-ids", + "solana-instruction 3.4.0", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-security-txt" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "156bb61a96c605fa124e052d630dba2f6fb57e08c7d15b757e1e958b3ed7b3fe" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "solana-seed-derivable" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beb82b5adb266c6ea90e5cf3967235644848eac476c5a1f2f9283a143b7c97f" +dependencies = [ + "solana-derivation-path 2.2.1", ] [[package]] @@ -9363,7 +11086,18 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff7bdb72758e3bec33ed0e2658a920f1f35dfb9ed576b951d20d63cb61ecd95c" dependencies = [ - "solana-derivation-path", + "solana-derivation-path 3.0.0", +] + +[[package]] +name = "solana-seed-phrase" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36187af2324f079f65a675ec22b31c24919cb4ac22c79472e85d819db9bbbc15" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "sha2 0.10.9", ] [[package]] @@ -9388,17 +11122,17 @@ dependencies = [ "itertools 0.12.1", "log", "solana-client", - "solana-clock", + "solana-clock 3.0.1", "solana-connection-cache", "solana-hash 3.1.0", - "solana-keypair", + "solana-keypair 3.1.2", "solana-measure", "solana-metrics 3.1.12", "solana-nonce-account", "solana-pubkey 3.0.0", "solana-quic-definitions", "solana-runtime", - "solana-signature", + "solana-signature 3.4.0", "solana-time-utils 3.0.0", "solana-tpu-client-next", "tokio", @@ -9414,6 +11148,15 @@ dependencies = [ "serde", ] +[[package]] +name = "solana-serde-varint" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7e155eba458ecfb0107b98236088c3764a09ddf0201ec29e52a0be40857113" +dependencies = [ + "serde", +] + [[package]] name = "solana-serde-varint" version = "3.0.1" @@ -9423,6 +11166,17 @@ dependencies = [ "serde", ] +[[package]] +name = "solana-serialize-utils" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "817a284b63197d2b27afdba829c5ab34231da4a9b4e763466a003c40ca4f535e" +dependencies = [ + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", +] + [[package]] name = "solana-serialize-utils" version = "3.1.1" @@ -9456,6 +11210,15 @@ dependencies = [ "solana-hash 4.2.0", ] +[[package]] +name = "solana-short-vec" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c54c66f19b9766a56fa0057d060de8378676cb64987533fa088861858fc5a69" +dependencies = [ + "serde", +] + [[package]] name = "solana-short-vec" version = "3.2.0" @@ -9476,6 +11239,20 @@ dependencies = [ "solana-sha256-hasher 3.1.0", ] +[[package]] +name = "solana-signature" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c" +dependencies = [ + "ed25519-dalek 1.0.1", + "five8 0.2.1", + "serde", + "serde-big-array", + "serde_derive", + "solana-sanitize 2.2.1", +] + [[package]] name = "solana-signature" version = "3.4.0" @@ -9492,6 +11269,17 @@ dependencies = [ "wincode 0.5.1", ] +[[package]] +name = "solana-signer" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c41991508a4b02f021c1342ba00bcfa098630b213726ceadc7cb032e051975b" +dependencies = [ + "solana-pubkey 2.4.0", + "solana-signature 2.3.0", + "solana-transaction-error 2.2.1", +] + [[package]] name = "solana-signer" version = "3.0.0" @@ -9499,8 +11287,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bfea97951fee8bae0d6038f39a5efcb6230ecdfe33425ac75196d1a1e3e3235" dependencies = [ "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-transaction-error 3.1.0", +] + +[[package]] +name = "solana-slot-hashes" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce" +dependencies = [ + "serde", + "serde_derive", + "solana-hash 2.3.0", + "solana-sdk-ids 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -9512,8 +11313,21 @@ dependencies = [ "serde", "serde_derive", "solana-hash 4.2.0", - "solana-sdk-ids", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-slot-history" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ccc1b2067ca22754d5283afb2b0126d61eae734fc616d23871b0943b0d935e" +dependencies = [ + "bv", + "serde", + "serde_derive", + "solana-sdk-ids 2.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -9525,8 +11339,18 @@ dependencies = [ "bv", "serde", "serde_derive", - "solana-sdk-ids", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-stable-layout" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f14f7d02af8f2bc1b5efeeae71bc1c2b7f0f65cd75bcc7d8180f2c762a57f54" +dependencies = [ + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", ] [[package]] @@ -9535,10 +11359,31 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9f6a291ba063a37780af29e7db14bdd3dc447584d8ba5b3fc4b88e2bbc982fa" dependencies = [ - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 4.2.0", ] +[[package]] +name = "solana-stake-interface" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c" +dependencies = [ + "borsh 0.10.4", + "borsh 1.6.0", + "num-traits", + "serde", + "serde_derive", + "solana-clock 2.2.3", + "solana-cpi 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-system-interface 1.0.0", + "solana-sysvar-id 2.2.1", +] + [[package]] name = "solana-stake-interface" version = "2.0.2" @@ -9548,14 +11393,14 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-clock", - "solana-cpi", - "solana-instruction", - "solana-program-error", + "solana-clock 3.0.1", + "solana-cpi 3.1.0", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", "solana-pubkey 3.0.0", "solana-system-interface 2.0.0", - "solana-sysvar", - "solana-sysvar-id", + "solana-sysvar 3.1.1", + "solana-sysvar-id 3.1.0", ] [[package]] @@ -9569,12 +11414,12 @@ dependencies = [ "serde", "solana-account-decoder", "solana-hash 3.1.0", - "solana-instruction", - "solana-message", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signature", - "solana-transaction", - "solana-transaction-error", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "solana-transaction-status", "tonic-prost-build", ] @@ -9607,7 +11452,7 @@ dependencies = [ "rustls 0.23.35", "smallvec", "socket2 0.6.1", - "solana-keypair", + "solana-keypair 3.1.2", "solana-measure", "solana-metrics 3.1.12", "solana-net-utils", @@ -9615,11 +11460,11 @@ dependencies = [ "solana-perf", "solana-pubkey 3.0.0", "solana-quic-definitions", - "solana-signature", - "solana-signer", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-time-utils 3.0.0", "solana-tls-utils", - "solana-transaction-error", + "solana-transaction-error 3.1.0", "solana-transaction-metrics-tracker", "thiserror 2.0.18", "tokio", @@ -9630,43 +11475,43 @@ dependencies = [ [[package]] name = "solana-svm" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "ahash 0.8.12", "log", "percentage", "qualifier_attr", "serde", - "solana-account", - "solana-clock", + "solana-account 3.4.0", + "solana-clock 3.0.1", "solana-fee-structure", "solana-hash 3.1.0", - "solana-instruction", - "solana-instructions-sysvar", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-instruction 3.4.0", + "solana-instructions-sysvar 3.0.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-loader-v4-program", - "solana-message", - "solana-nonce", + "solana-message 3.1.0", + "solana-nonce 3.1.0", "solana-nonce-account", - "solana-program-entrypoint", - "solana-program-pack", + "solana-program-entrypoint 3.1.1", + "solana-program-pack 3.1.0", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-callback", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-timings", "solana-svm-transaction", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-sysvar-id", - "solana-transaction-context", - "solana-transaction-error", - "spl-generic-token", + "solana-sysvar-id 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", + "spl-generic-token 2.0.1", "thiserror 2.0.18", ] @@ -9676,12 +11521,18 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb521c7f62db21661267a933f0d311a76b2b744a766b46f5a9a9395ce70f687c" dependencies = [ - "solana-account", - "solana-clock", + "solana-account 3.4.0", + "solana-clock 3.0.1", "solana-precompile-error", "solana-pubkey 3.0.0", ] +[[package]] +name = "solana-svm-feature-set" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f24b836eb4d74ec255217bdbe0f24f64a07adeac31aca61f334f91cd4a3b1d5" + [[package]] name = "solana-svm-feature-set" version = "3.1.12" @@ -9721,11 +11572,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ef6ff55ce4c24e26ad8b0e67bc604cbd54eabfc94540c4c2c93e51fa087ead5" dependencies = [ "solana-hash 3.1.0", - "solana-message", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-signature", - "solana-transaction", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", ] [[package]] @@ -9737,6 +11588,22 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "solana-system-interface" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d7c18cb1a91c6be5f5a8ac9276a1d7c737e39a21beba9ea710ab4b9c63bc90" +dependencies = [ + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "wasm-bindgen", +] + [[package]] name = "solana-system-interface" version = "2.0.0" @@ -9746,9 +11613,9 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-instruction", - "solana-msg", - "solana-program-error", + "solana-instruction 3.4.0", + "solana-msg 3.1.0", + "solana-program-error 3.0.0", "solana-pubkey 3.0.0", ] @@ -9762,9 +11629,9 @@ dependencies = [ "serde", "serde_derive", "solana-address 2.6.0", - "solana-instruction", - "solana-msg", - "solana-program-error", + "solana-instruction 3.4.0", + "solana-msg 3.1.0", + "solana-program-error 3.0.0", ] [[package]] @@ -9776,21 +11643,21 @@ dependencies = [ "bincode", "log", "serde", - "solana-account", - "solana-bincode", - "solana-fee-calculator", - "solana-instruction", - "solana-nonce", + "solana-account 3.4.0", + "solana-bincode 3.1.0", + "solana-fee-calculator 3.2.0", + "solana-instruction 3.4.0", + "solana-nonce 3.1.0", "solana-nonce-account", "solana-packet", "solana-program-runtime", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-log-collector", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-sysvar", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-transaction-context 3.1.12", ] [[package]] @@ -9800,12 +11667,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31b5699ec533621515e714f1533ee6b3b0e71c463301d919eb59b8c1e249d30" dependencies = [ "solana-hash 3.1.0", - "solana-keypair", - "solana-message", + "solana-keypair 3.1.2", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-signer", + "solana-signer 3.0.0", "solana-system-interface 2.0.0", - "solana-transaction", + "solana-transaction 3.1.0", +] + +[[package]] +name = "solana-sysvar" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8c3595f95069f3d90f275bb9bd235a1973c4d059028b0a7f81baca2703815db" +dependencies = [ + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "lazy_static", + "serde", + "serde_derive", + "solana-account-info 2.3.0", + "solana-clock 2.2.3", + "solana-define-syscall 2.3.0", + "solana-epoch-rewards 2.2.1", + "solana-epoch-schedule 2.2.1", + "solana-fee-calculator 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-last-restart-slot 2.2.1", + "solana-program-entrypoint 2.3.0", + "solana-program-error 2.2.2", + "solana-program-memory 2.3.1", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-sdk-macro 2.2.1", + "solana-slot-hashes 2.2.1", + "solana-slot-history 2.2.1", + "solana-stake-interface 1.2.1", + "solana-sysvar-id 2.2.1", ] [[package]] @@ -9821,25 +11725,35 @@ dependencies = [ "lazy_static", "serde", "serde_derive", - "solana-account-info", - "solana-clock", + "solana-account-info 3.1.1", + "solana-clock 3.0.1", "solana-define-syscall 4.0.1", - "solana-epoch-rewards", - "solana-epoch-schedule", - "solana-fee-calculator", + "solana-epoch-rewards 3.0.1", + "solana-epoch-schedule 3.1.0", + "solana-fee-calculator 3.2.0", "solana-hash 4.2.0", - "solana-instruction", - "solana-last-restart-slot", - "solana-program-entrypoint", - "solana-program-error", - "solana-program-memory", + "solana-instruction 3.4.0", + "solana-last-restart-slot 3.0.0", + "solana-program-entrypoint 3.1.1", + "solana-program-error 3.0.0", + "solana-program-memory 3.1.0", "solana-pubkey 4.2.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-sdk-macro", - "solana-slot-hashes", - "solana-slot-history", - "solana-sysvar-id", + "solana-sdk-ids 3.1.0", + "solana-sdk-macro 3.0.1", + "solana-slot-hashes 3.0.1", + "solana-slot-history 3.0.0", + "solana-sysvar-id 3.1.0", +] + +[[package]] +name = "solana-sysvar-id" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5762b273d3325b047cfda250787f8d796d781746860d5d0a746ee29f3e8812c1" +dependencies = [ + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", ] [[package]] @@ -9849,7 +11763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17358d1e9a13e5b9c2264d301102126cf11a47fd394cdf3dec174fe7bc96e1de" dependencies = [ "solana-address 2.6.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", ] [[package]] @@ -9871,9 +11785,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57a74352404ca3378d3bc6586a9a1e0d7362b687ce2218a0b646dccb767c7ba2" dependencies = [ "rustls 0.23.35", - "solana-keypair", + "solana-keypair 3.1.2", "solana-pubkey 3.0.0", - "solana-signer", + "solana-signer 3.0.0", "x509-parser", ] @@ -9887,26 +11801,26 @@ dependencies = [ "bincode", "futures-util", "indexmap 2.12.1", - "indicatif", + "indicatif 0.18.4", "log", "rayon", "solana-client-traits", - "solana-clock", - "solana-commitment-config", + "solana-clock 3.0.1", + "solana-commitment-config 3.1.1", "solana-connection-cache", - "solana-epoch-schedule", + "solana-epoch-schedule 3.1.0", "solana-measure", - "solana-message", + "solana-message 3.1.0", "solana-net-utils", "solana-pubkey 3.0.0", "solana-pubsub-client", "solana-quic-definitions", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-signer", - "solana-transaction", - "solana-transaction-error", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", ] @@ -9922,13 +11836,13 @@ dependencies = [ "log", "lru 0.7.8", "rustls 0.23.35", - "solana-clock", + "solana-clock 3.0.1", "solana-connection-cache", - "solana-keypair", + "solana-keypair 3.1.2", "solana-measure", "solana-metrics 3.1.12", "solana-quic-definitions", - "solana-rpc-client", + "solana-rpc-client 3.1.12", "solana-streamer", "solana-time-utils 3.0.0", "solana-tls-utils", @@ -9938,6 +11852,31 @@ dependencies = [ "tokio-util 0.7.17", ] +[[package]] +name = "solana-transaction" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80657d6088f721148f5d889c828ca60c7daeedac9a8679f9ec215e0c42bcbf41" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-bincode 2.2.1", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-keypair 2.2.3", + "solana-message 2.4.0", + "solana-pubkey 2.4.0", + "solana-sanitize 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-short-vec 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "solana-system-interface 1.0.0", + "solana-transaction-error 2.2.1", + "wasm-bindgen", +] + [[package]] name = "solana-transaction" version = "3.1.0" @@ -9949,32 +11888,61 @@ dependencies = [ "serde_derive", "solana-address 2.6.0", "solana-hash 4.2.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-instruction-error", - "solana-message", + "solana-message 3.1.0", "solana-sanitize 3.0.1", - "solana-sdk-ids", - "solana-short-vec", - "solana-signature", - "solana-signer", - "solana-transaction-error", + "solana-sdk-ids 3.1.0", + "solana-short-vec 3.2.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction-error 3.1.0", +] + +[[package]] +name = "solana-transaction-context" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a312304361987a85b2ef2293920558e6612876a639dd1309daf6d0d59ef2fe" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account 2.2.1", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sdk-ids 2.2.1", ] [[package]] name = "solana-transaction-context" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=v3#8d5041eddc6099cfddad8f348f6ff3e82e79e4c4" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" dependencies = [ "bincode", "qualifier_attr", "serde", - "solana-account", - "solana-instruction", - "solana-instructions-sysvar", + "solana-account 3.4.0", + "solana-instruction 3.4.0", + "solana-instructions-sysvar 3.0.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", +] + +[[package]] +name = "solana-transaction-error" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a9dc8fdb61c6088baab34fc3a8b8473a03a7a5fd404ed8dd502fa79b67cb1" +dependencies = [ + "serde", + "serde_derive", + "solana-instruction 2.3.3", + "solana-sanitize 2.2.1", ] [[package]] @@ -10001,8 +11969,8 @@ dependencies = [ "rand 0.8.5", "solana-packet", "solana-perf", - "solana-short-vec", - "solana-signature", + "solana-short-vec 3.2.0", + "solana-signature 3.4.0", ] [[package]] @@ -10015,36 +11983,59 @@ dependencies = [ "agave-reserved-account-keys", "base64 0.22.1", "bincode", - "borsh", + "borsh 1.6.0", "bs58", "log", "serde", "serde_json", "solana-account-decoder", - "solana-address-lookup-table-interface", - "solana-clock", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-loader-v2-interface", - "solana-loader-v3-interface", - "solana-message", - "solana-program-option", + "solana-instruction 3.4.0", + "solana-loader-v2-interface 3.0.0", + "solana-loader-v3-interface 6.1.1", + "solana-message 3.1.0", + "solana-program-option 3.1.0", "solana-pubkey 3.0.0", - "solana-reward-info", - "solana-sdk-ids", - "solana-signature", - "solana-stake-interface", + "solana-reward-info 3.0.0", + "solana-sdk-ids 3.1.0", + "solana-signature 3.4.0", + "solana-stake-interface 2.0.2", "solana-system-interface 2.0.0", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", - "solana-vote-interface", + "solana-transaction 3.1.0", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types 3.1.12", + "solana-vote-interface 4.0.4", "spl-associated-token-account-interface", "spl-memo-interface", - "spl-token-2022-interface", - "spl-token-group-interface", + "spl-token-2022-interface 2.1.0", + "spl-token-group-interface 0.7.2", "spl-token-interface", - "spl-token-metadata-interface", + "spl-token-metadata-interface 0.8.0", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-transaction-status-client-types" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f1d7c2387c35850848212244d2b225847666cb52d3bd59a5c409d2c300303d" +dependencies = [ + "base64 0.22.1", + "bincode", + "bs58", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types 2.3.13", + "solana-commitment-config 2.2.1", + "solana-message 2.4.0", + "solana-reward-info 2.2.1", + "solana-signature 2.3.0", + "solana-transaction 2.2.3", + "solana-transaction-context 2.3.13", + "solana-transaction-error 2.2.1", "thiserror 2.0.18", ] @@ -10059,16 +12050,16 @@ dependencies = [ "bs58", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-commitment-config", - "solana-instruction", - "solana-message", + "solana-account-decoder-client-types 3.1.12", + "solana-commitment-config 3.1.1", + "solana-instruction 3.4.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-reward-info", - "solana-signature", - "solana-transaction", - "solana-transaction-context", - "solana-transaction-error", + "solana-reward-info 3.0.0", + "solana-signature 3.4.0", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", ] @@ -10080,10 +12071,10 @@ checksum = "b32651092f28c7fa9fb622a055f21fcfb1a109e6851d964ce043336a0035a629" dependencies = [ "async-trait", "solana-connection-cache", - "solana-keypair", + "solana-keypair 3.1.2", "solana-net-utils", "solana-streamer", - "solana-transaction-error", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", ] @@ -10097,23 +12088,38 @@ dependencies = [ "assert_matches", "solana-pubkey 3.0.0", "solana-runtime-transaction", - "solana-transaction", + "solana-transaction 3.1.0", "static_assertions", "unwrap_none", ] +[[package]] +name = "solana-version" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3324d46c7f7b7f5d34bf7dc71a2883bdc072c7b28ca81d0b2167ecec4cf8da9f" +dependencies = [ + "agave-feature-set 2.3.13", + "rand 0.8.5", + "semver", + "serde", + "serde_derive", + "solana-sanitize 2.2.1", + "solana-serde-varint 2.2.2", +] + [[package]] name = "solana-version" version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f697aacc5aa4ac5534abdde8a91afdcf18c24d28bd52768e8001445dbda078db" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "rand 0.8.5", "semver", "serde", "solana-sanitize 3.0.1", - "solana-serde-varint", + "solana-serde-varint 3.0.1", ] [[package]] @@ -10125,24 +12131,48 @@ dependencies = [ "itertools 0.12.1", "log", "serde", - "solana-account", - "solana-bincode", - "solana-clock", + "solana-account 3.4.0", + "solana-bincode 3.1.0", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", "solana-packet", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-serialize-utils", - "solana-signature", - "solana-signer", + "solana-sdk-ids 3.1.0", + "solana-serialize-utils 3.1.1", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "solana-svm-transaction", - "solana-transaction", - "solana-vote-interface", + "solana-transaction 3.1.0", + "solana-vote-interface 4.0.4", "thiserror 2.0.18", ] +[[package]] +name = "solana-vote-interface" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b80d57478d6599d30acc31cc5ae7f93ec2361a06aefe8ea79bc81739a08af4c3" +dependencies = [ + "bincode", + "num-derive", + "num-traits", + "serde", + "serde_derive", + "solana-clock 2.2.3", + "solana-decode-error", + "solana-hash 2.3.0", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sdk-ids 2.2.1", + "solana-serde-varint 2.2.2", + "solana-serialize-utils 2.2.1", + "solana-short-vec 2.2.1", + "solana-system-interface 1.0.0", +] + [[package]] name = "solana-vote-interface" version = "4.0.4" @@ -10156,16 +12186,16 @@ dependencies = [ "serde", "serde_derive", "serde_with", - "solana-clock", + "solana-clock 3.0.1", "solana-hash 3.1.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-instruction-error", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-serde-varint", - "solana-serialize-utils", - "solana-short-vec", + "solana-sdk-ids 3.1.0", + "solana-serde-varint 3.0.1", + "solana-serialize-utils 3.1.1", + "solana-short-vec 3.2.0", "solana-system-interface 2.0.0", ] @@ -10175,29 +12205,29 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac7f37540da27c0ec132ee1b5380ad32d98663afba7ade3581f2d963fd2f63c2" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "bincode", "log", "num-derive", "num-traits", "serde", - "solana-account", - "solana-bincode", - "solana-clock", - "solana-epoch-schedule", + "solana-account 3.4.0", + "solana-bincode 3.1.0", + "solana-clock 3.0.1", + "solana-epoch-schedule 3.1.0", "solana-hash 3.1.0", - "solana-instruction", - "solana-keypair", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", "solana-packet", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-sdk-ids", - "solana-signer", - "solana-slot-hashes", - "solana-transaction", - "solana-transaction-context", - "solana-vote-interface", + "solana-sdk-ids 3.1.0", + "solana-signer 3.0.0", + "solana-slot-hashes 3.0.1", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", + "solana-vote-interface 4.0.4", "thiserror 2.0.18", ] @@ -10207,7 +12237,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5a91404c7de468dd80658cdb5d894ec803d1092ea6e2bfdf84eee6f07559c0d" dependencies = [ - "borsh", + "borsh 1.6.0", "bytemuck", "bytemuck_derive", ] @@ -10218,15 +12248,51 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cee65de587e6fe912668903e62f3f40c02a834f21967a18cc6c71f550c51a639" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "bytemuck", "num-derive", "num-traits", - "solana-instruction", + "solana-instruction 3.4.0", "solana-program-runtime", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-log-collector", - "solana-zk-sdk", + "solana-zk-sdk 4.0.0", +] + +[[package]] +name = "solana-zk-sdk" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b9fc6ec37d16d0dccff708ed1dd6ea9ba61796700c3bb7c3b401973f10f63b" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "js-sys", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-derivation-path 2.2.1", + "solana-instruction 2.3.3", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-seed-derivable 2.2.1", + "solana-seed-phrase 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "subtle", + "thiserror 2.0.18", + "wasm-bindgen", + "zeroize", ] [[package]] @@ -10252,14 +12318,14 @@ dependencies = [ "serde_derive", "serde_json", "sha3", - "solana-derivation-path", - "solana-instruction", + "solana-derivation-path 3.0.0", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-signature", - "solana-signer", + "solana-sdk-ids 3.1.0", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "subtle", "thiserror 2.0.18", "wasm-bindgen", @@ -10272,13 +12338,13 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ecb5f2989632b030709c8aebdbc586a8c0f867d0ec154d0cb7feafb86f72fb" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "bytemuck", "num-derive", "num-traits", - "solana-instruction", + "solana-instruction 3.4.0", "solana-program-runtime", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-svm-log-collector", "solana-zk-token-sdk", ] @@ -10303,15 +12369,15 @@ dependencies = [ "serde", "serde_json", "sha3", - "solana-curve25519", - "solana-derivation-path", - "solana-instruction", + "solana-curve25519 3.1.12", + "solana-derivation-path 3.0.0", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-seed-derivable", - "solana-seed-phrase", - "solana-signature", - "solana-signer", + "solana-sdk-ids 3.1.0", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", + "solana-signature 3.4.0", + "solana-signer 3.0.0", "subtle", "thiserror 2.0.18", "zeroize", @@ -10388,11 +12454,23 @@ dependencies = [ name = "spl-associated-token-account-interface" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" +checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" +dependencies = [ + "borsh 1.6.0", + "solana-instruction 3.4.0", + "solana-pubkey 3.0.0", +] + +[[package]] +name = "spl-discriminator" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ - "borsh", - "solana-instruction", - "solana-pubkey 3.0.0", + "bytemuck", + "solana-program-error 2.2.2", + "solana-sha256-hasher 2.2.1", + "spl-discriminator-derive", ] [[package]] @@ -10402,7 +12480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e597c5ff9ed7c74a54dbc47bae2f06e4db8c98f4356ad280200dc11878266db1" dependencies = [ "bytemuck", - "solana-program-error", + "solana-program-error 3.0.0", "solana-sha256-hasher 3.1.0", "spl-discriminator-derive", ] @@ -10431,6 +12509,29 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "spl-elgamal-registry" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce0f668975d2b0536e8a8fd60e56a05c467f06021dae037f1d0cfed0de2e231d" +dependencies = [ + "bytemuck", + "solana-program 2.3.0", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", + "spl-token-confidential-transfer-proof-extraction 0.2.1", +] + +[[package]] +name = "spl-generic-token" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741a62a566d97c58d33f9ed32337ceedd4e35109a686e31b1866c5dfa56abddc" +dependencies = [ + "bytemuck", + "solana-pubkey 2.4.0", +] + [[package]] name = "spl-generic-token" version = "2.0.1" @@ -10441,33 +12542,187 @@ dependencies = [ "solana-pubkey 3.0.0", ] +[[package]] +name = "spl-memo" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f09647c0974e33366efeb83b8e2daebb329f0420149e74d3a4bd2c08cf9f7cb" +dependencies = [ + "solana-account-info 2.3.0", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-entrypoint 2.3.0", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", +] + [[package]] name = "spl-memo-interface" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d4e2aedd58f858337fa609af5ad7100d4a243fdaf6a40d6eb4c28c5f19505d3" dependencies = [ - "solana-instruction", + "solana-instruction 3.4.0", "solana-pubkey 3.0.0", ] +[[package]] +name = "spl-pod" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d994afaf86b779104b4a95ba9ca75b8ced3fdb17ee934e38cb69e72afbe17799" +dependencies = [ + "borsh 1.6.0", + "bytemuck", + "bytemuck_derive", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-program-option 2.2.1", + "solana-pubkey 2.4.0", + "solana-zk-sdk 2.3.13", + "thiserror 2.0.18", +] + [[package]] name = "spl-pod" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f9c6e142cdf1e7e77f480053ec9f0ce989890768ddf91f619b50f39d1b456f5" dependencies = [ - "borsh", + "borsh 1.6.0", "bytemuck", "bytemuck_derive", "num-derive", "num-traits", "num_enum", - "solana-program-error", - "solana-program-option", + "solana-program-error 3.0.0", + "solana-program-option 3.1.0", "solana-pubkey 3.0.0", "solana-zero-copy", - "solana-zk-sdk", + "solana-zk-sdk 4.0.0", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-program-error" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d39b5186f42b2b50168029d81e58e800b690877ef0b30580d107659250da1d1" +dependencies = [ + "num-derive", + "num-traits", + "solana-program 2.3.0", + "spl-program-error-derive", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-program-error-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.9", + "syn 2.0.117", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd99ff1e9ed2ab86e3fd582850d47a739fec1be9f4661cba1782d3a0f26805f3" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-program-error", + "spl-type-length-value 0.7.0", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed320a6c934128d4f7e54fe00e16b8aeaecf215799d060ae14f93378da6dc834" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program 2.3.0", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-2022" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048b26b0df0290f929ff91317c83db28b3ef99af2b3493dd35baa146774924c" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program 2.3.0", + "solana-security-txt", + "solana-zk-sdk 2.3.13", + "spl-elgamal-registry", + "spl-memo", + "spl-pod 0.5.1", + "spl-token", + "spl-token-confidential-transfer-ciphertext-arithmetic", + "spl-token-confidential-transfer-proof-extraction 0.2.1", + "spl-token-confidential-transfer-proof-generation 0.3.0", + "spl-token-group-interface 0.5.0", + "spl-token-metadata-interface 0.6.0", + "spl-transfer-hook-interface", + "spl-type-length-value 0.7.0", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-2022-interface" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d7ae2ee6b856f8ddcbdc3b3a9f4d2141582bbe150f93e5298ee97e0251fa04" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-program-option 2.2.1", + "solana-program-pack 2.2.1", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", + "spl-token-confidential-transfer-proof-extraction 0.4.1", + "spl-token-confidential-transfer-proof-generation 0.4.1", + "spl-token-group-interface 0.6.0", + "spl-token-metadata-interface 0.7.0", + "spl-type-length-value 0.8.0", "thiserror 2.0.18", ] @@ -10482,20 +12737,66 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-account-info", - "solana-instruction", - "solana-program-error", - "solana-program-option", - "solana-program-pack", + "solana-account-info 3.1.1", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-zk-sdk", - "spl-pod", - "spl-token-confidential-transfer-proof-extraction", - "spl-token-confidential-transfer-proof-generation", - "spl-token-group-interface", - "spl-token-metadata-interface", - "spl-type-length-value", + "solana-sdk-ids 3.1.0", + "solana-zk-sdk 4.0.0", + "spl-pod 0.7.3", + "spl-token-confidential-transfer-proof-extraction 0.5.1", + "spl-token-confidential-transfer-proof-generation 0.5.1", + "spl-token-group-interface 0.7.2", + "spl-token-metadata-interface 0.8.0", + "spl-type-length-value 0.9.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-ciphertext-arithmetic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170378693c5516090f6d37ae9bad2b9b6125069be68d9acd4865bbe9fc8499fd" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "solana-curve25519 2.3.13", + "solana-zk-sdk 2.3.13", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff2d6a445a147c9d6dd77b8301b1e116c8299601794b558eafa409b342faf96" +dependencies = [ + "bytemuck", + "solana-curve25519 2.3.13", + "solana-program 2.3.0", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512c85bdbbb4cbcc2038849a9e164c958b16541f252b53ea1a3933191c0a4a1a" +dependencies = [ + "bytemuck", + "solana-account-info 2.3.0", + "solana-curve25519 2.3.13", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", "thiserror 2.0.18", ] @@ -10506,16 +12807,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879a9ebad0d77383d3ea71e7de50503554961ff0f4ef6cbca39ad126e6f6da3a" dependencies = [ "bytemuck", - "solana-account-info", - "solana-curve25519", - "solana-instruction", - "solana-instructions-sysvar", - "solana-msg", - "solana-program-error", + "solana-account-info 3.1.1", + "solana-curve25519 3.1.12", + "solana-instruction 3.4.0", + "solana-instructions-sysvar 3.0.0", + "solana-msg 3.1.0", + "solana-program-error 3.0.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", - "solana-zk-sdk", - "spl-pod", + "solana-sdk-ids 3.1.0", + "solana-zk-sdk 4.0.0", + "spl-pod 0.7.3", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3597628b0d2fe94e7900fd17cdb4cfbb31ee35c66f82809d27d86e44b2848b" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk 2.3.13", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa27b9174bea869a7ebf31e0be6890bce90b1a4288bc2bbf24bd413f80ae3fde" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk 2.3.13", "thiserror 2.0.18", ] @@ -10526,7 +12849,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0cd59fce3dc00f563c6fa364d67c3f200d278eae681f4dc250240afcfe044b1" dependencies = [ "curve25519-dalek 4.1.3", - "solana-zk-sdk", + "solana-zk-sdk 4.0.0", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d595667ed72dbfed8c251708f406d7c2814a3fa6879893b323d56a10bedfc799" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5597b4cd76f85ce7cd206045b7dc22da8c25516573d42d267c8d1fd128db5129" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", "thiserror 2.0.18", ] @@ -10541,11 +12902,11 @@ dependencies = [ "num-traits", "num_enum", "solana-address 2.6.0", - "solana-instruction", + "solana-instruction 3.4.0", "solana-nullable", - "solana-program-error", + "solana-program-error 3.0.0", "solana-zero-copy", - "spl-discriminator", + "spl-discriminator 0.5.2", "thiserror 2.0.18", ] @@ -10560,12 +12921,54 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-instruction", - "solana-program-error", - "solana-program-option", - "solana-program-pack", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", + "solana-program-option 3.1.0", + "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb9c89dbc877abd735f05547dcf9e6e12c00c11d6d74d8817506cab4c99fdbb" +dependencies = [ + "borsh 1.6.0", + "num-derive", + "num-traits", + "solana-borsh 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-type-length-value 0.7.0", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304d6e06f0de0c13a621464b1fd5d4b1bebf60d15ca71a44d3839958e0da16ee" +dependencies = [ + "borsh 1.6.0", + "num-derive", + "num-traits", + "solana-borsh 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-type-length-value 0.8.0", "thiserror 2.0.18", ] @@ -10575,16 +12978,77 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c467c7c3bd056f8fe60119e7ec34ddd6f23052c2fa8f1f51999098063b72676" dependencies = [ - "borsh", + "borsh 1.6.0", "num-derive", "num-traits", - "solana-borsh", - "solana-instruction", - "solana-program-error", + "solana-borsh 3.0.2", + "solana-instruction 3.4.0", + "solana-program-error 3.0.0", "solana-pubkey 3.0.0", - "spl-discriminator", - "spl-pod", - "spl-type-length-value", + "spl-discriminator 0.5.2", + "spl-pod 0.7.3", + "spl-type-length-value 0.9.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa7503d52107c33c88e845e1351565050362c2314036ddf19a36cd25137c043" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-cpi 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-program-error", + "spl-tlv-account-resolution", + "spl-type-length-value 0.7.0", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-type-length-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba70ef09b13af616a4c987797870122863cba03acc4284f226a4473b043923f9" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-type-length-value" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d417eb548214fa822d93f84444024b4e57c13ed6719d4dcc68eec24fb481e9f5" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info 2.3.0", + "solana-decode-error", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", "thiserror 2.0.18", ] @@ -10598,10 +13062,10 @@ dependencies = [ "num-derive", "num-traits", "num_enum", - "solana-account-info", - "solana-program-error", + "solana-account-info 3.1.1", + "solana-program-error 3.0.0", "solana-zero-copy", - "spl-discriminator", + "spl-discriminator 0.5.2", "thiserror 2.0.18", ] @@ -10763,7 +13227,7 @@ dependencies = [ name = "sysvars" version = "0.0.0" dependencies = [ - "solana-program", + "solana-program 3.0.0", ] [[package]] @@ -10857,23 +13321,31 @@ name = "test-chainlink" version = "0.0.0" dependencies = [ "bincode", + "borsh 1.6.0", + "compressed-delegation-client", "futures", "integration-test-tools", + "light-client", + "light-compressed-account", + "light-hasher", + "light-sdk", "magicblock-chainlink", "magicblock-config", + "magicblock-core", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "program-flexi-counter", "program-mini", - "solana-account", - "solana-commitment-config", - "solana-loader-v2-interface", - "solana-loader-v3-interface", - "solana-loader-v4-interface", + "solana-account 3.4.0", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", + "solana-loader-v2-interface 3.0.0", + "solana-loader-v3-interface 6.1.1", + "solana-loader-v4-interface 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", "spl-token-interface", "tokio", @@ -10888,7 +13360,7 @@ dependencies = [ "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "program-flexi-counter", "program-mini", - "solana-loader-v4-interface", + "solana-loader-v4-interface 3.1.0", "solana-sdk", "solana-system-interface 3.2.0", "spl-memo-interface", @@ -10909,9 +13381,9 @@ dependencies = [ "magicblock-config", "program-flexi-counter", "serial_test", - "solana-rpc-client", + "solana-rpc-client 3.1.12", "solana-sdk", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", "tempfile", "test-kit", @@ -10927,15 +13399,15 @@ dependencies = [ "magicblock-core", "magicblock-ledger", "magicblock-processor", - "solana-account", - "solana-instruction", - "solana-keypair", - "solana-program", - "solana-rpc-client", - "solana-signature", - "solana-signer", - "solana-transaction", - "solana-transaction-status-client-types", + "solana-account 3.4.0", + "solana-instruction 3.4.0", + "solana-keypair 3.1.2", + "solana-program 3.0.0", + "solana-rpc-client 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", + "solana-transaction-status-client-types 3.1.12", "tempfile", "tokio", "tracing", @@ -10954,10 +13426,10 @@ dependencies = [ "magicblock-config", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "program-flexi-counter", - "solana-commitment-config", - "solana-rpc-client", + "solana-commitment-config 3.1.1", + "solana-rpc-client 3.1.12", "solana-sdk", - "solana-sdk-ids", + "solana-sdk-ids 3.1.0", "solana-system-interface 3.2.0", "solana-transaction-status", "tempfile", @@ -10978,9 +13450,9 @@ dependencies = [ "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "magicblock-program", "magicblock-validator-admin", - "solana-commitment-config", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-commitment-config 3.1.1", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk", "solana-system-interface 3.2.0", "solana-transaction-status", @@ -10996,8 +13468,8 @@ dependencies = [ "futures", "integration-test-tools", "solana-pubsub-client", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk", "solana-system-interface 3.2.0", "tokio", @@ -11023,7 +13495,7 @@ dependencies = [ "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "magicblock-magic-program-api 0.9.0", "program-flexi-counter", - "solana-rpc-client-api", + "solana-rpc-client-api 3.1.12", "solana-sdk", "test-kit", "tracing", @@ -11036,10 +13508,10 @@ dependencies = [ "magicblock-rpc-client", "magicblock-table-mania", "paste", - "solana-address-lookup-table-interface", - "solana-commitment-config", + "solana-address-lookup-table-interface 3.1.0", + "solana-commitment-config 3.1.1", "solana-pubkey 3.0.0", - "solana-rpc-client", + "solana-rpc-client 3.1.12", "solana-sdk", "test-kit", "tokio", @@ -11059,7 +13531,7 @@ dependencies = [ "magicblock-task-scheduler", "program-flexi-counter", "program-schedulecommit", - "solana-rpc-client", + "solana-rpc-client 3.1.12", "solana-sdk", "tempfile", "tokio", @@ -11314,6 +13786,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.23" @@ -11945,9 +14426,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -11958,22 +14439,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11981,9 +14459,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -11994,18 +14472,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -12206,6 +14697,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + [[package]] name = "windows-result" version = "0.4.1" @@ -12741,6 +15243,12 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zopfli" version = "0.8.3" diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 4991bf088..53f4d2a36 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -19,7 +19,7 @@ members = [ "test-schedule-intent", "test-table-mania", "test-task-scheduler", - "test-tools" + "test-tools", ] resolver = "2" @@ -35,21 +35,32 @@ borsh = { version = "1.2.1", features = ["derive", "unstable__schema"] } chrono = "0.4" cleanass = "0.0.1" color-backtrace = { version = "0.7" } +compressed-delegation-api = { path = "../compressed-delegation-api" } +compressed-delegation-client = { path = "../compressed-delegation-client" } ctrlc = "3.4.7" ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "ccfc9f924dc40", default-features = false, features = [ "disable-realloc", - "modular-sdk" + "modular-sdk", ] } futures = "0.3.31" integration-test-tools = { path = "test-tools" } isocountry = "0.3.2" lazy_static = "1.4.0" +light-client = "0.23" +light-compressed-account = "0.11" +light-hasher = "5" +light-sdk = "0.23" +light-sdk-types = "0.23" magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain-program.git", rev = "335a22", default-features = false } -magicblock-accounts-db = { path = "../magicblock-accounts-db", features = ["dev-tools"] } +magicblock-accounts-db = { path = "../magicblock-accounts-db", features = [ + "dev-tools", +] } magicblock-api = { path = "../magicblock-api" } -magicblock-chainlink = { path = "../magicblock-chainlink", features = ["dev-context"] } +magicblock-chainlink = { path = "../magicblock-chainlink", features = [ + "dev-context", +] } magicblock-committor-program = { path = "../magicblock-committor-program", features = [ - "no-entrypoint" + "no-entrypoint", ] } magicblock-committor-service = { path = "../magicblock-committor-service" } magicblock-config = { path = "../magicblock-config" } @@ -70,7 +81,8 @@ rkyv = "0.7.45" schedulecommit-client = { path = "schedulecommit/client" } serde = "1.0.217" serial_test = "3.2.0" -solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } +shlex = "1.3.0" +solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } solana-address-lookup-table-interface = "3.1" solana-commitment-config = "3.1.1" solana-compute-budget-interface = "3.0" @@ -109,9 +121,9 @@ url = "2.5.0" solana-storage-proto = { path = "../storage-proto" } # same reason as above rocksdb = { git = "https://github.com/magicblock-labs/rust-rocksdb.git", rev = "6d975197" } -solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } -solana-program-runtime = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } -solana-svm = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } -solana-transaction-context = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "v3" } +solana-account = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } +solana-program-runtime = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } +solana-svm = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } +solana-transaction-context = { git = "https://github.com/magicblock-labs/magicblock-svm.git", branch = "fix/v3-compressed" } # Fix libsodium for ARM builds - upstream crates.io version breaks Linux ARM binaries libsodium-rs = { git = "https://github.com/jedisct1/libsodium-rs.git", rev = "0397a6c5785233f9f2ac91f3eedc3cceb74e0060" } diff --git a/test-integration/configs/chainlink-conf.devnet.toml b/test-integration/configs/chainlink-conf.devnet.toml index 16da71f89..80fc348db 100644 --- a/test-integration/configs/chainlink-conf.devnet.toml +++ b/test-integration/configs/chainlink-conf.devnet.toml @@ -49,5 +49,9 @@ id = "MiniV31111111111111111111111111111111111111" path = "../target/deploy/miniv3/program_mini.so" auth = "MiniV3AUTH111111111111111111111111111111111" +[[programs]] +id = "DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT" +path = "../programs/compressed_delegation/compressed_delegation.so" + [metrics] address = "0.0.0.0:9000" # Default if not specified, was disabled before but struct requires address diff --git a/test-integration/configs/committor-conf.devnet.toml b/test-integration/configs/committor-conf.devnet.toml index 62fc3ef10..74a8869c9 100644 --- a/test-integration/configs/committor-conf.devnet.toml +++ b/test-integration/configs/committor-conf.devnet.toml @@ -45,6 +45,10 @@ path = "../target/deploy/program_schedulecommit.so" id = "f1exzKGtdeVX3d6UXZ89cY7twiNJe9S5uq84RTA4Rq4" path = "../target/deploy/program_flexi_counter.so" +[[programs]] +id = "DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT" +path = "../programs/compressed_delegation/compressed_delegation.so" + [geyser-grpc] port = 10001 diff --git a/test-integration/programs/compressed_delegation/compressed_delegation.so b/test-integration/programs/compressed_delegation/compressed_delegation.so index 0bbaa5f117a83e3d1f3830ff6acaed8c54f26a44..701b36fa3a6219791625073fff1a64f9022fd28c 100755 GIT binary patch delta 20516 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 arB|O(sx*_XKZ>K=YLx(pmo=G-r2hx0vWegT delta 20719 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 diff --git a/test-integration/programs/flexi-counter/Cargo.toml b/test-integration/programs/flexi-counter/Cargo.toml index 4e9f424a4..fcd46c6ad 100644 --- a/test-integration/programs/flexi-counter/Cargo.toml +++ b/test-integration/programs/flexi-counter/Cargo.toml @@ -6,7 +6,12 @@ version.workspace = true [dependencies] bincode = { workspace = true } borsh = { workspace = true } +compressed-delegation-api = { workspace = true } +compressed-delegation-client = { workspace = true } ephemeral-rollups-sdk = { workspace = true } +light-hasher = { workspace = true } +light-sdk = { workspace = true, features = ["v2"] } +light-sdk-types = { workspace = true, features = ["v2"] } magicblock-magic-program-api = { workspace = true } serde = { workspace = true } solana-program = { workspace = true } diff --git a/test-integration/programs/flexi-counter/src/instruction.rs b/test-integration/programs/flexi-counter/src/instruction.rs index 795458892..9b12003d8 100644 --- a/test-integration/programs/flexi-counter/src/instruction.rs +++ b/test-integration/programs/flexi-counter/src/instruction.rs @@ -1,4 +1,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; +use compressed_delegation_api::instruction::{ + CdpCompressedAccountMeta, CdpPackedAddressTreeInfo, CdpValidityProof, +}; use ephemeral_rollups_sdk::{ consts::{MAGIC_CONTEXT_ID, MAGIC_PROGRAM_ID}, delegate_args::{DelegateAccountMetas, DelegateAccounts}, @@ -32,6 +35,20 @@ pub struct CancelArgs { pub task_id: i64, } +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)] +pub struct InitDelegationRecordArgs { + pub validity_proof: CdpValidityProof, + pub address_tree_info: CdpPackedAddressTreeInfo, + pub output_state_tree_index: u8, +} + +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)] +pub struct DelegateCompressedArgs { + pub validator: Option, + pub validity_proof: CdpValidityProof, + pub account_meta: CdpCompressedAccountMeta, +} + pub const MAX_ACCOUNT_ALLOC_PER_INSTRUCTION_SIZE: u16 = 10_240; /// The counter has both mul and add instructions in order to facilitate tests where @@ -267,6 +284,38 @@ pub enum FlexiCounterInstruction { num_commit: u8, num_commit_finalize: u8, }, + + /// Initializes a compressed delegation record for the FlexiCounter account + /// + /// Accounts: + /// 0. `[signer]` The payer that is initializing the delegation record. + /// 1. `[write]` The counter PDA account that will be initialized. + /// 2. `[]` The compressed delegation program id + /// 3. `[]` The CPI signer of the compressed delegation program + /// 4. `[]` The system program + /// + /// 5..N `[]` Remaining accounts using by the Light program + InitCompressedDelegationRecord(InitDelegationRecordArgs), + + /// Compressed delegation of the FlexiCounter account to an ephemaral validator + /// + /// Accounts: + /// 0. `[signer]` The payer that is delegating the account. + /// 1. `[write]` The counter PDA account that will be delegated. + /// 2. `[]` The compressed delegation program id + /// 3. `[]` The CPI signer of the compressed delegation program + /// + /// 4..N `[]` Remaining accounts using by the Light program + DelegateCompressed(DelegateCompressedArgs), + + /// Commits the compressed FlexiCounter + /// + /// Accounts: + /// 0. `[signer]` The payer that created the account. + /// 1. `[write]` The counter PDA account that will be updated. + /// 2. `[]` MagicContext (used to record scheduled commit) + /// 3. `[]` MagicBlock Program (used to schedule commit) + ScheduleCommitCompressed, } pub fn create_init_ix(payer: Pubkey, label: String) -> Instruction { @@ -687,3 +736,58 @@ pub fn create_intent_bundle_commit_and_finalize_ix( accounts, ) } +pub fn create_init_compressed_delegation_record_ix( + payer: Pubkey, + remaining_accounts: &[AccountMeta], + args: InitDelegationRecordArgs, +) -> Instruction { + let program_id = &crate::id(); + let (pda, _) = FlexiCounter::pda(&payer); + let mut accounts = vec![ + AccountMeta::new(payer, true), + AccountMeta::new(pda, false), + AccountMeta::new_readonly(compressed_delegation_api::ID, false), + ]; + accounts.extend(remaining_accounts.iter().cloned()); + Instruction::new_with_borsh( + *program_id, + &FlexiCounterInstruction::InitCompressedDelegationRecord(args), + accounts, + ) +} + +pub fn create_delegate_compressed_ix( + payer: Pubkey, + remaining_accounts: &[AccountMeta], + args: DelegateCompressedArgs, +) -> Instruction { + let program_id = &crate::id(); + let (pda, _) = FlexiCounter::pda(&payer); + let mut accounts = vec![ + AccountMeta::new(payer, true), + AccountMeta::new(pda, false), + AccountMeta::new_readonly(compressed_delegation_api::ID, false), + ]; + accounts.extend(remaining_accounts.iter().cloned()); + Instruction::new_with_borsh( + *program_id, + &FlexiCounterInstruction::DelegateCompressed(args), + accounts, + ) +} + +pub fn create_schedule_commit_compressed_ix(payer: Pubkey) -> Instruction { + let program_id = &crate::id(); + let (pda, _) = FlexiCounter::pda(&payer); + let accounts = vec![ + AccountMeta::new(payer, true), + AccountMeta::new(pda, false), + AccountMeta::new(MAGIC_CONTEXT_ID, false), + AccountMeta::new_readonly(MAGIC_PROGRAM_ID, false), + ]; + Instruction::new_with_borsh( + *program_id, + &FlexiCounterInstruction::ScheduleCommitCompressed, + accounts, + ) +} diff --git a/test-integration/programs/flexi-counter/src/processor.rs b/test-integration/programs/flexi-counter/src/processor.rs index 6e4a6b6fb..f87764810 100644 --- a/test-integration/programs/flexi-counter/src/processor.rs +++ b/test-integration/programs/flexi-counter/src/processor.rs @@ -4,8 +4,14 @@ mod schedule_intent; mod transfer_intent; use borsh::{to_vec, BorshDeserialize}; +use compressed_delegation_api::{ + ExternalUndelegateArgs, EXTERNAL_UNDELEGATE_DISCRIMINATOR_COMPRESSED, +}; use ephemeral_rollups_sdk::{ - consts::{EXTERNAL_UNDELEGATE_DISCRIMINATOR, MAGIC_PROGRAM_ID}, + consts::{ + DEFAULT_VALIDATOR_IDENTITY, EXTERNAL_UNDELEGATE_DISCRIMINATOR, + MAGIC_PROGRAM_ID, + }, cpi::{ delegate_account, undelegate_account, DelegateAccounts, DelegateConfig, }, @@ -30,7 +36,8 @@ use solana_system_interface::instruction as system_instruction; use crate::{ instruction::{ create_add_error_ix, create_add_ix, create_add_unsigned_ix, CancelArgs, - DelegateArgs, FlexiCounterInstruction, ScheduleArgs, + DelegateArgs, DelegateCompressedArgs, FlexiCounterInstruction, + InitDelegationRecordArgs, ScheduleArgs, MAX_ACCOUNT_ALLOC_PER_INSTRUCTION_SIZE, }, processor::{ @@ -67,6 +74,11 @@ pub fn process( if disc == TRANSFER_CALLBACK_DISCRIMINATOR { return process_transfer_callback(accounts, data); } + + if disc == EXTERNAL_UNDELEGATE_DISCRIMINATOR_COMPRESSED { + let args = ExternalUndelegateArgs::try_from_slice(data)?; + return process_external_undelegate_compressed(accounts, args); + } } let ix = FlexiCounterInstruction::try_from_slice(instruction_data)?; @@ -148,6 +160,13 @@ pub fn process( TransferActionHandler { amount, fail } => { process_transfer_action_handler(accounts, amount, fail) } + InitCompressedDelegationRecord(args) => { + process_init_compressed_delegation_record(accounts, args) + } + DelegateCompressed(args) => process_delegate_compressed(accounts, args), + ScheduleCommitCompressed => { + process_schedule_commit_compressed(accounts) + } }?; Ok(()) } @@ -555,3 +574,240 @@ fn process_cancel_task( Ok(()) } + +fn process_init_compressed_delegation_record( + accounts: &[AccountInfo], + args: InitDelegationRecordArgs, +) -> ProgramResult { + msg!("InitCompressedDelegationRecord"); + + let [payer_info, counter_pda_info, compressed_delegation_program_info, remaining_accounts @ ..] = + accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + if compressed_delegation_program_info + .key + .ne(&compressed_delegation_client::ID) + { + return Err(ProgramError::IncorrectProgramId); + } + + let pda_seeds = FlexiCounter::seeds(payer_info.key); + let (counter_pda, bump) = FlexiCounter::pda(payer_info.key); + if counter_pda_info.key.ne(&counter_pda) { + msg!( + "Invalid counter PDA {}, should be {}", + counter_pda_info.key, + counter_pda + ); + return Err(ProgramError::InvalidSeeds); + } + + // Cpi into delegation program + let bump_slice = &[bump]; + let signer_seeds = + FlexiCounter::seeds_with_bump(payer_info.key, bump_slice); + let signer = [signer_seeds.as_ref()]; + compressed_delegation_client::cpi::InitDelegationRecordCpi { + payer: payer_info.clone(), + delegated_account: counter_pda_info.clone(), + remaining_accounts: remaining_accounts + .iter() + .map(|account| { + (account.clone(), account.is_signer, account.is_writable) + }) + .collect(), + args: compressed_delegation_client::InitDelegationRecordArgs { + owner_program_id: crate::ID, + pda_seeds: pda_seeds + .iter() + .map(|seed| seed.to_vec()) + .collect::>(), + bump, + output_state_tree_index: args.output_state_tree_index, + address_tree_info: args.address_tree_info, + validity_proof: args.validity_proof, + }, + } + .invoke_signed(&signer)?; + + Ok(()) +} + +fn process_delegate_compressed( + accounts: &[AccountInfo], + args: DelegateCompressedArgs, +) -> ProgramResult { + msg!("DelegateCompressed"); + + let [payer_info, counter_pda_info, compressed_delegation_program_info, remaining_accounts @ ..] = + accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + if compressed_delegation_program_info + .key + .ne(&compressed_delegation_client::ID) + { + return Err(ProgramError::IncorrectProgramId); + } + + let pda_seeds = FlexiCounter::seeds(payer_info.key); + let (counter_pda, bump) = FlexiCounter::pda(payer_info.key); + if counter_pda_info.key.ne(&counter_pda) { + msg!( + "Invalid counter PDA {}, should be {}", + counter_pda_info.key, + counter_pda + ); + return Err(ProgramError::InvalidSeeds); + } + + // Close the counter + let account_data = { counter_pda_info.data.borrow().to_vec() }; + counter_pda_info.resize(0)?; + **payer_info.try_borrow_mut_lamports()? += counter_pda_info.lamports(); + **counter_pda_info.try_borrow_mut_lamports()? = 0; + + // Cpi into delegation program + let bump_slice = &[bump]; + let signer_seeds = + FlexiCounter::seeds_with_bump(payer_info.key, bump_slice); + let signer = [signer_seeds.as_ref()]; + compressed_delegation_client::cpi::DelegateCpi { + payer: payer_info.clone(), + delegated_account: counter_pda_info.clone(), + remaining_accounts: remaining_accounts + .iter() + .map(|account| { + (account.clone(), account.is_signer, account.is_writable) + }) + .collect(), + args: compressed_delegation_client::DelegateArgs { + validator: args.validator.unwrap_or(DEFAULT_VALIDATOR_IDENTITY), + validity_proof: args.validity_proof, + account_meta: args.account_meta, + lamports: 0, + account_data, + pda_seeds: pda_seeds + .iter() + .map(|seed| seed.to_vec()) + .collect::>(), + bump, + owner_program_id: crate::ID, + }, + } + .invoke_signed(&signer)?; + + Ok(()) +} + +fn process_schedule_commit_compressed( + accounts: &[AccountInfo], +) -> ProgramResult { + msg!("ScheduleCommitCompressed"); + + let [payer, counter, magic_context, magic_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + let (pda, _bump) = FlexiCounter::pda(payer.key); + assert_keys_equal(counter.key, &pda, || { + format!("Invalid counter PDA {}, should be {}", counter.key, pda) + })?; + + let instruction_data = MagicBlockInstruction::ScheduleCommitAndUndelegate + .try_to_vec() + .map_err(|_| ProgramError::BorshIoError)?; + + let account_metas = vec![ + AccountMeta::new(*payer.key, true), + AccountMeta::new(*magic_context.key, false), + AccountMeta::new(*counter.key, false), + ]; + + let account_refs = + vec![payer.clone(), magic_context.clone(), counter.clone()]; + + let ix = Instruction { + program_id: *magic_program.key, + data: instruction_data, + accounts: account_metas, + }; + + invoke(&ix, &account_refs)?; + + Ok(()) +} + +fn process_external_undelegate_compressed( + accounts: &[AccountInfo], + args: ExternalUndelegateArgs, +) -> ProgramResult { + msg!("External Undelegate Compressed"); + + let [payer, delegated_account, _system_program] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + let (pda, bump) = FlexiCounter::pda(payer.key); + if &pda != delegated_account.key { + msg!("Invalid seeds: {:?} != {:?}", pda, delegated_account.key); + return Err(ProgramError::InvalidSeeds); + } + + // Recreate the account + let rent = Rent::get()?; + let rent_exemption = + rent.minimum_balance(args.delegation_record.data.len()); + let bump = &[bump]; + let seeds = FlexiCounter::seeds_with_bump(payer.key, bump); + if delegated_account.lamports() > 0 { + if rent_exemption > delegated_account.lamports() { + invoke( + &system_instruction::transfer( + payer.key, + delegated_account.key, + rent_exemption - delegated_account.lamports(), + ), + &[payer.clone(), delegated_account.clone()], + )?; + } else if rent_exemption < delegated_account.lamports() { + invoke_signed( + &system_instruction::transfer( + delegated_account.key, + payer.key, + delegated_account.lamports() - rent_exemption, + ), + &[delegated_account.clone(), payer.clone()], + &[&seeds], + )?; + } + + delegated_account.resize(args.delegation_record.data.len())?; + delegated_account.assign(&crate::ID); + } else { + invoke_signed( + &system_instruction::create_account( + payer.key, + delegated_account.key, + rent_exemption, + args.delegation_record.data.len() as u64, + &crate::ID, + ), + &[payer.clone(), delegated_account.clone()], + &[&seeds], + )?; + } + + // Reset data + delegated_account + .data + .borrow_mut() + .copy_from_slice(&args.delegation_record.data); + + Ok(()) +} diff --git a/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs b/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs index 8e03cf676..14e384883 100644 --- a/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs +++ b/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs @@ -396,6 +396,7 @@ pub fn process_create_intent_bundle_commit_and_finalize( .collect(), )), commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, standalone_actions: vec![], }; diff --git a/test-integration/programs/flexi-counter/src/state.rs b/test-integration/programs/flexi-counter/src/state.rs index 2eb9a5255..d9a6c8ecc 100644 --- a/test-integration/programs/flexi-counter/src/state.rs +++ b/test-integration/programs/flexi-counter/src/state.rs @@ -1,7 +1,17 @@ use borsh::{BorshDeserialize, BorshSerialize}; +use light_sdk::{LightDiscriminator, LightHasher}; use solana_program::pubkey::Pubkey; -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive( + BorshSerialize, + BorshDeserialize, + Debug, + Clone, + PartialEq, + Eq, + LightDiscriminator, + LightHasher, +)] pub struct FlexiCounter { pub count: u64, pub updates: u64, diff --git a/test-integration/test-chainlink/Cargo.toml b/test-integration/test-chainlink/Cargo.toml index 8ab33f014..626c74f1d 100644 --- a/test-integration/test-chainlink/Cargo.toml +++ b/test-integration/test-chainlink/Cargo.toml @@ -5,18 +5,29 @@ edition.workspace = true [dependencies] bincode = { workspace = true } +borsh = { workspace = true } +compressed-delegation-client = { workspace = true } futures = { workspace = true } tracing = { workspace = true } +light-client = { workspace = true, features = ["v2"] } +light-compressed-account = { workspace = true } +light-hasher = { workspace = true } +light-sdk = { workspace = true, features = ["v2"] } magicblock-chainlink = { workspace = true } magicblock-config = { workspace = true } +magicblock-core = { workspace = true } magicblock-delegation-program-api = { workspace = true } program-mini = { workspace = true, features = ["no-entrypoint"] } program-flexi-counter = { workspace = true, features = ["no-entrypoint"] } solana-account = { workspace = true } solana-loader-v2-interface = { workspace = true, features = ["serde"] } solana-loader-v3-interface = { workspace = true, features = ["serde"] } -solana-loader-v4-interface = { workspace = true, features = ["bincode", "serde"] } +solana-loader-v4-interface = { workspace = true, features = [ + "bincode", + "serde", +] } solana-commitment-config = { workspace = true } +solana-compute-budget-interface = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index 0f1bf7a48..912ed055d 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -1,6 +1,21 @@ use std::sync::Arc; +use borsh::BorshDeserialize; +use compressed_delegation_client::{ + CommitAndFinalizeArgs, CompressedDelegationRecord, UndelegateArgs, +}; use integration_test_tools::dlp_interface; +use light_client::indexer::{ + photon_indexer::PhotonIndexer, AddressWithTree, CompressedAccount, Indexer, + ValidityProofWithContext, +}; +use light_sdk::{ + instruction::{ + account_meta::CompressedAccountMeta, PackedAccounts, + SystemAccountMetaConfig, + }, + sdk_types::PackedAddressTreeInfo, +}; use magicblock_chainlink::{ accounts_bank::mock::AccountsBankStub, cloner::{AccountCloneRequest, Cloner, DelegationActions}, @@ -9,7 +24,8 @@ use magicblock_chainlink::{ native_program_accounts, remote_account_provider::{ chain_rpc_client::ChainRpcClientImpl, - chain_updates_client::ChainUpdatesClient, Endpoint, Endpoints, + chain_updates_client::ChainUpdatesClient, + photon_client::PhotonClientImpl, Endpoint, Endpoints, RemoteAccountProvider, }, submux::SubMuxClient, @@ -17,9 +33,18 @@ use magicblock_chainlink::{ Chainlink, }; use magicblock_config::config::{ChainLinkConfig, LifecycleMode}; -use program_flexi_counter::state::FlexiCounter; +use magicblock_core::compression::{ + derive_cda_from_pda, ADDRESS_TREE, OUTPUT_QUEUE, +}; +use program_flexi_counter::{ + instruction::{ + create_init_compressed_delegation_record_ix, InitDelegationRecordArgs, + }, + state::FlexiCounter, +}; use solana_account::AccountSharedData; use solana_commitment_config::CommitmentConfig; +use solana_compute_budget_interface::ComputeBudgetInstruction; use solana_pubkey::Pubkey; use solana_rpc_client::nonblocking::rpc_client::RpcClient; use solana_rpc_client_api::config::RpcSendTransactionConfig; @@ -27,7 +52,7 @@ use solana_sdk::{ native_token::LAMPORTS_PER_SOL, signature::Keypair, signer::Signer, transaction::Transaction, }; -use solana_sdk_ids::native_loader; +use solana_sdk_ids::{native_loader, system_program}; use tokio::task; use tracing::*; @@ -38,11 +63,13 @@ pub type IxtestChainlink = Chainlink< SubMuxClient, AccountsBankStub, ClonerStub, + PhotonClientImpl, >; #[derive(Clone)] pub struct IxtestContext { pub rpc_client: Arc, + pub photon_client: Arc, pub chainlink: Arc, pub bank: Arc, pub remote_account_provider: Option< @@ -50,6 +77,7 @@ pub struct IxtestContext { RemoteAccountProvider< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, >, >, >, @@ -90,6 +118,10 @@ impl IxtestContext { url: "ws://localhost:7800".to_string(), label: "test-ws".to_string(), }, + Endpoint::Compression { + label: "test-compression".to_string(), + url: "http://localhost:8784".to_string(), + }, ]; let endpoints = Endpoints::from(endpoints_vec.as_slice()); // Add all native programs @@ -150,8 +182,11 @@ impl IxtestContext { .unwrap(); let rpc_client = IxtestContext::get_rpc_client(commitment); + let photon_client = + PhotonIndexer::new("http://localhost:8784".to_string()); Self { rpc_client: Arc::new(rpc_client), + photon_client: Arc::new(photon_client), chainlink: Arc::new(chainlink), bank, remote_account_provider, @@ -207,6 +242,7 @@ impl IxtestContext { .expect("Failed to init account"); self } + pub async fn add_accounts(&self, accs: &[(Pubkey, u64)]) { let mut joinset = task::JoinSet::new(); for (pubkey, sol) in accs { @@ -359,6 +395,352 @@ impl IxtestContext { self } + pub async fn init_compressed_delegation_record( + &self, + counter_auth: &Keypair, + ) -> &Self { + debug!( + "Initializing compressed delegation record for counter account {}", + counter_auth.pubkey() + ); + + let auth = counter_auth.pubkey(); + let (pda, _bump) = FlexiCounter::pda(&auth); + let record_address = derive_cda_from_pda(&pda); + + let mut remaining_accounts = self.get_packed_accounts(); + + let rpc_result: ValidityProofWithContext = self + .photon_client + .get_validity_proof( + vec![], + vec![AddressWithTree { + address: record_address.to_bytes(), + tree: ADDRESS_TREE.to_bytes().into(), + }], + None, + ) + .await + .unwrap() + .value; + + // Insert trees in accounts + let address_merkle_tree_pubkey_index = + remaining_accounts.insert_or_get(ADDRESS_TREE.to_bytes().into()); + let state_queue_pubkey_index = + remaining_accounts.insert_or_get(OUTPUT_QUEUE.to_bytes().into()); + + let packed_address_tree_info = PackedAddressTreeInfo { + root_index: rpc_result.addresses[0].root_index, + address_merkle_tree_pubkey_index, + address_queue_pubkey_index: address_merkle_tree_pubkey_index, + }; + + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + let init_compressed_delegation_record_ix = + create_init_compressed_delegation_record_ix( + counter_auth.pubkey(), + &remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + InitDelegationRecordArgs { + validity_proof: rpc_result.proof.into(), + address_tree_info: packed_address_tree_info.into(), + output_state_tree_index: state_queue_pubkey_index, + }, + ); + + let latest_block_hash = + self.rpc_client.get_latest_blockhash().await.unwrap(); + let tx = Transaction::new_signed_with_payer( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(300_000), + init_compressed_delegation_record_ix, + ], + Some(&counter_auth.pubkey()), + &[&counter_auth], + latest_block_hash, + ); + debug!( + "Init compressed delegation record transaction: {:?}", + tx.signatures[0] + ); + self.rpc_client + .send_and_confirm_transaction_with_spinner_and_config( + &tx, + CommitmentConfig::confirmed(), + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ) + .await + .expect("Failed to init compressed delegation record"); + + // Wait for the indexer to index the account + sleep_ms(1500).await; + + self + } + + pub async fn delegate_compressed_counter( + &self, + counter_auth: &Keypair, + ) -> &Self { + debug!( + "Delegating compressed counter account {}", + counter_auth.pubkey() + ); + use program_flexi_counter::instruction::*; + + let auth = counter_auth.pubkey(); + let (pda, _bump) = FlexiCounter::pda(&auth); + let record_address = derive_cda_from_pda(&pda); + + let mut remaining_accounts = self.get_packed_accounts(); + + let (compressed_delegated_record, proof) = + self.get_compressed_account_and_proof(&record_address).await; + + let packed_state_tree = proof + .pack_tree_infos(&mut remaining_accounts) + .state_trees + .unwrap(); + let account_meta = CompressedAccountMeta { + tree_info: packed_state_tree.packed_tree_infos[0], + address: compressed_delegated_record.address.unwrap(), + output_state_tree_index: packed_state_tree.output_tree_index, + }; + + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + let delegate_ix = create_delegate_compressed_ix( + counter_auth.pubkey(), + &remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + DelegateCompressedArgs { + validator: Some(self.validator_kp.pubkey()), + validity_proof: proof.proof.into(), + account_meta: account_meta.into(), + }, + ); + + let latest_block_hash = + self.rpc_client.get_latest_blockhash().await.unwrap(); + let tx = Transaction::new_signed_with_payer( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(300_000), + delegate_ix, + ], + Some(&counter_auth.pubkey()), + &[&counter_auth], + latest_block_hash, + ); + debug!("Delegate transaction: {:?}", tx.signatures[0]); + self.rpc_client + .send_and_confirm_transaction_with_spinner_and_config( + &tx, + CommitmentConfig::confirmed(), + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ) + .await + .expect("Failed to delegate account"); + + // Wait for the indexer to index the account + sleep_ms(1500).await; + + self + } + + pub async fn undelegate_compressed_counter( + &self, + counter_auth: &Keypair, + redelegate: bool, + ) -> &Self { + debug!( + "Undelegating compressed counter account {}", + counter_auth.pubkey() + ); + let counter_pda = self.counter_pda(&counter_auth.pubkey()); + // Match the non-compressed path: once commit+undelegate starts, the + // local delegated account must be treated as undelegating until the + // chain subscription delivers the post-undelegation state. + self.bank.force_undelegation(&counter_pda); + // The committor service will call this in order to have + // chainlink subscribe to account updates of the counter account + self.chainlink + .undelegation_requested(counter_pda) + .await + .unwrap(); + + // In order to make the account undelegatable we first need to + // commmit and finalize + let (pda, _bump) = FlexiCounter::pda(&counter_auth.pubkey()); + let record_address = derive_cda_from_pda(&pda); + let (compressed_account, proof) = + self.get_compressed_account_and_proof(&record_address).await; + let mut remaining_accounts = self.get_packed_accounts(); + + let packed_tree_accounts = proof + .pack_tree_infos(&mut remaining_accounts) + .state_trees + .unwrap(); + + let account_meta = CompressedAccountMeta { + tree_info: packed_tree_accounts.packed_tree_infos[0], + address: compressed_account.address.unwrap(), + output_state_tree_index: packed_tree_accounts.output_tree_index, + }; + + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + let commit_ix = + compressed_delegation_client::builders::CommitAndFinalizeBuilder { + validator: self.validator_kp.pubkey(), + delegated_account: pda, + args: CommitAndFinalizeArgs { + current_compressed_delegated_account_data: + compressed_account.data.unwrap().data.to_vec(), + new_data: borsh::to_vec(&FlexiCounter::new( + "COUNTER".to_string(), + )) + .unwrap(), + account_meta: account_meta.into(), + validity_proof: proof.proof.into(), + update_nonce: 1, + allow_undelegation: true, + }, + remaining_accounts: remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + } + .instruction() + .unwrap(); + + let latest_block_hash = + self.rpc_client.get_latest_blockhash().await.unwrap(); + self.rpc_client + .send_and_confirm_transaction_with_spinner_and_config( + &Transaction::new_signed_with_payer( + &[commit_ix], + Some(&self.validator_kp.pubkey()), + &[&self.validator_kp], + latest_block_hash, + ), + CommitmentConfig::confirmed(), + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ) + .await + .expect("Failed to commit account"); + + // Wait for the indexer to index the account + sleep_ms(500).await; + + let (compressed_account, proof) = + self.get_compressed_account_and_proof(&record_address).await; + + let mut remaining_accounts = self.get_packed_accounts(); + + let packed_state_tree = proof + .pack_tree_infos(&mut remaining_accounts) + .state_trees + .unwrap(); + let account_meta = CompressedAccountMeta { + tree_info: packed_state_tree.packed_tree_infos[0], + address: compressed_account.address.unwrap(), + output_state_tree_index: packed_state_tree.output_tree_index, + }; + + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + let undelegate_ix = + compressed_delegation_client::builders::UndelegateBuilder { + payer: counter_auth.pubkey(), + delegated_account: counter_pda, + owner_program: program_flexi_counter::ID, + system_program: system_program::ID, + args: UndelegateArgs { + validity_proof: proof.proof.into(), + delegation_record_account_meta: account_meta.into(), + compressed_delegated_record: + CompressedDelegationRecord::try_from_slice( + &compressed_account.data.clone().unwrap().data, + ) + .unwrap(), + }, + remaining_accounts: remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + } + .instruction() + .unwrap(); + let latest_block_hash = + self.rpc_client.get_latest_blockhash().await.unwrap(); + let tx = Transaction::new_signed_with_payer( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(250_000), + undelegate_ix, + ], + Some(&counter_auth.pubkey()), + &[&counter_auth], + latest_block_hash, + ); + debug!("Undelegate transaction: {:?}", tx.signatures[0]); + self.rpc_client + .send_and_confirm_transaction_with_spinner_and_config( + &tx, + CommitmentConfig::confirmed(), + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ) + .await + .expect("Failed to undelegate account"); + + // Build instructions and required signers + if redelegate { + // Wait for the indexer to index the account + sleep_ms(1500).await; + + self.delegate_compressed_counter(counter_auth).await + } else { + self + } + } + pub async fn top_up_ephemeral_fee_balance( &self, payer: &Keypair, @@ -403,4 +785,35 @@ impl IxtestContext { pub fn get_rpc_client(commitment: CommitmentConfig) -> RpcClient { RpcClient::new_with_commitment(RPC_URL.to_string(), commitment) } + + fn get_packed_accounts(&self) -> PackedAccounts { + let system_account_meta_config = SystemAccountMetaConfig::new( + compressed_delegation_client::ID.to_bytes().into(), + ); + let mut remaining_accounts = PackedAccounts::default(); + remaining_accounts + .add_system_accounts_v2(system_account_meta_config) + .unwrap(); + remaining_accounts + } + + async fn get_compressed_account_and_proof( + &self, + pubkey: &Pubkey, + ) -> (CompressedAccount, ValidityProofWithContext) { + let compressed_account = self + .photon_client + .get_compressed_account(pubkey.to_bytes(), None) + .await + .unwrap() + .value + .unwrap(); + let validity_proof = self + .photon_client + .get_validity_proof(vec![compressed_account.hash], vec![], None) + .await + .unwrap() + .value; + (compressed_account, validity_proof) + } } diff --git a/test-integration/test-chainlink/src/test_context.rs b/test-integration/test-chainlink/src/test_context.rs index 83277122a..57eeae490 100644 --- a/test-integration/test-chainlink/src/test_context.rs +++ b/test-integration/test-chainlink/src/test_context.rs @@ -17,6 +17,7 @@ use magicblock_chainlink::{ accounts::account_shared_with_owner, cloner_stub::ClonerStub, deleg::add_delegation_record_for, + photon_client_mock::PhotonClientMock, rpc_client_mock::{ChainRpcClientMock, ChainRpcClientMockBuilder}, utils::{create_test_lru_cache, create_test_lru_cache_with_config}, }, @@ -37,6 +38,7 @@ pub type TestChainlink = Chainlink< ChainPubsubClientMock, AccountsBankStub, ClonerStub, + PhotonClientMock, >; #[derive(Clone)] @@ -46,7 +48,13 @@ pub struct TestContext { pub chainlink: Arc, pub bank: Arc, pub remote_account_provider: Option< - Arc>, + Arc< + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, + >, >, pub cloner: Arc, pub validator_pubkey: Pubkey, @@ -54,13 +62,14 @@ pub struct TestContext { impl TestContext { pub async fn init(slot: Slot) -> Self { - let (rpc_client, pubsub_client) = { + let (rpc_client, pubsub_client, photon_client) = { let rpc_client = ChainRpcClientMockBuilder::new().slot(slot).build(); let (updates_sndr, updates_rcvr) = mpsc::channel(100); let pubsub_client = ChainPubsubClientMock::new(updates_sndr, updates_rcvr); - (rpc_client, pubsub_client) + let photon_client = PhotonClientMock::default(); + (rpc_client, pubsub_client, photon_client) }; let lifecycle_mode = LifecycleMode::Ephemeral; @@ -85,6 +94,7 @@ impl TestContext { RemoteAccountProvider::try_from_clients_and_mode( rpc_client.clone(), pubsub_client.clone(), + photon_client.clone(), tx, &config, subscribed_accounts, diff --git a/test-integration/test-chainlink/tests/ix_01_ensure-accounts.rs b/test-integration/test-chainlink/tests/ix_01_ensure-accounts.rs index b48f19e6d..e2c63d7d2 100644 --- a/test-integration/test-chainlink/tests/ix_01_ensure-accounts.rs +++ b/test-integration/test-chainlink/tests/ix_01_ensure-accounts.rs @@ -94,3 +94,44 @@ async fn ixtest_write_existing_account_valid_delegation_record() { // TODO(thlorenz): @ implement this test when we can actually delegate to a specific // authority: test_write_existing_account_other_authority + +// ----------------- +// BasicScenarios: Compressed account is initialized and already delegated to us +// ----------------- +#[tokio::test] +async fn ixtest_write_existing_account_compressed() { + init_logger(); + + let ctx = IxtestContext::init().await; + + let counter_auth = Keypair::new(); + ctx.init_counter(&counter_auth) + .await + .init_compressed_delegation_record(&counter_auth) + .await + .delegate_compressed_counter(&counter_auth) + .await; + + let counter_pda = ctx.counter_pda(&counter_auth.pubkey()); + info!(counter =% counter_pda, "init"); + let pubkeys = [counter_pda]; + + ctx.chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_delegated!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id() + ); + assert_not_subscribed!(ctx.chainlink, &[&counter_pda]); +} diff --git a/test-integration/test-chainlink/tests/ix_03_deleg_after_sub.rs b/test-integration/test-chainlink/tests/ix_03_deleg_after_sub.rs index 8c91555ae..e7badfdbc 100644 --- a/test-integration/test-chainlink/tests/ix_03_deleg_after_sub.rs +++ b/test-integration/test-chainlink/tests/ix_03_deleg_after_sub.rs @@ -95,3 +95,90 @@ async fn ixtest_deleg_after_subscribe_case2() { ); } } + +#[tokio::test] +async fn ixtest_deleg_after_subscribe_case2_compressed() { + init_logger(); + + let ctx = IxtestContext::init().await; + + let counter_auth = Keypair::new(); + let counter_pda = ctx.counter_pda(&counter_auth.pubkey()); + let pubkeys = [counter_pda]; + info!(counter =% counter_pda, "init"); + + // 1. Initially the account does not exist + { + info!("1. Initially the account does not exist"); + let res = ctx + .chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetAccount, + None, + ) + .await + .unwrap(); + + assert_not_found!(res, &pubkeys); + assert_not_cloned!(ctx.cloner, &pubkeys); + assert_not_subscribed!(ctx.chainlink, &[&counter_pda]); + } + + // 2. Account created with original owner (program) + { + info!("2. Create account owned by program_flexi_counter"); + ctx.init_counter(&counter_auth).await; + + ctx.chainlink + .ensure_accounts( + &pubkeys, + Some(&pubkeys), + AccountFetchOrigin::GetAccount, + None, + ) + .await + .unwrap(); + + // Assert cloned account state matches the remote account and slot + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_undelegated!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id() + ); + + assert_subscribed_without_delegation_record!(ctx.chainlink, &pubkeys); + } + + // 3. Account delegated to us + { + info!("3. Delegate account to us"); + ctx.init_compressed_delegation_record(&counter_auth) + .await + .delegate_compressed_counter(&counter_auth) + .await; + + ctx.chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetAccount, + None, + ) + .await + .unwrap(); + + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_delegated!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id() + ); + + assert_not_subscribed!(ctx.chainlink, &[&counter_pda]); + } +} diff --git a/test-integration/test-chainlink/tests/ix_06_redeleg_us_separate_slots.rs b/test-integration/test-chainlink/tests/ix_06_redeleg_us_separate_slots.rs index 64a6821e0..6b1a2ab53 100644 --- a/test-integration/test-chainlink/tests/ix_06_redeleg_us_separate_slots.rs +++ b/test-integration/test-chainlink/tests/ix_06_redeleg_us_separate_slots.rs @@ -12,6 +12,8 @@ use solana_sdk::{signature::Keypair, signer::Signer}; use test_chainlink::{ixtest_context::IxtestContext, sleep_ms}; use tracing::*; +const RETRIES: u64 = 30; + #[tokio::test] async fn ixtest_undelegate_redelegate_to_us_in_separate_slots() { init_logger(); @@ -51,7 +53,7 @@ async fn ixtest_undelegate_redelegate_to_us_in_separate_slots() { &[counter_pda], account.remote_slot(), program_flexi_counter::id(), - 30 + RETRIES ); // Accounts delegated to us should not be tracked via subscription @@ -95,7 +97,7 @@ async fn ixtest_undelegate_redelegate_to_us_in_separate_slots() { &[counter_pda], account.remote_slot(), program_flexi_counter::id(), - 30 + RETRIES ); // Accounts delegated to us should not be tracked via subscription @@ -105,3 +107,102 @@ async fn ixtest_undelegate_redelegate_to_us_in_separate_slots() { ); } } + +#[tokio::test] +async fn ixtest_undelegate_redelegate_to_us_in_separate_slots_compressed() { + init_logger(); + + let ctx = IxtestContext::init().await; + + // Create and delegate a counter account to us + let counter_auth = Keypair::new(); + ctx.init_counter(&counter_auth) + .await + .init_compressed_delegation_record(&counter_auth) + .await + .delegate_compressed_counter(&counter_auth) + .await; + + let counter_pda = ctx.counter_pda(&counter_auth.pubkey()); + let pubkeys = [counter_pda]; + + // 1. Account delegated to us - readable and writable + { + info!("1. Account delegated to us"); + + ctx.chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + sleep_ms(1_500).await; + + // Account should be cloned as delegated + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_delegated_with_retries!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id(), + RETRIES + ); + + // Accounts delegated to us should not be tracked via subscription + assert_not_subscribed!(ctx.chainlink, &[&counter_pda]); + } + + // 2. Account is undelegated - writes refused, subscription set + { + info!( + "2. Account is undelegated - Would refuse write (undelegated on chain)" + ); + + ctx.undelegate_compressed_counter(&counter_auth, false) + .await; + sleep_ms(1_500).await; + + // Account should be cloned as undelegated (owned by program again) + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_undelegated!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id() + ); + + assert_subscribed_without_delegation_record!(ctx.chainlink, &pubkeys); + } + + // 3. Account redelegated to us (separate slot) - writes allowed again + { + info!("3. Account redelegated to us - Would allow write"); + ctx.delegate_compressed_counter(&counter_auth).await; + + ctx.chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + + // Account should be cloned as delegated back to us + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_delegated_with_retries!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id(), + RETRIES + ); + + // Accounts delegated to us should not be tracked via subscription + assert_not_subscribed!(ctx.chainlink, &[&counter_pda]); + } +} diff --git a/test-integration/test-chainlink/tests/ix_07_redeleg_us_same_slot.rs b/test-integration/test-chainlink/tests/ix_07_redeleg_us_same_slot.rs index 75641f651..94dd8d583 100644 --- a/test-integration/test-chainlink/tests/ix_07_redeleg_us_same_slot.rs +++ b/test-integration/test-chainlink/tests/ix_07_redeleg_us_same_slot.rs @@ -87,3 +87,74 @@ async fn ixtest_undelegate_redelegate_to_us_in_same_slot() { ); } } + +#[tokio::test] +async fn ixtest_undelegate_redelegate_to_us_in_same_slot_compressed() { + init_logger(); + + let ctx = IxtestContext::init().await; + + // Create and delegate a counter account to us + let counter_auth = Keypair::new(); + ctx.init_counter(&counter_auth) + .await + .init_compressed_delegation_record(&counter_auth) + .await + .delegate_compressed_counter(&counter_auth) + .await; + + let counter_pda = ctx.counter_pda(&counter_auth.pubkey()); + let pubkeys = [counter_pda]; + + // 1. Account delegated to us - readable and writable + { + info!("1. Account delegated to us"); + + ctx.chainlink + .ensure_accounts( + &pubkeys, + None, + AccountFetchOrigin::GetMultipleAccounts, + None, + ) + .await + .unwrap(); + sleep_ms(1_500).await; + + // Account should be cloned as delegated + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_delegated!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id() + ); + + // Accounts delegated to us should not be tracked via subscription + assert_not_subscribed!(ctx.chainlink, &[&counter_pda]); + } + + // 2. Account is undelegated and redelegated to us (same slot) - writes allowed again + { + info!( + "2. Account is undelegated and redelegated to us in the same slot" + ); + + ctx.undelegate_compressed_counter(&counter_auth, true).await; + + // Wait for pubsub update to trigger subscription handler + sleep_ms(1_500).await; + + // Account should still be cloned as delegated to us + let account = ctx.cloner.get_account(&counter_pda).unwrap(); + assert_cloned_as_delegated!( + ctx.cloner, + &[counter_pda], + account.remote_slot(), + program_flexi_counter::id() + ); + + // Accounts delegated to us should not be tracked via subscription + assert_not_subscribed!(ctx.chainlink, &[&counter_pda]); + } +} diff --git a/test-integration/test-chainlink/tests/ix_remote_account_provider.rs b/test-integration/test-chainlink/tests/ix_remote_account_provider.rs index c1f6da65c..5821146f1 100644 --- a/test-integration/test-chainlink/tests/ix_remote_account_provider.rs +++ b/test-integration/test-chainlink/tests/ix_remote_account_provider.rs @@ -2,15 +2,15 @@ use magicblock_chainlink::{ remote_account_provider::{ chain_rpc_client::ChainRpcClientImpl, chain_updates_client::ChainUpdatesClient, - config::RemoteAccountProviderConfig, Endpoint, Endpoints, - RemoteAccountProvider, RemoteAccountUpdateSource, + config::RemoteAccountProviderConfig, photon_client::PhotonClientImpl, + Endpoint, Endpoints, RemoteAccountProvider, RemoteAccountUpdateSource, }, submux::SubMuxClient, testing::utils::{ airdrop, await_next_slot, current_slot, dump_remote_account_lamports, dump_remote_account_update_source, get_remote_account_lamports, get_remote_account_update_sources, init_logger, random_pubkey, - sleep_ms, PUBSUB_URL, RPC_URL, + sleep_ms, COMPRESSION_URL, PUBSUB_URL, RPC_URL, }, AccountFetchOrigin, }; @@ -22,9 +22,11 @@ use solana_rpc_client_api::{ use tokio::sync::mpsc; use tracing::{debug, info}; -async fn init_remote_account_provider( -) -> RemoteAccountProvider> -{ +async fn init_remote_account_provider() -> RemoteAccountProvider< + ChainRpcClientImpl, + SubMuxClient, + PhotonClientImpl, +> { let (fwd_tx, _fwd_rx) = mpsc::channel(100); let endpoints_vec = vec![ Endpoint::Rpc { @@ -35,11 +37,16 @@ async fn init_remote_account_provider( url: PUBSUB_URL.to_string(), label: "test-ws".to_string(), }, + Endpoint::Compression { + label: "test-compression".to_string(), + url: COMPRESSION_URL.to_string(), + }, ]; let endpoints = Endpoints::from(endpoints_vec.as_slice()); let provider = RemoteAccountProvider::< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, >::try_from_urls_and_config( &endpoints, CommitmentConfig::confirmed(), diff --git a/test-integration/test-committor-service/Cargo.toml b/test-integration/test-committor-service/Cargo.toml index 53e29921d..b39e180b0 100644 --- a/test-integration/test-committor-service/Cargo.toml +++ b/test-integration/test-committor-service/Cargo.toml @@ -6,8 +6,13 @@ edition.workspace = true [dev-dependencies] async-trait = { workspace = true } borsh = { workspace = true } +compressed-delegation-client = { workspace = true } tracing = { workspace = true } futures = { workspace = true } +light-client = { workspace = true, features = ["v2"] } +light-compressed-account = { workspace = true } +light-sdk = { workspace = true, features = ["v2"] } +light-sdk-types = { workspace = true, features = ["v2"] } magicblock-core = { workspace = true } magicblock-committor-program = { workspace = true, features = [ "no-entrypoint", @@ -26,6 +31,7 @@ program-schedulecommit = { workspace = true, features = ["no-entrypoint"] } rand = { workspace = true } solana-account = { workspace = true } solana-commitment-config = { workspace = true } +solana-compute-budget-interface = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/test-committor-service/tests/common.rs b/test-integration/test-committor-service/tests/common.rs index 66f896211..cb688240e 100644 --- a/test-integration/test-committor-service/tests/common.rs +++ b/test-integration/test-committor-service/tests/common.rs @@ -7,11 +7,12 @@ use std::{ }; use async_trait::async_trait; +use light_client::indexer::photon_indexer::PhotonIndexer; use magicblock_committor_service::{ intent_executor::{ task_info_fetcher::{ - CacheTaskInfoFetcher, TaskInfoFetcher, TaskInfoFetcherError, - TaskInfoFetcherResult, + CacheTaskInfoFetcher, CompressedData, TaskInfoFetcher, + TaskInfoFetcherError, TaskInfoFetcherResult, }, IntentExecutorImpl, }, @@ -45,9 +46,15 @@ pub async fn create_test_client() -> MagicblockRpcClient { MagicblockRpcClient::new(Arc::new(rpc_client)) } +pub fn create_test_photon_indexer() -> Arc { + Arc::new(PhotonIndexer::new("http://localhost:8784".to_string())) +} + // Test fixture structure pub struct TestFixture { pub rpc_client: MagicblockRpcClient, + #[allow(dead_code)] + pub photon_indexer: Arc, pub table_mania: TableMania, #[allow(dead_code)] pub authority: Keypair, @@ -63,6 +70,7 @@ impl TestFixture { pub async fn new_with_keypair(authority: Keypair) -> Self { let rpc_client = create_test_client().await; + let photon_indexer = create_test_photon_indexer(); // TableMania let gc_config = GarbageCollectorConfig::default(); @@ -81,6 +89,7 @@ impl TestFixture { let compute_budget_config = ComputeBudgetConfig::new(1_000_000); Self { rpc_client, + photon_indexer, table_mania, authority, compute_budget_config, @@ -171,6 +180,7 @@ impl TaskInfoFetcher for MockTaskInfoFetcher { async fn fetch_next_commit_nonces( &self, pubkeys: &[Pubkey], + _: bool, _: u64, ) -> TaskInfoFetcherResult> { Ok(pubkeys.iter().map(|pubkey| (*pubkey, 0)).collect()) @@ -179,6 +189,7 @@ impl TaskInfoFetcher for MockTaskInfoFetcher { async fn fetch_current_commit_nonces( &self, pubkeys: &[Pubkey], + _: bool, _: u64, ) -> TaskInfoFetcherResult> { Ok(pubkeys.iter().map(|pubkey| (*pubkey, 0)).collect()) @@ -211,6 +222,14 @@ impl TaskInfoFetcher for MockTaskInfoFetcher { .collect() }) } + + async fn get_compressed_data( + &self, + _: &Pubkey, + _: Option, + ) -> TaskInfoFetcherResult { + Ok(CompressedData::default()) + } } #[allow(dead_code)] diff --git a/test-integration/test-committor-service/tests/test_intent_executor.rs b/test-integration/test-committor-service/tests/test_intent_executor.rs index 5355379d3..418492c37 100644 --- a/test-integration/test-committor-service/tests/test_intent_executor.rs +++ b/test-integration/test-committor-service/tests/test_intent_executor.rs @@ -103,9 +103,11 @@ impl TestEnv { .await; let transaction_preparator = fixture.create_transaction_preparator(); - let task_info_fetcher = Arc::new(CacheTaskInfoFetcher::new( - RpcTaskInfoFetcher::new(fixture.rpc_client.clone()), - )); + let task_info_fetcher = + Arc::new(CacheTaskInfoFetcher::new(RpcTaskInfoFetcher::new( + fixture.rpc_client.clone(), + fixture.photon_indexer.clone(), + ))); let tm = &fixture.table_mania; let mut pre_test_tablemania_state = HashMap::new(); @@ -160,6 +162,7 @@ async fn test_commit_id_error_parsing() { task_info_fetcher .fetch_next_commit_nonces( &intent.get_undelegate_intent_pubkeys().unwrap(), + false, remote_slot, ) .await @@ -486,7 +489,11 @@ async fn test_commit_id_error_recovery() { // Invalidate commit nonce cache let res = task_info_fetcher - .fetch_next_commit_nonces(&[committed_account.pubkey], remote_slot) + .fetch_next_commit_nonces( + &[committed_account.pubkey], + false, + remote_slot, + ) .await; assert!(res.is_ok()); assert!(res.unwrap().contains_key(&committed_account.pubkey)); @@ -696,7 +703,11 @@ async fn test_commit_id_and_action_errors_recovery() { // Invalidate commit nonce cache let res = task_info_fetcher - .fetch_next_commit_nonces(&[committed_account.pubkey], remote_slot) + .fetch_next_commit_nonces( + &[committed_account.pubkey], + false, + remote_slot, + ) .await; assert!(res.is_ok()); assert!(res.unwrap().contains_key(&committed_account.pubkey)); @@ -917,7 +928,7 @@ async fn test_commit_id_actions_cpi_limit_errors_recovery() { // Force CommitIDError by invalidating the commit-nonce cache before running let pubkeys: Vec<_> = committed_accounts.iter().map(|c| c.pubkey).collect(); let mut invalidated_keys = task_info_fetcher - .fetch_next_commit_nonces(&pubkeys, Default::default()) + .fetch_next_commit_nonces(&pubkeys, false, Default::default()) .await .unwrap(); @@ -1273,9 +1284,11 @@ async fn test_action_callback_fired_on_timeout() { // Build executor with zero timeout so actions time out before execution let callback_executor = MockActionsCallbackExecutor::default(); - let task_info_fetcher = Arc::new(CacheTaskInfoFetcher::new( - RpcTaskInfoFetcher::new(fixture.rpc_client.clone()), - )); + let task_info_fetcher = + Arc::new(CacheTaskInfoFetcher::new(RpcTaskInfoFetcher::new( + fixture.rpc_client.clone(), + fixture.photon_indexer.clone(), + ))); let mut intent_executor = IntentExecutorImpl::new( fixture.rpc_client.clone(), fixture.create_transaction_preparator(), diff --git a/test-integration/test-committor-service/tests/utils/instructions.rs b/test-integration/test-committor-service/tests/utils/instructions.rs index 7e4b6585f..f117da566 100644 --- a/test-integration/test-committor-service/tests/utils/instructions.rs +++ b/test-integration/test-committor-service/tests/utils/instructions.rs @@ -1,3 +1,28 @@ +use std::sync::Arc; + +use light_client::indexer::{ + photon_indexer::PhotonIndexer, AddressWithTree, Indexer, + ValidityProofWithContext, +}; +use light_sdk::{ + instruction::{ + account_meta::CompressedAccountMeta, PackedAccounts, + SystemAccountMetaConfig, + }, + sdk_types::PackedAddressTreeInfo, +}; +use magicblock_core::compression::{ + derive_cda_from_pda, ADDRESS_TREE, OUTPUT_QUEUE, +}; +use magicblock_program::validator::validator_authority_id; +use program_flexi_counter::{ + instruction::{ + create_delegate_compressed_ix, + create_init_compressed_delegation_record_ix, create_init_ix, + DelegateCompressedArgs, InitDelegationRecordArgs, + }, + state::FlexiCounter, +}; use solana_pubkey::Pubkey; use solana_sdk::{instruction::Instruction, rent::Rent, signature::Keypair}; use test_kit::Signer; @@ -18,6 +43,18 @@ pub struct InitAccountAndDelegateIxs { pub rent_excempt: u64, } +pub struct InitAccountAndCompressedRecordIxs { + pub init: Instruction, + pub init_record: Instruction, + pub pda: Pubkey, +} + +pub struct DelegateCompressedIx { + pub delegate: Instruction, + pub pda: Pubkey, + pub address: [u8; 32], +} + pub fn init_account_and_delegate_ixs( payer: Pubkey, bytes: u64, @@ -51,6 +88,142 @@ pub fn init_account_and_delegate_ixs( } } +pub async fn init_account_and_compressed_record_ixs( + payer: Pubkey, + photon_indexer: Arc, +) -> InitAccountAndCompressedRecordIxs { + let (pda, _bump) = FlexiCounter::pda(&payer); + let record_address = derive_cda_from_pda(&pda); + + let init_counter_ix = create_init_ix(payer, "COUNTER".to_string()); + + let system_account_meta_config = SystemAccountMetaConfig::new( + compressed_delegation_client::ID.to_bytes().into(), + ); + let mut remaining_accounts = PackedAccounts::default(); + remaining_accounts + .add_system_accounts_v2(system_account_meta_config) + .unwrap(); + + let rpc_result: ValidityProofWithContext = photon_indexer + .get_validity_proof( + vec![], + vec![AddressWithTree { + address: record_address.to_bytes(), + tree: ADDRESS_TREE.to_bytes().into(), + }], + None, + ) + .await + .unwrap() + .value; + + // Insert trees in accounts + let address_merkle_tree_pubkey_index = + remaining_accounts.insert_or_get(ADDRESS_TREE.to_bytes().into()); + let state_queue_pubkey_index = + remaining_accounts.insert_or_get(OUTPUT_QUEUE.to_bytes().into()); + + let packed_address_tree_info = PackedAddressTreeInfo { + root_index: rpc_result.addresses[0].root_index, + address_merkle_tree_pubkey_index, + address_queue_pubkey_index: address_merkle_tree_pubkey_index, + }; + + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + let init_record_ix = create_init_compressed_delegation_record_ix( + payer, + &remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + InitDelegationRecordArgs { + validity_proof: rpc_result.proof.into(), + address_tree_info: packed_address_tree_info.into(), + output_state_tree_index: state_queue_pubkey_index, + }, + ); + + InitAccountAndCompressedRecordIxs { + init: init_counter_ix, + init_record: init_record_ix, + pda, + } +} + +pub async fn delegate_compressed_ixs( + payer: Pubkey, + photon_indexer: Arc, +) -> DelegateCompressedIx { + let (pda, _bump) = FlexiCounter::pda(&payer); + let record_address = derive_cda_from_pda(&pda); + + let compressed_account = photon_indexer + .get_compressed_account(record_address.to_bytes(), None) + .await + .unwrap() + .value + .unwrap(); + + let system_account_meta_config = SystemAccountMetaConfig::new( + compressed_delegation_client::ID.to_bytes().into(), + ); + let mut remaining_accounts = PackedAccounts::default(); + remaining_accounts + .add_system_accounts_v2(system_account_meta_config) + .unwrap(); + + let rpc_result: ValidityProofWithContext = photon_indexer + .get_validity_proof(vec![compressed_account.hash], vec![], None) + .await + .unwrap() + .value; + + // Insert trees in accounts + let state_queue_pubkey_index = + remaining_accounts.insert_or_get(OUTPUT_QUEUE.to_bytes().into()); + + let packed_trees_info = rpc_result.pack_tree_infos(&mut remaining_accounts); + let packed_state_tree_info = packed_trees_info.state_trees.unwrap(); + + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + let delegate_ix = create_delegate_compressed_ix( + payer, + &remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + DelegateCompressedArgs { + validator: Some(validator_authority_id()), + validity_proof: rpc_result.proof.into(), + account_meta: CompressedAccountMeta { + tree_info: packed_state_tree_info.packed_tree_infos[0], + address: compressed_account.address.unwrap(), + output_state_tree_index: state_queue_pubkey_index, + } + .into(), + }, + ); + + DelegateCompressedIx { + delegate: delegate_ix, + pda, + address: record_address.to_bytes(), + } +} + pub struct InitOrderBookAndDelegateIxs { pub init: Instruction, pub delegate: Instruction, diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index 5e01d0005..4497348a6 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -1,5 +1,9 @@ +use std::sync::Arc; + +use light_client::indexer::{photon_indexer::PhotonIndexer, Indexer}; use solana_account::Account; use solana_commitment_config::CommitmentConfig; +use solana_compute_budget_interface::ComputeBudgetInstruction; use solana_pubkey::Pubkey; use solana_rpc_client::nonblocking::rpc_client::RpcClient; use solana_rpc_client_api::config::{ @@ -14,8 +18,10 @@ use solana_system_interface::instruction as system_instruction; use tracing::{debug, error}; use crate::utils::instructions::{ + delegate_compressed_ixs, init_account_and_compressed_record_ixs, init_account_and_delegate_ixs, init_order_book_account_and_delegate_ixs, - init_validator_fees_vault_ix, InitAccountAndDelegateIxs, + init_validator_fees_vault_ix, DelegateCompressedIx, + InitAccountAndCompressedRecordIxs, InitAccountAndDelegateIxs, InitOrderBookAndDelegateIxs, }; @@ -317,6 +323,98 @@ pub async fn init_and_delegate_account_on_chain( (pda, pda_acc) } +/// This needs to be run for each test that required a new counter to be compressed delegated +#[allow(dead_code)] +pub async fn init_and_delegate_compressed_record_on_chain( + counter_auth: &Keypair, +) -> (Pubkey, [u8; 32], Account) { + let rpc_client = RpcClient::new("http://localhost:7799".to_string()); + let photon_indexer = + Arc::new(PhotonIndexer::new("http://localhost:8784".to_string())); + + rpc_client + .request_airdrop(&counter_auth.pubkey(), 777 * LAMPORTS_PER_SOL) + .await + .unwrap(); + debug!("Airdropped to counter auth: {} SOL", 777 * LAMPORTS_PER_SOL); + + let InitAccountAndCompressedRecordIxs { + init: init_counter_ix, + init_record: init_record_ix, + pda, + } = init_account_and_compressed_record_ixs( + counter_auth.pubkey(), + photon_indexer.clone(), + ) + .await; + + let latest_block_hash = rpc_client.get_latest_blockhash().await.unwrap(); + // 1. Init account and record + rpc_client + .send_and_confirm_transaction_with_spinner_and_config( + &Transaction::new_signed_with_payer( + &[init_counter_ix, init_record_ix], + Some(&counter_auth.pubkey()), + &[&counter_auth], + latest_block_hash, + ), + CommitmentConfig::confirmed(), + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ) + .await + .expect("Failed to init account"); + debug!("Init account: {:?}", pda); + + let pda_acc = get_account!(rpc_client, pda, "pda"); + + // 2. Delegate + let DelegateCompressedIx { + delegate: delegate_ix, + pda, + address, + } = delegate_compressed_ixs(counter_auth.pubkey(), photon_indexer.clone()) + .await; + let tx = Transaction::new_signed_with_payer( + &[ + ComputeBudgetInstruction::set_compute_unit_limit(250_000), + delegate_ix, + ], + Some(&counter_auth.pubkey()), + &[&counter_auth], + latest_block_hash, + ); + rpc_client + .send_and_confirm_transaction_with_spinner_and_config( + &tx, + CommitmentConfig::confirmed(), + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ) + .await + .inspect_err(|err| { + error!( + "Failed to init compressed record: {err:?}, signature: {:?}", + tx.signatures[0] + ) + }) + .expect("Failed to init compressed record"); + + let compressed_account = photon_indexer + .get_compressed_account(address, None) + .await + .unwrap() + .value + .unwrap(); + debug!("Compressed record: {:?}", compressed_account); + + (pda, address, pda_acc) +} + /// This needs to be run for each test that required a new order_book to be delegated #[allow(dead_code)] pub async fn init_and_delegate_order_book_on_chain( diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index 63e4b97be..499f6ccda 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -9,13 +9,16 @@ use integration_test_tools::{ loaded_accounts::LoadedAccounts, toml_to_args::ProgramLoader, validator::{ - resolve_workspace_dir, start_magic_block_validator_with_config, + resolve_workspace_dir, start_light_validator_with_config, + start_magic_block_validator_with_config, start_test_validator_with_config, TestRunnerPaths, }, }; use teepee::Teepee; use test_runner::{ - cleanup::{cleanup_devnet_only, cleanup_validators}, + cleanup::{ + cleanup_devnet_only, cleanup_light_validator, cleanup_validators, + }, env_config::TestConfigViaEnvVars, signal::wait_for_ctrlc, }; @@ -152,7 +155,7 @@ fn run_restore_ledger_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(devnet_validator, None, None, success_output()) } } @@ -189,7 +192,7 @@ fn run_chainlink_tests( }; let start_devnet_validator = || match start_validator( "chainlink-conf.devnet.toml", - ValidatorCluster::Chain(None), + ValidatorCluster::Light, &loaded_chain_accounts, ) { Some(validator) => validator, @@ -207,7 +210,7 @@ fn run_chainlink_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run chainlink tests: {:?}", err); - cleanup_devnet_only(&mut devnet_validator); + cleanup_light_validator(&mut devnet_validator, "light"); return Err(err.into()); } }; @@ -216,7 +219,7 @@ fn run_chainlink_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(None, None, devnet_validator, success_output()) } } @@ -240,7 +243,7 @@ fn run_table_mania_and_committor_tests( let start_devnet_validator = || match start_validator( "committor-conf.devnet.toml", - ValidatorCluster::Chain(None), + ValidatorCluster::Light, &loaded_chain_accounts, ) { Some(validator) => validator, @@ -297,7 +300,7 @@ fn run_table_mania_and_committor_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run committor: {:?}", err); - cleanup_devnet_only(&mut devnet_validator); + cleanup_light_validator(&mut devnet_validator, "light"); return Err(err.into()); } } @@ -306,7 +309,7 @@ fn run_table_mania_and_committor_tests( success_output() }; - cleanup_devnet_only(&mut devnet_validator); + cleanup_light_validator(&mut devnet_validator, "light"); Ok((table_mania_test_output, committor_test_output)) } else { @@ -314,7 +317,7 @@ fn run_table_mania_and_committor_tests( || config.setup_devnet(COMMITTOR_TEST); let devnet_validator = setup_needed.then(start_devnet_validator); Ok(( - wait_for_ctrlc(devnet_validator, None, success_output())?, + wait_for_ctrlc(None, None, devnet_validator, success_output())?, success_output(), )) } @@ -409,7 +412,12 @@ fn run_schedule_commit_tests( let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); eprintln!("Setup validator(s)"); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output())?; + wait_for_ctrlc( + devnet_validator, + ephem_validator, + None, + success_output(), + )?; Ok((success_output(), success_output())) } } @@ -493,7 +501,12 @@ fn run_cloning_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + None, + success_output(), + ) } } @@ -550,7 +563,12 @@ fn run_magicblock_api_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + None, + success_output(), + ) } } @@ -609,7 +627,12 @@ fn run_magicblock_pubsub_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + None, + success_output(), + ) } } @@ -656,7 +679,7 @@ fn run_config_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(devnet_validator, None, None, success_output()) } } @@ -726,7 +749,12 @@ fn run_schedule_intents_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + None, + success_output(), + ) } } @@ -775,7 +803,7 @@ fn run_task_scheduler_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(devnet_validator, None, None, success_output()) } } @@ -851,6 +879,7 @@ fn resolve_paths(config_file: &str) -> TestRunnerPaths { enum ValidatorCluster { Chain(Option), Ephem, + Light, } impl ValidatorCluster { @@ -858,6 +887,7 @@ impl ValidatorCluster { match self { ValidatorCluster::Chain(_) => "CHAIN", ValidatorCluster::Ephem => "EPHEM", + ValidatorCluster::Light => "LIGHT", } } } @@ -881,6 +911,12 @@ fn start_validator( log_suffix, ) } + ValidatorCluster::Light => start_light_validator_with_config( + &test_runner_paths, + None, + loaded_chain_accounts, + log_suffix, + ), _ => start_magic_block_validator_with_config( &test_runner_paths, log_suffix, diff --git a/test-integration/test-runner/src/cleanup.rs b/test-integration/test-runner/src/cleanup.rs index b595559fe..491ef89f1 100644 --- a/test-integration/test-runner/src/cleanup.rs +++ b/test-integration/test-runner/src/cleanup.rs @@ -9,6 +9,15 @@ pub fn cleanup_validators( kill_validators(); } +pub fn cleanup_validators_with_light( + ephem_validator: &mut Child, + light_validator: &mut Child, +) { + cleanup_validator(ephem_validator, "ephemeral"); + cleanup_light_validator(light_validator, "light"); + kill_validators(); +} + pub fn cleanup_devnet_only(devnet_validator: &mut Child) { cleanup_validator(devnet_validator, "devnet"); kill_validators(); @@ -20,6 +29,20 @@ pub fn cleanup_validator(validator: &mut Child, label: &str) { }); } +pub fn cleanup_light_validator(validator: &mut Child, label: &str) { + validator.kill().unwrap_or_else(|err| { + panic!("Failed to kill {} validator ({:?})", label, err) + }); + let command = process::Command::new("light") + .arg("test-validator") + .arg("--stop") + .output() + .unwrap(); + if !command.status.success() { + panic!("Failed to stop light validator: {:?}", command); + } +} + fn kill_process(name: &str) { process::Command::new("pkill") .arg("-15") // SIGTERM (default) diff --git a/test-integration/test-runner/src/signal.rs b/test-integration/test-runner/src/signal.rs index 75fd97c0c..9cbdaeb93 100644 --- a/test-integration/test-runner/src/signal.rs +++ b/test-integration/test-runner/src/signal.rs @@ -4,11 +4,12 @@ use std::{ sync::mpsc::channel, }; -use crate::cleanup::cleanup_validator; +use crate::cleanup::{cleanup_light_validator, cleanup_validator}; pub fn wait_for_ctrlc( devnet_validator: Option, ephem_validator: Option, + light_validator: Option, output: Output, ) -> Result> { let (tx, rx) = channel(); @@ -25,6 +26,9 @@ pub fn wait_for_ctrlc( if let Some(mut validator) = ephem_validator { cleanup_validator(&mut validator, "ephemeral"); } + if let Some(mut validator) = light_validator { + cleanup_light_validator(&mut validator, "light"); + } Ok(output) } diff --git a/test-integration/test-tools/Cargo.toml b/test-integration/test-tools/Cargo.toml index ff3ace58e..3474c8392 100644 --- a/test-integration/test-tools/Cargo.toml +++ b/test-integration/test-tools/Cargo.toml @@ -14,7 +14,10 @@ serde = { workspace = true } ureq = { workspace = true } url = { workspace = true } magicblock-config = { workspace = true } -magicblock-delegation-program-api = { workspace = true, features = ["instruction"] } +magicblock-delegation-program-api = { workspace = true, features = [ + "instruction", +] } +shlex = { workspace = true } solana-commitment-config = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client = { workspace = true } diff --git a/test-integration/test-tools/src/validator.rs b/test-integration/test-tools/src/validator.rs index 9cfba52fc..b876ad41f 100644 --- a/test-integration/test-tools/src/validator.rs +++ b/test-integration/test-tools/src/validator.rs @@ -83,44 +83,7 @@ pub fn start_test_validator_with_config( let mut args = config_to_args(config_path, program_loader); let accounts_dir = workspace_dir.join("configs").join("accounts"); - let accounts = [ - ( - loaded_accounts.validator_authority().to_string(), - "validator-authority.json".to_string(), - ), - ( - loaded_accounts.luzid_authority().to_string(), - "luzid-authority.json".to_string(), - ), - ( - loaded_accounts.validator_fees_vault().to_string(), - "validator-fees-vault.json".to_string(), - ), - ( - loaded_accounts.protocol_fees_vault().to_string(), - "protocol-fees-vault.json".to_string(), - ), - ( - loaded_accounts.magic_fee_vault().to_string(), - "magic-fee-vault.json".to_string(), - ), - ( - "9yXjZTevvMp1XgZSZEaziPRgFiXtAQChpnP2oX9eCpvt".to_string(), - "non-delegated-cloneable-account1.json".to_string(), - ), - ( - "BHBuATGifAD4JbRpM5nVdyhKzPgv3p2CxLEHAqwBzAj5".to_string(), - "non-delegated-cloneable-account2.json".to_string(), - ), - ( - "2o48ieM95rmHqMWC5B3tTX4DL7cLm4m1Kuwjay3keQSv".to_string(), - "non-delegated-cloneable-account3.json".to_string(), - ), - ( - "2EmfL3MqL3YHABudGNmajjCpR13NNEn9Y4LWxbDm6SwR".to_string(), - "non-delegated-cloneable-account4.json".to_string(), - ), - ]; + let accounts = devnet_accounts(loaded_accounts); let resolved_extra_accounts = loaded_accounts.extra_accounts(workspace_dir, &accounts_dir); let accounts = accounts.iter().chain(&resolved_extra_accounts); @@ -157,6 +120,105 @@ pub fn start_test_validator_with_config( wait_for_validator(validator, port) } +pub fn start_light_validator_with_config( + test_runner_paths: &TestRunnerPaths, + program_loader: Option, + loaded_accounts: &LoadedAccounts, + log_suffix: &str, +) -> Option { + let TestRunnerPaths { + config_path, + root_dir, + workspace_dir, + } = test_runner_paths; + + let port = rpc_port_from_config(config_path); + let mut devnet_args = config_to_args(config_path, program_loader); + + // Remove args already set by light test-validator (and their values) + let args_to_remove = [ + ("--rpc-port", true), + ("--limit-ledger-size", true), + ("--log", false), + ("-r", false), + ]; + let mut filtered_devnet_args = Vec::with_capacity(devnet_args.len()); + let mut skip_next = false; + for arg in devnet_args { + if skip_next { + skip_next = false; + continue; + } + if let Some(&(_, has_value)) = + args_to_remove.iter().find(|&&(flag, _)| flag == arg) + { + skip_next = has_value; + continue; + } + filtered_devnet_args.push(arg); + } + devnet_args = filtered_devnet_args; + + // Add accounts to the validator args + let accounts_dir = workspace_dir.join("configs").join("accounts"); + let accounts = devnet_accounts(loaded_accounts); + let resolved_extra_accounts = + loaded_accounts.extra_accounts(workspace_dir, &accounts_dir); + let account_args = accounts + .iter() + .chain(&resolved_extra_accounts) + .flat_map(|(account, file)| { + let account_path = accounts_dir.join(file).canonicalize().unwrap(); + vec![ + "--account".to_string(), + account.clone(), + account_path.to_str().unwrap().to_string(), + ] + }) + .collect::>(); + devnet_args.extend(account_args); + + // Split args using shlex so that the light CLI can pass them to the validator + let validator_args = shlex::split( + format!("--validator-args=\"{}\"", devnet_args.join(" ")).as_str(), + ) + .ok_or_else(|| anyhow::anyhow!("invalid validator args")) + .unwrap(); + + let prover_port = 3001; + let mut light_args = vec![ + "--rpc-port".to_string(), + port.to_string(), + "--prover-port".to_string(), + prover_port.to_string(), + "--no-use-surfpool".to_string(), + ]; + light_args.extend(validator_args); + + let mut script = "#!/bin/bash\nlight test-validator".to_string(); + for arg in &light_args { + script.push_str(&format!(" \\\n {}", arg)); + } + let mut command = process::Command::new("light"); + let rust_log_style = + std::env::var("RUST_LOG_STYLE").unwrap_or(log_suffix.to_string()); + command + .arg("test-validator") + .args(light_args) + .env("RUST_LOG", "solana=warn") + .env("RUST_LOG_STYLE", rust_log_style) + .current_dir(root_dir); + + eprintln!("Starting light validator with {:?}", command); + eprintln!("{}", script); + let validator = command.spawn().expect("Failed to start validator"); + // Waiting for the prover, which is the last thing to start + let child = wait_for_validator(validator, prover_port); + // Waiting more because light starts the prover immediately but is not ready to serve RPC yet + sleep(Duration::from_secs(10)); + child +} + pub fn wait_for_validator(mut validator: Child, port: u16) -> Option { const SLEEP_DURATION: Duration = Duration::from_millis(400); let max_retries = if std::env::var("CI").is_ok() { @@ -350,6 +412,43 @@ pub fn resolve_programs( // Utilities // ----------------- +fn devnet_accounts(loaded_accounts: &LoadedAccounts) -> [(String, String); 8] { + [ + ( + loaded_accounts.validator_authority().to_string(), + "validator-authority.json".to_string(), + ), + ( + loaded_accounts.luzid_authority().to_string(), + "luzid-authority.json".to_string(), + ), + ( + loaded_accounts.validator_fees_vault().to_string(), + "validator-fees-vault.json".to_string(), + ), + ( + loaded_accounts.protocol_fees_vault().to_string(), + "protocol-fees-vault.json".to_string(), + ), + ( + "9yXjZTevvMp1XgZSZEaziPRgFiXtAQChpnP2oX9eCpvt".to_string(), + "non-delegated-cloneable-account1.json".to_string(), + ), + ( + "BHBuATGifAD4JbRpM5nVdyhKzPgv3p2CxLEHAqwBzAj5".to_string(), + "non-delegated-cloneable-account2.json".to_string(), + ), + ( + "2o48ieM95rmHqMWC5B3tTX4DL7cLm4m1Kuwjay3keQSv".to_string(), + "non-delegated-cloneable-account3.json".to_string(), + ), + ( + "2EmfL3MqL3YHABudGNmajjCpR13NNEn9Y4LWxbDm6SwR".to_string(), + "non-delegated-cloneable-account4.json".to_string(), + ), + ] +} + /// Unwraps the provided result and ensures to kill the validator before panicking /// if the result was an error #[macro_export] From 4071212d8a21b5cb321a19c267ae827162986a74 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Tue, 28 Apr 2026 15:20:14 +0200 Subject: [PATCH 003/110] feat: committor tests --- .github/workflows/ci-test-integration.yml | 2 +- Cargo.lock | 1 + .../src/remote_account_provider/mod.rs | 3 +- .../intent_scheduler.rs | 120 +++++- .../src/persist/commit_persister.rs | 13 + .../tasks/commit_finalize_compressed_task.rs | 21 +- .../src/tasks/task_builder.rs | 73 +++- .../src/tasks/task_strategist.rs | 9 +- magicblock-magic-program-api/src/args.rs | 6 + .../src/instruction.rs | 1 + .../src/magic_scheduled_base_intent.rs | 100 ++++- .../process_schedule_commit_tests.rs | 1 + test-integration/Cargo.lock | 1 + .../src/processor/schedule_intent.rs | 1 + .../programs/schedulecommit/Cargo.toml | 4 +- .../programs/schedulecommit/src/lib.rs | 153 ++++++-- .../tests/02_commit_and_undelegate.rs | 7 +- .../tests/test_ix_commit_local.rs | 351 ++++++++++++++---- .../tests/utils/instructions.rs | 31 +- .../tests/utils/transactions.rs | 44 ++- test-integration/test-runner/bin/run_tests.rs | 16 +- test-kit/Cargo.toml | 1 + test-kit/src/lib.rs | 5 +- 23 files changed, 802 insertions(+), 162 deletions(-) diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index 3eed205c9..e92bec2a8 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -86,7 +86,7 @@ jobs: - name: Install zk-compression CLI if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' run: | - npm i -g @lightprotocol/zk-compression-cli@0.28.3 + npm i -g @lightprotocol/zk-compression-cli@0.28.4 shell: bash - name: Run integration tests - ${{ matrix.batch_tests }} diff --git a/Cargo.lock b/Cargo.lock index 2f50eaf50..3f7f60e0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11275,6 +11275,7 @@ dependencies = [ "solana-instruction 3.4.0", "solana-keypair 3.1.2", "solana-program 3.0.0", + "solana-pubkey 3.0.0", "solana-rpc-client 3.1.12", "solana-signature 3.4.0", "solana-signer 3.0.0", diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index a61c4f2eb..971f70599 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -69,7 +69,8 @@ use magicblock_metrics::metrics::{ AccountFetchOrigin, ProgramFetchResult, }; use remote_account::{ - is_synthetic_mark_empty_fresh, should_prefer_rpc_over_photon_compressed_shell, + is_synthetic_mark_empty_fresh, + should_prefer_rpc_over_photon_compressed_shell, }; pub use remote_account::{ResolvedAccount, ResolvedAccountSharedData}; diff --git a/magicblock-committor-service/src/intent_execution_manager/intent_scheduler.rs b/magicblock-committor-service/src/intent_execution_manager/intent_scheduler.rs index 580acebf6..888e4e365 100644 --- a/magicblock-committor-service/src/intent_execution_manager/intent_scheduler.rs +++ b/magicblock-committor-service/src/intent_execution_manager/intent_scheduler.rs @@ -1,5 +1,6 @@ use std::collections::{hash_map::Entry, HashMap, VecDeque}; +use magicblock_core::compression::OUTPUT_QUEUE; use magicblock_program::magic_scheduled_base_intent::ScheduledIntentBundle; use solana_pubkey::Pubkey; use thiserror::Error; @@ -14,6 +15,23 @@ struct IntentMeta { intent: ScheduledIntentBundle, } +fn scheduling_pubkeys(intent_bundle: &ScheduledIntentBundle) -> Vec { + let mut pubkeys = intent_bundle.get_all_committed_pubkeys(); + if intent_bundle + .get_commit_finalize_compressed_intent_accounts() + .is_some() + || intent_bundle + .get_commit_finalize_compressed_and_undelegate_intent_accounts() + .is_some() + { + // Compressed finalize updates flow through Light's shared output queue. + // Without this lock, disjoint account intents can race inside the + // compression program even though their committed account keys differ. + pubkeys.push(OUTPUT_QUEUE); + } + pubkeys +} + /// A scheduler that ensures mutually exclusive access to pubkeys across intents /// /// # Data Structures @@ -111,7 +129,7 @@ impl IntentScheduler { return None; } - let pubkeys = intent_bundle.get_all_committed_pubkeys(); + let pubkeys = scheduling_pubkeys(&intent_bundle); if pubkeys.is_empty() { return Some(intent_bundle); }; @@ -152,7 +170,7 @@ impl IntentScheduler { ) -> IntentSchedulerResult<()> { // Release data for completed intent let intent_id = intent_bundle.id; - let pubkeys = intent_bundle.get_all_committed_pubkeys(); + let pubkeys = scheduling_pubkeys(intent_bundle); if pubkeys.is_empty() { // This means BaseAction, it doesn't have to be scheduled return Ok(()); @@ -341,6 +359,54 @@ mod simple_test { assert_eq!(scheduler.intents_blocked(), 0); } + #[test] + fn test_compressed_finalize_intents_share_queue_lock() { + setup(); + let mut scheduler = IntentScheduler::new(); + let msg1 = create_test_compressed_intent( + 1, + &[pubkey!("1111111111111111111111111111111111111111111")], + false, + ); + let msg2 = create_test_compressed_intent( + 2, + &[pubkey!("22222222222222222222222222222222222222222222")], + false, + ); + + assert!(scheduler.schedule(msg1.clone()).is_some()); + assert!(scheduler.schedule(msg2.clone()).is_none()); + assert_eq!(scheduler.intents_blocked(), 1); + + assert!(scheduler.complete(&msg1).is_ok()); + assert_eq!(scheduler.pop_next_scheduled_intent(), Some(msg2)); + assert_eq!(scheduler.intents_blocked(), 0); + } + + #[test] + fn test_compressed_undelegate_finalize_intents_share_queue_lock() { + setup(); + let mut scheduler = IntentScheduler::new(); + let msg1 = create_test_compressed_intent( + 1, + &[pubkey!("1111111111111111111111111111111111111111111")], + true, + ); + let msg2 = create_test_compressed_intent( + 2, + &[pubkey!("22222222222222222222222222222222222222222222")], + true, + ); + + assert!(scheduler.schedule(msg1.clone()).is_some()); + assert!(scheduler.schedule(msg2.clone()).is_none()); + assert_eq!(scheduler.intents_blocked(), 1); + + assert!(scheduler.complete(&msg1).is_ok()); + assert_eq!(scheduler.pop_next_scheduled_intent(), Some(msg2)); + assert_eq!(scheduler.intents_blocked(), 0); + } + /// Ensure intents conflicting intents get blocked #[test] fn test_conflicting_intents() { @@ -898,6 +964,56 @@ pub(crate) fn create_test_intent( intent } +#[cfg(test)] +pub(crate) fn create_test_compressed_intent( + id: u64, + pubkeys: &[Pubkey], + is_undelegate: bool, +) -> ScheduledIntentBundle { + use magicblock_core::intent::CommittedAccount; + use magicblock_program::magic_scheduled_base_intent::{ + CommitAndUndelegate, CommitType, MagicIntentBundle, + ScheduledIntentBundle, UndelegateType, + }; + use solana_account::Account; + use solana_hash::Hash; + use solana_transaction::Transaction; + + let committed_accounts = pubkeys + .iter() + .copied() + .map(|pubkey| CommittedAccount { + pubkey, + account: Account::default(), + remote_slot: Default::default(), + }) + .collect(); + + let commit_type = CommitType::Standalone(committed_accounts); + let mut intent = ScheduledIntentBundle { + id, + slot: 0, + blockhash: Hash::default(), + sent_transaction: Transaction::default(), + payer: Pubkey::default(), + intent_bundle: MagicIntentBundle::default(), + }; + + if is_undelegate { + intent + .intent_bundle + .commit_finalize_compressed_and_undelegate = + Some(CommitAndUndelegate { + commit_action: commit_type, + undelegate_action: UndelegateType::Standalone, + }); + } else { + intent.intent_bundle.commit_finalize_compressed = Some(commit_type); + } + + intent +} + #[cfg(test)] pub(crate) fn create_test_intent_bundle( id: u64, diff --git a/magicblock-committor-service/src/persist/commit_persister.rs b/magicblock-committor-service/src/persist/commit_persister.rs index 9a40183d8..bbe5c9a67 100644 --- a/magicblock-committor-service/src/persist/commit_persister.rs +++ b/magicblock-committor-service/src/persist/commit_persister.rs @@ -141,6 +141,15 @@ impl IntentPersisterImpl { intent_bundle .get_commit_finalize_and_undelegate_intent_accounts(), ), + ( + false, + intent_bundle.get_commit_finalize_compressed_intent_accounts(), + ), + ( + true, + intent_bundle + .get_commit_finalize_compressed_and_undelegate_intent_accounts(), + ), ] .into_iter() .filter_map(|(undelegate, accounts)| { @@ -502,6 +511,7 @@ mod tests { commit_finalize: None, commit_finalize_and_undelegate: None, commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, standalone_actions: vec![], } } @@ -516,6 +526,7 @@ mod tests { commit_finalize: None, commit_finalize_and_undelegate: None, commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, standalone_actions: vec![], } } @@ -530,6 +541,7 @@ mod tests { commit_finalize: None, commit_finalize_and_undelegate: None, commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, standalone_actions: vec![], } } @@ -541,6 +553,7 @@ mod tests { commit_finalize: None, commit_finalize_and_undelegate: None, commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, standalone_actions: vec![], } } diff --git a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs index 6947d2eef..99bacc5df 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs @@ -2,15 +2,12 @@ use borsh::BorshDeserialize; use compressed_delegation_api::{ CommitAndFinalizeArgs, CompressedDelegationRecord, }; -use magicblock_committor_program::Chunks; use magicblock_core::intent::CommittedAccount; use solana_instruction::Instruction; use solana_pubkey::Pubkey; use crate::{ - consts::MAX_WRITE_CHUNK_SIZE, - intent_executor::task_info_fetcher::CompressedData, - tasks::{commit_task::CommitBufferStage, BaseTaskImpl, PreparationTask}, + intent_executor::task_info_fetcher::CompressedData, tasks::BaseTaskImpl, }; /// A task that commits a delegated account's state to the base layer and finalizes it in the same @@ -64,22 +61,6 @@ impl CommitFinalizeCompressedTask { .instruction() .expect("The serializing the args should not fail") } - - pub fn state_preparation_stage(&self) -> CommitBufferStage { - let data = self.committed_account.account.data.clone(); - self.preparation_stage(data) - } - - fn preparation_stage(&self, buffer_data: Vec) -> CommitBufferStage { - let chunks = - Chunks::from_data_length(buffer_data.len(), MAX_WRITE_CHUNK_SIZE); - CommitBufferStage::Preparation(PreparationTask { - commit_id: self.commit_id, - pubkey: self.committed_account.pubkey, - buffer_data, - chunks, - }) - } } impl From for BaseTaskImpl { diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index dfd294c6c..563b0e847 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -14,10 +14,12 @@ use tracing::error; use crate::{ intent_executor::task_info_fetcher::{ - TaskInfoFetcher, TaskInfoFetcherError, TaskInfoFetcherResult, + CompressedData, TaskInfoFetcher, TaskInfoFetcherError, + TaskInfoFetcherResult, }, persist::IntentPersister, tasks::{ + commit_finalize_compressed_task::CommitFinalizeCompressedTask, commit_task::{CommitDelivery, CommitTask}, BaseActionTask, BaseActionTaskV1, BaseActionTaskV2, BaseTaskImpl, CommitFinalizeTask, FinalizeTask, UndelegateTask, @@ -150,6 +152,30 @@ impl TaskBuilderImpl { .await } + async fn fetch_compressed_data( + task_info_fetcher: &Arc, + accounts: &[(bool, bool, bool, CommittedAccount)], + min_context_slot: u64, + ) -> TaskInfoFetcherResult> { + let pubkeys = accounts + .iter() + .filter(|(_, _, compressed, _)| *compressed) + .map(|(_, _, _, account)| account.pubkey) + .collect::>(); + Ok(pubkeys + .iter() + .zip( + task_info_fetcher + .get_compressed_data_for_accounts( + &pubkeys, + Some(min_context_slot), + ) + .await?, + ) + .filter_map(|(pk, data)| data.map(|data| (*pk, data))) + .collect()) + } + pub fn create_commit_finalize_task( commit_id: u64, allow_undelegation: bool, @@ -180,13 +206,14 @@ impl TaskBuilderImpl { pub fn create_commit_finalize_compressed_task( commit_id: u64, allow_undelegation: bool, - account: CommittedAccount, - ) -> CommitFinalizeTask { - CommitFinalizeTask { + committed_account: CommittedAccount, + compressed_data: CompressedData, + ) -> CommitFinalizeCompressedTask { + CommitFinalizeCompressedTask { commit_id, allow_undelegation, - committed_account: account, - delivery: CommitDelivery::StateInArgs, + committed_account, + compressed_data, } } } @@ -216,6 +243,9 @@ impl TasksBuilder for TaskBuilderImpl { let commit_finalize_compressed_accounts = intent_bundle .get_commit_finalize_compressed_intent_accounts() .cloned(); + let commit_finalize_compressed_and_undelegate_accounts = intent_bundle + .get_commit_finalize_compressed_and_undelegate_intent_accounts() + .cloned(); let flagged_accounts: Vec<_> = [ (false, false, false, committed_accounts), @@ -223,6 +253,12 @@ impl TasksBuilder for TaskBuilderImpl { (false, true, false, commit_finalize_accounts), (true, true, false, commit_finalize_and_undelegate_accounts), (false, true, true, commit_finalize_compressed_accounts), + ( + true, + true, + true, + commit_finalize_compressed_and_undelegate_accounts, + ), ] .into_iter() .flat_map(|(allow_undelegation, finalize, compressed, accounts)| { @@ -238,7 +274,7 @@ impl TasksBuilder for TaskBuilderImpl { .map(|(_, _, _, account)| account.remote_slot) .max() .unwrap_or(0); - let (commit_ids, base_accounts) = tokio::join!( + let (commit_ids, base_accounts, compressed_data) = tokio::join!( Self::fetch_commit_nonces( task_info_fetcher, &flagged_accounts, @@ -248,12 +284,21 @@ impl TasksBuilder for TaskBuilderImpl { task_info_fetcher, &flagged_accounts, min_context_slot + ), + Self::fetch_compressed_data( + task_info_fetcher, + &flagged_accounts, + min_context_slot ) ); let commit_ids = commit_ids.map_err(TaskBuilderError::CommitTasksBuildError)?; let mut base_accounts = base_accounts.unwrap_or_else(|err| { - tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); + tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); + Default::default() + }); + let compressed_data = compressed_data.unwrap_or_else(|err| { + tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch compressed data, falling back to empty compressed data"); Default::default() }); @@ -267,7 +312,7 @@ impl TasksBuilder for TaskBuilderImpl { }); // Create commit tasks - let commit_tasks_iter = flagged_accounts.into_iter().map( + let commit_tasks_iter = flagged_accounts.into_iter().filter_map( |(allow_undelegation, finalize, compressed, account)| { let commit_id = commit_ids .get(&account.pubkey) @@ -282,11 +327,15 @@ impl TasksBuilder for TaskBuilderImpl { let base_account = base_accounts.remove(&account.pubkey); if compressed { - Self::create_commit_finalize_compressed_task(commit_id, allow_undelegation, account.clone()).into() + let Some(compressed_data) = compressed_data.get(&account.pubkey).cloned() else { + error!(pubkey = %account.pubkey, "Compressed data absent for pubkey"); + return None; + }; + Some(Self::create_commit_finalize_compressed_task(commit_id, allow_undelegation, account.clone(), compressed_data).into()) } else if finalize { - Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account).into() + Some(Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account).into()) } else { - Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account).into() + Some(Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account).into()) } }, ); diff --git a/magicblock-committor-service/src/tasks/task_strategist.rs b/magicblock-committor-service/src/tasks/task_strategist.rs index 59a77403d..4705ec296 100644 --- a/magicblock-committor-service/src/tasks/task_strategist.rs +++ b/magicblock-committor-service/src/tasks/task_strategist.rs @@ -364,7 +364,14 @@ impl TaskStrategist { &commit_finalize_task.delivery, ), ), - _ => continue, + BaseTaskImpl::CommitFinalizeCompressed(task) => ( + task.commit_id, + task.committed_account.pubkey, + CommitStrategy::StateArgs, + ), + BaseTaskImpl::Undelegate(_) + | BaseTaskImpl::Finalize(_) + | BaseTaskImpl::BaseAction(_) => continue, }; if let Err(err) = persistor.set_commit_strategy( commit_id, diff --git a/magicblock-magic-program-api/src/args.rs b/magicblock-magic-program-api/src/args.rs index 759f8f678..33a737e3d 100644 --- a/magicblock-magic-program-api/src/args.rs +++ b/magicblock-magic-program-api/src/args.rs @@ -88,6 +88,7 @@ pub enum MagicBaseIntentArgs { CommitFinalize(CommitTypeArgs), CommitFinalizeAndUndelegate(CommitAndUndelegateArgs), CommitFinalizeCompressed(CommitTypeArgs), + CommitFinalizeAndUndelegateCompressed(CommitAndUndelegateArgs), } #[derive(Clone, Default, Serialize, Deserialize, Debug, PartialEq, Eq)] @@ -97,6 +98,8 @@ pub struct MagicIntentBundleArgs { pub commit_finalize: Option, pub commit_finalize_and_undelegate: Option, pub commit_finalize_compressed: Option, + pub commit_finalize_compressed_and_undelegate: + Option, pub standalone_actions: Vec, } @@ -120,6 +123,9 @@ impl From for MagicIntentBundleArgs { MagicBaseIntentArgs::CommitFinalizeCompressed(value) => { this.commit_finalize_compressed = Some(value) } + MagicBaseIntentArgs::CommitFinalizeAndUndelegateCompressed( + value, + ) => this.commit_finalize_compressed_and_undelegate = Some(value), } this diff --git a/magicblock-magic-program-api/src/instruction.rs b/magicblock-magic-program-api/src/instruction.rs index 1456ff3a4..c8909fc1f 100644 --- a/magicblock-magic-program-api/src/instruction.rs +++ b/magicblock-magic-program-api/src/instruction.rs @@ -8,6 +8,7 @@ use crate::args::{ ScheduleTaskArgs, }; +#[allow(clippy::large_enum_variant)] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] pub enum MagicBlockInstruction { /// Modify one or more accounts diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 4c3d10dbb..a4199cad6 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -173,6 +173,13 @@ impl ScheduledIntentBundle { .get_commit_finalize_compressed_intent_accounts() } + pub fn get_commit_finalize_compressed_and_undelegate_intent_accounts( + &self, + ) -> Option<&Vec> { + self.intent_bundle + .get_commit_finalize_compressed_and_undelegate_intent_accounts() + } + /// Returns `Commit` intent's accounts pub fn get_commit_intent_accounts_mut( &mut self, @@ -226,6 +233,7 @@ pub struct MagicIntentBundle { pub commit_finalize: Option, pub commit_finalize_and_undelegate: Option, pub commit_finalize_compressed: Option, + pub commit_finalize_compressed_and_undelegate: Option, pub standalone_actions: Vec, } @@ -247,10 +255,10 @@ impl From for MagicIntentBundle { this.commit_finalize_and_undelegate = Some(value) } MagicBaseIntent::CommitFinalizeCompressed(value) => { - this.commit_finalize = Some(value) + this.commit_finalize_compressed = Some(value) } MagicBaseIntent::CommitFinalizeAndUndelegateCompressed(value) => { - this.commit_finalize_and_undelegate = Some(value) + this.commit_finalize_compressed_and_undelegate = Some(value) } } @@ -290,6 +298,11 @@ impl MagicIntentBundle { .map(|value| CommitType::try_from_args(value, context)) .transpose()?; + let commit_finalize_compressed_and_undelegate = args + .commit_finalize_compressed_and_undelegate + .map(|value| CommitAndUndelegate::try_from_args(value, context)) + .transpose()?; + let actions = args .standalone_actions .into_iter() @@ -302,6 +315,7 @@ impl MagicIntentBundle { commit_finalize, commit_finalize_and_undelegate, commit_finalize_compressed, + commit_finalize_compressed_and_undelegate, standalone_actions: actions, }; this.post_validation(context)?; @@ -390,6 +404,19 @@ impl MagicIntentBundle { { check(commit_finalize_and_undelegate.get_committed_accounts())?; } + if let Some(commit_finalize_compressed) = + &self.commit_finalize_compressed + { + check(commit_finalize_compressed.get_committed_accounts())?; + } + if let Some(commit_finalize_compressed_and_undelegate) = + &self.commit_finalize_compressed_and_undelegate + { + check( + commit_finalize_compressed_and_undelegate + .get_committed_accounts(), + )?; + } Ok(()) } @@ -412,6 +439,7 @@ impl MagicIntentBundle { pub fn has_undelegate_intent(&self) -> bool { self.commit_and_undelegate.is_some() || self.commit_finalize_and_undelegate.is_some() + || self.commit_finalize_compressed_and_undelegate.is_some() } pub fn has_committed_accounts(&self) -> bool { @@ -431,11 +459,22 @@ impl MagicIntentBundle { .get_commit_finalize_and_undelegate_intent_accounts() .map(|el| !el.is_empty()) .unwrap_or(false); + let has_commit_finalize_compressed_intent_accounts = self + .get_commit_finalize_compressed_intent_accounts() + .map(|el| !el.is_empty()) + .unwrap_or(false); + let has_commit_finalize_compressed_and_undelegate_intent_accounts = + self.get_commit_finalize_compressed_and_undelegate_intent_accounts( + ) + .map(|el| !el.is_empty()) + .unwrap_or(false); has_commit_intent_accounts || has_undelegate_intent_accounts || has_commit_finalize_intent_accounts || has_commit_finalize_and_undelegate_intent_accounts + || has_commit_finalize_compressed_intent_accounts + || has_commit_finalize_compressed_and_undelegate_intent_accounts } /// Returns `[CommitAndUndelegate]` intent's accounts @@ -476,6 +515,16 @@ impl MagicIntentBundle { ) } + pub fn get_commit_finalize_compressed_and_undelegate_intent_accounts( + &self, + ) -> Option<&Vec> { + Some( + self.commit_finalize_compressed_and_undelegate + .as_ref()? + .get_committed_accounts(), + ) + } + /// Returns `Commit` intent's accounts pub fn get_commit_finalize_intent_accounts( &self, @@ -498,12 +547,18 @@ impl MagicIntentBundle { let commit_finalize = self.get_commit_finalize_intent_accounts(); let commit_finalize_and_undelegate = self.get_commit_finalize_and_undelegate_intent_accounts(); + let commit_finalize_compressed = + self.get_commit_finalize_compressed_intent_accounts(); + let commit_finalize_compressed_and_unde = self + .get_commit_finalize_compressed_and_undelegate_intent_accounts(); [ committed, undelegated, commit_finalize, commit_finalize_and_undelegate, + commit_finalize_compressed, + commit_finalize_compressed_and_unde, ] .into_iter() .flatten() @@ -518,6 +573,8 @@ impl MagicIntentBundle { self.get_undelegate_intent_pubkeys(), self.get_commit_finalize_intent_pubkeys(), self.get_commit_finalize_and_undelegate_intent_pubkeys(), + self.get_commit_finalize_compressed_intent_pubkeys(), + self.get_commit_finalize_compressed_and_undelegate_intent_pubkeys(), ] .into_iter() .flatten() @@ -551,6 +608,22 @@ impl MagicIntentBundle { .map(|value| value.get_committed_pubkeys()) } + pub fn get_commit_finalize_compressed_intent_pubkeys( + &self, + ) -> Option> { + self.commit_finalize_compressed + .as_ref() + .map(|value| value.get_committed_pubkeys()) + } + + pub fn get_commit_finalize_compressed_and_undelegate_intent_pubkeys( + &self, + ) -> Option> { + self.commit_finalize_compressed_and_undelegate + .as_ref() + .map(|value| value.get_committed_pubkeys()) + } + pub fn is_empty(&self) -> bool { let no_committed = self.commit.as_ref().map(|el| el.is_empty()).unwrap_or(true); @@ -572,6 +645,17 @@ impl MagicIntentBundle { .as_ref() .map(|el| el.is_empty()) .unwrap_or(true); + let no_commit_finalize_compressed = self + .commit_finalize_compressed + .as_ref() + .map(|el| el.is_empty()) + .unwrap_or(true); + + let no_commit_finalize_compressed_and_undelegate = self + .commit_finalize_compressed_and_undelegate + .as_ref() + .map(|el| el.is_empty()) + .unwrap_or(true); let no_actions = self.standalone_actions.is_empty(); @@ -579,6 +663,8 @@ impl MagicIntentBundle { && no_committed_and_undelegated && no_commit_finalize && no_commit_finalize_and_undelegate + && no_commit_finalize_compressed + && no_commit_finalize_compressed_and_undelegate && no_actions } @@ -661,6 +747,15 @@ impl MagicBaseIntent { let commit = CommitType::try_from_args(type_, context)?; Ok(MagicBaseIntent::CommitFinalizeCompressed(commit)) } + MagicBaseIntentArgs::CommitFinalizeAndUndelegateCompressed( + type_, + ) => { + let commit_and_undelegate = + CommitAndUndelegate::try_from_args(type_, context)?; + Ok(MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( + commit_and_undelegate, + )) + } } } @@ -1433,6 +1528,7 @@ mod tests { commit_finalize: None, commit_finalize_and_undelegate: None, commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, standalone_actions: vec![make_base_action(50_000)], }, }; diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs index 5e5baa951..33c25c001 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_tests.rs @@ -418,6 +418,7 @@ mod tests { commit_finalize: None, commit_finalize_and_undelegate: None, commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, standalone_actions: vec![BaseActionArgs { args: ActionArgs::new(vec![1, 2, 3]).with_escrow_index(0), compute_units: 100_000, diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 215db9f62..5519aef5b 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -13403,6 +13403,7 @@ dependencies = [ "solana-instruction 3.4.0", "solana-keypair 3.1.2", "solana-program 3.0.0", + "solana-pubkey 3.0.0", "solana-rpc-client 3.1.12", "solana-signature 3.4.0", "solana-signer 3.0.0", diff --git a/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs b/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs index 14e384883..f1ece6acc 100644 --- a/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs +++ b/test-integration/programs/flexi-counter/src/processor/schedule_intent.rs @@ -397,6 +397,7 @@ pub fn process_create_intent_bundle_commit_and_finalize( )), commit_finalize_and_undelegate: None, commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, standalone_actions: vec![], }; diff --git a/test-integration/programs/schedulecommit/Cargo.toml b/test-integration/programs/schedulecommit/Cargo.toml index cd8496973..b76a09e71 100644 --- a/test-integration/programs/schedulecommit/Cargo.toml +++ b/test-integration/programs/schedulecommit/Cargo.toml @@ -6,7 +6,9 @@ version.workspace = true [dependencies] borsh = { workspace = true } ephemeral-rollups-sdk = { workspace = true } -magicblock-delegation-program-api = { workspace = true, features = ["instruction"] } +magicblock-delegation-program-api = { workspace = true, features = [ + "instruction", +] } magicblock-magic-program-api = { workspace = true } rkyv = { workspace = true } solana-program = { workspace = true } diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 95c86c7a7..5128921a6 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -9,11 +9,15 @@ use ephemeral_rollups_sdk::{ ephem::{ commit_accounts, commit_and_undelegate_accounts, commit_finalize_accounts, commit_finalize_and_undelegate_accounts, - CallHandler, FoldableIntentBuilder, MagicIntentBundleBuilder, }, - ActionArgs, ShortAccountMeta, }; -use magicblock_magic_program_api::instruction::MagicBlockInstruction; +use magicblock_magic_program_api::{ + args::{ + ActionArgs, BaseActionArgs, CommitTypeArgs, MagicIntentBundleArgs, + ShortAccountMeta, + }, + instruction::MagicBlockInstruction, +}; use solana_program::{ account_info::{next_account_info, AccountInfo}, declare_id, @@ -207,6 +211,8 @@ pub enum ScheduleCommitType { CommitAndUndelegate, CommitFinalize, CommitFinalizeAndUndelegate, + CommitFinalizeCompressed, + CommitFinalizeCompressedAndUndelegate, } impl ScheduleCommitType { @@ -249,6 +255,58 @@ impl ScheduleCommitType { magic_program, ) } + ScheduleCommitType::CommitFinalizeCompressed => { + let ix = Instruction::new_with_bincode( + magicblock_magic_program_api::ID, + &magicblock_magic_program_api::instruction::MagicBlockInstruction::ScheduleCommitCompressed, + [vec![ + AccountMeta { + pubkey: *payer.key, + is_signer: true, + is_writable: true, + }, + AccountMeta { + pubkey: *magic_context.key, + is_signer: false, + is_writable: true, + }, + ], accounts.iter().map(|account| AccountMeta { + pubkey: *account.key, + is_signer: account.is_signer, + is_writable: account.is_writable, + }).collect()].concat(), + ); + let mut all_accounts = + vec![payer.clone(), magic_context.clone()]; + all_accounts.extend(accounts.into_iter().cloned()); + invoke(&ix, &all_accounts) + } + ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + let ix = Instruction::new_with_bincode( + magicblock_magic_program_api::ID, + &magicblock_magic_program_api::instruction::MagicBlockInstruction::ScheduleCommitAndUndelegateCompressed, + [vec![ + AccountMeta { + pubkey: *payer.key, + is_signer: true, + is_writable: true, + }, + AccountMeta { + pubkey: *magic_context.key, + is_signer: false, + is_writable: true, + }, + ], accounts.iter().map(|account| AccountMeta { + pubkey: *account.key, + is_signer: account.is_signer, + is_writable: account.is_writable, + }).collect()].concat(), + ); + let mut all_accounts = + vec![payer.clone(), magic_context.clone()]; + all_accounts.extend(accounts.into_iter().cloned()); + invoke(&ix, &all_accounts) + } } } } @@ -819,16 +877,16 @@ pub fn process_schedulecommit_with_vault_and_order_book_cpi( return Err(ProgramError::InvalidArgument); } - let mut builder = MagicIntentBundleBuilder::new( - payer.clone(), - magic_context.clone(), - magic_program.clone(), - ) - .magic_fee_vault(magic_fee_vault.clone()) - .commit(&committees); + let committed_accounts = (0..committees.len()) + .map(|idx| { + // Magic program CPI account layout: + // payer, magic_context, magic_fee_vault, then committed accounts. + u8::try_from(idx + 3) + }) + .collect::, _>>() + .map_err(|_| ProgramError::InvalidInstructionData)?; - if args.with_actions { - // Build the UpdateOrderBook instruction data with one hardcoded bid + let commit = if args.with_actions { let update_ix_data = to_vec(&ScheduleCommitInstruction::UpdateOrderBook(BookUpdate { bids: vec![OrderLevel { @@ -839,24 +897,63 @@ pub fn process_schedulecommit_with_vault_and_order_book_cpi( })) .map_err(|_| ProgramError::InvalidInstructionData)?; - // Post-commit action: call UpdateOrderBook on the order book account - let call_handler = CallHandler { - args: ActionArgs { - data: update_ix_data, - escrow_index: 1, // payer/escrow_authority inserted at index 1 - }, - compute_units: 50_000, - escrow_authority: payer.clone(), - destination_program: id(), - accounts: vec![ShortAccountMeta { - pubkey: *order_book.key, - is_writable: true, + CommitTypeArgs::WithBaseActions { + committed_accounts, + base_actions: vec![BaseActionArgs { + args: ActionArgs { + data: update_ix_data, + escrow_index: 1, + }, + compute_units: 50_000, + escrow_authority: 0, + destination_program: id(), + accounts: vec![ShortAccountMeta { + pubkey: *order_book.key, + is_writable: true, + }], }], - }; - builder = builder.add_post_commit_actions([call_handler]); - } + } + } else { + CommitTypeArgs::Standalone(committed_accounts) + }; + + let ix = Instruction::new_with_bincode( + *magic_program.key, + &MagicBlockInstruction::ScheduleIntentBundle(MagicIntentBundleArgs { + commit: Some(commit), + commit_and_undelegate: None, + commit_finalize: None, + commit_finalize_and_undelegate: None, + commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, + standalone_actions: vec![], + }), + [ + vec![ + AccountMeta::new(*payer.key, true), + AccountMeta::new(*magic_context.key, false), + AccountMeta::new(*magic_fee_vault.key, false), + ], + committees + .iter() + .map(|account| AccountMeta { + pubkey: *account.key, + is_signer: account.is_signer, + is_writable: account.is_writable, + }) + .collect(), + ] + .concat(), + ); + + let mut cpi_accounts = vec![ + payer.clone(), + magic_context.clone(), + magic_fee_vault.clone(), + ]; + cpi_accounts.extend(committees); - builder.build_and_invoke() + invoke(&ix, &cpi_accounts) } fn process_increase_count(accounts: &[AccountInfo]) -> ProgramResult { diff --git a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs index a1305b12c..99523b075 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs @@ -391,11 +391,14 @@ fn run_test_for_commit_huge_order_book_account( assert_one_committee_was_committed(&ctx, &res, true); match commit_type { - ScheduleCommitType::Commit | ScheduleCommitType::CommitFinalize => { + ScheduleCommitType::Commit + | ScheduleCommitType::CommitFinalize + | ScheduleCommitType::CommitFinalizeCompressed => { assert_one_committee_account_was_not_undelegated_on_chain(&ctx); } ScheduleCommitType::CommitAndUndelegate - | ScheduleCommitType::CommitFinalizeAndUndelegate => { + | ScheduleCommitType::CommitFinalizeAndUndelegate + | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { assert_one_committee_account_was_undelegated_on_chain(&ctx); } } diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index dfe3c1db8..7d8ccc69e 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -38,6 +38,7 @@ use crate::utils::{ transactions::{ fund_validator_auth_and_ensure_validator_fees_vault, init_and_delegate_account_on_chain, + init_and_delegate_compressed_record_on_chain, }, }; @@ -242,9 +243,23 @@ async fn commit_single_account( let service = CommittorServiceExt::new(Arc::new(service)); let counter_auth = Keypair::new(); - let (pubkey, mut account) = - init_and_delegate_account_on_chain(&counter_auth, bytes as u64, None) - .await; + let (pubkey, mut account) = match commit_type { + ScheduleCommitType::CommitFinalizeCompressed + | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + let (pubkey, _address, account) = + init_and_delegate_compressed_record_on_chain(&counter_auth) + .await; + (pubkey, account) + } + _ => { + init_and_delegate_account_on_chain( + &counter_auth, + bytes as u64, + None, + ) + .await + } + }; let counter = FlexiCounter { label: "Counter".to_string(), @@ -282,6 +297,19 @@ async fn commit_single_account( undelegate_action: UndelegateType::Standalone, }) } + ScheduleCommitType::CommitFinalizeCompressed => { + MagicBaseIntent::CommitFinalizeCompressed(CommitType::Standalone( + vec![account], + )) + } + ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( + CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }, + ) + } }; let intent = ScheduledIntentBundle { @@ -362,6 +390,19 @@ async fn commit_book_order_account( undelegate_action: UndelegateType::Standalone, }) } + ScheduleCommitType::CommitFinalizeCompressed => { + MagicBaseIntent::CommitFinalizeCompressed(CommitType::Standalone( + vec![account], + )) + } + ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( + CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }, + ) + } }; let intent = ScheduledIntentBundle { @@ -640,6 +681,7 @@ async fn test_ix_execute_intent_bundle_commit_and_cau_simultaneously_union_of_ac &[], &[1024, 2048], expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), + false, ) .await; } @@ -651,6 +693,7 @@ async fn test_ix_execute_intent_bundle_commit_three_accounts_cau_one_account() { &[], &[512], expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), + false, ) .await; } @@ -662,6 +705,7 @@ async fn test_ix_execute_intent_bundle_mixed_fits_in_args() { &[], &[20], expect_strategies(&[(CommitStrategy::StateArgs, 4)]), + false, ) .await; } @@ -673,6 +717,7 @@ async fn test_ix_execute_intent_bundle_commit_finalize_only() { &[10, 20], &[], expect_strategies(&[(CommitStrategy::StateArgs, 2)]), + false, ) .await; } @@ -684,6 +729,102 @@ async fn test_ix_execute_intent_bundle_commit_and_commit_finalize_mixed() { &[1024, 2048], &[], expect_strategies(&[(CommitStrategy::DiffArgs, 4)]), + false, + ) + .await; +} + +// ----------------- +// Compressed Account Commits +// ----------------- + +#[tokio::test] +async fn test_ix_commit_single_compressed_account_100_bytes() { + commit_n_accounts_x_bytes::<1, 100>( + 1, + expect_strategies(&[(CommitStrategy::StateArgs, 1)]), + ScheduleCommitType::CommitFinalizeCompressed, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_single_compressed_account_100_bytes_and_undelegate() { + commit_n_accounts_x_bytes::<1, 100>( + 1, + expect_strategies(&[(CommitStrategy::StateArgs, 1)]), + ScheduleCommitType::CommitFinalizeCompressedAndUndelegate, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_single_compressed_account_500_bytes() { + commit_n_accounts_x_bytes::<1, 500>( + 1, + expect_strategies(&[(CommitStrategy::StateArgs, 1)]), + ScheduleCommitType::CommitFinalizeCompressed, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_single_compressed_account_500_bytes_and_undelegate() { + commit_n_accounts_x_bytes::<1, 500>( + 1, + expect_strategies(&[(CommitStrategy::StateArgs, 1)]), + ScheduleCommitType::CommitFinalizeCompressedAndUndelegate, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_two_compressed_accounts_512_bytes() { + commit_n_accounts_x_bytes::<2, 512>( + 1, + expect_strategies(&[(CommitStrategy::StateArgs, 2)]), + ScheduleCommitType::CommitFinalizeCompressed, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_three_compressed_accounts_512_bytes() { + commit_n_accounts_x_bytes::<3, 512>( + 1, + expect_strategies(&[(CommitStrategy::StateArgs, 3)]), + ScheduleCommitType::CommitFinalizeCompressed, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_six_compressed_accounts_512_bytes() { + commit_n_accounts_x_bytes::<6, 512>( + 1, + expect_strategies(&[(CommitStrategy::StateArgs, 6)]), + ScheduleCommitType::CommitFinalizeCompressed, + ) + .await; +} + +#[tokio::test] +async fn test_commit_20_compressed_accounts_100bytes_bundle_size_2() { + commit_n_accounts_x_bytes::<20, 100>( + 2, + expect_strategies(&[(CommitStrategy::StateArgs, 20)]), + ScheduleCommitType::CommitFinalizeCompressed, + ) + .await; +} + +#[tokio::test] +async fn test_commit_5_compressed_accounts_100bytes_bundle_size_2_undelegate_all( +) { + commit_n_accounts_x_bytes::<5, 100>( + 2, + expect_strategies(&[(CommitStrategy::StateArgs, 5)]), + ScheduleCommitType::CommitFinalizeCompressedAndUndelegate, ) .await; } @@ -693,13 +834,10 @@ async fn commit_5_accounts_1kb( expected_strategies: ExpectedStrategies, commit_type: ScheduleCommitType, ) { - init_logger!(); - let accs = (0..5).map(|_| 1024).collect::>(); - commit_multiple_accounts( - &accs, + commit_n_accounts_x_bytes::<5, 1024>( bundle_size, - commit_type, expected_strategies, + commit_type, ) .await; } @@ -709,13 +847,10 @@ async fn commit_8_accounts_1kb( expected_strategies: ExpectedStrategies, commit_type: ScheduleCommitType, ) { - init_logger!(); - let accs = (0..8).map(|_| 1024).collect::>(); - commit_multiple_accounts( - &accs, + commit_n_accounts_x_bytes::<8, 1024>( bundle_size, - commit_type, expected_strategies, + commit_type, ) .await; } @@ -724,9 +859,25 @@ async fn commit_20_accounts_1kb( bundle_size: usize, expected_strategies: ExpectedStrategies, commit_type: ScheduleCommitType, +) { + commit_n_accounts_x_bytes::<20, 1024>( + bundle_size, + expected_strategies, + commit_type, + ) + .await; +} + +async fn commit_n_accounts_x_bytes< + const ACCOUNTS: usize, + const BYTES: usize, +>( + bundle_size: usize, + expected_strategies: ExpectedStrategies, + commit_type: ScheduleCommitType, ) { init_logger!(); - let accs = (0..20).map(|_| 1024).collect::>(); + let accs = (0..ACCOUNTS).map(|_| BYTES).collect::>(); commit_multiple_accounts( &accs, bundle_size, @@ -738,38 +889,62 @@ async fn commit_20_accounts_1kb( async fn create_and_delegate_accounts( bytess: &[usize], + compressed: bool, ) -> Vec { - let mut join_set = JoinSet::new(); - for bytes in bytess { - let bytes = *bytes; - join_set.spawn(async move { + if compressed { + let mut out = Vec::with_capacity(bytess.len()); + for bytes in bytess { + let bytes = *bytes; let counter_auth = Keypair::new(); - let (pda, mut pda_acc) = init_and_delegate_account_on_chain( - &counter_auth, - bytes as u64, - None, - ) - .await; + let (pda, mut pda_acc) = { + let (pubkey, _address, account) = + init_and_delegate_compressed_record_on_chain(&counter_auth) + .await; + (pubkey, account) + }; pda_acc.owner = program_flexi_counter::id(); pda_acc.data = vec![0u8; bytes]; - CommittedAccount { + out.push(CommittedAccount { pubkey: pda, account: pda_acc, remote_slot: Default::default(), - } - }); - } + }); + } + out + } else { + let mut join_set = JoinSet::new(); + for bytes in bytess { + let bytes = *bytes; + join_set.spawn(async move { + let counter_auth = Keypair::new(); + let (pda, mut pda_acc) = init_and_delegate_account_on_chain( + &counter_auth, + bytes as u64, + None, + ) + .await; + + pda_acc.owner = program_flexi_counter::id(); + pda_acc.data = vec![0u8; bytes]; + CommittedAccount { + pubkey: pda, + account: pda_acc, + remote_slot: Default::default(), + } + }); + } - // Wait for all tasks to complete - join_set.join_all().await + join_set.join_all().await + } } async fn create_bundles( bundle_size: usize, bytess: &[usize], + compressed: bool, ) -> Vec> { - let committed = create_and_delegate_accounts(bytess).await; + let committed = create_and_delegate_accounts(bytess, compressed).await; committed .chunks(bundle_size) .map(|chunk| chunk.to_vec()) @@ -797,7 +972,16 @@ async fn commit_multiple_accounts( let service = CommittorServiceExt::new(Arc::new(service)); // Create bundles of committed accounts - let bundles_of_committees = create_bundles(bundle_size, bytess).await; + let bundles_of_committees = create_bundles( + bundle_size, + bytess, + matches!( + commit_type, + ScheduleCommitType::CommitFinalizeCompressed + | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate + ), + ) + .await; // Create intent for each bundle let intents = bundles_of_committees .into_iter() @@ -824,6 +1008,19 @@ async fn commit_multiple_accounts( }, ) } + ScheduleCommitType::CommitFinalizeCompressed => { + MagicBaseIntent::CommitFinalizeCompressed( + CommitType::Standalone(committees), + ) + } + ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( + CommitAndUndelegate { + commit_action: CommitType::Standalone(committees), + undelegate_action: UndelegateType::Standalone, + }, + ) + } }) .enumerate() .map(|(id, base_intent)| ScheduledIntentBundle { @@ -850,6 +1047,7 @@ async fn execute_intent_bundle( bytess_to_commit_finalize: &[usize], bytes_to_undelegate: &[usize], expected_strategies: ExpectedStrategies, + compressed: bool, ) { init_logger!(); @@ -866,10 +1064,11 @@ async fn execute_intent_bundle( let service = CommittorServiceExt::new(Arc::new(service)); // Create bundles of committed accounts - let to_commit = create_and_delegate_accounts(bytess_to_commit); + let to_commit = create_and_delegate_accounts(bytess_to_commit, compressed); let to_commit_finalize = - create_and_delegate_accounts(bytess_to_commit_finalize); - let to_undelegate = create_and_delegate_accounts(bytes_to_undelegate); + create_and_delegate_accounts(bytess_to_commit_finalize, compressed); + let to_undelegate = + create_and_delegate_accounts(bytes_to_undelegate, compressed); let (committees, commit_finalize_committees, undelegetees) = tokio::join!(to_commit, to_commit_finalize, to_undelegate); @@ -999,11 +1198,17 @@ async fn ix_commit_local( let undelegated_accounts = base_intent.get_undelegate_intent_accounts(); let commit_finalized_and_undelegated_accounts = base_intent.get_commit_finalize_and_undelegate_intent_accounts(); + let commit_finalize_compressed_accounts = + base_intent.get_commit_finalize_compressed_intent_accounts(); + let commit_finalize_compressed_and_undelegate_accounts = base_intent + .get_commit_finalize_compressed_and_undelegate_intent_accounts(); let has_commit_flow = committed_accounts.is_some() || undelegated_accounts.is_some(); let has_commit_finalize_flow = committed_finalize_accounts.is_some() - || commit_finalized_and_undelegated_accounts.is_some(); + || commit_finalized_and_undelegated_accounts.is_some() + || commit_finalize_compressed_accounts.is_some() + || commit_finalize_compressed_and_undelegate_accounts.is_some(); if has_commit_flow { assert!( tx_logs_contain(&rpc_client, &commit_signature, "CommitState") @@ -1025,8 +1230,10 @@ async fn ix_commit_local( ); } + let has_compressed_undelegate = + commit_finalize_compressed_and_undelegate_accounts.is_some(); let has_undelegate = base_intent.has_undelegate_intent(); - if has_undelegate { + if has_undelegate && !has_compressed_undelegate { // Undelegate is part of atomic Finalization Stage assert!( tx_logs_contain(&rpc_client, &finalize_signature, "Undelegate") @@ -1035,15 +1242,21 @@ async fn ix_commit_local( } let mut committed_accounts: HashMap = [ - (false, committed_accounts), - (true, undelegated_accounts), - (false, committed_finalize_accounts), - (true, commit_finalized_and_undelegated_accounts), + (false, false, committed_accounts), + (true, false, undelegated_accounts), + (false, false, committed_finalize_accounts), + (true, false, commit_finalized_and_undelegated_accounts), + (false, true, commit_finalize_compressed_accounts), + ( + true, + true, + commit_finalize_compressed_and_undelegate_accounts, + ), ] .into_iter() - .flat_map(|(allow_undelegation, accounts)| { + .flat_map(|(allow_undelegation, compressed, accounts)| { accounts.into_iter().flatten().map(move |account| { - (account.pubkey, (allow_undelegation, account)) + (account.pubkey, (allow_undelegation, compressed, account)) }) }) .collect(); @@ -1065,35 +1278,37 @@ async fn ix_commit_local( assert_eq!(statuses.len(), committed_accounts.len()); for commit_status in statuses { - let (is_undelegate, account) = committed_accounts + let (is_undelegate, is_compressed, account) = committed_accounts .remove(&commit_status.pubkey) .expect("Account should be persisted"); println!("account: {}", account.pubkey); - // When we finalize it is possible to also undelegate the account - let expected_owner = if is_undelegate { - program_id - } else { - dlp_api::id() - }; - - let lamports = account.account.lamports; - get_account!( - rpc_client, - account.pubkey, - "delegated state", - |acc: &Account, remaining_tries: u8| { - validate_account( - acc, - remaining_tries, - &account.account.data, - lamports, - expected_owner, - account.pubkey, - has_undelegate, - ) - } - ); + if !is_compressed { + // When we finalize it is possible to also undelegate the account + let expected_owner = if is_undelegate { + program_id + } else { + dlp_api::id() + }; + + let lamports = account.account.lamports; + get_account!( + rpc_client, + account.pubkey, + "delegated state", + |acc: &Account, remaining_tries: u8| { + validate_account( + acc, + remaining_tries, + &account.account.data, + lamports, + expected_owner, + account.pubkey, + has_undelegate, + ) + } + ); + } // Track the strategy used let strategy = commit_status.commit_strategy; diff --git a/test-integration/test-committor-service/tests/utils/instructions.rs b/test-integration/test-committor-service/tests/utils/instructions.rs index f117da566..310019349 100644 --- a/test-integration/test-committor-service/tests/utils/instructions.rs +++ b/test-integration/test-committor-service/tests/utils/instructions.rs @@ -26,6 +26,7 @@ use program_flexi_counter::{ use solana_pubkey::Pubkey; use solana_sdk::{instruction::Instruction, rent::Rent, signature::Keypair}; use test_kit::Signer; +use tokio::time::{sleep, Duration}; pub fn init_validator_fees_vault_ix(validator_auth: Pubkey) -> Instruction { dlp_api::instruction_builder::init_validator_fees_vault( @@ -164,12 +165,30 @@ pub async fn delegate_compressed_ixs( let (pda, _bump) = FlexiCounter::pda(&payer); let record_address = derive_cda_from_pda(&pda); - let compressed_account = photon_indexer - .get_compressed_account(record_address.to_bytes(), None) - .await - .unwrap() - .value - .unwrap(); + let compressed_account = { + const MAX_ATTEMPTS: u32 = 150; + let mut compressed_account = None; + for attempt in 0..MAX_ATTEMPTS { + if let Ok(resp) = photon_indexer + .get_compressed_account(record_address.to_bytes(), None) + .await + { + if let Some(acc) = resp.value { + compressed_account = Some(acc); + break; + } + } + if attempt + 1 == MAX_ATTEMPTS { + panic!( + "Photon did not return compressed account for {:?} after {} ms", + record_address, + MAX_ATTEMPTS * 200 + ); + } + sleep(Duration::from_millis(200)).await; + } + compressed_account.expect("Photon indexing loop exited without account") + }; let system_account_meta_config = SystemAccountMetaConfig::new( compressed_delegation_client::ID.to_bytes().into(), diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index 4497348a6..c9b0ed9a6 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use borsh::BorshDeserialize; +use compressed_delegation_client::CompressedDelegationRecord; use light_client::indexer::{photon_indexer::PhotonIndexer, Indexer}; use solana_account::Account; use solana_commitment_config::CommitmentConfig; @@ -90,7 +92,7 @@ pub async fn fetch_tx_logs( // line: 0, column: 0)) // } // Therefore we retry a few times. - const MAX_RETRIES: usize = 5; + const MAX_RETRIES: usize = 10; let mut retries = MAX_RETRIES; let tx = loop { match rpc_client @@ -110,7 +112,7 @@ pub async fn fetch_tx_logs( retries -= 1; if retries == 0 { panic!( - "Failed to get transaction after {} retries", + "Failed to get transaction {signature} after {} retries", MAX_RETRIES ); } @@ -195,6 +197,9 @@ pub async fn tx_logs_contain( log.contains(needle) || log.contains("CommitDiff") || log.contains("CommitFinalize") + || log.contains("CommitAndFinalize") + } else if needle == "CommitFinalize" { + log.contains(needle) || log.contains("CommitAndFinalize") } else { log.contains(needle) } @@ -377,6 +382,7 @@ pub async fn init_and_delegate_compressed_record_on_chain( address, } = delegate_compressed_ixs(counter_auth.pubkey(), photon_indexer.clone()) .await; + let latest_block_hash = rpc_client.get_latest_blockhash().await.unwrap(); let tx = Transaction::new_signed_with_payer( &[ ComputeBudgetInstruction::set_compute_unit_limit(250_000), @@ -404,13 +410,33 @@ pub async fn init_and_delegate_compressed_record_on_chain( }) .expect("Failed to init compressed record"); - let compressed_account = photon_indexer - .get_compressed_account(address, None) - .await - .unwrap() - .value - .unwrap(); - debug!("Compressed record: {:?}", compressed_account); + // Retry until we get a valid delegation record + const MAX_RETRIES: usize = 10; + let mut retries = MAX_RETRIES; + let compressed_delegation_record = loop { + let compressed_account = photon_indexer + .get_compressed_account(address, None) + .await + .unwrap() + .value + .unwrap(); + if let Some(compressed_delegation_record) = + compressed_account.data.and_then(|data| { + CompressedDelegationRecord::try_from_slice(&data.data).ok() + }) + { + break compressed_delegation_record; + } + retries -= 1; + if retries == 0 { + panic!( + "Failed to get compressed account after {} retries", + MAX_RETRIES + ); + } + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + }; + debug!("Compressed record: {:?}", compressed_delegation_record); (pda, address, pda_acc) } diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index 499f6ccda..133574d2d 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -18,6 +18,7 @@ use teepee::Teepee; use test_runner::{ cleanup::{ cleanup_devnet_only, cleanup_light_validator, cleanup_validators, + cleanup_validators_with_light, }, env_config::TestConfigViaEnvVars, signal::wait_for_ctrlc, @@ -337,7 +338,7 @@ fn run_schedule_commit_tests( let start_devnet_validator = || match start_validator( "schedulecommit-conf.devnet.toml", - ValidatorCluster::Chain(None), + ValidatorCluster::Light, &loaded_chain_accounts, ) { Some(validator) => validator, @@ -380,7 +381,7 @@ fn run_schedule_commit_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run security: {:?}", err); - cleanup_validators( + cleanup_validators_with_light( &mut ephem_validator, &mut devnet_validator, ); @@ -396,7 +397,7 @@ fn run_schedule_commit_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run scenarios: {:?}", err); - cleanup_validators( + cleanup_validators_with_light( &mut ephem_validator, &mut devnet_validator, ); @@ -404,7 +405,10 @@ fn run_schedule_commit_tests( } }; - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators_with_light( + &mut ephem_validator, + &mut devnet_validator, + ); Ok((test_security_output, test_scenarios_output)) } else { let devnet_validator = @@ -413,9 +417,9 @@ fn run_schedule_commit_tests( config.setup_ephem(TEST_NAME).then(start_ephem_validator); eprintln!("Setup validator(s)"); wait_for_ctrlc( - devnet_validator, - ephem_validator, None, + ephem_validator, + devnet_validator, success_output(), )?; Ok((success_output(), success_output())) diff --git a/test-kit/Cargo.toml b/test-kit/Cargo.toml index 925e3456a..05d376402 100644 --- a/test-kit/Cargo.toml +++ b/test-kit/Cargo.toml @@ -15,6 +15,7 @@ magicblock-ledger = { workspace = true } magicblock-processor = { workspace = true } solana-account = { workspace = true } +solana-pubkey = { workspace = true } solana-instruction = { workspace = true } solana-keypair = { workspace = true } solana-program = { workspace = true } diff --git a/test-kit/src/lib.rs b/test-kit/src/lib.rs index c1a3801e1..9d8017001 100644 --- a/test-kit/src/lib.rs +++ b/test-kit/src/lib.rs @@ -33,9 +33,8 @@ use magicblock_processor::{ use solana_account::AccountSharedData; pub use solana_instruction::*; use solana_keypair::Keypair; -use solana_program::{ - hash::Hasher, native_token::LAMPORTS_PER_SOL, pubkey::Pubkey, -}; +use solana_program::{hash::Hasher, native_token::LAMPORTS_PER_SOL}; +use solana_pubkey::Pubkey; use solana_signature::Signature; pub use solana_signer::Signer; use solana_transaction::Transaction; From 691c1be902c4d188ca27b93ba6adda76cfeabb9f Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Tue, 28 Apr 2026 15:56:53 +0200 Subject: [PATCH 004/110] fix: install for schedulecommit tests --- .github/workflows/ci-test-integration.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index e92bec2a8..c0beb4da8 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -71,20 +71,20 @@ jobs: - uses: ./magicblock-validator/.github/actions/setup-solana - name: Install Photon indexer - if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' + if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'schedulecommit' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' shell: bash env: RUSTFLAGS: "-A dead-code" run: cargo install --git https://github.com/lightprotocol/photon.git --rev 3f82b926be6717a07bd41aedb84b4d9e6b0ab0d3 --locked --force - name: Setup Node.js - if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' + if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'schedulecommit' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' uses: actions/setup-node@v4 with: node-version: "20" - name: Install zk-compression CLI - if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' + if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'schedulecommit' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' run: | npm i -g @lightprotocol/zk-compression-cli@0.28.4 shell: bash From 53e15744075a0fbaf32e9ad73b13f235da91f4f0 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Tue, 28 Apr 2026 16:45:12 +0200 Subject: [PATCH 005/110] fix: non optional light validator --- .github/workflows/ci-test-integration.yml | 3 - test-integration/test-runner/bin/run_tests.rs | 90 +++++-------------- test-integration/test-runner/src/cleanup.rs | 15 +--- test-integration/test-runner/src/signal.rs | 6 +- 4 files changed, 28 insertions(+), 86 deletions(-) diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index c0beb4da8..135d0bbc7 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -71,20 +71,17 @@ jobs: - uses: ./magicblock-validator/.github/actions/setup-solana - name: Install Photon indexer - if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'schedulecommit' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' shell: bash env: RUSTFLAGS: "-A dead-code" run: cargo install --git https://github.com/lightprotocol/photon.git --rev 3f82b926be6717a07bd41aedb84b4d9e6b0ab0d3 --locked --force - name: Setup Node.js - if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'schedulecommit' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' uses: actions/setup-node@v4 with: node-version: "20" - name: Install zk-compression CLI - if: matrix.batch_tests == 'table_mania' || matrix.batch_tests == 'schedulecommit' || matrix.batch_tests == 'committor' || matrix.batch_tests == 'chainlink' run: | npm i -g @lightprotocol/zk-compression-cli@0.28.4 shell: bash diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index 133574d2d..84319f202 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -10,16 +10,12 @@ use integration_test_tools::{ toml_to_args::ProgramLoader, validator::{ resolve_workspace_dir, start_light_validator_with_config, - start_magic_block_validator_with_config, - start_test_validator_with_config, TestRunnerPaths, + start_magic_block_validator_with_config, TestRunnerPaths, }, }; use teepee::Teepee; use test_runner::{ - cleanup::{ - cleanup_devnet_only, cleanup_light_validator, cleanup_validators, - cleanup_validators_with_light, - }, + cleanup::{cleanup_devnet_only, cleanup_validators}, env_config::TestConfigViaEnvVars, signal::wait_for_ctrlc, }; @@ -156,7 +152,7 @@ fn run_restore_ledger_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, None, success_output()) + wait_for_ctrlc(devnet_validator, None, success_output()) } } @@ -193,7 +189,7 @@ fn run_chainlink_tests( }; let start_devnet_validator = || match start_validator( "chainlink-conf.devnet.toml", - ValidatorCluster::Light, + ValidatorCluster::Chain(None), &loaded_chain_accounts, ) { Some(validator) => validator, @@ -211,7 +207,7 @@ fn run_chainlink_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run chainlink tests: {:?}", err); - cleanup_light_validator(&mut devnet_validator, "light"); + cleanup_devnet_only(&mut devnet_validator); return Err(err.into()); } }; @@ -220,7 +216,7 @@ fn run_chainlink_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(None, None, devnet_validator, success_output()) + wait_for_ctrlc(devnet_validator, None, success_output()) } } @@ -244,7 +240,7 @@ fn run_table_mania_and_committor_tests( let start_devnet_validator = || match start_validator( "committor-conf.devnet.toml", - ValidatorCluster::Light, + ValidatorCluster::Chain(None), &loaded_chain_accounts, ) { Some(validator) => validator, @@ -301,7 +297,7 @@ fn run_table_mania_and_committor_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run committor: {:?}", err); - cleanup_light_validator(&mut devnet_validator, "light"); + cleanup_devnet_only(&mut devnet_validator); return Err(err.into()); } } @@ -310,7 +306,7 @@ fn run_table_mania_and_committor_tests( success_output() }; - cleanup_light_validator(&mut devnet_validator, "light"); + cleanup_devnet_only(&mut devnet_validator); Ok((table_mania_test_output, committor_test_output)) } else { @@ -318,7 +314,7 @@ fn run_table_mania_and_committor_tests( || config.setup_devnet(COMMITTOR_TEST); let devnet_validator = setup_needed.then(start_devnet_validator); Ok(( - wait_for_ctrlc(None, None, devnet_validator, success_output())?, + wait_for_ctrlc(devnet_validator, None, success_output())?, success_output(), )) } @@ -338,7 +334,7 @@ fn run_schedule_commit_tests( let start_devnet_validator = || match start_validator( "schedulecommit-conf.devnet.toml", - ValidatorCluster::Light, + ValidatorCluster::Chain(None), &loaded_chain_accounts, ) { Some(validator) => validator, @@ -381,7 +377,7 @@ fn run_schedule_commit_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run security: {:?}", err); - cleanup_validators_with_light( + cleanup_validators( &mut ephem_validator, &mut devnet_validator, ); @@ -397,7 +393,7 @@ fn run_schedule_commit_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run scenarios: {:?}", err); - cleanup_validators_with_light( + cleanup_validators( &mut ephem_validator, &mut devnet_validator, ); @@ -405,10 +401,7 @@ fn run_schedule_commit_tests( } }; - cleanup_validators_with_light( - &mut ephem_validator, - &mut devnet_validator, - ); + cleanup_validators(&mut ephem_validator, &mut devnet_validator); Ok((test_security_output, test_scenarios_output)) } else { let devnet_validator = @@ -416,12 +409,7 @@ fn run_schedule_commit_tests( let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); eprintln!("Setup validator(s)"); - wait_for_ctrlc( - None, - ephem_validator, - devnet_validator, - success_output(), - )?; + wait_for_ctrlc(devnet_validator, ephem_validator, success_output())?; Ok((success_output(), success_output())) } } @@ -505,12 +493,7 @@ fn run_cloning_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc( - devnet_validator, - ephem_validator, - None, - success_output(), - ) + wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) } } @@ -567,12 +550,7 @@ fn run_magicblock_api_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc( - devnet_validator, - ephem_validator, - None, - success_output(), - ) + wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) } } @@ -631,12 +609,7 @@ fn run_magicblock_pubsub_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc( - devnet_validator, - ephem_validator, - None, - success_output(), - ) + wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) } } @@ -683,7 +656,7 @@ fn run_config_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, None, success_output()) + wait_for_ctrlc(devnet_validator, None, success_output()) } } @@ -753,12 +726,7 @@ fn run_schedule_intents_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc( - devnet_validator, - ephem_validator, - None, - success_output(), - ) + wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) } } @@ -807,7 +775,7 @@ fn run_task_scheduler_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, None, success_output()) + wait_for_ctrlc(devnet_validator, None, success_output()) } } @@ -883,15 +851,13 @@ fn resolve_paths(config_file: &str) -> TestRunnerPaths { enum ValidatorCluster { Chain(Option), Ephem, - Light, } impl ValidatorCluster { fn log_suffix(&self) -> &'static str { match self { - ValidatorCluster::Chain(_) => "CHAIN", ValidatorCluster::Ephem => "EPHEM", - ValidatorCluster::Light => "LIGHT", + ValidatorCluster::Chain(_) => "CHAIN", } } } @@ -905,22 +871,14 @@ fn start_validator( let test_runner_paths = resolve_paths(config_file); match cluster { - ValidatorCluster::Chain(program_loader) - if std::env::var("FORCE_MAGIC_BLOCK_VALIDATOR").is_err() => - { - start_test_validator_with_config( + ValidatorCluster::Chain(program_loader) => { + start_light_validator_with_config( &test_runner_paths, program_loader, loaded_chain_accounts, log_suffix, ) } - ValidatorCluster::Light => start_light_validator_with_config( - &test_runner_paths, - None, - loaded_chain_accounts, - log_suffix, - ), _ => start_magic_block_validator_with_config( &test_runner_paths, log_suffix, diff --git a/test-integration/test-runner/src/cleanup.rs b/test-integration/test-runner/src/cleanup.rs index 491ef89f1..f8a40dff5 100644 --- a/test-integration/test-runner/src/cleanup.rs +++ b/test-integration/test-runner/src/cleanup.rs @@ -1,20 +1,11 @@ use std::process::{self, Child}; pub fn cleanup_validators( - ephem_validator: &mut Child, - devnet_validator: &mut Child, -) { - cleanup_validator(ephem_validator, "ephemeral"); - cleanup_validator(devnet_validator, "devnet"); - kill_validators(); -} - -pub fn cleanup_validators_with_light( ephem_validator: &mut Child, light_validator: &mut Child, ) { cleanup_validator(ephem_validator, "ephemeral"); - cleanup_light_validator(light_validator, "light"); + cleanup_light_validator(light_validator); kill_validators(); } @@ -29,9 +20,9 @@ pub fn cleanup_validator(validator: &mut Child, label: &str) { }); } -pub fn cleanup_light_validator(validator: &mut Child, label: &str) { +pub fn cleanup_light_validator(validator: &mut Child) { validator.kill().unwrap_or_else(|err| { - panic!("Failed to kill {} validator ({:?})", label, err) + panic!("Failed to kill light validator ({:?})", err) }); let command = process::Command::new("light") .arg("test-validator") diff --git a/test-integration/test-runner/src/signal.rs b/test-integration/test-runner/src/signal.rs index 9cbdaeb93..84ce66d1e 100644 --- a/test-integration/test-runner/src/signal.rs +++ b/test-integration/test-runner/src/signal.rs @@ -9,7 +9,6 @@ use crate::cleanup::{cleanup_light_validator, cleanup_validator}; pub fn wait_for_ctrlc( devnet_validator: Option, ephem_validator: Option, - light_validator: Option, output: Output, ) -> Result> { let (tx, rx) = channel(); @@ -21,14 +20,11 @@ pub fn wait_for_ctrlc( rx.recv().expect("Could not receive from channel."); if let Some(mut validator) = devnet_validator { - cleanup_validator(&mut validator, "devnet"); + cleanup_light_validator(&mut validator); } if let Some(mut validator) = ephem_validator { cleanup_validator(&mut validator, "ephemeral"); } - if let Some(mut validator) = light_validator { - cleanup_light_validator(&mut validator, "light"); - } Ok(output) } From 2b634b17b90f4cd2ec5ce76f7a970f2c064cf8c7 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 00:52:42 +0200 Subject: [PATCH 006/110] feat: optional compression --- .github/workflows/ci-test-integration.yml | 3 + magicblock-api/src/magic_validator.rs | 27 +++++- .../src/chainlink/fetch_cloner/tests.rs | 2 +- .../src/remote_account_provider/mod.rs | 37 ++++--- .../tests/utils/test_context.rs | 2 +- .../src/committor_processor.rs | 96 ++++++++++++++++++- magicblock-committor-service/src/config.rs | 8 +- magicblock-committor-service/src/error.rs | 5 + .../src/intent_executor/task_info_fetcher.rs | 24 +++-- magicblock-config/src/config/compression.rs | 14 +-- magicblock-config/src/consts.rs | 4 - magicblock-config/src/lib.rs | 2 +- magicblock-config/src/tests.rs | 18 +++- .../process_schedule_commit.rs | 9 ++ programs/magicblock/src/validator.rs | 14 ++- .../configs/chainlink-conf.devnet.toml | 3 + .../configs/committor-conf.devnet.toml | 3 + .../configs/schedulecommit-conf.devnet.toml | 3 + .../test-chainlink/src/test_context.rs | 2 +- .../tests/test_intent_executor.rs | 4 +- test-integration/test-runner/bin/run_tests.rs | 24 ++++- 21 files changed, 242 insertions(+), 62 deletions(-) diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index 135d0bbc7..e71ad3be9 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -71,17 +71,20 @@ jobs: - uses: ./magicblock-validator/.github/actions/setup-solana - name: Install Photon indexer + if: contains(fromJSON('["schedulecommit","chainlink","committor"]'), matrix.batch_tests) shell: bash env: RUSTFLAGS: "-A dead-code" run: cargo install --git https://github.com/lightprotocol/photon.git --rev 3f82b926be6717a07bd41aedb84b4d9e6b0ab0d3 --locked --force - name: Setup Node.js + if: contains(fromJSON('["schedulecommit","chainlink","committor"]'), matrix.batch_tests) uses: actions/setup-node@v4 with: node-version: "20" - name: Install zk-compression CLI + if: contains(fromJSON('["schedulecommit","chainlink","committor"]'), matrix.batch_tests) run: | npm i -g @lightprotocol/zk-compression-cli@0.28.4 shell: bash diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 7e8d0e146..967edd013 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -288,6 +288,14 @@ impl MagicValidator { } let base_fee = config.validator.basefee; + if config + .compression + .as_ref() + .is_some_and(|compression| compression.photon_url.is_some()) + { + validator::set_compression_enabled(true); + } + // Mode switch channel for transitioning from StartingUp to Primary // or Replica mode after ledger replay let (mode_tx, mode_rx) = channel(1); @@ -435,7 +443,10 @@ impl MagicValidator { committor_persist_path, ChainConfig { rpc_uri: config.rpc_url().to_owned(), - photon_uri: config.compression.photon_url.clone(), + photon_uri: config + .compression + .as_ref() + .and_then(|compression| compression.photon_url.clone()), commitment: CommitmentConfig::confirmed(), compute_budget_config: ComputeBudgetConfig::new( config.commit.compute_unit_price, @@ -481,10 +492,16 @@ impl MagicValidator { ) })?; - endpoints.push(Endpoint::Compression { - label: "photon".to_string(), - url: config.compression.photon_url.clone(), - }); + if let Some(photon_url) = config + .compression + .as_ref() + .and_then(|compression| compression.photon_url.clone()) + { + endpoints.push(Endpoint::Compression { + label: "photon".to_string(), + url: photon_url.clone(), + }); + } let cloner = ChainlinkCloner::new( committor_service, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index b208153f1..41b59270d 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -158,7 +158,7 @@ where RemoteAccountProvider::new( rpc_client, pubsub_client, - photon_client, + Some(photon_client), forward_tx, &config, subscribed_accounts, diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 971f70599..02ace2e42 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -114,7 +114,7 @@ pub struct RemoteAccountProvider< /// states up to date pubsub_client: U, /// The photon client to fetch compressed accounts from - photon_client: P, + photon_client: Option

, /// Minimal tracking of accounts currently being fetched to handle race conditions /// between fetch and subscription updates. Only used during active fetch operations. fetching_accounts: Arc, @@ -223,7 +223,7 @@ impl pub async fn try_from_clients_and_mode( rpc_client: T, pubsub_client: U, - photon_client: P, + photon_client: Option

, subscription_forwarder: mpsc::Sender, config: &RemoteAccountProviderConfig, lrucache_subscribed_accounts: Arc, @@ -283,7 +283,7 @@ impl pub(crate) async fn new( rpc_client: T, pubsub_client: U, - photon_client: P, + photon_client: Option

, subscription_forwarder: mpsc::Sender, config: &RemoteAccountProviderConfig, lrucache_subscribed_accounts: Arc, @@ -365,12 +365,8 @@ impl let rpc_client = ChainRpcClientImpl::new_from_url(rpc_url.as_str(), commitment); - let photon_url = endpoints.photon_url().ok_or_else(|| { - RemoteAccountProviderError::AccountSubscriptionsTaskFailed( - "No compression endpoint found".to_string(), - ) - })?; - let photon_client = PhotonClientImpl::new_from_url(photon_url); + let photon_client = + endpoints.photon_url().map(PhotonClientImpl::new_from_url); // Create chain_slot to be shared with all pubsub clients let chain_slot = Arc::::default(); @@ -1442,11 +1438,24 @@ impl } async fn fetch_from_photon( - photon_client: P, + photon_client: Option

, pubkeys: Vec, mark_empty_if_not_found: &[Pubkey], min_context_slot: u64, ) -> ChainlinkResult<(FetchedRemoteAccounts, u64, u64)> { + let Some(photon_client) = photon_client else { + // If no photon client is provided, we return a vector of not found accounts + return Ok(( + FetchedRemoteAccounts::Rpc(vec![ + RemoteAccount::NotFound( + min_context_slot + ); + pubkeys.len() + ]), + 0, + pubkeys.len() as u64, + )); + }; if tracing::enabled!(tracing::Level::TRACE) { trace!( pubkeys = pubkeys_str(&pubkeys), @@ -1750,7 +1759,7 @@ mod test { RemoteAccountProvider::new( rpc_client, pubsub_client, - photon_client, + Some(photon_client), fwd_tx, &config, subscribed_accounts, @@ -1804,7 +1813,7 @@ mod test { RemoteAccountProvider::new( rpc_client.clone(), pubsub_client, - photon_client, + Some(photon_client), fwd_tx, &config, subscribed_accounts, @@ -1892,7 +1901,7 @@ mod test { RemoteAccountProvider::new( rpc_client, pubsub_client, - photon_client, + Some(photon_client), forward_tx, &config, subscribed_accounts, @@ -2104,7 +2113,7 @@ mod test { let provider = RemoteAccountProvider::new( rpc_client, pubsub_client, - photon_client, + Some(photon_client), forward_tx, &config, subscribed_accounts, diff --git a/magicblock-chainlink/tests/utils/test_context.rs b/magicblock-chainlink/tests/utils/test_context.rs index c6a8e783b..4390fd478 100644 --- a/magicblock-chainlink/tests/utils/test_context.rs +++ b/magicblock-chainlink/tests/utils/test_context.rs @@ -94,7 +94,7 @@ impl TestContext { RemoteAccountProvider::try_from_clients_and_mode( rpc_client.clone(), pubsub_client.clone(), - photon_client.clone(), + Some(photon_client.clone()), tx, &config, subscribed_accounts, diff --git a/magicblock-committor-service/src/committor_processor.rs b/magicblock-committor-service/src/committor_processor.rs index 42c3e30c7..1f6672248 100644 --- a/magicblock-committor-service/src/committor_processor.rs +++ b/magicblock-committor-service/src/committor_processor.rs @@ -18,7 +18,7 @@ use tracing::{error, instrument}; use crate::{ config::ChainConfig, - error::CommittorServiceResult, + error::{CommittorServiceError, CommittorServiceResult}, intent_execution_manager::{ db::DummyDB, BroadcastedIntentExecutionResult, IntentExecutionManager, }, @@ -42,6 +42,7 @@ pub(crate) struct CommittorProcessor { persister: IntentPersisterImpl, commits_scheduler: IntentExecutionManager, task_info_fetcher: Arc>, + compression_enabled: bool, } impl CommittorProcessor { @@ -61,8 +62,11 @@ impl CommittorProcessor { ); let rpc_client = Arc::new(rpc_client); let magic_block_rpc_client = MagicblockRpcClient::new(rpc_client); - let photon_client = - Arc::new(PhotonIndexer::new(chain_config.photon_uri.to_string())); + let photon_client = chain_config + .photon_uri + .as_ref() + .map(|uri| Arc::new(PhotonIndexer::new(uri.to_string()))); + let compression_enabled = photon_client.is_some(); // Create TableMania let gc_config = GarbageCollectorConfig::default(); @@ -103,9 +107,19 @@ impl CommittorProcessor { commits_scheduler, persister, task_info_fetcher, + compression_enabled, }) } + fn requires_compression(intent_bundle: &ScheduledIntentBundle) -> bool { + intent_bundle + .get_commit_finalize_compressed_intent_accounts() + .is_some() + || intent_bundle + .get_commit_finalize_compressed_and_undelegate_intent_accounts() + .is_some() + } + pub async fn active_lookup_tables(&self) -> Vec { self.table_mania.active_table_addresses().await } @@ -157,6 +171,12 @@ impl CommittorProcessor { &self, intent_bundles: Vec, ) -> CommittorServiceResult<()> { + if !self.compression_enabled + && intent_bundles.iter().any(Self::requires_compression) + { + return Err(CommittorServiceError::CompressionNotConfigured); + } + if let Err(err) = self.persister.start_base_intents(&intent_bundles) { // We will still try to perform the commits, but the fact that we cannot // persist the intent is very serious and we should probably restart the @@ -193,3 +213,73 @@ impl CommittorProcessor { .await } } + +#[cfg(test)] +mod tests { + use magicblock_core::{ + intent::BaseActionCallback, + traits::{ + ActionResult, ActionsCallbackScheduler, CallbackScheduleError, + }, + }; + use solana_hash::Hash; + use solana_signature::Signature; + use solana_transaction::Transaction; + use tempfile::NamedTempFile; + + use super::*; + use crate::{ + compute_budget::ComputeBudgetConfig, + config::{ChainConfig, DEFAULT_ACTIONS_TIMEOUT}, + error::CommittorServiceError, + intent_execution_manager::intent_scheduler::create_test_compressed_intent, + }; + + #[derive(Clone, Default)] + struct NoopActionsCallbackScheduler; + + impl ActionsCallbackScheduler for NoopActionsCallbackScheduler { + fn schedule( + &self, + callbacks: Vec, + _signature: Option, + _result: ActionResult, + ) -> Vec> { + callbacks + .iter() + .map(|_| Ok(Signature::new_unique())) + .collect() + } + } + + #[tokio::test] + async fn compressed_intents_fail_without_photon_indexer() { + let persist_file = NamedTempFile::new().unwrap(); + let processor = CommittorProcessor::try_new( + Keypair::new(), + persist_file.path(), + ChainConfig { + rpc_uri: "http://localhost:7799".to_string(), + photon_uri: None, + commitment: + solana_commitment_config::CommitmentConfig::processed(), + compute_budget_config: ComputeBudgetConfig::new(1_000_000), + actions_timeout: DEFAULT_ACTIONS_TIMEOUT, + }, + NoopActionsCallbackScheduler, + ) + .unwrap(); + + let mut intent = + create_test_compressed_intent(1, &[Pubkey::new_unique()], false); + intent.blockhash = Hash::new_unique(); + intent.sent_transaction = Transaction::default(); + + let result = processor.schedule_intent_bundle(vec![intent]).await; + + assert!(matches!( + result, + Err(CommittorServiceError::CompressionNotConfigured) + )); + } +} diff --git a/magicblock-committor-service/src/config.rs b/magicblock-committor-service/src/config.rs index 116b0e274..e54ec7442 100644 --- a/magicblock-committor-service/src/config.rs +++ b/magicblock-committor-service/src/config.rs @@ -9,7 +9,7 @@ pub const DEFAULT_ACTIONS_TIMEOUT: Duration = Duration::from_secs(60); #[derive(Debug, Clone)] pub struct ChainConfig { pub rpc_uri: String, - pub photon_uri: String, + pub photon_uri: Option, pub commitment: CommitmentConfig, pub compute_budget_config: ComputeBudgetConfig, pub actions_timeout: Duration, @@ -19,7 +19,7 @@ impl ChainConfig { pub fn devnet(compute_budget_config: ComputeBudgetConfig) -> Self { Self { rpc_uri: "https://api.devnet.solana.com".to_string(), - photon_uri: "http://localhost:8784".to_string(), + photon_uri: Some("http://localhost:8784".to_string()), commitment: CommitmentConfig::confirmed(), compute_budget_config, actions_timeout: DEFAULT_ACTIONS_TIMEOUT, @@ -29,7 +29,7 @@ impl ChainConfig { pub fn mainnet(compute_budget_config: ComputeBudgetConfig) -> Self { Self { rpc_uri: "https://api.mainnet-beta.solana.com".to_string(), - photon_uri: "http://localhost:8784".to_string(), + photon_uri: Some("http://localhost:8784".to_string()), commitment: CommitmentConfig::confirmed(), compute_budget_config, actions_timeout: DEFAULT_ACTIONS_TIMEOUT, @@ -39,7 +39,7 @@ impl ChainConfig { pub fn local(compute_budget_config: ComputeBudgetConfig) -> Self { Self { rpc_uri: "http://localhost:7799".to_string(), - photon_uri: "http://localhost:8784".to_string(), + photon_uri: Some("http://localhost:8784".to_string()), commitment: CommitmentConfig::processed(), compute_budget_config, actions_timeout: DEFAULT_ACTIONS_TIMEOUT, diff --git a/magicblock-committor-service/src/error.rs b/magicblock-committor-service/src/error.rs index fa13e49b8..492ba2701 100644 --- a/magicblock-committor-service/src/error.rs +++ b/magicblock-committor-service/src/error.rs @@ -64,6 +64,11 @@ pub enum CommittorServiceError { #[error("Could not find commit strategy for bundle {0}")] CouldNotFindCommitStrategyForBundle(u64), + #[error( + "Compression is not configured; cannot schedule compressed commits" + )] + CompressionNotConfigured, + #[error("Failed to fetch metadata account for {0}")] FailedToFetchDelegationMetadata(Pubkey), diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 4e5d4a47a..457e52649 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -112,13 +112,13 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { /// Pure RPC implementation of [`TaskInfoFetcher`] — no caching. pub struct RpcTaskInfoFetcher { rpc_client: MagicblockRpcClient, - photon_client: Arc, + photon_client: Option>, } impl RpcTaskInfoFetcher { pub fn new( rpc_client: MagicblockRpcClient, - photon_client: Arc, + photon_client: Option>, ) -> Self { Self { rpc_client, @@ -126,6 +126,12 @@ impl RpcTaskInfoFetcher { } } + fn photon_client(&self) -> TaskInfoFetcherResult<&PhotonIndexer> { + self.photon_client + .as_deref() + .ok_or(TaskInfoFetcherError::CompressionNotConfigured) + } + /// Fetches [`DelegationMetadata`]s with some num of retries pub async fn fetch_metadata_with_retries( rpc_client: &MagicblockRpcClient, @@ -217,6 +223,9 @@ impl RpcTaskInfoFetcher { TaskInfoFetcherError::IndexerError(_) => { break Err(err); } + TaskInfoFetcherError::CompressionNotConfigured => { + break Err(err); + } TaskInfoFetcherError::CompressedAccountNotFound(_) => { break Err(err); } @@ -325,7 +334,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .collect::>(); let nonces = self - .photon_client + .photon_client()? .get_multiple_compressed_accounts(Some(cdas), None, None) .await? .value @@ -373,7 +382,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .collect::>(); let nonces = self - .photon_client + .photon_client()? .get_multiple_compressed_accounts(Some(cdas), None, None) .await? .value @@ -433,7 +442,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { ) -> TaskInfoFetcherResult { let cda = derive_cda_from_pda(pubkey); let compressed_delegation_record = self - .photon_client + .photon_client()? .get_compressed_account( cda.to_bytes(), min_context_slot.map(|slot| IndexerRpcConfig { @@ -445,7 +454,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .value .ok_or(TaskInfoFetcherError::EmptyCompressedAccount)?; let proof_result = self - .photon_client + .photon_client()? .get_validity_proof( vec![compressed_delegation_record.hash], vec![], @@ -881,6 +890,8 @@ pub enum TaskInfoFetcherError { MagicBlockRpcClientError(Box), #[error("Indexer error: {0}")] IndexerError(#[from] light_client::indexer::IndexerError), + #[error("Compression is not configured")] + CompressionNotConfigured, #[error("Compressed account not found for: {0}")] CompressedAccountNotFound(Pubkey), #[error("Empty compressed account")] @@ -944,6 +955,7 @@ impl TaskInfoFetcherError { Self::MinContextSlotNotReachedError(_, err) => err.signature(), Self::MagicBlockRpcClientError(err) => err.signature(), Self::IndexerError(_) => None, + Self::CompressionNotConfigured => None, Self::CompressedAccountNotFound(_) => None, Self::EmptyCompressedAccount => None, Self::LightSdkError(_) => None, diff --git a/magicblock-config/src/config/compression.rs b/magicblock-config/src/config/compression.rs index 3c32a75f7..a872b56aa 100644 --- a/magicblock-config/src/config/compression.rs +++ b/magicblock-config/src/config/compression.rs @@ -1,19 +1,9 @@ use serde::{Deserialize, Serialize}; -use crate::consts; - /// Configuration for the compression service. -#[derive(Deserialize, Serialize, Debug, Clone)] +#[derive(Deserialize, Serialize, Debug, Clone, Default)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct CompressionConfig { /// The URL of the Photon indexer. - pub photon_url: String, -} - -impl Default for CompressionConfig { - fn default() -> Self { - Self { - photon_url: consts::DEFAULT_PHOTON_URL.to_string(), - } - } + pub photon_url: Option, } diff --git a/magicblock-config/src/consts.rs b/magicblock-config/src/consts.rs index 952a29c18..e164d8485 100644 --- a/magicblock-config/src/consts.rs +++ b/magicblock-config/src/consts.rs @@ -73,7 +73,3 @@ pub const DEFAULT_RESUBSCRIPTION_DELAY_MS: u64 = 50; /// Default capacity for the LRU cache of subscribed accounts pub const DEFAULT_MAX_MONITORED_ACCOUNTS: usize = 5_000; - -// Compression Defaults -/// Default URL of the Photon indexer -pub const DEFAULT_PHOTON_URL: &str = "http://localhost:8784"; diff --git a/magicblock-config/src/lib.rs b/magicblock-config/src/lib.rs index 12807aabe..07f6df853 100644 --- a/magicblock-config/src/lib.rs +++ b/magicblock-config/src/lib.rs @@ -64,7 +64,7 @@ pub struct ValidatorParams { pub chainlink: ChainLinkConfig, pub chain_operation: Option, pub task_scheduler: TaskSchedulerConfig, - pub compression: CompressionConfig, + pub compression: Option, pub programs: Vec, } diff --git a/magicblock-config/src/tests.rs b/magicblock-config/src/tests.rs index d666fa310..4e7c1038f 100644 --- a/magicblock-config/src/tests.rs +++ b/magicblock-config/src/tests.rs @@ -295,7 +295,18 @@ fn test_compression_config() { let config = run_cli(vec![config_path.to_str().unwrap()]); - assert_eq!(config.compression.photon_url, "http://localhost:8784"); + assert_eq!( + config.compression.as_ref().unwrap().photon_url, + Some("http://localhost:8784".to_string()) + ); +} + +#[test] +#[parallel] +fn test_compression_config_is_optional() { + let config = run_cli(vec![]); + + assert!(config.compression.is_none()); } // ============================================================================ @@ -468,7 +479,10 @@ fn test_example_config_full_coverage() { ); // Compression config is present - assert_eq!(config.compression.photon_url, "http://localhost:8784"); + assert_eq!( + config.compression.as_ref().unwrap().photon_url, + Some("http://localhost:8784".to_string()) + ); // The example file has the programs section with 2 entries assert_eq!( diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs index fbb675940..d75f03ad6 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs @@ -26,6 +26,7 @@ use crate::{ }, instruction_utils::InstructionUtils, }, + validator::is_compression_enabled, MagicContext, }; @@ -40,6 +41,14 @@ pub(crate) fn process_schedule_commit( invoke_context: &mut InvokeContext, opts: ProcessScheduleCommitOptions, ) -> Result<(), InstructionError> { + if opts.compressed && !is_compression_enabled() { + ic_msg!( + invoke_context, + "ScheduleCommit: compression is not enabled, but compressed accounts are being committed" + ); + return Err(InstructionError::InvalidInstructionData); + } + const PAYER_IDX: u16 = 0; const MAGIC_CONTEXT_IDX: u16 = PAYER_IDX + 1; diff --git a/programs/magicblock/src/validator.rs b/programs/magicblock/src/validator.rs index 4a4f6e572..613bf4dcc 100644 --- a/programs/magicblock/src/validator.rs +++ b/programs/magicblock/src/validator.rs @@ -1,4 +1,7 @@ -use std::sync::RwLock; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + RwLock, +}; use lazy_static::lazy_static; use solana_keypair::Keypair; @@ -9,6 +12,7 @@ lazy_static! { static ref VALIDATOR_AUTHORITY: RwLock> = RwLock::new(None); static ref VALIDATOR_AUTHORITY_OVERRIDE: RwLock> = RwLock::new(None); + static ref IS_COMPRESSION_ENABLED: AtomicBool = AtomicBool::new(false); } pub fn validator_authority() -> Keypair { @@ -82,3 +86,11 @@ pub fn generate_validator_authority_if_needed() { } validator_authority_lock.replace(Keypair::new()); } + +pub fn set_compression_enabled(enabled: bool) { + IS_COMPRESSION_ENABLED.store(enabled, Ordering::Relaxed); +} + +pub fn is_compression_enabled() -> bool { + IS_COMPRESSION_ENABLED.load(Ordering::Relaxed) +} diff --git a/test-integration/configs/chainlink-conf.devnet.toml b/test-integration/configs/chainlink-conf.devnet.toml index 80fc348db..e0eea7e74 100644 --- a/test-integration/configs/chainlink-conf.devnet.toml +++ b/test-integration/configs/chainlink-conf.devnet.toml @@ -53,5 +53,8 @@ auth = "MiniV3AUTH111111111111111111111111111111111" id = "DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT" path = "../programs/compressed_delegation/compressed_delegation.so" +[compression] +photon-url = "http://localhost:8784" + [metrics] address = "0.0.0.0:9000" # Default if not specified, was disabled before but struct requires address diff --git a/test-integration/configs/committor-conf.devnet.toml b/test-integration/configs/committor-conf.devnet.toml index 74a8869c9..5d1b61426 100644 --- a/test-integration/configs/committor-conf.devnet.toml +++ b/test-integration/configs/committor-conf.devnet.toml @@ -49,6 +49,9 @@ path = "../target/deploy/program_flexi_counter.so" id = "DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT" path = "../programs/compressed_delegation/compressed_delegation.so" +[compression] +photon-url = "http://localhost:8784" + [geyser-grpc] port = 10001 diff --git a/test-integration/configs/schedulecommit-conf.devnet.toml b/test-integration/configs/schedulecommit-conf.devnet.toml index 2862ce1f4..2d3084f36 100644 --- a/test-integration/configs/schedulecommit-conf.devnet.toml +++ b/test-integration/configs/schedulecommit-conf.devnet.toml @@ -50,5 +50,8 @@ path = "../target/deploy/program_schedulecommit.so" id = "4RaQH3CUBMSMQsSHPVaww2ifeNEEuaDZjF9CUdFwr3xr" path = "../target/deploy/program_schedulecommit_security.so" +[compression] +photon-url = "http://localhost:8784" + [metrics] address = "0.0.0.0:9000" diff --git a/test-integration/test-chainlink/src/test_context.rs b/test-integration/test-chainlink/src/test_context.rs index 57eeae490..4b7dc6201 100644 --- a/test-integration/test-chainlink/src/test_context.rs +++ b/test-integration/test-chainlink/src/test_context.rs @@ -94,7 +94,7 @@ impl TestContext { RemoteAccountProvider::try_from_clients_and_mode( rpc_client.clone(), pubsub_client.clone(), - photon_client.clone(), + Some(photon_client.clone()), tx, &config, subscribed_accounts, diff --git a/test-integration/test-committor-service/tests/test_intent_executor.rs b/test-integration/test-committor-service/tests/test_intent_executor.rs index 418492c37..13c358965 100644 --- a/test-integration/test-committor-service/tests/test_intent_executor.rs +++ b/test-integration/test-committor-service/tests/test_intent_executor.rs @@ -106,7 +106,7 @@ impl TestEnv { let task_info_fetcher = Arc::new(CacheTaskInfoFetcher::new(RpcTaskInfoFetcher::new( fixture.rpc_client.clone(), - fixture.photon_indexer.clone(), + Some(fixture.photon_indexer.clone()), ))); let tm = &fixture.table_mania; @@ -1287,7 +1287,7 @@ async fn test_action_callback_fired_on_timeout() { let task_info_fetcher = Arc::new(CacheTaskInfoFetcher::new(RpcTaskInfoFetcher::new( fixture.rpc_client.clone(), - fixture.photon_indexer.clone(), + Some(fixture.photon_indexer.clone()), ))); let mut intent_executor = IntentExecutorImpl::new( fixture.rpc_client.clone(), diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index 84319f202..4ca3ca392 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -10,7 +10,8 @@ use integration_test_tools::{ toml_to_args::ProgramLoader, validator::{ resolve_workspace_dir, start_light_validator_with_config, - start_magic_block_validator_with_config, TestRunnerPaths, + start_magic_block_validator_with_config, + start_test_validator_with_config, TestRunnerPaths, }, }; use teepee::Teepee; @@ -189,7 +190,7 @@ fn run_chainlink_tests( }; let start_devnet_validator = || match start_validator( "chainlink-conf.devnet.toml", - ValidatorCluster::Chain(None), + ValidatorCluster::Light, &loaded_chain_accounts, ) { Some(validator) => validator, @@ -237,10 +238,15 @@ fn run_table_mania_and_committor_tests( let loaded_chain_accounts = LoadedAccounts::with_delegation_program_test_authority(); + let cluster = if !config.skip_entirely(COMMITTOR_TEST) { + ValidatorCluster::Chain(None) + } else { + ValidatorCluster::Light + }; let start_devnet_validator = || match start_validator( "committor-conf.devnet.toml", - ValidatorCluster::Chain(None), + cluster, &loaded_chain_accounts, ) { Some(validator) => validator, @@ -334,7 +340,7 @@ fn run_schedule_commit_tests( let start_devnet_validator = || match start_validator( "schedulecommit-conf.devnet.toml", - ValidatorCluster::Chain(None), + ValidatorCluster::Light, &loaded_chain_accounts, ) { Some(validator) => validator, @@ -851,6 +857,7 @@ fn resolve_paths(config_file: &str) -> TestRunnerPaths { enum ValidatorCluster { Chain(Option), Ephem, + Light, } impl ValidatorCluster { @@ -858,6 +865,7 @@ impl ValidatorCluster { match self { ValidatorCluster::Ephem => "EPHEM", ValidatorCluster::Chain(_) => "CHAIN", + ValidatorCluster::Light => "LIGHT", } } } @@ -872,13 +880,19 @@ fn start_validator( match cluster { ValidatorCluster::Chain(program_loader) => { - start_light_validator_with_config( + start_test_validator_with_config( &test_runner_paths, program_loader, loaded_chain_accounts, log_suffix, ) } + ValidatorCluster::Light => start_light_validator_with_config( + &test_runner_paths, + None, + loaded_chain_accounts, + log_suffix, + ), _ => start_magic_block_validator_with_config( &test_runner_paths, log_suffix, From 681988be3bb13a43768dbd4ad32ec171d8d15ecc Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 08:48:28 +0200 Subject: [PATCH 007/110] fix: fetch without photon --- magicblock-chainlink/src/chainlink/errors.rs | 3 +++ .../src/remote_account_provider/mod.rs | 14 ++------------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/errors.rs b/magicblock-chainlink/src/chainlink/errors.rs index a9a086b61..131e78876 100644 --- a/magicblock-chainlink/src/chainlink/errors.rs +++ b/magicblock-chainlink/src/chainlink/errors.rs @@ -53,4 +53,7 @@ pub enum ChainlinkError { #[error("Photon client error: {0}")] PhotonClientError(#[from] magicblock_core::traits::PhotonClientError), + + #[error("Compression is not enabled")] + CompressionNotEnabled, } diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 02ace2e42..07a04bfbe 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -75,7 +75,7 @@ use remote_account::{ pub use remote_account::{ResolvedAccount, ResolvedAccountSharedData}; use crate::{ - errors::ChainlinkResult, + errors::{ChainlinkError, ChainlinkResult}, remote_account_provider::{ chain_updates_client::ChainUpdatesClient, photon_client::PhotonClientImpl, pubsub_common::SubscriptionUpdate, @@ -1444,17 +1444,7 @@ impl min_context_slot: u64, ) -> ChainlinkResult<(FetchedRemoteAccounts, u64, u64)> { let Some(photon_client) = photon_client else { - // If no photon client is provided, we return a vector of not found accounts - return Ok(( - FetchedRemoteAccounts::Rpc(vec![ - RemoteAccount::NotFound( - min_context_slot - ); - pubkeys.len() - ]), - 0, - pubkeys.len() as u64, - )); + return Err(ChainlinkError::CompressionNotEnabled); }; if tracing::enabled!(tracing::Level::TRACE) { trace!( From addb8b2955126b2e44007504e0b6d4f7eb3bbaa7 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 08:49:23 +0200 Subject: [PATCH 008/110] fix: license --- Cargo.lock | 4 ++-- compressed-delegation-api/Cargo.toml | 10 ++++++---- compressed-delegation-client/Cargo.toml | 12 ++++++------ test-integration/Cargo.lock | 4 ++-- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f7f60e0e..54cbd4c43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1299,7 +1299,7 @@ dependencies = [ [[package]] name = "compressed-delegation-api" -version = "0.1.0" +version = "0.9.0" dependencies = [ "borsh 1.6.1", "light-compressed-account", @@ -1310,7 +1310,7 @@ dependencies = [ [[package]] name = "compressed-delegation-client" -version = "0.1.0" +version = "0.9.0" dependencies = [ "borsh 1.6.1", "compressed-delegation-api", diff --git a/compressed-delegation-api/Cargo.toml b/compressed-delegation-api/Cargo.toml index 00dc3a37b..a8da3b4d9 100644 --- a/compressed-delegation-api/Cargo.toml +++ b/compressed-delegation-api/Cargo.toml @@ -1,9 +1,11 @@ [package] name = "compressed-delegation-api" -version = "0.1.0" -edition = "2021" -license-file = "../../LICENSE" -publish = false +version.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true +license.workspace = true +edition.workspace = true [dependencies] borsh = { workspace = true, features = ["derive"] } diff --git a/compressed-delegation-client/Cargo.toml b/compressed-delegation-client/Cargo.toml index c399093d8..306f195ac 100644 --- a/compressed-delegation-client/Cargo.toml +++ b/compressed-delegation-client/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "compressed-delegation-client" -description = "A new Solana program using the Metaplex Project Template" -version = "0.1.0" -edition = "2021" -readme = "README.md" -license-file = "../../LICENSE" -repository = "https://github.com/metaplex-foundation/compressed-delegation-program" +version.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true +license.workspace = true +edition.workspace = true [lib] crate-type = ["lib"] diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 5519aef5b..2b777bb4e 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -1607,7 +1607,7 @@ dependencies = [ [[package]] name = "compressed-delegation-api" -version = "0.1.0" +version = "0.9.0" dependencies = [ "borsh 1.6.0", "light-compressed-account", @@ -1618,7 +1618,7 @@ dependencies = [ [[package]] name = "compressed-delegation-client" -version = "0.1.0" +version = "0.9.0" dependencies = [ "borsh 1.6.0", "compressed-delegation-api", From 1da6e11c25b1c1f11baadc0f1276664de20e31ec Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 08:55:06 +0200 Subject: [PATCH 009/110] fix: try from proof --- compressed-delegation-api/src/instruction.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/compressed-delegation-api/src/instruction.rs b/compressed-delegation-api/src/instruction.rs index b56337796..579e7094b 100644 --- a/compressed-delegation-api/src/instruction.rs +++ b/compressed-delegation-api/src/instruction.rs @@ -189,13 +189,16 @@ pub struct ExternalUndelegateArgs { )] pub struct CdpValidityProof(pub Option<[u8; 128]>); -impl From for ValidityProof { - fn from(cdp_validity_proof: CdpValidityProof) -> Self { - Self( - cdp_validity_proof - .0 - .and_then(|bytes| CompressedProof::try_from(&bytes[..]).ok()), - ) +impl TryFrom for ValidityProof { + type Error = light_compressed_account::CompressedAccountError; + fn try_from( + cdp_validity_proof: CdpValidityProof, + ) -> Result { + let Some(bytes) = cdp_validity_proof.0 else { + return Ok(Self(None)); + }; + let proof = CompressedProof::try_from(&bytes[..])?; + Ok(Self(Some(proof))) } } From 82da4c5e3450e571d0b98ba01fbb9878f71c8d9b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 08:56:05 +0200 Subject: [PATCH 010/110] docs: fix name --- compressed-delegation-client/src/builders/commit_finalize.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compressed-delegation-client/src/builders/commit_finalize.rs b/compressed-delegation-client/src/builders/commit_finalize.rs index 0ef413dcd..c6e35a1c7 100644 --- a/compressed-delegation-client/src/builders/commit_finalize.rs +++ b/compressed-delegation-client/src/builders/commit_finalize.rs @@ -3,7 +3,7 @@ use solana_pubkey::Pubkey; use crate::{CommitAndFinalizeArgs, DelegationProgramDiscriminator}; -/// Instruction builder for `Commit`. +/// Instruction builder for `CommitAndFinalize`. /// /// ### Accounts: /// From d519b24fdcd8f47f9bb5ae6050213835e6272452 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 08:56:47 +0200 Subject: [PATCH 011/110] fix: unnecessary clone --- magicblock-api/src/magic_validator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 967edd013..a0356e908 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -499,7 +499,7 @@ impl MagicValidator { { endpoints.push(Endpoint::Compression { label: "photon".to_string(), - url: photon_url.clone(), + url: photon_url, }); } From c65a61b6cd9c61ad306dddae6ca3fef78dd372bb Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:01:51 +0200 Subject: [PATCH 012/110] fix: unresolved accounts --- .../src/remote_account_provider/mod.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 07a04bfbe..5297c5e48 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -1152,6 +1152,29 @@ impl remote_accounts_results, ); + if remote_accounts.len() != pubkeys.len() { + let msg = format!( + "resolved {} of {} accounts after fetch", + remote_accounts.len(), + pubkeys.len() + ); + let mut fetching = fetching_accounts + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + for pubkey in &pubkeys { + if let Some((_, requests)) = fetching.remove(pubkey) { + for request in requests { + let _ = request.send(Err( + RemoteAccountProviderError::AccountResolutionsFailed(msg.clone()) + )); + } + } + } + return Err( + RemoteAccountProviderError::AccountResolutionsFailed(msg), + ); + } + // Update metrics for successful RPC fetch inc_account_fetches_success(pubkeys.len() as u64); inc_account_fetches_found(fetch_origin, found_cnt); From f62e3b778e9211372d470bd6672ccc75a4053104 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:02:50 +0200 Subject: [PATCH 013/110] fix: unnecessary log --- .../src/remote_account_provider/photon_client.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/magicblock-chainlink/src/remote_account_provider/photon_client.rs b/magicblock-chainlink/src/remote_account_provider/photon_client.rs index 1b522d4c3..003c89085 100644 --- a/magicblock-chainlink/src/remote_account_provider/photon_client.rs +++ b/magicblock-chainlink/src/remote_account_provider/photon_client.rs @@ -29,7 +29,6 @@ impl PhotonClientImpl { Self(photon_indexer) } pub fn new_from_url(url: String) -> Self { - debug!(url = %url, "Creating PhotonClient"); Self::new(Arc::new(PhotonIndexer::new(url))) } } From 0e77bf64398c0413a037755d8746fbcf42279666 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:08:00 +0200 Subject: [PATCH 014/110] feat: return none for multiple accounts --- .../src/intent_executor/task_info_fetcher.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 457e52649..3d47ada3c 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -97,9 +97,10 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { min_context_slot: Option, ) -> TaskInfoFetcherResult>> { try_join_all(pubkeys.iter().map(|pubkey| async move { - Ok(Some( - self.get_compressed_data(pubkey, min_context_slot).await?, - )) + Ok(self + .get_compressed_data(pubkey, min_context_slot) + .await + .ok()) })) .await } From d0f114407c3b686efe44af0daeea1ae7144f8fa7 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:10:15 +0200 Subject: [PATCH 015/110] fix: prevent mismatched length --- .../src/intent_executor/task_info_fetcher.rs | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 3d47ada3c..e0eb96cab 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -334,25 +334,27 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .map(|pubkey| derive_cda_from_pda(pubkey).to_bytes()) .collect::>(); - let nonces = self + let items = self .photon_client()? .get_multiple_compressed_accounts(Some(cdas), None, None) .await? .value - .items - .into_iter() - .filter_map(|compressed_account| { - let record = compressed_account - .and_then(|acc| acc.data) - .and_then(|compressed_account| { - CompressedDelegationRecord::try_from_slice( - &compressed_account.data, - ) + .items; + let mut result = HashMap::with_capacity(pubkeys.len()); + for (pubkey, compressed_account) in pubkeys.iter().zip(items) { + let nonce = compressed_account + .and_then(|acc| acc.data) + .and_then(|data| { + CompressedDelegationRecord::try_from_slice(&data.data) .ok() - })?; - Some(record.last_update_nonce + 1) - }); - Ok(pubkeys.iter().copied().zip(nonces).collect()) + }) + .map(|record| record.last_update_nonce + 1) + .ok_or(TaskInfoFetcherError::CompressedAccountNotFound( + *pubkey, + ))?; + result.insert(*pubkey, nonce); + } + Ok(result) } } @@ -382,25 +384,27 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .map(|pubkey| derive_cda_from_pda(pubkey).to_bytes()) .collect::>(); - let nonces = self + let items = self .photon_client()? .get_multiple_compressed_accounts(Some(cdas), None, None) .await? .value - .items - .into_iter() - .filter_map(|compressed_account| { - let record = compressed_account - .and_then(|acc| acc.data) - .and_then(|compressed_account| { - CompressedDelegationRecord::try_from_slice( - &compressed_account.data, - ) + .items; + let mut result = HashMap::with_capacity(pubkeys.len()); + for (pubkey, compressed_account) in pubkeys.iter().zip(items) { + let nonce = compressed_account + .and_then(|acc| acc.data) + .and_then(|data| { + CompressedDelegationRecord::try_from_slice(&data.data) .ok() - })?; - Some(record.last_update_nonce) - }); - Ok(pubkeys.iter().copied().zip(nonces).collect()) + }) + .map(|record| record.last_update_nonce) + .ok_or(TaskInfoFetcherError::CompressedAccountNotFound( + *pubkey, + ))?; + result.insert(*pubkey, nonce); + } + Ok(result) } } From ffdfbdfe80734991c346823cfa523be7d482914b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:17:01 +0200 Subject: [PATCH 016/110] feat: fail missing compressed data --- .../src/tasks/task_builder.rs | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 563b0e847..59069ccd4 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -297,10 +297,8 @@ impl TasksBuilder for TaskBuilderImpl { tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); Default::default() }); - let compressed_data = compressed_data.unwrap_or_else(|err| { - tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch compressed data, falling back to empty compressed data"); - Default::default() - }); + let compressed_data = + compressed_data.map_err(TaskBuilderError::CommitTasksBuildError)?; // Persist commit ids for commitees commit_ids @@ -312,8 +310,10 @@ impl TasksBuilder for TaskBuilderImpl { }); // Create commit tasks - let commit_tasks_iter = flagged_accounts.into_iter().filter_map( - |(allow_undelegation, finalize, compressed, account)| { + let commit_tasks = flagged_accounts + .into_iter() + .map( + |(allow_undelegation, finalize, compressed, account)| -> TaskBuilderResult { let commit_id = commit_ids .get(&account.pubkey) .copied() @@ -327,19 +327,34 @@ impl TasksBuilder for TaskBuilderImpl { let base_account = base_accounts.remove(&account.pubkey); if compressed { - let Some(compressed_data) = compressed_data.get(&account.pubkey).cloned() else { - error!(pubkey = %account.pubkey, "Compressed data absent for pubkey"); - return None; - }; - Some(Self::create_commit_finalize_compressed_task(commit_id, allow_undelegation, account.clone(), compressed_data).into()) + let compressed_data = compressed_data + .get(&account.pubkey) + .cloned() + .ok_or_else(|| { + TaskBuilderError::CommitFinalizeCompressedTasksBuildError( + std::io::Error::new( + std::io::ErrorKind::NotFound, + format!( + "compressed data absent for pubkey {}", + account.pubkey + ), + ), + ) + })?; + Ok(Self::create_commit_finalize_compressed_task( + commit_id, + allow_undelegation, + account.clone(), + compressed_data, + ).into()) } else if finalize { - Some(Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account).into()) + Ok(Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account).into()) } else { - Some(Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account).into()) + Ok(Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account).into()) } }, - ); - tasks.extend(commit_tasks_iter); + ).collect::>>()?; + tasks.extend(commit_tasks); Ok(tasks) } From 0e5c5da4639a1e613d57e05549e82f2335c72ebe Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:23:05 +0200 Subject: [PATCH 017/110] fix: determine bundle compression --- programs/magicblock/src/magic_scheduled_base_intent.rs | 10 ++++++++++ .../process_schedule_intent_bundle.rs | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index a4199cad6..7b303a626 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -708,6 +708,16 @@ impl MagicIntentBundle { self.standalone_actions.get_mut(index.checked_sub(offset)?) } + + pub fn is_compressed(&self) -> bool { + self.has_committed_accounts() + && (self.commit_finalize_compressed_and_undelegate.is_some() + || self.commit_finalize_compressed.is_some()) + && !self.commit_finalize_and_undelegate.is_some() + && !self.commit_finalize.is_some() + && !self.commit_and_undelegate.is_some() + && !self.commit.is_some() + } } impl MagicBaseIntent { diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index 9aade2143..67653fa79 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -142,15 +142,17 @@ pub(crate) fn process_schedule_intent_bundle( PAYER_IDX, MAGIC_CONTEXT_IDX + 1, )?; + let is_compressed = scheduled_intent.intent_bundle.is_compressed(); if let Some(magic_fee_vault) = magic_fee_vault { let chargable_accounts = scheduled_intent.get_all_committed_accounts(); - let nonces = fetch_current_commit_nonces(&chargable_accounts, false)?; + let nonces = + fetch_current_commit_nonces(&chargable_accounts, is_compressed)?; let fee = scheduled_intent.calculate_fee(&nonces)?; charge_delegated_payer(&payer_account, &magic_fee_vault, fee)?; } else if let Some(commit_accounts) = scheduled_intent.get_commit_intent_accounts() { - check_commit_limits(commit_accounts, false, invoke_context)?; + check_commit_limits(commit_accounts, is_compressed, invoke_context)?; } let action_sent_signature = scheduled_intent.sent_transaction.signatures[0]; From 5aadf7717006ddd03841ef3d383e956d6bfbcf13 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:28:51 +0200 Subject: [PATCH 018/110] fix: assert magic program --- .../programs/flexi-counter/src/processor.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test-integration/programs/flexi-counter/src/processor.rs b/test-integration/programs/flexi-counter/src/processor.rs index f87764810..361715508 100644 --- a/test-integration/programs/flexi-counter/src/processor.rs +++ b/test-integration/programs/flexi-counter/src/processor.rs @@ -714,6 +714,13 @@ fn process_schedule_commit_compressed( return Err(ProgramError::NotEnoughAccountKeys); }; + assert_keys_equal(magic_program.key, &MAGIC_PROGRAM_ID, || { + format!( + "Invalid magic program {}, should be {}", + magic_program.key, MAGIC_PROGRAM_ID + ) + })?; + let (pda, _bump) = FlexiCounter::pda(payer.key); assert_keys_equal(counter.key, &pda, || { format!("Invalid counter PDA {}, should be {}", counter.key, pda) @@ -727,10 +734,15 @@ fn process_schedule_commit_compressed( AccountMeta::new(*payer.key, true), AccountMeta::new(*magic_context.key, false), AccountMeta::new(*counter.key, false), + AccountMeta::new(*magic_program.key, false), ]; - let account_refs = - vec![payer.clone(), magic_context.clone(), counter.clone()]; + let account_refs = vec![ + payer.clone(), + magic_context.clone(), + counter.clone(), + magic_program.clone(), + ]; let ix = Instruction { program_id: *magic_program.key, From 5aeca8f3520498d42be500d571b4ac4be5e91553 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:31:44 +0200 Subject: [PATCH 019/110] fix: used passed magic program key --- test-integration/programs/schedulecommit/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 5128921a6..787dae545 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -257,7 +257,7 @@ impl ScheduleCommitType { } ScheduleCommitType::CommitFinalizeCompressed => { let ix = Instruction::new_with_bincode( - magicblock_magic_program_api::ID, + *magic_program.key, &magicblock_magic_program_api::instruction::MagicBlockInstruction::ScheduleCommitCompressed, [vec![ AccountMeta { @@ -283,7 +283,7 @@ impl ScheduleCommitType { } ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { let ix = Instruction::new_with_bincode( - magicblock_magic_program_api::ID, + *magic_program.key, &magicblock_magic_program_api::instruction::MagicBlockInstruction::ScheduleCommitAndUndelegateCompressed, [vec![ AccountMeta { From af7ee4433e001477c50cdad17947c58ff0a4e5a1 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:39:03 +0200 Subject: [PATCH 020/110] test: assert record state --- .../tests/test_ix_commit_local.rs | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 7d8ccc69e..e7f68fceb 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -4,7 +4,9 @@ use std::{ time::{Duration, Instant}, }; -use borsh::to_vec; +use borsh::{to_vec, BorshDeserialize}; +use compressed_delegation_client::CompressedDelegationRecord; +use light_client::indexer::{photon_indexer::PhotonIndexer, Indexer}; use magicblock_committor_service::{ config::ChainConfig, intent_executor::{error::IntentExecutorError, ExecutionOutput}, @@ -12,7 +14,9 @@ use magicblock_committor_service::{ service_ext::{BaseIntentCommittorExt, CommittorServiceExt}, BaseIntentCommittor, CommittorService, ComputeBudgetConfig, }; -use magicblock_core::intent::CommittedAccount; +use magicblock_core::{ + compression::derive_cda_from_pda, intent::CommittedAccount, +}; use magicblock_program::magic_scheduled_base_intent::{ CommitAndUndelegate, CommitType, MagicBaseIntent, MagicIntentBundle, ScheduledIntentBundle, UndelegateType, @@ -1150,6 +1154,8 @@ async fn ix_commit_local( service.release_common_pubkeys().await.unwrap(); let rpc_client = RpcClient::new("http://localhost:7799".to_string()); + let photon_indexer = + PhotonIndexer::new("http://localhost:7799".to_string()); let mut strategies = ExpectedStrategies::new(); for (execution_result, base_intent) in execution_outputs .into_iter() @@ -1308,6 +1314,23 @@ async fn ix_commit_local( ) } ); + } else { + let cda = derive_cda_from_pda(&account.pubkey); + let compressed_account = photon_indexer + .get_compressed_account(cda.to_bytes(), None) + .await + .unwrap() + .value + .unwrap(); + let compressed_record = + CompressedDelegationRecord::try_from_slice( + &compressed_account.data.unwrap().data, + ) + .unwrap(); + assert_eq!(compressed_record.owner, program_id); + assert_eq!(compressed_record.data, account.account.data); + assert_eq!(compressed_record.lamports, 0); + assert_eq!(compressed_record.is_undelegatable, is_undelegate); } // Track the strategy used From 71b955506b341ec13210042e1aaf52cb9db7ace7 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:40:26 +0200 Subject: [PATCH 021/110] fix: airdrop and confirm --- .../tests/utils/transactions.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index c9b0ed9a6..c77e2666f 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -337,10 +337,13 @@ pub async fn init_and_delegate_compressed_record_on_chain( let photon_indexer = Arc::new(PhotonIndexer::new("http://localhost:8784".to_string())); - rpc_client - .request_airdrop(&counter_auth.pubkey(), 777 * LAMPORTS_PER_SOL) - .await - .unwrap(); + airdrop_and_confirm( + &rpc_client, + &counter_auth.pubkey(), + 777 * LAMPORTS_PER_SOL, + "counter auth", + ) + .await; debug!("Airdropped to counter auth: {} SOL", 777 * LAMPORTS_PER_SOL); let InitAccountAndCompressedRecordIxs { From 03ffe15b40639c2258d6d54b9946ae10c551a00c Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:43:13 +0200 Subject: [PATCH 022/110] fix: retryable fetch --- .../tests/utils/transactions.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index c77e2666f..c08af12ac 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -417,17 +417,17 @@ pub async fn init_and_delegate_compressed_record_on_chain( const MAX_RETRIES: usize = 10; let mut retries = MAX_RETRIES; let compressed_delegation_record = loop { - let compressed_account = photon_indexer + let maybe_record = photon_indexer .get_compressed_account(address, None) .await .unwrap() .value - .unwrap(); - if let Some(compressed_delegation_record) = - compressed_account.data.and_then(|data| { - CompressedDelegationRecord::try_from_slice(&data.data).ok() - }) - { + .and_then(|compressed_account| { + compressed_account.data.and_then(|data| { + CompressedDelegationRecord::try_from_slice(&data.data).ok() + }) + }); + if let Some(compressed_delegation_record) = maybe_record { break compressed_delegation_record; } retries -= 1; From 0d25159c191b0442a39676004b56861139d080f6 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 09:47:10 +0200 Subject: [PATCH 023/110] fix: cleanup light validator --- test-integration/test-runner/bin/run_tests.rs | 22 ++++++++++++++----- test-integration/test-runner/src/cleanup.rs | 11 ++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index 4ca3ca392..a8cd93efc 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -16,7 +16,10 @@ use integration_test_tools::{ }; use teepee::Teepee; use test_runner::{ - cleanup::{cleanup_devnet_only, cleanup_validators}, + cleanup::{ + cleanup_devnet_only, cleanup_devnet_validator, cleanup_light_validator, + cleanup_validators, + }, env_config::TestConfigViaEnvVars, signal::wait_for_ctrlc, }; @@ -208,11 +211,11 @@ fn run_chainlink_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run chainlink tests: {:?}", err); - cleanup_devnet_only(&mut devnet_validator); + cleanup_light_validator(&mut devnet_validator); return Err(err.into()); } }; - cleanup_devnet_only(&mut devnet_validator); + cleanup_light_validator(&mut devnet_validator); Ok(output) } else { let devnet_validator = @@ -243,6 +246,7 @@ fn run_table_mania_and_committor_tests( } else { ValidatorCluster::Light }; + let uses_light_validator = matches!(&cluster, ValidatorCluster::Light); let start_devnet_validator = || match start_validator( "committor-conf.devnet.toml", @@ -275,7 +279,10 @@ fn run_table_mania_and_committor_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run table-mania: {:?}", err); - cleanup_devnet_only(&mut devnet_validator); + cleanup_devnet_validator( + &mut devnet_validator, + uses_light_validator, + ); return Err(err.into()); } } @@ -303,7 +310,10 @@ fn run_table_mania_and_committor_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run committor: {:?}", err); - cleanup_devnet_only(&mut devnet_validator); + cleanup_devnet_validator( + &mut devnet_validator, + uses_light_validator, + ); return Err(err.into()); } } @@ -312,7 +322,7 @@ fn run_table_mania_and_committor_tests( success_output() }; - cleanup_devnet_only(&mut devnet_validator); + cleanup_devnet_validator(&mut devnet_validator, uses_light_validator); Ok((table_mania_test_output, committor_test_output)) } else { diff --git a/test-integration/test-runner/src/cleanup.rs b/test-integration/test-runner/src/cleanup.rs index f8a40dff5..1ff770834 100644 --- a/test-integration/test-runner/src/cleanup.rs +++ b/test-integration/test-runner/src/cleanup.rs @@ -9,6 +9,17 @@ pub fn cleanup_validators( kill_validators(); } +pub fn cleanup_devnet_validator( + devnet_validator: &mut process::Child, + uses_light_validator: bool, +) { + if uses_light_validator { + cleanup_light_validator(devnet_validator); + } else { + cleanup_devnet_only(devnet_validator); + } +} + pub fn cleanup_devnet_only(devnet_validator: &mut Child) { cleanup_validator(devnet_validator, "devnet"); kill_validators(); From f29cd51911a7bafce4e448fb1a9bd176f5ff9909 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:11:35 +0200 Subject: [PATCH 024/110] style: lint --- programs/magicblock/src/magic_scheduled_base_intent.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 7b303a626..2d76e83f6 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -713,10 +713,10 @@ impl MagicIntentBundle { self.has_committed_accounts() && (self.commit_finalize_compressed_and_undelegate.is_some() || self.commit_finalize_compressed.is_some()) - && !self.commit_finalize_and_undelegate.is_some() - && !self.commit_finalize.is_some() - && !self.commit_and_undelegate.is_some() - && !self.commit.is_some() + && self.commit_finalize_and_undelegate.is_none() + && self.commit_finalize.is_none() + && self.commit_and_undelegate.is_none() + && self.commit.is_none() } } From 9876d5d7e13bf43f023354512841374a8b3ae8ca Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:33:01 +0200 Subject: [PATCH 025/110] fix: stale comment --- compressed-delegation-api/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/compressed-delegation-api/Cargo.toml b/compressed-delegation-api/Cargo.toml index a8da3b4d9..a9117fe01 100644 --- a/compressed-delegation-api/Cargo.toml +++ b/compressed-delegation-api/Cargo.toml @@ -9,7 +9,6 @@ edition.workspace = true [dependencies] borsh = { workspace = true, features = ["derive"] } -# borsh10 = { workspace = true } light-compressed-account = { workspace = true } light-hasher = { workspace = true, features = ["solana"] } light-sdk = { workspace = true, features = ["v2"] } From 5c3f131c2606b09fecdf3ad53df079627b062467 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:33:49 +0200 Subject: [PATCH 026/110] docs: stale comment --- compressed-delegation-api/src/instruction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compressed-delegation-api/src/instruction.rs b/compressed-delegation-api/src/instruction.rs index 579e7094b..64d95d4d3 100644 --- a/compressed-delegation-api/src/instruction.rs +++ b/compressed-delegation-api/src/instruction.rs @@ -33,7 +33,7 @@ impl CompressedDelegationInstructionDiscriminator { #[derive(Clone, Debug)] pub enum CompressedDelegationProgramInstruction { - /// Delegate the compressed account to a validator. + /// Initialize a new delegation record. InitDelegationRecord { args: InitDelegationRecordArgs }, /// Delegate the compressed account to a validator. From 48c888358bf0a614568cf744f92e0afcd27f1f1f Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:35:05 +0200 Subject: [PATCH 027/110] fix: disable compression --- magicblock-api/src/magic_validator.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index a0356e908..3bbd03c46 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -288,13 +288,11 @@ impl MagicValidator { } let base_fee = config.validator.basefee; - if config + let compression_enabled = config .compression .as_ref() - .is_some_and(|compression| compression.photon_url.is_some()) - { - validator::set_compression_enabled(true); - } + .is_some_and(|compression| compression.photon_url.is_some()); + validator::set_compression_enabled(compression_enabled); // Mode switch channel for transitioning from StartingUp to Primary // or Replica mode after ledger replay From 884f2bc446fc0670c4f386e5c489035880d0907b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:36:23 +0200 Subject: [PATCH 028/110] fix: unused variant --- magicblock-chainlink/src/chainlink/errors.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/errors.rs b/magicblock-chainlink/src/chainlink/errors.rs index 131e78876..bcacd8e0d 100644 --- a/magicblock-chainlink/src/chainlink/errors.rs +++ b/magicblock-chainlink/src/chainlink/errors.rs @@ -48,9 +48,6 @@ pub enum ChainlinkError { #[error("Missing accounts required by delegation actions: {0:?}")] MissingDelegationActionAccounts(Vec), - #[error("Failed to deserialize compressed delegation record: {0}")] - FailedToDeserializeCompressedDelegationRecord(#[from] std::io::Error), - #[error("Photon client error: {0}")] PhotonClientError(#[from] magicblock_core::traits::PhotonClientError), From 04ba73a2a376268a8db9cc2893bf8cfde0e755ea Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:36:59 +0200 Subject: [PATCH 029/110] feat: reduce log level --- magicblock-chainlink/src/remote_account_provider/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 5297c5e48..8655d77af 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -1118,7 +1118,7 @@ impl min_context_slot, ) ); - debug!(rpc_accounts = ?rpc_accounts, photon_accounts = ?photon_accounts, "Fetched accounts from RPC and Photon"); + trace!(rpc_accounts = ?rpc_accounts, photon_accounts = ?photon_accounts, "Fetched accounts from RPC and Photon"); let mut remote_accounts_results = Vec::with_capacity(2); let mut found_cnt = 0; From 577aa4a16f1666d27c69788afbcf555e4a60430e Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:38:19 +0200 Subject: [PATCH 030/110] fix: metrics on success --- .../src/remote_account_provider/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 8655d77af..520ea6684 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -1121,6 +1121,7 @@ impl trace!(rpc_accounts = ?rpc_accounts, photon_accounts = ?photon_accounts, "Fetched accounts from RPC and Photon"); let mut remote_accounts_results = Vec::with_capacity(2); + let mut rpc_fetch_success = false; let mut found_cnt = 0; let mut not_found_cnt = 0; let mut compressed_found_count = 0; @@ -1131,6 +1132,7 @@ impl for result in results { match result { Ok((FetchedRemoteAccounts::Rpc(accs), fc, nfc)) => { + rpc_fetch_success = true; remote_accounts_results .push(FetchedRemoteAccounts::Rpc(accs)); found_cnt += fc; @@ -1176,9 +1178,11 @@ impl } // Update metrics for successful RPC fetch - inc_account_fetches_success(pubkeys.len() as u64); - inc_account_fetches_found(fetch_origin, found_cnt); - inc_account_fetches_not_found(fetch_origin, not_found_cnt); + if rpc_fetch_success { + inc_account_fetches_success(pubkeys.len() as u64); + inc_account_fetches_found(fetch_origin, found_cnt); + inc_account_fetches_not_found(fetch_origin, not_found_cnt); + } let compressed_total = compressed_found_count + compressed_not_found_count; From ae162b48d43acd84e2ef4eae50ae5492234bc38c Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:39:31 +0200 Subject: [PATCH 031/110] feat: remove log if compression disabled --- magicblock-chainlink/src/remote_account_provider/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 520ea6684..d15fede4a 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -1144,6 +1144,10 @@ impl compressed_found_count += fc; compressed_not_found_count += nfc; } + Err(ChainlinkError::CompressionNotEnabled) => { + // Not an error, just skip + continue; + } Err(err) => { error!("Failed to fetch accounts: {err:?}"); } From a1ca4553889fdc2026ba5bb973d12cfe637f1aaf Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:40:42 +0200 Subject: [PATCH 032/110] fix: missing data as absent --- .../src/remote_account_provider/photon_client.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/magicblock-chainlink/src/remote_account_provider/photon_client.rs b/magicblock-chainlink/src/remote_account_provider/photon_client.rs index 003c89085..3687eac42 100644 --- a/magicblock-chainlink/src/remote_account_provider/photon_client.rs +++ b/magicblock-chainlink/src/remote_account_provider/photon_client.rs @@ -103,11 +103,12 @@ fn account_from_compressed_account( compressed_acc: Option, ) -> Option { let compressed_acc = compressed_acc?; + let data = compressed_acc.data?.data; // NOTE: delegated compressed accounts are set to zero lamports when cloned // Actual lamports have to be paid back when undelegating Some(Account { lamports: 0, - data: compressed_acc.data.unwrap_or_default().data, + data, owner: compressed_acc.owner.to_bytes().into(), executable: false, rent_epoch: 0, From 943cfee28a347642817c20422ff7e8d696b6fc23 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:42:28 +0200 Subject: [PATCH 033/110] feat: validate photon account --- .../src/intent_executor/task_info_fetcher.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index e0eb96cab..7fb737cac 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -500,12 +500,19 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { } .into(); + let compressed_delegation_record_bytes = compressed_delegation_record + .data + .ok_or(TaskInfoFetcherError::MissingCompressedData)? + .data; + CompressedDelegationRecord::try_from_slice( + &compressed_delegation_record_bytes, + ) + .map_err(|_| TaskInfoFetcherError::InvalidAccountDataError(*pubkey))?; + Ok(CompressedData { hash: compressed_delegation_record.hash, - compressed_delegation_record_bytes: compressed_delegation_record - .data - .ok_or(TaskInfoFetcherError::MissingCompressedData)? - .data, + compressed_delegation_record_bytes: + compressed_delegation_record_bytes, remaining_accounts: remaining_accounts .to_account_metas() .0 From fee7e648cc78a75e93e11cbdeeaecb9553027d58 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:44:16 +0200 Subject: [PATCH 034/110] feat: commit fees --- programs/magicblock/src/magic_scheduled_base_intent.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 2d76e83f6..2c1b29c52 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -432,6 +432,12 @@ impl MagicIntentBundle { if let Some(ref cau) = self.commit_and_undelegate { fee += cau.calculate_fee(commit_nonces)?; } + if let Some(ref commit) = self.commit_finalize_compressed { + fee += commit.calculate_fee(commit_nonces)?; + } + if let Some(ref cau) = self.commit_finalize_compressed_and_undelegate { + fee += cau.calculate_fee(commit_nonces)?; + } fee += calculate_actions_fee(&self.standalone_actions); Ok(fee) } From 1d0ceb24607e54c8ef6df5bdba9db113031d58e2 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:44:55 +0200 Subject: [PATCH 035/110] feat: read only program --- test-integration/programs/flexi-counter/src/processor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-integration/programs/flexi-counter/src/processor.rs b/test-integration/programs/flexi-counter/src/processor.rs index 361715508..61fc02a2d 100644 --- a/test-integration/programs/flexi-counter/src/processor.rs +++ b/test-integration/programs/flexi-counter/src/processor.rs @@ -734,7 +734,7 @@ fn process_schedule_commit_compressed( AccountMeta::new(*payer.key, true), AccountMeta::new(*magic_context.key, false), AccountMeta::new(*counter.key, false), - AccountMeta::new(*magic_program.key, false), + AccountMeta::new_readonly(*magic_program.key, false), ]; let account_refs = vec![ From b16e79610d87e06d6b97327903498d146d3904d0 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:45:29 +0200 Subject: [PATCH 036/110] fix: photon url --- .../test-committor-service/tests/test_ix_commit_local.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index e7f68fceb..689e0ef08 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -1155,7 +1155,7 @@ async fn ix_commit_local( let rpc_client = RpcClient::new("http://localhost:7799".to_string()); let photon_indexer = - PhotonIndexer::new("http://localhost:7799".to_string()); + PhotonIndexer::new("http://localhost:8784".to_string()); let mut strategies = ExpectedStrategies::new(); for (execution_result, base_intent) in execution_outputs .into_iter() From 700589139447bd0bfb3f00680adc3dd2301f8a38 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 10:47:20 +0200 Subject: [PATCH 037/110] fix: cleanup light validator --- test-integration/test-runner/bin/run_tests.rs | 36 ++++++++++++++----- test-integration/test-runner/src/cleanup.rs | 9 +++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index a8cd93efc..c92acd0af 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -396,6 +396,7 @@ fn run_schedule_commit_tests( cleanup_validators( &mut ephem_validator, &mut devnet_validator, + true, ); return Err(err.into()); } @@ -412,12 +413,13 @@ fn run_schedule_commit_tests( cleanup_validators( &mut ephem_validator, &mut devnet_validator, + true, ); return Err(err.into()); } }; - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators(&mut ephem_validator, &mut devnet_validator, true); Ok((test_security_output, test_scenarios_output)) } else { let devnet_validator = @@ -498,11 +500,15 @@ fn run_cloning_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run cloning tests: {:?}", err); - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators( + &mut ephem_validator, + &mut devnet_validator, + false, + ); return Err(err.into()); } }; - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators(&mut ephem_validator, &mut devnet_validator, false); Ok(output) } else { let devnet_validator = @@ -555,11 +561,15 @@ fn run_magicblock_api_tests( let output = run_test(test_dir, Default::default()).map_err(|err| { eprintln!("Failed to magicblock api tests: {:?}", err); - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators( + &mut ephem_validator, + &mut devnet_validator, + false, + ); err })?; - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators(&mut ephem_validator, &mut devnet_validator, false); Ok(output) } else { let devnet_validator = @@ -614,11 +624,15 @@ fn run_magicblock_pubsub_tests( let output = run_test(test_dir, Default::default()).map_err(|err| { eprintln!("Failed to magicblock pubsub tests: {:?}", err); - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators( + &mut ephem_validator, + &mut devnet_validator, + false, + ); err })?; - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators(&mut ephem_validator, &mut devnet_validator, false); Ok(output) } else { let devnet_validator = @@ -731,11 +745,15 @@ fn run_schedule_intents_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run issues: {:?}", err); - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators( + &mut ephem_validator, + &mut devnet_validator, + false, + ); return Err(err.into()); } }; - cleanup_validators(&mut ephem_validator, &mut devnet_validator); + cleanup_validators(&mut ephem_validator, &mut devnet_validator, false); Ok(test_output) } else { let devnet_validator = diff --git a/test-integration/test-runner/src/cleanup.rs b/test-integration/test-runner/src/cleanup.rs index 1ff770834..e889e0e05 100644 --- a/test-integration/test-runner/src/cleanup.rs +++ b/test-integration/test-runner/src/cleanup.rs @@ -2,10 +2,15 @@ use std::process::{self, Child}; pub fn cleanup_validators( ephem_validator: &mut Child, - light_validator: &mut Child, + devnet_validator: &mut Child, + uses_light_validator: bool, ) { cleanup_validator(ephem_validator, "ephemeral"); - cleanup_light_validator(light_validator); + if uses_light_validator { + cleanup_light_validator(devnet_validator); + } else { + cleanup_validator(devnet_validator, "devnet"); + } kill_validators(); } From c46b00bbc9228cdfe7830400df7992f0d050549f Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 11:21:52 +0200 Subject: [PATCH 038/110] feat: use min context slot --- .../src/intent_executor/task_info_fetcher.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 7fb737cac..231a52bfc 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -336,7 +336,11 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { let items = self .photon_client()? - .get_multiple_compressed_accounts(Some(cdas), None, None) + .get_multiple_compressed_accounts( + Some(cdas), + None, + Some(IndexerRpcConfig::new(min_context_slot)), + ) .await? .value .items; @@ -386,7 +390,11 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { let items = self .photon_client()? - .get_multiple_compressed_accounts(Some(cdas), None, None) + .get_multiple_compressed_accounts( + Some(cdas), + None, + Some(IndexerRpcConfig::new(min_context_slot)), + ) .await? .value .items; From 9c148f31a737c22888f64687474d5ded19779d7b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 11:27:54 +0200 Subject: [PATCH 039/110] feat: guard length mismatch --- .../src/intent_executor/task_info_fetcher.rs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 231a52bfc..63701fcf1 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -245,6 +245,9 @@ impl RpcTaskInfoFetcher { TaskInfoFetcherError::LightSdkError(_) => { break Err(err); } + TaskInfoFetcherError::PhotonItemsMismatch(_, _) => { + break Err(err); + } } if i >= max_retries.get() { @@ -344,6 +347,14 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .await? .value .items; + + if items.len() != pubkeys.len() { + return Err(TaskInfoFetcherError::PhotonItemsMismatch( + items.len(), + pubkeys.len(), + )); + } + let mut result = HashMap::with_capacity(pubkeys.len()); for (pubkey, compressed_account) in pubkeys.iter().zip(items) { let nonce = compressed_account @@ -398,6 +409,14 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .await? .value .items; + + if items.len() != pubkeys.len() { + return Err(TaskInfoFetcherError::PhotonItemsMismatch( + items.len(), + pubkeys.len(), + )); + } + let mut result = HashMap::with_capacity(pubkeys.len()); for (pubkey, compressed_account) in pubkeys.iter().zip(items) { let nonce = compressed_account @@ -519,8 +538,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { Ok(CompressedData { hash: compressed_delegation_record.hash, - compressed_delegation_record_bytes: - compressed_delegation_record_bytes, + compressed_delegation_record_bytes, remaining_accounts: remaining_accounts .to_account_metas() .0 @@ -924,6 +942,8 @@ pub enum TaskInfoFetcherError { MissingCompressedData, #[error("LightSdkError: {0}")] LightSdkError(Box), + #[error("Photon returned {0} items for {1} pubkeys")] + PhotonItemsMismatch(usize, usize), } impl TaskInfoFetcherError { @@ -982,6 +1002,7 @@ impl TaskInfoFetcherError { Self::MissingStateTrees => None, Self::MissingAddress => None, Self::MissingCompressedData => None, + Self::PhotonItemsMismatch(_, _) => None, } } } From cfc0796f38f51c48bf5af3bb0068cbbfa8c47a0a Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 11:29:37 +0200 Subject: [PATCH 040/110] feat: explicitly reject compression --- .../tests/test_ix_commit_local.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 689e0ef08..00f0e3337 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -394,18 +394,9 @@ async fn commit_book_order_account( undelegate_action: UndelegateType::Standalone, }) } - ScheduleCommitType::CommitFinalizeCompressed => { - MagicBaseIntent::CommitFinalizeCompressed(CommitType::Standalone( - vec![account], - )) - } - ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { - MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( - CommitAndUndelegate { - commit_action: CommitType::Standalone(vec![account]), - undelegate_action: UndelegateType::Standalone, - }, - ) + ScheduleCommitType::CommitFinalizeCompressed + | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + unimplemented!("Order book compressed delegation not yet supported") } }; From b44f82cd08daf6b4a540d8949b22640fd4693c0e Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 11:32:49 +0200 Subject: [PATCH 041/110] feat: parallel creation --- .../tests/test_ix_commit_local.rs | 54 +++++++------------ 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 00f0e3337..e44f5c8af 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -886,52 +886,36 @@ async fn create_and_delegate_accounts( bytess: &[usize], compressed: bool, ) -> Vec { - if compressed { - let mut out = Vec::with_capacity(bytess.len()); - for bytes in bytess { - let bytes = *bytes; + let mut join_set = JoinSet::new(); + for bytes in bytess { + let bytes = *bytes; + join_set.spawn(async move { let counter_auth = Keypair::new(); - let (pda, mut pda_acc) = { - let (pubkey, _address, account) = + let (pda, mut pda_acc) = if compressed { + let (pda, _address, account) = init_and_delegate_compressed_record_on_chain(&counter_auth) .await; - (pubkey, account) + (pda, account) + } else { + init_and_delegate_account_on_chain( + &counter_auth, + bytes as u64, + None, + ) + .await }; pda_acc.owner = program_flexi_counter::id(); pda_acc.data = vec![0u8; bytes]; - out.push(CommittedAccount { + CommittedAccount { pubkey: pda, account: pda_acc, remote_slot: Default::default(), - }); - } - out - } else { - let mut join_set = JoinSet::new(); - for bytes in bytess { - let bytes = *bytes; - join_set.spawn(async move { - let counter_auth = Keypair::new(); - let (pda, mut pda_acc) = init_and_delegate_account_on_chain( - &counter_auth, - bytes as u64, - None, - ) - .await; - - pda_acc.owner = program_flexi_counter::id(); - pda_acc.data = vec![0u8; bytes]; - CommittedAccount { - pubkey: pda, - account: pda_acc, - remote_slot: Default::default(), - } - }); - } - - join_set.join_all().await + } + }); } + + join_set.join_all().await } async fn create_bundles( From 95771720de225353fe1a0022b8403bd1c1c35609 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 11:39:14 +0200 Subject: [PATCH 042/110] fix: wait for light cleanup --- test-integration/test-runner/bin/run_tests.rs | 50 +++++++++++++++---- test-integration/test-runner/src/signal.rs | 9 ++-- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index c92acd0af..e3a1a7483 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -156,7 +156,7 @@ fn run_restore_ledger_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(devnet_validator, None, false, success_output()) } } @@ -220,7 +220,7 @@ fn run_chainlink_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(devnet_validator, None, true, success_output()) } } @@ -330,7 +330,12 @@ fn run_table_mania_and_committor_tests( || config.setup_devnet(COMMITTOR_TEST); let devnet_validator = setup_needed.then(start_devnet_validator); Ok(( - wait_for_ctrlc(devnet_validator, None, success_output())?, + wait_for_ctrlc( + devnet_validator, + None, + uses_light_validator, + success_output(), + )?, success_output(), )) } @@ -427,7 +432,12 @@ fn run_schedule_commit_tests( let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); eprintln!("Setup validator(s)"); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output())?; + wait_for_ctrlc( + devnet_validator, + ephem_validator, + true, + success_output(), + )?; Ok((success_output(), success_output())) } } @@ -515,7 +525,12 @@ fn run_cloning_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + false, + success_output(), + ) } } @@ -576,7 +591,12 @@ fn run_magicblock_api_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + false, + success_output(), + ) } } @@ -639,7 +659,12 @@ fn run_magicblock_pubsub_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + false, + success_output(), + ) } } @@ -686,7 +711,7 @@ fn run_config_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(devnet_validator, None, false, success_output()) } } @@ -760,7 +785,12 @@ fn run_schedule_intents_tests( config.setup_devnet(TEST_NAME).then(start_devnet_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); - wait_for_ctrlc(devnet_validator, ephem_validator, success_output()) + wait_for_ctrlc( + devnet_validator, + ephem_validator, + false, + success_output(), + ) } } @@ -809,7 +839,7 @@ fn run_task_scheduler_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, success_output()) + wait_for_ctrlc(devnet_validator, None, false, success_output()) } } diff --git a/test-integration/test-runner/src/signal.rs b/test-integration/test-runner/src/signal.rs index 84ce66d1e..384795daf 100644 --- a/test-integration/test-runner/src/signal.rs +++ b/test-integration/test-runner/src/signal.rs @@ -4,11 +4,12 @@ use std::{ sync::mpsc::channel, }; -use crate::cleanup::{cleanup_light_validator, cleanup_validator}; +use crate::cleanup::{cleanup_devnet_validator, cleanup_validator}; pub fn wait_for_ctrlc( devnet_validator: Option, ephem_validator: Option, + uses_light_validator: bool, output: Output, ) -> Result> { let (tx, rx) = channel(); @@ -19,12 +20,12 @@ pub fn wait_for_ctrlc( println!("Hit Ctrl-C to stop validator(s)..."); rx.recv().expect("Could not receive from channel."); - if let Some(mut validator) = devnet_validator { - cleanup_light_validator(&mut validator); - } if let Some(mut validator) = ephem_validator { cleanup_validator(&mut validator, "ephemeral"); } + if let Some(mut validator) = devnet_validator { + cleanup_devnet_validator(&mut validator, uses_light_validator); + } Ok(output) } From 882e769f68c729a33586fb30ed84a61b9508a2fb Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 12:15:34 +0200 Subject: [PATCH 043/110] fix: light for table_mania --- .github/workflows/ci-test-integration.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index e71ad3be9..778e106a1 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -71,20 +71,20 @@ jobs: - uses: ./magicblock-validator/.github/actions/setup-solana - name: Install Photon indexer - if: contains(fromJSON('["schedulecommit","chainlink","committor"]'), matrix.batch_tests) + if: contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) shell: bash env: RUSTFLAGS: "-A dead-code" run: cargo install --git https://github.com/lightprotocol/photon.git --rev 3f82b926be6717a07bd41aedb84b4d9e6b0ab0d3 --locked --force - name: Setup Node.js - if: contains(fromJSON('["schedulecommit","chainlink","committor"]'), matrix.batch_tests) + if: contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) uses: actions/setup-node@v4 with: node-version: "20" - name: Install zk-compression CLI - if: contains(fromJSON('["schedulecommit","chainlink","committor"]'), matrix.batch_tests) + if: contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) run: | npm i -g @lightprotocol/zk-compression-cli@0.28.4 shell: bash From c589080acfed64ae94132fb9e342e57d3a2955b3 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 14:15:05 +0200 Subject: [PATCH 044/110] fix: prevent race condition --- .../test-task-scheduler/src/lib.rs | 101 +++++++++++++----- 1 file changed, 74 insertions(+), 27 deletions(-) diff --git a/test-integration/test-task-scheduler/src/lib.rs b/test-integration/test-task-scheduler/src/lib.rs index 8a6c15287..d52e1de23 100644 --- a/test-integration/test-task-scheduler/src/lib.rs +++ b/test-integration/test-task-scheduler/src/lib.rs @@ -129,8 +129,14 @@ pub fn create_delegated_counter( validator ); - // Wait for account to be delegated - expect!(ctx.wait_for_delta_slot_ephem(10), validator); + let (counter_pda, _) = FlexiCounter::pda(&payer.pubkey()); + wait_for_incremented_counter( + ctx, + &counter_pda, + 0, + Duration::from_secs(10), + validator, + ); } pub fn wait_for_incremented_counter( @@ -141,24 +147,46 @@ pub fn wait_for_incremented_counter( validator: &mut Child, ) { let now = Instant::now(); + let mut last_count = None; + let mut last_error = None; while now.elapsed() < max_timeout { - let counter_account = expect!( - ctx.try_ephem_client().and_then(|client| client - .get_account(counter_pda) - .map_err(|e| anyhow::anyhow!("Failed to get account: {}", e))), - validator - ); - let counter = - expect!(FlexiCounter::try_decode(&counter_account.data), validator); - if counter.count == expected_count { - return; + let counter = ctx + .try_ephem_client() + .and_then(|client| { + client.get_account(counter_pda).map_err(|e| { + anyhow::anyhow!("Failed to get account: {}", e) + }) + }) + .and_then(|counter_account| { + FlexiCounter::try_decode(&counter_account.data).map_err(|e| { + anyhow::anyhow!( + "Failed to decode counter account ({} bytes): {}", + counter_account.data.len(), + e + ) + }) + }); + match counter { + Ok(counter) => { + last_count = Some(counter.count); + last_error = None; + if counter.count == expected_count { + return; + } + } + Err(err) => { + last_error = Some(err.to_string()); + } } expect!(ctx.wait_for_next_slot_ephem(), validator); } assert!( false, cleanup(validator), - "Failed to wait for incremented counter" + "Failed to wait for incremented counter; expected_count: {}, last_count: {:?}, last_error: {:?}", + expected_count, + last_count, + last_error ); } @@ -170,27 +198,46 @@ pub fn wait_for_committed_count( validator: &mut Child, ) { let now = Instant::now(); + let mut last_count = None; + let mut last_error = None; while now.elapsed() < max_timeout { - let account = expect!( - ctx.try_chain_client().and_then(|client| client - .get_account(committee) - .map_err(|e| anyhow::anyhow!( - "Failed to get chain account: {}", - e - ))), - validator - ); - let state = expect!(MainAccount::try_decode(&account.data), validator); - if state.count == expected_count { - return; + let state = ctx + .try_chain_client() + .and_then(|client| { + client.get_account(committee).map_err(|e| { + anyhow::anyhow!("Failed to get chain account: {}", e) + }) + }) + .and_then(|account| { + MainAccount::try_decode(&account.data).map_err(|e| { + anyhow::anyhow!( + "Failed to decode chain account ({} bytes): {}", + account.data.len(), + e + ) + }) + }); + match state { + Ok(state) => { + last_count = Some(state.count); + last_error = None; + if state.count == expected_count { + return; + } + } + Err(err) => { + last_error = Some(err.to_string()); + } } expect!(ctx.wait_for_next_slot_ephem(), validator); } assert!( false, cleanup(validator), - "Timed out waiting for committed count {} on {}", + "Timed out waiting for committed count {} on {}; last_count: {:?}, last_error: {:?}", expected_count, - committee + committee, + last_count, + last_error ); } From 3c94603346348ef7563311bade30ff5b08d32a26 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 15:13:41 +0200 Subject: [PATCH 045/110] fix: legacy magic program instructions --- .../magicblock/src/magicblock_processor.rs | 125 ++++++++++++++++-- 1 file changed, 117 insertions(+), 8 deletions(-) diff --git a/programs/magicblock/src/magicblock_processor.rs b/programs/magicblock/src/magicblock_processor.rs index 2664906e8..a610325a2 100644 --- a/programs/magicblock/src/magicblock_processor.rs +++ b/programs/magicblock/src/magicblock_processor.rs @@ -1,6 +1,15 @@ -use magicblock_magic_program_api::instruction::MagicBlockInstruction; +use magicblock_magic_program_api::{ + args::{ + BaseActionArgs, CommitAndUndelegateArgs, CommitTypeArgs, + MagicIntentBundleArgs, + }, + instruction::{AccountModificationForInstruction, MagicBlockInstruction}, +}; +use serde::Deserialize; use solana_instruction::error::InstructionError; use solana_program_runtime::declare_process_instruction; +use solana_pubkey::Pubkey; +use std::collections::HashMap; use crate::{ clone_account::{ @@ -27,16 +36,116 @@ use crate::{ pub const DEFAULT_COMPUTE_UNITS: u64 = 150; +/// This enables the program to still be able to deserialize +/// instructions despite the changes in instructions introduced +/// by compressed commits. +#[allow(dead_code)] +#[derive(Deserialize)] +enum LegacyMagicBlockInstruction { + ModifyAccounts { + accounts: HashMap, + message: Option, + }, + ScheduleCommit, + ScheduleCommitAndUndelegate, + AcceptScheduleCommits, + ScheduledCommitSent((u64, u64)), + ScheduleBaseIntent(LegacyMagicBaseIntentArgs), + ScheduleTask(magicblock_magic_program_api::args::ScheduleTaskArgs), + CancelTask { + task_id: i64, + }, + DisableExecutableCheck, + EnableExecutableCheck, + Noop(u64), + ScheduleIntentBundle(LegacyMagicIntentBundleArgs), +} + +#[derive(Deserialize)] +enum LegacyMagicBaseIntentArgs { + BaseActions(Vec), + Commit(CommitTypeArgs), + CommitAndUndelegate(CommitAndUndelegateArgs), + CommitFinalize(CommitTypeArgs), + CommitFinalizeAndUndelegate(CommitAndUndelegateArgs), +} + +impl From for MagicIntentBundleArgs { + fn from(value: LegacyMagicBaseIntentArgs) -> Self { + let mut args = MagicIntentBundleArgs::default(); + match value { + LegacyMagicBaseIntentArgs::BaseActions(actions) => { + args.standalone_actions = actions + } + LegacyMagicBaseIntentArgs::Commit(commit) => { + args.commit = Some(commit) + } + LegacyMagicBaseIntentArgs::CommitAndUndelegate(cau) => { + args.commit_and_undelegate = Some(cau) + } + LegacyMagicBaseIntentArgs::CommitFinalize(commit) => { + args.commit_finalize = Some(commit) + } + LegacyMagicBaseIntentArgs::CommitFinalizeAndUndelegate(cau) => { + args.commit_finalize_and_undelegate = Some(cau) + } + } + args + } +} + +#[derive(Deserialize)] +struct LegacyMagicIntentBundleArgs { + commit: Option, + commit_and_undelegate: Option, + commit_finalize: Option, + commit_finalize_and_undelegate: Option, + standalone_actions: Vec, +} + +impl From for MagicIntentBundleArgs { + fn from(value: LegacyMagicIntentBundleArgs) -> Self { + Self { + commit: value.commit, + commit_and_undelegate: value.commit_and_undelegate, + commit_finalize: value.commit_finalize, + commit_finalize_and_undelegate: value + .commit_finalize_and_undelegate, + commit_finalize_compressed: None, + commit_finalize_compressed_and_undelegate: None, + standalone_actions: value.standalone_actions, + } + } +} + +fn deserialize_legacy_instruction( + data: &[u8], +) -> Result { + let legacy = bincode::deserialize::(data) + .map_err(|_| InstructionError::InvalidInstructionData)?; + + match legacy { + LegacyMagicBlockInstruction::ScheduleBaseIntent(args) => { + Ok(MagicBlockInstruction::ScheduleIntentBundle(args.into())) + } + LegacyMagicBlockInstruction::ScheduleIntentBundle(args) => { + Ok(MagicBlockInstruction::ScheduleIntentBundle(args.into())) + } + _ => Err(InstructionError::InvalidInstructionData), + } +} + fn deserialize_instruction( invoke_context: &mut solana_program_runtime::invoke_context::InvokeContext, ) -> Result { - bincode::deserialize( - invoke_context - .transaction_context - .get_current_instruction_context()? - .get_instruction_data(), - ) - .map_err(|_| InstructionError::InvalidInstructionData) + let instruction_context = invoke_context + .transaction_context + .get_current_instruction_context()?; + let data = instruction_context.get_instruction_data(); + + bincode::deserialize(data) + .or_else(|_| deserialize_legacy_instruction(data)) + .map_err(|_| InstructionError::InvalidInstructionData) } declare_process_instruction!( From a9e0959c9eb7b047392a25a4f90f0764e49bb7b2 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 16:10:05 +0200 Subject: [PATCH 046/110] fix: transient record subscription --- .../src/chainlink/fetch_cloner/delegation.rs | 31 ++++----- .../src/chainlink/fetch_cloner/pipeline.rs | 17 +++-- .../src/chainlink/fetch_cloner/tests.rs | 67 +++++++++++++++++++ .../test-chainlink/tests/ix_full_scenarios.rs | 13 ++-- 4 files changed, 98 insertions(+), 30 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index e03686a04..841b9be85 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -15,7 +15,10 @@ use solana_pubkey::Pubkey; use solana_signer::Signer; use tracing::*; -use super::FetchCloner; +use super::{ + subscription::{cancel_subs, CancelStrategy}, + FetchCloner, +}; use crate::{ chainlink::errors::{ChainlinkError, ChainlinkResult}, cloner::{Cloner, DelegationActions}, @@ -215,23 +218,15 @@ where Err(_) => None, }; - if !was_watching_deleg_record - // Handle edge case where it was cloned in the meantime. - // The small possiblility of a fetch + clone of this delegation record being in process - // still exits, but it's negligible - && this - .accounts_bank - .get_account(&delegation_record_pubkey) - .is_none() - { - // We only subscribed to fetch the delegation record, so unsubscribe now - if let Err(err) = this - .remote_account_provider - .unsubscribe(&delegation_record_pubkey) - .await - { - warn!(pubkey = %delegation_record_pubkey, error = %err, "Failed to unsubscribe from delegation record"); - } + if !was_watching_deleg_record { + // We only subscribed to fetch the delegation record, so unsubscribe now. + // Use the shared cancellation path so a concurrent explicit fetch can keep + // the subscription while its request is still pending. + cancel_subs( + &this.remote_account_provider, + CancelStrategy::All([delegation_record_pubkey].into()), + ) + .await; } res diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index c439943f1..b11c01886 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -51,12 +51,21 @@ where .iter() .map(get_loaderv3_get_program_data_address) .collect::>(); - let existing_subs: HashSet = pubkeys + let existing_requested_subs = + pubkeys.iter().filter(|x| this.is_watching(x)).copied(); + // A watched companion account only represents a pre-existing subscription if + // it is already materialized locally; otherwise it may be a transient fetch. + let existing_delegation_record_subs = + delegation_records.iter().filter(|x| { + this.is_watching(x) && this.accounts_bank.get_account(x).is_some() + }); + let existing_program_data_subs = program_data_accounts .iter() - .chain(delegation_records.iter()) - .chain(program_data_accounts.iter()) .filter(|x| this.is_watching(x)) - .copied() + .copied(); + let existing_subs: HashSet = existing_requested_subs + .chain(existing_delegation_record_subs.copied()) + .chain(existing_program_data_subs) .collect(); ExistingSubs { existing_subs } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index 41b59270d..3668b814f 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -436,6 +436,73 @@ async fn test_fetch_and_clone_single_delegated_account_with_valid_delegation_rec ); } +#[tokio::test] +async fn test_fetch_and_clone_delegated_account_cancels_transient_delegation_record_sub( +) { + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); + let account_pubkey = random_pubkey(); + let account_owner = random_pubkey(); + const CURRENT_SLOT: u64 = 100; + + let account = Account { + lamports: 1_234, + data: vec![1, 2, 3, 4], + owner: dlp_api::id(), + executable: false, + rent_epoch: 0, + }; + + let FetcherTestCtx { + remote_account_provider, + accounts_bank, + rpc_client, + fetch_cloner, + .. + } = setup( + [(account_pubkey, account.clone())], + CURRENT_SLOT, + validator_keypair.insecure_clone(), + ) + .await; + + let deleg_record_pubkey = add_delegation_record_for( + &rpc_client, + account_pubkey, + validator_pubkey, + account_owner, + ); + + remote_account_provider + .subscribe(&deleg_record_pubkey) + .await + .unwrap(); + assert!(accounts_bank.get_account(&deleg_record_pubkey).is_none()); + + let result = fetch_cloner + .fetch_and_clone_accounts( + &[account_pubkey], + None, + None, + AccountFetchOrigin::GetAccount, + None, + ) + .await; + + assert!(result.is_ok()); + assert_cloned_delegated_account!( + accounts_bank, + account_pubkey, + account, + CURRENT_SLOT, + account_owner + ); + assert_not_subscribed!( + remote_account_provider, + &[&account_pubkey, &deleg_record_pubkey] + ); +} + #[tokio::test] async fn test_fetch_and_clone_single_delegated_account_with_different_authority( ) { diff --git a/test-integration/test-chainlink/tests/ix_full_scenarios.rs b/test-integration/test-chainlink/tests/ix_full_scenarios.rs index 89e28a033..930d4d4c1 100644 --- a/test-integration/test-chainlink/tests/ix_full_scenarios.rs +++ b/test-integration/test-chainlink/tests/ix_full_scenarios.rs @@ -4,7 +4,10 @@ use magicblock_chainlink::{ assert_not_subscribed, assert_subscribed_without_delegation_record, assert_subscribed_without_loaderv3_program_data_account, remote_account_provider::program_account::RemoteProgramLoader, - testing::{init_logger, utils::random_pubkey}, + testing::{ + init_logger, + utils::random_pubkey, + }, AccountFetchOrigin, }; use solana_loader_v4_interface::state::LoaderV4Status; @@ -16,7 +19,6 @@ use test_chainlink::{ ixtest_context::IxtestContext, logging::{stringify_maybe_pubkeys, stringify_pubkeys}, programs::MEMOV2, - sleep_ms, }; use tokio::task; use tracing::*; @@ -207,12 +209,7 @@ async fn ixtest_accounts_for_tx_2_delegated_3_readonly_3_programs_one_native() { // After we add the account to chain and run the same request again it will // return all accounts { - ctx.rpc_client - .request_airdrop(&new_pubkey, 1_000_000_000) - .await - .unwrap(); - - sleep_ms(500).await; + ctx.add_account(&new_pubkey, 1).await; let (fetched_pubkeys, fetched_strs) = { let fetched_accounts = ctx From 761f1ea6e11e4d1ddd1f5255f03d8ccd9172b257 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 16:58:29 +0200 Subject: [PATCH 047/110] style: lint --- test-integration/test-chainlink/tests/ix_full_scenarios.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test-integration/test-chainlink/tests/ix_full_scenarios.rs b/test-integration/test-chainlink/tests/ix_full_scenarios.rs index 930d4d4c1..2885b6ad0 100644 --- a/test-integration/test-chainlink/tests/ix_full_scenarios.rs +++ b/test-integration/test-chainlink/tests/ix_full_scenarios.rs @@ -4,10 +4,7 @@ use magicblock_chainlink::{ assert_not_subscribed, assert_subscribed_without_delegation_record, assert_subscribed_without_loaderv3_program_data_account, remote_account_provider::program_account::RemoteProgramLoader, - testing::{ - init_logger, - utils::random_pubkey, - }, + testing::{init_logger, utils::random_pubkey}, AccountFetchOrigin, }; use solana_loader_v4_interface::state::LoaderV4Status; From d5b074ebb3e9f36838990c93be3c9491acee39b5 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 17:29:26 +0200 Subject: [PATCH 048/110] fix: do not skip if fetching record --- .../src/chainlink/fetch_cloner/mod.rs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 2a16dd48a..0f5f0c3fd 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -1863,6 +1863,19 @@ where pending.remove(*pubkey); } } + // Subscription updates resolve delegated accounts by fetching the account + // with its delegation record. While that provider fetch is in flight, the + // bank can still hold the older undelegated view; do not short-circuit. + let delegation_record_pubkey = + delegation_record_pda_from_delegated_account(pubkey); + let pending_delegation_update = self.is_watching(pubkey) + && !account_in_bank.delegated() + && !account_in_bank.compressed() + && (self.remote_account_provider.is_pending(pubkey) + || self + .remote_account_provider + .is_pending(&delegation_record_pubkey)); + // After undelegation the bank can hold a plain (non-compressed) undelegated // view while a newer compressed redelegation exists only in Photon. If we // short-circuited here, we would never run RPC+Photon merge and would miss @@ -1876,7 +1889,12 @@ where } && self.is_watching(pubkey) && !account_in_bank.delegated() && !account_in_bank.compressed(); - if may_have_newer_photon { + if pending_delegation_update { + debug!( + pubkey = %pubkey, + "Account has pending delegation update; not treating bank entry as fetch-complete" + ); + } else if may_have_newer_photon { debug!( pubkey = %pubkey, "Post-undelegation, non-delegated, non-compressed in bank; refetching to merge possible Photon state" From e03db575e0747e56d67ad2f36afb11b043408d34 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 19:13:53 +0200 Subject: [PATCH 049/110] fix: fetching compressed commit ids --- .../src/intent_executor/utils.rs | 77 ++++++++++++------- .../tasks/commit_finalize_compressed_task.rs | 4 + magicblock-committor-service/src/tasks/mod.rs | 33 +++++++- test-integration/Cargo.lock | 2 +- 4 files changed, 86 insertions(+), 30 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/utils.rs b/magicblock-committor-service/src/intent_executor/utils.rs index c0f09464b..ea24005a3 100644 --- a/magicblock-committor-service/src/intent_executor/utils.rs +++ b/magicblock-committor-service/src/intent_executor/utils.rs @@ -70,37 +70,59 @@ pub(in crate::intent_executor) async fn handle_commit_id_error< committed_pubkeys: &[Pubkey], strategy: &mut TransactionStrategy, ) -> Result { - let commit_tasks: Vec<_> = strategy + let min_context_slot = strategy .optimized_tasks - .iter_mut() - .filter_map(|task| { - if let BaseTaskImpl::Commit(commit_task) = task { - Some(commit_task) - } else { - None + .iter() + .filter_map(|task| match task { + BaseTaskImpl::Commit(task) => { + Some(task.committed_account.remote_slot) + } + BaseTaskImpl::CommitFinalize(task) => { + Some(task.committed_account.remote_slot) + } + BaseTaskImpl::CommitFinalizeCompressed(task) => { + Some(task.committed_account.remote_slot) } + _ => None, }) - .collect(); - let min_context_slot = commit_tasks - .iter() - .map(|task| task.committed_account.remote_slot) .max() .unwrap_or_default(); + let regular_pubkeys = strategy + .optimized_tasks + .iter() + .filter_map(|task| match task { + BaseTaskImpl::Commit(task) => Some(task.committed_account.pubkey), + BaseTaskImpl::CommitFinalize(task) => { + Some(task.committed_account.pubkey) + } + _ => None, + }) + .collect::>(); + let compressed_pubkeys = strategy + .optimized_tasks + .iter() + .filter_map(|task| match task { + BaseTaskImpl::CommitFinalizeCompressed(task) => { + Some(task.committed_account.pubkey) + } + _ => None, + }) + .collect::>(); // We reset TaskInfoFetcher for all committed accounts // We re-fetch them to fix out of sync tasks task_info_fetcher.reset(ResetType::Specific(committed_pubkeys)); let commit_ids = { let regular_nonces = task_info_fetcher - .fetch_next_commit_nonces( - committed_pubkeys, - false, - min_context_slot, - ) + .fetch_next_commit_nonces(®ular_pubkeys, false, min_context_slot) .await .map_err(TaskBuilderError::CommitTasksBuildError)?; let compressed_nonces = task_info_fetcher - .fetch_next_commit_nonces(committed_pubkeys, true, min_context_slot) + .fetch_next_commit_nonces( + &compressed_pubkeys, + true, + min_context_slot, + ) .await .map_err(TaskBuilderError::CommitTasksBuildError)?; regular_nonces @@ -112,18 +134,17 @@ pub(in crate::intent_executor) async fn handle_commit_id_error< // Here we find the broken tasks and reset them // Broken tasks are prepared incorrectly so they have to be cleaned up let mut to_cleanup = Vec::new(); - for task in commit_tasks { - let Some(commit_id) = commit_ids.get(&task.committed_account.pubkey) - else { - continue; - }; - if commit_id == &task.commit_id { - continue; + for task in &mut strategy.optimized_tasks { + if let Some(commit_id) = task + .committed_account() + .and_then(|ca| commit_ids.get(&ca.pubkey)) + { + if task.commit_id().is_some_and(|id| commit_id == &id) { + continue; + } + to_cleanup.push(task.clone()); + task.reset_commit_id(*commit_id); } - - // Handle invalid tasks - to_cleanup.push(BaseTaskImpl::Commit(task.clone())); - task.reset_commit_id(*commit_id); } let old_alts = strategy.dummy_revaluate_alts(authority); diff --git a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs index 99bacc5df..d85193b9b 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs @@ -61,6 +61,10 @@ impl CommitFinalizeCompressedTask { .instruction() .expect("The serializing the args should not fail") } + + pub fn reset_commit_id(&mut self, commit_id: u64) { + self.commit_id = commit_id; + } } impl From for BaseTaskImpl { diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index fc81dce0e..e1d154b9a 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -10,7 +10,7 @@ use magicblock_committor_program::{ }, pdas, ChangesetChunks, Chunks, }; -use magicblock_core::intent::BaseActionCallback; +use magicblock_core::intent::{BaseActionCallback, CommittedAccount}; use magicblock_metrics::metrics::LabelValue; use magicblock_program::magic_scheduled_base_intent::BaseAction; use solana_instruction::{AccountMeta, Instruction}; @@ -122,6 +122,37 @@ impl BaseTaskImpl { | Self::CommitFinalizeCompressed(_) => TaskStrategy::Args, } } + + pub fn commit_id(&self) -> Option { + match self { + Self::Commit(task) => Some(task.commit_id), + Self::CommitFinalize(task) => Some(task.commit_id), + Self::CommitFinalizeCompressed(task) => Some(task.commit_id), + _ => None, + } + } + + pub fn reset_commit_id(&mut self, commit_id: u64) { + match self { + Self::Commit(task) => task.reset_commit_id(commit_id), + Self::CommitFinalize(task) => task.reset_commit_id(commit_id), + Self::CommitFinalizeCompressed(task) => { + task.reset_commit_id(commit_id) + } + _ => {} + } + } + + pub fn committed_account(&self) -> Option<&CommittedAccount> { + match self { + Self::Commit(task) => Some(&task.committed_account), + Self::CommitFinalize(task) => Some(&task.committed_account), + Self::CommitFinalizeCompressed(task) => { + Some(&task.committed_account) + } + _ => None, + } + } } impl LabelValue for BaseTaskImpl { diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 2b777bb4e..0e4b32cec 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -2436,7 +2436,7 @@ dependencies = [ "getrandom 0.2.16", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade)", "magicblock-magic-program-api 0.9.0 (git+https://github.com/magicblock-labs/magicblock-validator.git?branch=bmuddha%2Fepic%2Fmigration-solana-v3)", - "solana-account 2.2.1", + "solana-account 3.4.0", "solana-account-info 3.1.1", "solana-cpi 3.1.0", "solana-instruction 3.4.0", From 57205acaa951aabfbf14d3b76ebd4c925e216567 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 19:16:49 +0200 Subject: [PATCH 050/110] style: lint --- programs/magicblock/src/magicblock_processor.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/magicblock/src/magicblock_processor.rs b/programs/magicblock/src/magicblock_processor.rs index a610325a2..bf5a44847 100644 --- a/programs/magicblock/src/magicblock_processor.rs +++ b/programs/magicblock/src/magicblock_processor.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use magicblock_magic_program_api::{ args::{ BaseActionArgs, CommitAndUndelegateArgs, CommitTypeArgs, @@ -9,7 +11,6 @@ use serde::Deserialize; use solana_instruction::error::InstructionError; use solana_program_runtime::declare_process_instruction; use solana_pubkey::Pubkey; -use std::collections::HashMap; use crate::{ clone_account::{ From 1fac1463abf3bab1525d890bf96ae14c6c617ae1 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 20:05:05 +0200 Subject: [PATCH 051/110] test: magicblock processor --- .../magicblock/src/magicblock_processor.rs | 213 +++++++++++++++++- 1 file changed, 211 insertions(+), 2 deletions(-) diff --git a/programs/magicblock/src/magicblock_processor.rs b/programs/magicblock/src/magicblock_processor.rs index bf5a44847..930253434 100644 --- a/programs/magicblock/src/magicblock_processor.rs +++ b/programs/magicblock/src/magicblock_processor.rs @@ -42,6 +42,7 @@ pub const DEFAULT_COMPUTE_UNITS: u64 = 150; /// by compressed commits. #[allow(dead_code)] #[derive(Deserialize)] +#[cfg_attr(test, derive(serde::Serialize))] enum LegacyMagicBlockInstruction { ModifyAccounts { accounts: HashMap, @@ -63,6 +64,7 @@ enum LegacyMagicBlockInstruction { } #[derive(Deserialize)] +#[cfg_attr(test, derive(serde::Serialize))] enum LegacyMagicBaseIntentArgs { BaseActions(Vec), Commit(CommitTypeArgs), @@ -96,6 +98,7 @@ impl From for MagicIntentBundleArgs { } #[derive(Deserialize)] +#[cfg_attr(test, derive(serde::Serialize))] struct LegacyMagicIntentBundleArgs { commit: Option, commit_and_undelegate: Option, @@ -377,12 +380,218 @@ declare_process_instruction!( #[cfg(test)] mod test { - use magicblock_magic_program_api::args::ScheduleTaskArgs; + use std::cell::RefCell; + + use magicblock_magic_program_api::args::{ + CommitAndUndelegateArgs, CommitTypeArgs, MagicBaseIntentArgs, + MagicIntentBundleArgs, ScheduleTaskArgs, UndelegateTypeArgs, + }; use solana_instruction::AccountMeta; - use solana_program_runtime::invoke_context::mock_process_instruction; + use solana_program_runtime::{ + declare_process_instruction, invoke_context::mock_process_instruction, + }; use super::*; + thread_local! { + static EXPECTED_INSTRUCTION: RefCell> = + const { RefCell::new(None) }; + } + + declare_process_instruction!( + DecodeOnlyEntrypoint, + DEFAULT_COMPUTE_UNITS, + |invoke_context| { + let decoded = deserialize_instruction(invoke_context)?; + EXPECTED_INSTRUCTION.with(|expected| { + assert_eq!( + decoded, + expected.borrow().as_ref().unwrap().clone() + ); + }); + Ok(()) + } + ); + + fn assert_deserialize_instruction_decodes( + instruction_data: &[u8], + expected_instruction: MagicBlockInstruction, + ) { + EXPECTED_INSTRUCTION.with(|expected| { + *expected.borrow_mut() = Some(expected_instruction); + }); + + mock_process_instruction( + &crate::id(), + None, + instruction_data, + Vec::new(), + vec![AccountMeta::new_readonly(crate::id(), false)], + Ok(()), + DecodeOnlyEntrypoint::vm, + |_invoke_context| {}, + |_invoke_context| {}, + ); + + EXPECTED_INSTRUCTION.with(|expected| { + assert!(expected.borrow_mut().take().is_some()); + }); + } + + fn standalone_commit(accounts: &[u8]) -> CommitTypeArgs { + CommitTypeArgs::Standalone(accounts.to_vec()) + } + + fn standalone_commit_and_undelegate( + accounts: &[u8], + ) -> CommitAndUndelegateArgs { + CommitAndUndelegateArgs { + commit_type: standalone_commit(accounts), + undelegate_type: UndelegateTypeArgs::Standalone, + } + } + + fn legacy_base_intent_payload() -> Vec { + bincode::serialize(&LegacyMagicBlockInstruction::ScheduleBaseIntent( + LegacyMagicBaseIntentArgs::Commit(standalone_commit(&[2, 3])), + )) + .unwrap() + } + + fn expected_legacy_base_intent_instruction() -> MagicBlockInstruction { + MagicBlockInstruction::ScheduleIntentBundle(MagicIntentBundleArgs { + commit: Some(standalone_commit(&[2, 3])), + ..MagicIntentBundleArgs::default() + }) + } + + fn legacy_intent_bundle_payload() -> Vec { + bincode::serialize(&LegacyMagicBlockInstruction::ScheduleIntentBundle( + LegacyMagicIntentBundleArgs { + commit: Some(standalone_commit(&[4])), + commit_and_undelegate: None, + commit_finalize: None, + commit_finalize_and_undelegate: Some( + standalone_commit_and_undelegate(&[5]), + ), + standalone_actions: vec![], + }, + )) + .unwrap() + } + + fn expected_legacy_intent_bundle_instruction() -> MagicBlockInstruction { + MagicBlockInstruction::ScheduleIntentBundle(MagicIntentBundleArgs { + commit: Some(standalone_commit(&[4])), + commit_finalize_and_undelegate: Some( + standalone_commit_and_undelegate(&[5]), + ), + ..MagicIntentBundleArgs::default() + }) + } + + fn commit_finalize_instruction( + compressed: bool, + request_undelegation: bool, + ) -> MagicBlockInstruction { + match (compressed, request_undelegation) { + (false, false) => MagicBlockInstruction::ScheduleCommitFinalize { + request_undelegation: false, + }, + (false, true) => MagicBlockInstruction::ScheduleCommitFinalize { + request_undelegation: true, + }, + (true, false) => MagicBlockInstruction::ScheduleCommitCompressed, + (true, true) => { + MagicBlockInstruction::ScheduleCommitAndUndelegateCompressed + } + } + } + + #[test] + fn deserialize_instruction_decodes_current_format() { + let expected = MagicBlockInstruction::ScheduleIntentBundle( + MagicIntentBundleArgs { + commit_finalize_compressed: Some(standalone_commit(&[1, 2])), + ..MagicIntentBundleArgs::default() + }, + ); + let data = bincode::serialize(&expected).unwrap(); + + assert_deserialize_instruction_decodes(&data, expected); + } + + #[test] + fn deserialize_legacy_schedule_base_intent_remaps_to_intent_bundle() { + let decoded = + deserialize_legacy_instruction(&legacy_base_intent_payload()) + .expect("legacy ScheduleBaseIntent should decode"); + + assert_eq!(decoded, expected_legacy_base_intent_instruction()); + } + + #[test] + fn deserialize_instruction_decodes_legacy_base_as_current_variant() { + assert_deserialize_instruction_decodes( + &legacy_base_intent_payload(), + MagicBlockInstruction::ScheduleBaseIntent( + MagicBaseIntentArgs::Commit(standalone_commit(&[2, 3])), + ), + ); + } + + #[test] + fn deserialize_legacy_schedule_intent_bundle_remaps_to_intent_bundle() { + let decoded = + deserialize_legacy_instruction(&legacy_intent_bundle_payload()) + .expect("legacy ScheduleIntentBundle should decode"); + + assert_eq!(decoded, expected_legacy_intent_bundle_instruction()); + } + + #[test] + fn deserialize_instruction_falls_back_to_legacy_schedule_intent_bundle() { + assert_deserialize_instruction_decodes( + &legacy_intent_bundle_payload(), + expected_legacy_intent_bundle_instruction(), + ); + } + + #[test] + fn deserialize_instruction_decodes_commit_finalize_routing_matrix() { + for compressed in [false, true] { + for request_undelegation in [false, true] { + let expected = commit_finalize_instruction( + compressed, + request_undelegation, + ); + let data = bincode::serialize(&expected).unwrap(); + + assert_deserialize_instruction_decodes(&data, expected); + } + } + } + + #[test] + fn crank_entrypoint_decodes_execute_crank_before_account_validation() { + let data = bincode::serialize(&MagicBlockInstruction::ExecuteCrank { + instructions: vec![], + }) + .unwrap(); + + mock_process_instruction( + &crate::CRANK_PROGRAM_ID, + None, + &data, + Vec::new(), + vec![AccountMeta::new_readonly(crate::CRANK_PROGRAM_ID, false)], + Err(InstructionError::MissingAccount), + CrankEntrypoint::vm, + |_invoke_context| {}, + |_invoke_context| {}, + ); + } + #[test] fn crank_entrypoint_rejects_non_execute_crank_instructions() { let data = bincode::serialize(&MagicBlockInstruction::ScheduleTask( From 83004f2af0ce7e645cdcad2e42ce296d1180faf4 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 20:41:43 +0200 Subject: [PATCH 052/110] fix: not using bank as proxy for subscription --- .../src/chainlink/fetch_cloner/pipeline.rs | 6 +- .../src/chainlink/fetch_cloner/tests.rs | 58 +++++++++++++++++-- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index b11c01886..015a089f6 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -53,12 +53,8 @@ where .collect::>(); let existing_requested_subs = pubkeys.iter().filter(|x| this.is_watching(x)).copied(); - // A watched companion account only represents a pre-existing subscription if - // it is already materialized locally; otherwise it may be a transient fetch. let existing_delegation_record_subs = - delegation_records.iter().filter(|x| { - this.is_watching(x) && this.accounts_bank.get_account(x).is_some() - }); + delegation_records.iter().filter(|x| this.is_watching(x)); let existing_program_data_subs = program_data_accounts .iter() .filter(|x| this.is_watching(x)) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index 3668b814f..9698dd2eb 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -437,7 +437,57 @@ async fn test_fetch_and_clone_single_delegated_account_with_valid_delegation_rec } #[tokio::test] -async fn test_fetch_and_clone_delegated_account_cancels_transient_delegation_record_sub( +async fn test_build_existing_subs_keeps_watched_unmaterialized_delegation_record( +) { + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); + let account_pubkey = random_pubkey(); + let account_owner = random_pubkey(); + const CURRENT_SLOT: u64 = 100; + + let account = Account { + lamports: 1_234, + data: vec![1, 2, 3, 4], + owner: dlp_api::id(), + executable: false, + rent_epoch: 0, + }; + + let FetcherTestCtx { + remote_account_provider, + accounts_bank, + rpc_client, + fetch_cloner, + .. + } = setup( + [(account_pubkey, account)], + CURRENT_SLOT, + validator_keypair.insecure_clone(), + ) + .await; + + let deleg_record_pubkey = add_delegation_record_for( + &rpc_client, + account_pubkey, + validator_pubkey, + account_owner, + ); + + remote_account_provider + .subscribe(&deleg_record_pubkey) + .await + .unwrap(); + assert!(accounts_bank.get_account(&deleg_record_pubkey).is_none()); + + let existing_subs = + pipeline::build_existing_subs(&fetch_cloner, &[account_pubkey]) + .existing_subs; + + assert!(existing_subs.contains(&deleg_record_pubkey)); +} + +#[tokio::test] +async fn test_fetch_and_clone_delegated_account_keeps_existing_delegation_record_sub( ) { let validator_keypair = Keypair::new(); let validator_pubkey = validator_keypair.pubkey(); @@ -497,10 +547,8 @@ async fn test_fetch_and_clone_delegated_account_cancels_transient_delegation_rec CURRENT_SLOT, account_owner ); - assert_not_subscribed!( - remote_account_provider, - &[&account_pubkey, &deleg_record_pubkey] - ); + assert_subscribed!(remote_account_provider, &[&deleg_record_pubkey]); + assert_not_subscribed!(remote_account_provider, &[&account_pubkey]); } #[tokio::test] From 650935c78bdf41341fef26cd811905f85957da2b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 21:25:56 +0200 Subject: [PATCH 053/110] fix: clear post_undelegation_photon_merge_pending --- .../src/chainlink/fetch_cloner/mod.rs | 33 +++++++++ .../src/chainlink/fetch_cloner/tests.rs | 73 +++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 0f5f0c3fd..2880de295 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -2060,6 +2060,39 @@ where } joinset.join_all().await; + // Clear `post_undelegation_photon_merge_pending` for accounts that were fetched successfully + if let Ok(result) = &result { + for pubkey in &fetch_new { + let fetch_left_pubkey_unresolved = result + .not_found_on_chain + .iter() + .any(|(missing_pubkey, _)| missing_pubkey == pubkey) + || result + .missing_delegation_record + .iter() + .any(|(missing_pubkey, _)| missing_pubkey == pubkey); + if fetch_left_pubkey_unresolved { + continue; + } + + if let Some(account_in_bank) = + self.accounts_bank.get_account(pubkey) + { + if self.is_watching(pubkey) + && !account_in_bank.delegated() + && !account_in_bank.compressed() + { + self.post_undelegation_photon_merge_pending + .lock() + .expect( + "post_undelegation_photon_merge_pending lock poisoned", + ) + .remove(pubkey); + } + } + } + } + result } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index 9698dd2eb..145800ed9 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -1303,6 +1303,79 @@ async fn test_undelegation_requested_subscription_behavior() { assert_subscribed!(remote_account_provider, &[&account_pubkey]); } +#[tokio::test] +async fn test_post_undelegation_plain_refresh_clears_photon_merge_marker() { + init_logger(); + let validator_keypair = Keypair::new(); + let account_owner = random_pubkey(); + const CURRENT_SLOT: u64 = 100; + + let account_pubkey = random_pubkey(); + let account = Account { + lamports: 1_000_000, + data: vec![1, 2, 3, 4], + owner: account_owner, + executable: false, + rent_epoch: 0, + }; + + let FetcherTestCtx { + remote_account_provider, + accounts_bank, + fetch_cloner, + .. + } = setup( + [(account_pubkey, account.clone())], + CURRENT_SLOT, + validator_keypair.insecure_clone(), + ) + .await; + + accounts_bank + .insert(account_pubkey, AccountSharedData::from(account.clone())); + fetch_cloner + .subscribe_to_account(&account_pubkey) + .await + .expect("failed to subscribe to account"); + assert_subscribed!(remote_account_provider, &[&account_pubkey]); + + fetch_cloner.mark_post_undelegation_photon_merge_pending(account_pubkey); + + let result = fetch_cloner + .fetch_and_clone_accounts_with_dedup( + &[account_pubkey], + None, + None, + AccountFetchOrigin::GetAccount, + None, + ) + .await; + assert!(result.is_ok()); + + let marker_still_pending = fetch_cloner + .post_undelegation_photon_merge_pending + .lock() + .expect("post_undelegation_photon_merge_pending lock poisoned") + .contains(&account_pubkey); + assert!( + !marker_still_pending, + "plain refresh should clear post-undelegation Photon merge marker" + ); + + let fetch_count_after_plain_refresh = fetch_cloner.fetch_count(); + let result = fetch_cloner + .fetch_and_clone_accounts_with_dedup( + &[account_pubkey], + None, + None, + AccountFetchOrigin::GetAccount, + None, + ) + .await; + assert!(result.is_ok()); + assert_eq!(fetch_cloner.fetch_count(), fetch_count_after_plain_refresh); +} + #[tokio::test] async fn test_delegated_authoritative_skip_unsubscribes_subscription() { init_logger(); From d2ba6951eedbbc18fa90a65eda893a37d6a9bd77 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 21:37:38 +0200 Subject: [PATCH 054/110] fix: skip on failed refetch --- .../src/chainlink/fetch_cloner/mod.rs | 22 ++++--- .../src/chainlink/fetch_cloner/tests.rs | 63 +++++++++++++++++++ 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 2880de295..cb73d1c4d 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -901,18 +901,19 @@ where &self, pubkey: Pubkey, account: AccountSharedData, - ) -> (AccountSharedData, Option) { + ) -> Option<(AccountSharedData, Option)> { let min_slot = account.remote_slot(); if let Some((out, delegation_slot)) = compression::try_decompress_compressed_delegation( self, &account, min_slot, ) { - return (out, Some(delegation_slot)); + return Some((out, Some(delegation_slot))); } if !account.data().is_empty() { - return (account, None); + return Some((account, None)); } + let skip_on_failed_refetch = account.compressed(); if let Ok(fetched) = self .remote_account_provider .try_get_multi( @@ -933,14 +934,18 @@ where min_slot.max(fresh.remote_slot()), ) { - return (out, Some(delegation_slot)); + return Some((out, Some(delegation_slot))); } } } } else { warn!(pubkey = %pubkey, "Refetch for compressed subscription account failed"); } - (account, None) + if skip_on_failed_refetch { + None + } else { + Some((account, None)) + } } // Fourth return value: `CompressedDelegationRecord::delegation_slot` for compressed (no DLP) @@ -1109,9 +1114,12 @@ where } } } else { - let (account, compressed_delegation_slot) = self + let Some((account, compressed_delegation_slot)) = self .decompress_or_refetch_compressed_account(pubkey, account) - .await; + .await + else { + return (None, None, DelegationActions::default(), None); + }; let (account, deleg_record) = self .maybe_project_ata_from_subscription_update(pubkey, account) .await; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index 145800ed9..490766945 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -1376,6 +1376,69 @@ async fn test_post_undelegation_plain_refresh_clears_photon_merge_marker() { assert_eq!(fetch_cloner.fetch_count(), fetch_count_after_plain_refresh); } +#[tokio::test] +async fn test_empty_compressed_subscription_update_skips_when_refetch_cannot_decompress( +) { + init_logger(); + let validator_keypair = Keypair::new(); + let account_owner = random_pubkey(); + const CURRENT_SLOT: u64 = 100; + + let account_pubkey = random_pubkey(); + let bank_account = Account { + lamports: 1_000_000, + data: vec![1, 2, 3, 4], + owner: account_owner, + executable: false, + rent_epoch: 0, + }; + + let FetcherTestCtx { + accounts_bank, + fetch_cloner, + .. + } = setup( + [(account_pubkey, bank_account.clone())], + CURRENT_SLOT + 1, + validator_keypair.insecure_clone(), + ) + .await; + + let mut expected_bank_account = AccountSharedData::from(bank_account); + expected_bank_account.set_remote_slot(CURRENT_SLOT); + accounts_bank.insert(account_pubkey, expected_bank_account.clone()); + + use crate::remote_account_provider::{ + RemoteAccount, RemoteAccountUpdateSource, + }; + let empty_compressed_shell = Account { + lamports: 0, + data: vec![], + owner: compressed_delegation_client::ID, + executable: false, + rent_epoch: 0, + }; + fetch_cloner + .process_subscription_update( + account_pubkey, + ForwardedSubscriptionUpdate { + pubkey: account_pubkey, + account: RemoteAccount::from_fresh_account( + empty_compressed_shell, + CURRENT_SLOT + 1, + RemoteAccountUpdateSource::Compressed, + ), + }, + ) + .await; + + assert_eq!( + accounts_bank.get_account(&account_pubkey), + Some(expected_bank_account), + "empty compressed shell should be skipped when refetch cannot decompress" + ); +} + #[tokio::test] async fn test_delegated_authoritative_skip_unsubscribes_subscription() { init_logger(); From e87b0775910131cee1e42945a7c6644c48af8ddc Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 23:55:27 +0200 Subject: [PATCH 055/110] fix: separate fetch-owned from explicit subs --- .../src/chainlink/fetch_cloner/delegation.rs | 12 ++- .../src/chainlink/fetch_cloner/mod.rs | 12 ++- .../src/chainlink/fetch_cloner/pipeline.rs | 31 ++++++- .../chainlink/fetch_cloner/subscription.rs | 67 +++++++++++++-- .../src/chainlink/fetch_cloner/tests.rs | 86 +++++++++++++++++++ .../src/chainlink/fetch_cloner/types.rs | 6 +- .../src/remote_account_provider/mod.rs | 57 +++++++++++- 7 files changed, 252 insertions(+), 19 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 841b9be85..4535feeac 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use dlp_api::{ args::PostDelegationActions, decrypt::Decrypt, pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, @@ -187,6 +189,9 @@ where let was_watching_deleg_record = this .remote_account_provider .is_watching(&delegation_record_pubkey); + let deleg_record_generation = this + .remote_account_provider + .subscription_generation(&delegation_record_pubkey); let res = match this .remote_account_provider @@ -224,7 +229,12 @@ where // the subscription while its request is still pending. cancel_subs( &this.remote_account_provider, - CancelStrategy::All([delegation_record_pubkey].into()), + CancelStrategy::OnlyIfUnchanged { + pubkeys: HashMap::from([( + delegation_record_pubkey, + deleg_record_generation, + )]), + }, ) .await; } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index cb73d1c4d..dd5fd1ed2 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -47,8 +47,9 @@ pub use self::types::FetchAndCloneResult; use self::{ subscription::{cancel_subs, CancelStrategy}, types::{ - AccountWithCompanion, ClassifiedAccounts, PartitionedNotFound, - RefreshDecision, ResolvedDelegatedAccounts, ResolvedPrograms, + AccountWithCompanion, ClassifiedAccounts, ExistingSubs, + PartitionedNotFound, RefreshDecision, ResolvedDelegatedAccounts, + ResolvedPrograms, }, }; use super::errors::{ChainlinkError, ChainlinkResult}; @@ -1383,8 +1384,10 @@ where // We keep all existing subscriptions including delegation records and program data // accounts that were directly requested - let mut existing_subs = - pipeline::build_existing_subs(self, pubkeys).existing_subs; + let ExistingSubs { + mut existing_subs, + existing_sub_generations, + } = pipeline::build_existing_subs(self, pubkeys); // Track all new subscriptions created during this call let mut new_subs: HashSet = HashSet::new(); @@ -1691,6 +1694,7 @@ where record_subs, program_data_subs, existing_subs, + existing_sub_generations, new_subs, ); diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 015a089f6..8be74ee79 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -1,4 +1,7 @@ -use std::{collections::HashSet, sync::atomic::Ordering}; +use std::{ + collections::{HashMap, HashSet}, + sync::atomic::Ordering, +}; use dlp_api::pda::delegation_record_pda_from_delegated_account; use magicblock_accounts_db::traits::AccountsBank; @@ -63,8 +66,20 @@ where .chain(existing_delegation_record_subs.copied()) .chain(existing_program_data_subs) .collect(); + let existing_sub_generations = existing_subs + .iter() + .map(|pubkey| { + ( + *pubkey, + this.remote_account_provider.subscription_generation(pubkey), + ) + }) + .collect(); - ExistingSubs { existing_subs } + ExistingSubs { + existing_subs, + existing_sub_generations, + } } pub(crate) fn collect_delegation_action_dependencies( @@ -623,6 +638,7 @@ pub(crate) fn compute_cancel_strategy( record_subs: Vec, program_data_subs: HashSet, existing_subs: HashSet, + existing_sub_generations: HashMap, new_subs: HashSet, ) -> CancelStrategy { // Cancel subs for delegated accounts (accounts we clone but don't need to watch) @@ -650,6 +666,16 @@ pub(crate) fn compute_cancel_strategy( let new_subs_to_cancel: HashSet = new_subs.difference(&accounts_to_keep).copied().collect(); + let existing_temporary_record_subs = record_subs + .iter() + .filter_map(|pubkey| { + existing_sub_generations + .get(pubkey) + .copied() + .filter(|generation| *generation == 0) + .map(|generation| (*pubkey, generation)) + }) + .collect(); // Safety check: under test, verify new approach matches old approach #[cfg(test)] @@ -678,6 +704,7 @@ pub(crate) fn compute_cancel_strategy( new_subs: new_subs_to_cancel, existing_subs, all: delegated_accounts_to_cancel, + only_if_unchanged: existing_temporary_record_subs, } } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs index 263e04673..a4822b4d4 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs @@ -1,4 +1,8 @@ -use std::{collections::HashSet, fmt, sync::Arc}; +use std::{ + collections::{HashMap, HashSet}, + fmt, + sync::Arc, +}; use magicblock_core::traits::PhotonClient; use solana_pubkey::Pubkey; @@ -23,7 +27,11 @@ pub(crate) enum CancelStrategy { new_subs: HashSet, existing_subs: HashSet, all: HashSet, + only_if_unchanged: HashMap, }, + /// Cancel subscriptions for accounts that are explicitly subscribed to + /// and have not changed since the last snapshot. + OnlyIfUnchanged { pubkeys: HashMap }, } impl CancelStrategy { @@ -38,11 +46,14 @@ impl CancelStrategy { new_subs, existing_subs, all, + only_if_unchanged, } => { new_subs.is_empty() && existing_subs.is_empty() && all.is_empty() + && only_if_unchanged.is_empty() } + CancelStrategy::OnlyIfUnchanged { pubkeys } => pubkeys.is_empty(), } } } @@ -80,9 +91,10 @@ impl fmt::Display for CancelStrategy { new_subs, existing_subs, all, + only_if_unchanged, } => write!( f, - "Hybrid(New: {}, Existing: {}, All: {})", + "Hybrid(New: {}, Existing: {}, All: {}, OnlyIfUnchanged: {})", new_subs .iter() .map(|p| p.to_string()) @@ -94,6 +106,20 @@ impl fmt::Display for CancelStrategy { .collect::>() .join(", "), all.iter() + .map(|p| p.to_string()) + .collect::>() + .join(", "), + only_if_unchanged + .keys() + .map(|p| p.to_string()) + .collect::>() + .join(", ") + ), + CancelStrategy::OnlyIfUnchanged { pubkeys } => write!( + f, + "OnlyIfUnchanged({})", + pubkeys + .keys() .map(|p| p.to_string()) .collect::>() .join(", ") @@ -118,32 +144,47 @@ pub(crate) async fn cancel_subs< let mut joinset = JoinSet::new(); trace!("Canceling subscriptions"); - let subs_to_cancel = match strategy { - CancelStrategy::All(pubkeys) => pubkeys, + let subs_to_cancel: HashMap> = match strategy { + CancelStrategy::All(pubkeys) => { + pubkeys.into_iter().map(|pubkey| (pubkey, None)).collect() + } CancelStrategy::New { new_subs, existing_subs, - } => new_subs.difference(&existing_subs).cloned().collect(), + } => new_subs + .difference(&existing_subs) + .map(|pubkey| (*pubkey, None)) + .collect(), CancelStrategy::Hybrid { new_subs, existing_subs, all, + only_if_unchanged, } => new_subs .difference(&existing_subs) - .cloned() - .chain(all.into_iter()) + .map(|pubkey| (*pubkey, None)) + .chain(all.into_iter().map(|pubkey| (pubkey, None))) + .chain( + only_if_unchanged + .into_iter() + .map(|(pubkey, generation)| (pubkey, Some(generation))), + ) + .collect(), + CancelStrategy::OnlyIfUnchanged { pubkeys } => pubkeys + .into_iter() + .map(|(pubkey, generation)| (pubkey, Some(generation))) .collect(), }; if tracing::enabled!(tracing::Level::TRACE) { let pubkeys_str = subs_to_cancel .iter() - .map(|p| p.to_string()) + .map(|(p, _)| p.to_string()) .collect::>() .join(", "); trace!(pubkeys = %pubkeys_str, "Canceling subscriptions for"); } - for pubkey in subs_to_cancel { + for (pubkey, expected_generation) in subs_to_cancel { let provider_clone = provider.clone(); joinset.spawn(async move { // Check if there are pending requests for this account before unsubscribing @@ -152,6 +193,14 @@ pub(crate) async fn cancel_subs< debug!(pubkey = %pubkey, "Skipping unsubscribe - has pending requests"); return; } + if let Some(expected_generation) = expected_generation { + if provider_clone.subscription_generation(&pubkey) + != expected_generation + { + debug!(pubkey = %pubkey, "Skipping unsubscribe - subscription changed"); + return; + } + } if let Err(err) = provider_clone.unsubscribe(&pubkey).await { warn!(pubkey = %pubkey, error = ?err, "Failed to unsubscribe"); diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index 490766945..7e198e206 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -1439,6 +1439,92 @@ async fn test_empty_compressed_subscription_update_skips_when_refetch_cannot_dec ); } +#[tokio::test] +async fn test_only_if_unchanged_cancellation_preserves_newer_subscription() { + init_logger(); + let validator_keypair = Keypair::new(); + const CURRENT_SLOT: u64 = 100; + + let FetcherTestCtx { + remote_account_provider, + .. + } = setup( + Vec::<(Pubkey, Account)>::new(), + CURRENT_SLOT, + validator_keypair.insecure_clone(), + ) + .await; + + use super::subscription::{cancel_subs, CancelStrategy}; + + let pubkey = random_pubkey(); + let generation_before_temporary_subscription = + remote_account_provider.subscription_generation(&pubkey); + + remote_account_provider + .subscribe_for_fetch(&pubkey) + .await + .expect("temporary subscription should succeed"); + remote_account_provider + .subscribe(&pubkey) + .await + .expect("newer subscription should succeed"); + + cancel_subs( + &remote_account_provider, + CancelStrategy::OnlyIfUnchanged { + pubkeys: HashMap::from([( + pubkey, + generation_before_temporary_subscription, + )]), + }, + ) + .await; + + assert_subscribed!(remote_account_provider, &[&pubkey]); +} + +#[tokio::test] +async fn test_only_if_unchanged_cancellation_removes_temporary_subscription() { + init_logger(); + let validator_keypair = Keypair::new(); + const CURRENT_SLOT: u64 = 100; + + let FetcherTestCtx { + remote_account_provider, + .. + } = setup( + Vec::<(Pubkey, Account)>::new(), + CURRENT_SLOT, + validator_keypair.insecure_clone(), + ) + .await; + + use super::subscription::{cancel_subs, CancelStrategy}; + + let pubkey = random_pubkey(); + let generation_before_temporary_subscription = + remote_account_provider.subscription_generation(&pubkey); + + remote_account_provider + .subscribe_for_fetch(&pubkey) + .await + .expect("temporary subscription should succeed"); + + cancel_subs( + &remote_account_provider, + CancelStrategy::OnlyIfUnchanged { + pubkeys: HashMap::from([( + pubkey, + generation_before_temporary_subscription, + )]), + }, + ) + .await; + + assert_not_subscribed!(remote_account_provider, &[&pubkey]); +} + #[tokio::test] async fn test_delegated_authoritative_skip_unsubscribes_subscription() { init_logger(); diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs index b43445419..d7ddd6d46 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs @@ -1,4 +1,7 @@ -use std::{collections::HashSet, fmt}; +use std::{ + collections::{HashMap, HashSet}, + fmt, +}; use solana_account::AccountSharedData; use solana_pubkey::Pubkey; @@ -26,6 +29,7 @@ pub(crate) enum RefreshDecision { // Pipeline helper types pub(crate) struct ExistingSubs { pub(crate) existing_subs: HashSet, + pub(crate) existing_sub_generations: HashMap, } pub(crate) struct ClassifiedAccounts { diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index d15fede4a..3926e469a 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -118,6 +118,9 @@ pub struct RemoteAccountProvider< /// Minimal tracking of accounts currently being fetched to handle race conditions /// between fetch and subscription updates. Only used during active fetch operations. fetching_accounts: Arc, + /// Tracking of accounts used to distinguish between "the fetch still owns this sub" + /// from "another caller started watching after the fetch began". + subscription_generations: Arc>>, /// The current slot on chain. /// /// This value is updated from two sources and always stores the maximum @@ -142,7 +145,6 @@ pub struct RemoteAccountProvider< /// Tracks which accounts are currently subscribed to lrucache_subscribed_accounts: Arc, - /// Channel to notify when an account is removed from the cache and thus no /// longer being watched removed_account_tx: mpsc::Sender, @@ -312,6 +314,8 @@ impl last_update_slot: Arc::::default(), received_updates_count: Arc::::default(), lrucache_subscribed_accounts, + subscription_generations: + Arc::>>::default(), subscription_forwarder: Arc::new(subscription_forwarder), removed_account_tx, removed_account_rx: Mutex::new(Some(removed_account_rx)), @@ -906,7 +910,7 @@ impl let subscription_results = join_all( subscribe_and_fetch .iter() - .map(|(pubkey, _)| self.subscribe(pubkey)), + .map(|(pubkey, _)| self.subscribe_for_fetch(pubkey)), ) .await; @@ -1020,6 +1024,34 @@ impl self.lrucache_subscribed_accounts.contains(pubkey) } + /// Returns the current explicit-watcher generation for `pubkey`. + /// + /// Callers that create temporary fetch subscriptions can snapshot this + /// value and later cancel only if it is unchanged, preserving any explicit + /// watcher that subscribed concurrently. + pub(crate) fn subscription_generation(&self, pubkey: &Pubkey) -> u64 { + self.subscription_generations + .lock() + .expect("subscription_generations lock poisoned") + .get(pubkey) + .copied() + .unwrap_or_default() + } + + /// Marks that an explicit watcher subscribed or renewed interest in + /// `pubkey`. + /// + /// This is deliberately separate from fetch-owned subscriptions: fetches may + /// subscribe only to resolve an account and should not prevent their own + /// cleanup from removing that temporary subscription. + fn bump_subscription_generation(&self, pubkey: &Pubkey) { + let mut generations = self + .subscription_generations + .lock() + .expect("subscription_generations lock poisoned"); + *generations.entry(*pubkey).or_default() += 1; + } + /// Check if an account is currently pending (being fetched) pub fn is_pending(&self, pubkey: &Pubkey) -> bool { let fetching = self.fetching_accounts.lock().unwrap(); @@ -1035,13 +1067,34 @@ impl if self.is_watching(pubkey) { // Promote in LRU cache even if already subscribed self.lrucache_subscribed_accounts.add(*pubkey); + self.bump_subscription_generation(pubkey); return Ok(()); } self.register_subscription(pubkey).await?; + self.bump_subscription_generation(pubkey); Ok(()) } + /// Subscribe while resolving a fetch without claiming explicit watcher + /// ownership. + /// + /// Fetch-created subscriptions are cleaned up by `cancel_subs`; because they + /// do not bump `subscription_generations`, generation-aware cleanup can still + /// remove them even if the fetch path internally retries or promotes the + /// same subscription. + pub(crate) async fn subscribe_for_fetch( + &self, + pubkey: &Pubkey, + ) -> RemoteAccountProviderResult<()> { + if self.is_watching(pubkey) { + self.lrucache_subscribed_accounts.add(*pubkey); + return Ok(()); + } + + self.register_subscription(pubkey).await + } + /// Subscribe to program account updates #[instrument(skip(self))] pub async fn subscribe_program( From 7d1d0ab258a315e4ae46d45bf253debe7874af8b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 29 Apr 2026 23:56:38 +0200 Subject: [PATCH 056/110] feat: simpler conditional light tools --- .github/workflows/ci-test-integration.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index 778e106a1..e7623d627 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -39,6 +39,8 @@ jobs: run_integration_tests: needs: build runs-on: ubuntu-latest-m + env: + NEEDS_COMPRESSION_TOOLS: ${{ contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) }} strategy: matrix: batch_tests: @@ -71,20 +73,20 @@ jobs: - uses: ./magicblock-validator/.github/actions/setup-solana - name: Install Photon indexer - if: contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) + if: env.NEEDS_COMPRESSION_TOOLS == 'true' shell: bash env: RUSTFLAGS: "-A dead-code" run: cargo install --git https://github.com/lightprotocol/photon.git --rev 3f82b926be6717a07bd41aedb84b4d9e6b0ab0d3 --locked --force - name: Setup Node.js - if: contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) + if: env.NEEDS_COMPRESSION_TOOLS == 'true' uses: actions/setup-node@v4 with: node-version: "20" - name: Install zk-compression CLI - if: contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) + if: env.NEEDS_COMPRESSION_TOOLS == 'true' run: | npm i -g @lightprotocol/zk-compression-cli@0.28.4 shell: bash From f9e6873cb8c006e4d0cf0efbc310a48a9f36c9a6 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 01:17:56 +0200 Subject: [PATCH 057/110] fix: rustls install --- Cargo.lock | 1 + Cargo.toml | 4 ++++ magicblock-chainlink/Cargo.toml | 1 + .../src/chainlink/fetch_cloner/pipeline.rs | 2 +- .../src/chainlink/fetch_cloner/subscription.rs | 4 ++-- magicblock-chainlink/src/remote_account_provider/mod.rs | 8 ++++++++ test-integration/Cargo.lock | 1 + 7 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54cbd4c43..5d6d4f338 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4606,6 +4606,7 @@ dependencies = [ "magicblock-magic-program-api", "magicblock-metrics", "parking_lot", + "rustls 0.23.38", "scc", "solana-account 3.4.0", "solana-account-decoder", diff --git a/Cargo.toml b/Cargo.toml index 7f4d1f91e..4cea49c52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,6 +142,10 @@ reqwest = "0.12" rusqlite = { version = "0.37.0", features = ["bundled"] } rustc-hash = "2.1" rustc_version = "0.4" +rustls = { version = "0.23", default-features = false, features = [ + "aws_lc_rs", + "std", +] } scc = "2.4" semver = "1.0.22" serde = "1.0.217" diff --git a/magicblock-chainlink/Cargo.toml b/magicblock-chainlink/Cargo.toml index eb7081456..936a4fd9e 100644 --- a/magicblock-chainlink/Cargo.toml +++ b/magicblock-chainlink/Cargo.toml @@ -20,6 +20,7 @@ magicblock-delegation-program-api = { workspace = true } magicblock-magic-program-api = { workspace = true } magicblock-metrics = { workspace = true } parking_lot = { workspace = true } +rustls = { workspace = true } scc = { workspace = true } solana-account = { workspace = true } solana-account-decoder = { workspace = true } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 8be74ee79..287f2fac6 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -630,7 +630,7 @@ where } /// Computes the subscription cancellation strategy based on what accounts were resolved -#[allow(unused_variables)] // Parameters used in cfg(test) block +#[allow(unused_variables, clippy::too_many_arguments)] // Parameters used in cfg(test) block pub(crate) fn compute_cancel_strategy( pubkeys: &[Pubkey], accounts_to_clone: &[AccountCloneRequest], diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs index a4822b4d4..0803ea319 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs @@ -177,8 +177,8 @@ pub(crate) async fn cancel_subs< }; if tracing::enabled!(tracing::Level::TRACE) { let pubkeys_str = subs_to_cancel - .iter() - .map(|(p, _)| p.to_string()) + .keys() + .map(|p| p.to_string()) .collect::>() .join(", "); trace!(pubkeys = %pubkeys_str, "Canceling subscriptions for"); diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 3926e469a..806261d1f 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -87,6 +87,10 @@ use crate::{ const ACTIVE_SUBSCRIPTIONS_UPDATE_INTERVAL_MS: u64 = 60_000; pub(crate) const DEFAULT_SUBSCRIPTION_RETRIES: usize = 5; +fn install_default_rustls_crypto_provider() { + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); +} + // Maps pubkey -> (fetch_start_slot, requests_waiting) type FetchResult = Result; type FetchingAccounts = @@ -291,6 +295,8 @@ impl lrucache_subscribed_accounts: Arc, chain_slot: ChainSlot, ) -> RemoteAccountProviderResult { + install_default_rustls_crypto_provider(); + let (removed_account_tx, removed_account_rx) = tokio::sync::mpsc::channel(100); @@ -352,6 +358,8 @@ impl PhotonClientImpl, >, > { + install_default_rustls_crypto_provider(); + if endpoints.is_empty() { return Err( RemoteAccountProviderError::AccountSubscriptionsTaskFailed( diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 0e4b32cec..911ea7062 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -5076,6 +5076,7 @@ dependencies = [ "magicblock-magic-program-api 0.9.0", "magicblock-metrics", "parking_lot", + "rustls 0.23.35", "scc", "solana-account 3.4.0", "solana-account-decoder", From 75eaec4cf6bb83c25d10e2a0bdcbc91fb2b9eded Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 01:43:31 +0200 Subject: [PATCH 058/110] fix: remove sub when not preexisting --- magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 287f2fac6..c0a849692 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -339,7 +339,9 @@ where companion_account: delegation_record, } in accounts_fully_resolved.into_iter() { - record_subs.push(delegation_record_pubkey); + if !existing_subs.contains(&delegation_record_pubkey) { + record_subs.push(delegation_record_pubkey); + } // If the account is delegated we set the owner and delegation state let (commit_frequency_ms, delegated_to_other, delegation_actions) = From 068a910e9487edac11782b20b1c5b0b4f2ccfbfa Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 09:40:02 +0200 Subject: [PATCH 059/110] docs: explain assertions --- .../test-committor-service/tests/test_ix_commit_local.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index e44f5c8af..e14eced94 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -1302,6 +1302,8 @@ async fn ix_commit_local( &compressed_account.data.unwrap().data, ) .unwrap(); + // Compressed accounts never have lamports when delegated/committed + // and they are not delegated by the validator, just marked as undelegatable assert_eq!(compressed_record.owner, program_id); assert_eq!(compressed_record.data, account.account.data); assert_eq!(compressed_record.lamports, 0); From d04d2002b5bc953030f1f250373a66670691388e Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 12:33:04 +0200 Subject: [PATCH 060/110] fix: updated sdk --- test-integration/Cargo.lock | 2162 ++++++++++++++++++++--------------- test-integration/Cargo.toml | 2 +- 2 files changed, 1259 insertions(+), 905 deletions(-) diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 911ea7062..3e1b4651f 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -39,7 +39,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "generic-array", ] @@ -51,7 +51,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -79,7 +79,7 @@ dependencies = [ "solana-epoch-schedule 2.2.1", "solana-hash 2.3.0", "solana-pubkey 2.4.0", - "solana-sha256-hasher 2.2.1", + "solana-sha256-hasher 2.3.0", "solana-svm-feature-set 2.3.13", ] @@ -196,7 +196,7 @@ dependencies = [ "crossbeam-channel", "log", "lz4", - "rand 0.8.5", + "rand 0.8.6", "regex", "semver", "solana-accounts-db", @@ -268,7 +268,7 @@ dependencies = [ "solana-packet", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-signature 3.4.0", "solana-svm-transaction", "solana-transaction-context 3.1.12", @@ -293,7 +293,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "version_check", ] @@ -361,21 +361,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" -dependencies = [ - "anstyle", - "anstyle-parse 0.2.7", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - [[package]] name = "anstream" version = "1.0.0" @@ -383,7 +368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", - "anstyle-parse 1.0.0", + "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", @@ -393,18 +378,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" - -[[package]] -name = "anstyle-parse" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" -dependencies = [ - "utf8parse", -] +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" @@ -437,9 +413,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "anza-quinn" @@ -452,9 +428,9 @@ dependencies = [ "cfg_aliases", "pin-project-lite", "quinn-udp", - "rustc-hash 2.1.1", - "rustls 0.23.35", - "socket2 0.6.1", + "rustc-hash 2.1.2", + "rustls 0.23.40", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -471,12 +447,12 @@ dependencies = [ "fastbloom", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", - "rustc-hash 2.1.1", - "rustls 0.23.35", + "rustc-hash 2.1.2", + "rustls 0.23.40", "rustls-pki-types", - "rustls-platform-verifier", + "rustls-platform-verifier 0.6.2", "slab", "thiserror 2.0.18", "tinyvec", @@ -500,9 +476,12 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.7.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" +dependencies = [ + "rustversion", +] [[package]] name = "ark-bn254" @@ -732,7 +711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -742,7 +721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ "num-traits", - "rand 0.8.5", + "rand 0.8.6", "rayon", ] @@ -811,22 +790,21 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.4.36" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" dependencies = [ "compression-codecs", "compression-core", - "futures-core", "pin-project-lite", "tokio", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", @@ -940,16 +918,16 @@ dependencies = [ "rustversion", "serde", "sync_wrapper 1.0.2", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", ] [[package]] name = "axum" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core 0.5.6", "bytes", @@ -965,7 +943,7 @@ dependencies = [ "pin-project-lite", "serde_core", "sync_wrapper 1.0.2", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", ] @@ -1074,7 +1052,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "cexpr", "clang-sys", "itertools 0.12.1", @@ -1094,14 +1072,14 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "cexpr", "clang-sys", "itertools 0.13.0", "proc-macro2", "quote", "regex", - "rustc-hash 2.1.1", + "rustc-hash 2.1.2", "shlex", "syn 2.0.117", ] @@ -1114,9 +1092,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] @@ -1144,16 +1122,17 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.2" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "digest 0.10.7", + "cpufeatures 0.3.0", + "digest 0.11.2", ] [[package]] @@ -1174,6 +1153,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "block2" version = "0.6.2" @@ -1223,11 +1211,12 @@ dependencies = [ [[package]] name = "borsh" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ - "borsh-derive 1.6.0", + "borsh-derive 1.6.1", + "bytes", "cfg_aliases", ] @@ -1246,12 +1235,12 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", - "proc-macro-crate 3.4.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.117", @@ -1311,9 +1300,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bv" @@ -1381,9 +1370,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -1419,9 +1408,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.56" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "jobserver", @@ -1469,9 +1458,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -1496,7 +1485,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] @@ -1513,9 +1502,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -1523,11 +1512,11 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "anstream 0.6.21", + "anstream", "anstyle", "clap_lex", "strsim", @@ -1535,9 +1524,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -1547,9 +1536,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cleanass" @@ -1566,6 +1555,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + [[package]] name = "color-backtrace" version = "0.7.2" @@ -1578,9 +1573,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" @@ -1609,7 +1604,7 @@ dependencies = [ name = "compressed-delegation-api" version = "0.9.0" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "light-compressed-account", "light-hasher", "light-sdk", @@ -1620,7 +1615,7 @@ dependencies = [ name = "compressed-delegation-client" version = "0.9.0" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "compressed-delegation-api", "light-compressed-account", "light-hasher", @@ -1631,16 +1626,16 @@ dependencies = [ "solana-account-info 3.1.1", "solana-cpi 3.1.0", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "thiserror 2.0.18", ] [[package]] name = "compression-codecs" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" dependencies = [ "brotli", "compression-core", @@ -1650,9 +1645,9 @@ dependencies = [ [[package]] name = "compression-core" -version = "0.4.31" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" [[package]] name = "concurrent-queue" @@ -1726,9 +1721,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" @@ -1766,19 +1761,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "core2" -version = "0.4.0" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "memchr", + "libc", ] [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -1855,6 +1850,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", +] + [[package]] name = "crypto-mac" version = "0.8.0" @@ -1898,15 +1902,24 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix", + "nix 0.31.2", "windows-sys 0.61.2", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -1927,7 +1940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", @@ -1955,8 +1968,18 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -1973,22 +1996,46 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + [[package]] name = "darling_macro" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core", + "darling_core 0.21.3", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", "quote", "syn 2.0.117", ] [[package]] name = "dary_heap" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06d2e3287df1c007e74221c49ca10a95d557349e54b3a75dc2fb14712c751f04" +checksum = "8b1e3a325bc115f096c8b77bbf027a7c2592230e70be2d985be950d3d5e60ebe" [[package]] name = "dashmap" @@ -2007,9 +2054,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "der" @@ -2037,9 +2084,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -2064,18 +2111,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", @@ -2108,10 +2155,21 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.1", + "ctutils", +] + [[package]] name = "dir-diff" version = "0.3.3" @@ -2123,11 +2181,11 @@ dependencies = [ [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "block2", "libc", "objc2", @@ -2399,9 +2457,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" dependencies = [ "log", "regex", @@ -2413,7 +2471,7 @@ version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ - "anstream 1.0.0", + "anstream", "anstyle", "env_filter", "jiff", @@ -2422,25 +2480,25 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk" -version = "0.11.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=ccfc9f924dc40#ccfc9f924dc403e6ec93780e575fa655af1bebb5" +version = "0.12.0" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" dependencies = [ "base64ct", "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "ephemeral-rollups-sdk-attribute-action", "ephemeral-rollups-sdk-attribute-commit", "ephemeral-rollups-sdk-attribute-delegate", "ephemeral-rollups-sdk-attribute-ephemeral", "ephemeral-rollups-sdk-attribute-ephemeral-accounts", - "getrandom 0.2.16", + "getrandom 0.2.17", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade)", - "magicblock-magic-program-api 0.9.0 (git+https://github.com/magicblock-labs/magicblock-validator.git?branch=bmuddha%2Fepic%2Fmigration-solana-v3)", + "magicblock-magic-program-api 0.9.0 (git+https://github.com/magicblock-labs/magicblock-validator.git?branch=dode%2Fcompression-3x)", "solana-account 3.4.0", "solana-account-info 3.1.1", "solana-cpi 3.1.0", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-memory 3.1.0", "solana-pubkey 3.0.0", "solana-system-interface 3.2.0", @@ -2449,8 +2507,8 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-action" -version = "0.11.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=ccfc9f924dc40#ccfc9f924dc403e6ec93780e575fa655af1bebb5" +version = "0.12.0" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" dependencies = [ "quote", "syn 1.0.109", @@ -2458,8 +2516,8 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-commit" -version = "0.11.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=ccfc9f924dc40#ccfc9f924dc403e6ec93780e575fa655af1bebb5" +version = "0.12.0" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" dependencies = [ "quote", "syn 1.0.109", @@ -2467,8 +2525,8 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-delegate" -version = "0.11.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=ccfc9f924dc40#ccfc9f924dc403e6ec93780e575fa655af1bebb5" +version = "0.12.0" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" dependencies = [ "proc-macro2", "quote", @@ -2477,8 +2535,8 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-ephemeral" -version = "0.11.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=ccfc9f924dc40#ccfc9f924dc403e6ec93780e575fa655af1bebb5" +version = "0.12.0" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" dependencies = [ "proc-macro2", "quote", @@ -2487,8 +2545,8 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-ephemeral-accounts" -version = "0.11.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=ccfc9f924dc40#ccfc9f924dc403e6ec93780e575fa655af1bebb5" +version = "0.12.0" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" dependencies = [ "proc-macro2", "quote", @@ -2546,30 +2604,30 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastbloom" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c1ddb9231d8554c2d6bdf4cfaabf0c59251658c68b6c95cd52dd0c513a912a" +checksum = "4e7f34442dbe69c60fe8eaf58a8cafff81a1f278816d8ab4db255b3bef4ac3c4" dependencies = [ "getrandom 0.3.4", "libm", - "rand 0.9.2", - "siphasher 1.0.1", + "rand 0.9.4", + "siphasher 1.0.2", ] [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "faststr" -version = "0.2.32" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baec6a0289d7f1fe5665586ef7340af82e3037207bef60f5785e57569776f0c8" +checksum = "1ca7d44d22004409a61c393afb3369c8f7bb74abcae49fe249ee01dcc3002113" dependencies = [ "bytes", - "rkyv 0.8.12", + "rkyv 0.8.16", "serde", "simdutf8", ] @@ -2583,10 +2641,10 @@ dependencies = [ "base64 0.21.7", "bytes", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "pin-project", - "rand 0.8.5", + "rand 0.8.6", "sha1", "simdutf8", "thiserror 1.0.69", @@ -2644,14 +2702,13 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.60.2", ] [[package]] @@ -2722,13 +2779,13 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", - "libz-rs-sys", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -2796,9 +2853,12 @@ dependencies = [ [[package]] name = "fragile" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +checksum = "8878864ba14bb86e818a412bfd6f18f9eabd4ec0f008a28e8f7eb61db532fcf9" +dependencies = [ + "futures-core", +] [[package]] name = "fs_extra" @@ -2824,9 +2884,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -2839,9 +2899,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -2849,15 +2909,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -2866,15 +2926,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", @@ -2883,15 +2943,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" @@ -2901,9 +2961,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -2913,7 +2973,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -2951,9 +3010,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -2971,11 +3030,24 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + [[package]] name = "gimli" version = "0.32.3" @@ -3023,7 +3095,7 @@ dependencies = [ "parking_lot", "portable-atomic", "quanta", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "spinning_top", ] @@ -3050,7 +3122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "rand_xorshift", "subtle", @@ -3078,18 +3150,18 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.12.1", + "indexmap 2.14.0", "slab", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -3097,10 +3169,10 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.12.1", + "indexmap 2.14.0", "slab", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -3159,6 +3231,12 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "hashlink" version = "0.10.0" @@ -3195,7 +3273,7 @@ dependencies = [ "laserstream-core-proto", "prost 0.12.6", "prost-types 0.12.6", - "rand 0.8.5", + "rand 0.8.6", "reqwest 0.11.27", "serde", "serde_json", @@ -3342,6 +3420,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hybrid-array" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "0.14.32" @@ -3368,22 +3455,21 @@ dependencies = [ [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "httparse", "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -3405,18 +3491,18 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.8" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2b52f86d1d4bc0d6b4e6826d960b1b333217e07d36b882dca570a5e1c48895b" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http 1.4.0", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", - "rustls 0.23.35", + "rustls 0.23.40", "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.4", + "webpki-roots 1.0.7", ] [[package]] @@ -3425,7 +3511,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "pin-project-lite", "tokio", @@ -3453,7 +3539,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "native-tls", "tokio", @@ -3463,24 +3549,23 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http 1.4.0", "http-body 1.0.1", - "hyper 1.8.1", + "hyper 1.9.0", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", - "system-configuration", + "socket2 0.6.3", + "system-configuration 0.7.0", "tokio", "tower-service", "tracing", @@ -3489,9 +3574,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3513,12 +3598,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -3526,9 +3612,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -3539,9 +3625,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -3553,15 +3639,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -3573,15 +3659,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -3592,6 +3678,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -3611,9 +3703,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -3667,12 +3759,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -3723,11 +3815,11 @@ name = "integration-test-tools" version = "0.0.0" dependencies = [ "anyhow", - "borsh 1.6.0", + "borsh 1.6.1", "color-backtrace", "magicblock-config", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", - "rand 0.8.5", + "rand 0.8.6", "rayon", "serde", "shlex", @@ -3747,20 +3839,20 @@ dependencies = [ [[package]] name = "io-uring" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd7bddefd0a8833b88a4b68f90dae22c7450d11b354198baee3874fd811b344" +checksum = "4d09b98f7eace8982db770e4408e7470b028ce513ac28fecdc6bf4c30fe92b62" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "cfg-if", "libc", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" @@ -3815,17 +3907,26 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" +checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d" dependencies = [ "jiff-static", "log", @@ -3836,9 +3937,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" +checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7" dependencies = [ "proc-macro2", "quote", @@ -3854,18 +3955,70 @@ dependencies = [ "cesu8", "cfg-if", "combine 4.6.7", - "jni-sys", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine 4.6.7", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", +] + [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] [[package]] name = "jobserver" @@ -3879,9 +4032,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" dependencies = [ "cfg-if", "futures-util", @@ -3920,11 +4073,11 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -3967,7 +4120,7 @@ dependencies = [ "solana-signature 3.4.0", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status", "tonic 0.14.5", "tonic-build 0.14.5", @@ -3987,33 +4140,39 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.178" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libflate" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3248b8d211bd23a104a42d81b4fa8bb8ac4a3b75e7a43d85d2c9ccb6179cd74" +checksum = "cd96e993e5f3368b0cb8497dae6c860c22af8ff18388c61c6c0b86c58d86b5df" dependencies = [ "adler32", - "core2", "crc32fast", "dary_heap", "libflate_lz77", + "no_std_io2", ] [[package]] name = "libflate_lz77" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a599cb10a9cd92b1300debcef28da8f70b935ec937f44fcd1b70a7c986a11c5c" +checksum = "ff7a10e427698aef6eef269482776debfef63384d30f13aad39a1a95e0e098fd" dependencies = [ - "core2", "hashbrown 0.16.1", + "no_std_io2", "rle-decode-fast", ] @@ -4029,19 +4188,20 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.11" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "libc", - "redox_syscall 0.6.0", + "plain", + "redox_syscall 0.7.4", ] [[package]] @@ -4123,9 +4283,9 @@ dependencies = [ [[package]] name = "libsodium-sys-stable" -version = "1.23.2" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5d23f4a051a13cf1085b2c5a050d4d890d80c754534cc4247eff525fa5283d" +checksum = "72b04bf6da2c98b727af37ab62cb505f4d751b975b034a9b9ad491d333b0564e" dependencies = [ "cc", "libc", @@ -4133,7 +4293,7 @@ dependencies = [ "minisign-verify", "pkg-config", "tar", - "ureq 3.2.0", + "ureq 3.3.0", "vcpkg", "zip", ] @@ -4149,20 +4309,11 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "libz-rs-sys" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415" -dependencies = [ - "zlib-rs", -] - [[package]] name = "libz-sys" -version = "1.1.23" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" dependencies = [ "cc", "pkg-config", @@ -4291,7 +4442,7 @@ dependencies = [ "light-token-interface", "num-bigint 0.4.6", "photon-api", - "rand 0.8.5", + "rand 0.8.6", "reqwest 0.12.28", "serde_json", "smallvec", @@ -4623,7 +4774,7 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2160586e2b381827d1ca921b5b9e3383e65c013e2c32e8c14a09d913ca7e1312" dependencies = [ - "darling", + "darling 0.21.3", "light-hasher", "light-sdk-types", "proc-macro2", @@ -4710,7 +4861,7 @@ dependencies = [ "light-macros", "light-program-profiler", "light-zero-copy", - "pinocchio 0.9.2", + "pinocchio 0.9.3", "pinocchio-pubkey", "solana-account-info 2.3.0", "solana-msg 2.2.1", @@ -4775,15 +4926,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lmdb-rkv" @@ -4834,9 +4985,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.16.2" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" dependencies = [ "hashbrown 0.16.1", ] @@ -4871,7 +5022,7 @@ name = "magic-domain-program" version = "0.3.0" source = "git+https://github.com/magicblock-labs/magic-domain-program.git?rev=335a22#335a22ba5aa7b8c4bc84d5053444c74c3b05cdac" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck_derive", "solana-program 3.0.0", "solana-system-interface 3.2.0", @@ -4883,7 +5034,7 @@ version = "0.9.0" dependencies = [ "async-trait", "bincode", - "lru 0.16.2", + "lru 0.16.4", "magicblock-accounts-db", "magicblock-chainlink", "magicblock-committor-service", @@ -4893,7 +5044,7 @@ dependencies = [ "magicblock-magic-program-api 0.9.0", "magicblock-program", "magicblock-rpc-client", - "rand 0.9.2", + "rand 0.9.4", "solana-account 3.4.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", @@ -4925,10 +5076,10 @@ dependencies = [ "solana-hash 3.1.0", "solana-pubkey 3.0.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", "url", ] @@ -4939,7 +5090,7 @@ version = "0.9.0" dependencies = [ "lmdb-rkv", "magicblock-config", - "memmap2 0.9.9", + "memmap2 0.9.10", "parking_lot", "reflink-copy", "solana-account 3.4.0", @@ -4962,7 +5113,7 @@ dependencies = [ "fastwebsockets", "futures", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "libloading", "magicblock-account-cloner", @@ -4986,12 +5137,12 @@ dependencies = [ "solana-signature 3.4.0", "solana-system-transaction", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status", "sonic-rs", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5001,7 +5152,7 @@ version = "0.9.0" dependencies = [ "agave-feature-set 3.1.12", "anyhow", - "borsh 1.6.0", + "borsh 1.6.1", "fd-lock", "light-client", "magic-domain-program", @@ -5047,11 +5198,11 @@ dependencies = [ "solana-system-program", "solana-sysvar 3.1.1", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "spl-token-interface", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5063,12 +5214,12 @@ dependencies = [ "arc-swap", "async-trait", "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "compressed-delegation-client", "futures-util", "helius-laserstream", "light-client", - "lru 0.16.2", + "lru 0.16.4", "magicblock-accounts-db", "magicblock-config", "magicblock-core", @@ -5076,7 +5227,7 @@ dependencies = [ "magicblock-magic-program-api 0.9.0", "magicblock-metrics", "parking_lot", - "rustls 0.23.35", + "rustls 0.23.40", "scc", "solana-account 3.4.0", "solana-account-decoder", @@ -5101,13 +5252,13 @@ dependencies = [ "solana-signer 3.0.0", "solana-system-interface 3.2.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "spl-token-2022-interface 2.1.0", "spl-token-interface", "thiserror 2.0.18", "tokio", "tokio-stream", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tonic 0.14.5", "tracing", "url", @@ -5117,7 +5268,7 @@ dependencies = [ name = "magicblock-committor-program" version = "0.9.0" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "paste", "solana-account 3.4.0", "solana-account-info 3.1.1", @@ -5135,13 +5286,13 @@ dependencies = [ "async-trait", "base64 0.21.7", "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "compressed-delegation-api", "compressed-delegation-client", "futures-util", "light-client", "light-sdk", - "lru 0.16.2", + "lru 0.16.4", "magicblock-committor-program", "magicblock-core", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", @@ -5167,12 +5318,12 @@ dependencies = [ "solana-signer 3.0.0", "solana-system-program", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "static_assertions", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5217,7 +5368,7 @@ dependencies = [ "solana-signature 3.4.0", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "spl-token-2022-interface 2.1.0", "spl-token-interface", @@ -5234,7 +5385,7 @@ version = "0.3.0" source = "git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" dependencies = [ "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "const-crypto", "num_enum", @@ -5242,7 +5393,7 @@ dependencies = [ "pinocchio-log", "pinocchio-pubkey", "pinocchio-system", - "rkyv 0.7.45", + "rkyv 0.7.46", "serde", "solana-address 2.6.0", "solana-instruction 3.4.0", @@ -5252,7 +5403,7 @@ dependencies = [ "solana-sha256-hasher 3.1.0", "solana-system-interface 2.0.0", "static_assertions", - "strum 0.27.2", + "strum 0.28.0", "thiserror 2.0.18", ] @@ -5262,7 +5413,7 @@ version = "0.3.0" source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" dependencies = [ "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "const-crypto", "libsodium-rs", @@ -5271,7 +5422,7 @@ dependencies = [ "pinocchio-log", "pinocchio-pubkey", "pinocchio-system", - "rkyv 0.7.45", + "rkyv 0.7.46", "serde", "solana-address 2.6.0", "solana-instruction 3.4.0", @@ -5282,7 +5433,7 @@ dependencies = [ "solana-sha256-hasher 3.1.0", "solana-system-interface 2.0.0", "static_assertions", - "strum 0.27.2", + "strum 0.28.0", "thiserror 2.0.18", ] @@ -5316,11 +5467,11 @@ dependencies = [ "solana-svm-measure", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5338,9 +5489,10 @@ dependencies = [ [[package]] name = "magicblock-magic-program-api" version = "0.9.0" -source = "git+https://github.com/magicblock-labs/magicblock-validator.git?branch=bmuddha%2Fepic%2Fmigration-solana-v3#ef8ebb18879f0a3c41c11159eb5a5358dd3c89c0" +source = "git+https://github.com/magicblock-labs/magicblock-validator.git?branch=dode%2Fcompression-3x#068a910e9487edac11782b20b1c5b0b4f2ccfbfa" dependencies = [ "bincode", + "const-crypto", "serde", "solana-program 3.0.0", "solana-signature 3.4.0", @@ -5351,13 +5503,13 @@ name = "magicblock-metrics" version = "0.9.0" dependencies = [ "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "lazy_static", "prometheus", "solana-signature 3.4.0", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5375,7 +5527,7 @@ dependencies = [ "magicblock-metrics", "magicblock-program", "parking_lot", - "rustc-hash 2.1.1", + "rustc-hash 2.1.2", "serde", "solana-account 3.4.0", "solana-bpf-loader-program", @@ -5397,11 +5549,11 @@ dependencies = [ "solana-system-program", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status", "solana-zk-elgamal-proof-program", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5454,7 +5606,7 @@ dependencies = [ "solana-rpc-client 3.1.12", "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "thiserror 2.0.18", "tokio", @@ -5489,7 +5641,7 @@ dependencies = [ "ed25519-dalek 1.0.1", "magicblock-metrics", "magicblock-rpc-client", - "rand 0.9.2", + "rand 0.9.4", "sha3", "solana-address-lookup-table-interface 3.1.0", "solana-clock 3.0.1", @@ -5527,10 +5679,10 @@ dependencies = [ "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5547,7 +5699,7 @@ dependencies = [ "solana-signer 3.0.0", "solana-transaction 3.1.0", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", ] @@ -5588,9 +5740,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" @@ -5603,9 +5755,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", ] @@ -5645,9 +5797,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "minisign-verify" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e856fdd13623a2f5f2f54676a4ee49502a96a80ef4a62bcedd23d52427c44d43" +checksum = "22f9645cb765ea72b8111f36c522475d2daa0d22c957a9826437e97534bc4e9e" [[package]] name = "miniz_oxide" @@ -5661,9 +5813,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi 0.11.1+wasi-snapshot-preview1", @@ -5720,9 +5872,9 @@ dependencies = [ [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "munge" @@ -5750,14 +5902,14 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", @@ -5765,7 +5917,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -5776,19 +5928,40 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", "memoffset", ] +[[package]] +name = "nix" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "no-std-compat" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" +[[package]] +name = "no_std_io2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" +dependencies = [ + "memchr", +] + [[package]] name = "nom" version = "7.1.3" @@ -5868,9 +6041,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-derive" @@ -5946,9 +6119,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -5956,11 +6129,11 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.4.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5974,9 +6147,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -6007,9 +6180,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -6025,11 +6198,11 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "cfg-if", "foreign-types", "libc", @@ -6051,9 +6224,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" @@ -6066,9 +6239,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -6092,7 +6265,7 @@ dependencies = [ "lazy_static", "percent-encoding", "pin-project", - "rand 0.8.5", + "rand 0.8.6", "thiserror 1.0.69", ] @@ -6142,9 +6315,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" +checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" [[package]] name = "pbkdf2" @@ -6209,7 +6382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.12.1", + "indexmap 2.14.0", ] [[package]] @@ -6220,7 +6393,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset 0.5.7", "hashbrown 0.15.2", - "indexmap 2.12.1", + "indexmap 2.14.0", ] [[package]] @@ -6230,25 +6403,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95609d4f08f2cf86d6e41f5b483cfbbfd914099eb0f7c6ea15e98b358f4614f8" dependencies = [ "progenitor-client", - "reqwest 0.13.2", + "reqwest 0.13.3", "serde", "serde_json", ] [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", @@ -6257,21 +6430,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pinocchio" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b971851087bc3699b001954ad02389d50c41405ece3548cbcafc88b3e20017a" +checksum = "b8afe4f39c0e25cc471b35b89963312791a5162d45a86578cbeaad9e5e7d1b3b" [[package]] name = "pinocchio" @@ -6283,7 +6450,7 @@ dependencies = [ "solana-address 2.6.0", "solana-define-syscall 4.0.1", "solana-instruction-view", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", ] [[package]] @@ -6313,7 +6480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0225638cadcbebae8932cb7f49cb5da7c15c21beb19f048f05a5ca7d93f065" dependencies = [ "five8_const 0.1.4", - "pinocchio 0.9.2", + "pinocchio 0.9.3", "sha2-const-stable", ] @@ -6339,9 +6506,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "polyval" @@ -6350,7 +6523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] @@ -6363,18 +6536,18 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -6410,15 +6583,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", @@ -6426,9 +6599,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.36" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn 2.0.117", @@ -6445,11 +6618,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.9", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -6504,7 +6677,7 @@ dependencies = [ "bytes", "futures-core", "percent-encoding", - "reqwest 0.13.2", + "reqwest 0.13.3", "serde", "serde_json", "serde_urlencoded", @@ -6515,7 +6688,7 @@ name = "program-flexi-counter" version = "0.0.0" dependencies = [ "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "compressed-delegation-api", "compressed-delegation-client", "ephemeral-rollups-sdk", @@ -6544,11 +6717,11 @@ dependencies = [ name = "program-schedulecommit" version = "0.0.0" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "ephemeral-rollups-sdk", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "magicblock-magic-program-api 0.9.0", - "rkyv 0.7.45", + "rkyv 0.7.46", "solana-program 3.0.0", "solana-system-interface 3.2.0", "static_assertions", @@ -6558,7 +6731,7 @@ dependencies = [ name = "program-schedulecommit-security" version = "0.0.0" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "ephemeral-rollups-sdk", "program-schedulecommit", "solana-program 3.0.0", @@ -6636,7 +6809,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ "heck 0.5.0", - "itertools 0.13.0", + "itertools 0.14.0", "log", "multimap", "petgraph 0.8.3", @@ -6670,7 +6843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -6755,7 +6928,7 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "memchr", "unicase", ] @@ -6815,9 +6988,9 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", - "rustls 0.23.35", - "socket2 0.6.1", + "rustc-hash 2.1.2", + "rustls 0.23.40", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -6826,18 +6999,18 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", - "rustc-hash 2.1.1", - "rustls 0.23.35", + "rustc-hash 2.1.2", + "rustls 0.23.40", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -6855,7 +7028,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] @@ -6875,6 +7048,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -6905,9 +7084,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -6916,12 +7095,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -6951,7 +7130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -6969,14 +7148,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] @@ -7014,14 +7193,14 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", ] [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -7043,16 +7222,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", ] [[package]] name = "redox_syscall" -version = "0.6.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96166dafa0886eb81fe1c0a388bece180fbef2135f97c1e2cf8302e74b43b5" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", ] [[package]] @@ -7077,9 +7256,9 @@ dependencies = [ [[package]] name = "reflink-copy" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbed272e39c47a095a5242218a67412a220006842558b03fe2935e8f3d7b92" +checksum = "13362233b147e57674c37b802d216b7c5e3dcccbed8967c84f0d8d223868ae27" dependencies = [ "cfg-if", "libc", @@ -7089,9 +7268,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -7101,9 +7280,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -7112,9 +7291,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rend" @@ -7163,11 +7342,11 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio", "tokio-native-tls", "tokio-rustls 0.24.1", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tower-service", "url", "wasm-bindgen", @@ -7189,12 +7368,12 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", - "hyper-rustls 0.27.8", + "hyper 1.9.0", + "hyper-rustls 0.27.9", "hyper-tls 0.6.0", "hyper-util", "js-sys", @@ -7204,7 +7383,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.35", + "rustls 0.23.40", "rustls-pki-types", "serde", "serde_json", @@ -7213,21 +7392,21 @@ dependencies = [ "tokio", "tokio-native-tls", "tokio-rustls 0.26.4", - "tower 0.5.2", + "tower 0.5.3", "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 1.0.4", + "webpki-roots 1.0.7", ] [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -7236,25 +7415,25 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", - "hyper-rustls 0.27.8", + "hyper 1.9.0", + "hyper-rustls 0.27.9", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.35", + "rustls 0.23.40", "rustls-pki-types", - "rustls-platform-verifier", + "rustls-platform-verifier 0.7.0", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.2", "tokio", "tokio-rustls 0.26.4", - "tokio-util 0.7.17", - "tower 0.5.2", + "tokio-util 0.7.18", + "tower 0.5.3", "tower-http", "tower-service", "url", @@ -7297,7 +7476,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -7305,9 +7484,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" dependencies = [ "bitvec", "bytecheck", @@ -7315,7 +7494,7 @@ dependencies = [ "hashbrown 0.12.3", "ptr_meta 0.1.4", "rend 0.4.2", - "rkyv_derive 0.7.45", + "rkyv_derive 0.7.46", "seahash", "tinyvec", "uuid", @@ -7323,27 +7502,27 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.12" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a640b26f007713818e9a9b65d34da1cf58538207b052916a83d80e43f3ffa4" +checksum = "73389e0c99e664f919275ab5b5b0471391fe9a8de61e1dff9b1eaf56a90f16e3" dependencies = [ "bytes", - "hashbrown 0.15.2", - "indexmap 2.12.1", + "hashbrown 0.17.0", + "indexmap 2.14.0", "munge", "ptr_meta 0.3.1", "rancor", "rend 0.5.3", - "rkyv_derive 0.8.12", + "rkyv_derive 0.8.16", "tinyvec", "uuid", ] [[package]] name = "rkyv_derive" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" dependencies = [ "proc-macro2", "quote", @@ -7352,9 +7531,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.12" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd83f5f173ff41e00337d97f6572e416d022ef8a19f371817259ae960324c482" +checksum = "5d2ed0b54125315fb36bd021e82d314d1c126548f871634b483f46b31d13cac6" dependencies = [ "proc-macro2", "quote", @@ -7382,7 +7561,7 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -7392,9 +7571,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -7404,9 +7583,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -7428,11 +7607,11 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys", @@ -7453,30 +7632,30 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.8", + "rustls-webpki 0.103.13", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework", ] [[package]] @@ -7499,9 +7678,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.2" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -7515,14 +7694,35 @@ checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", - "jni", + "jni 0.21.1", + "log", + "once_cell", + "rustls 0.23.40", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.13", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni 0.22.4", "log", "once_cell", - "rustls 0.23.35", + "rustls 0.23.40", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.8", - "security-framework 3.5.1", + "rustls-webpki 0.103.13", + "security-framework", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -7546,9 +7746,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -7564,9 +7764,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -7588,9 +7788,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -7600,7 +7800,7 @@ name = "schedulecommit-client" version = "0.0.0" dependencies = [ "anyhow", - "borsh 1.6.0", + "borsh 1.6.1", "integration-test-tools", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "program-schedulecommit", @@ -7619,7 +7819,7 @@ name = "schedulecommit-committor-service" version = "0.0.0" dependencies = [ "async-trait", - "borsh 1.6.0", + "borsh 1.6.1", "compressed-delegation-client", "futures", "light-client", @@ -7635,7 +7835,7 @@ dependencies = [ "magicblock-table-mania", "program-flexi-counter", "program-schedulecommit", - "rand 0.8.5", + "rand 0.8.6", "solana-account 3.4.0", "solana-commitment-config 3.1.1", "solana-compute-budget-interface 3.0.0", @@ -7654,7 +7854,7 @@ dependencies = [ name = "schedulecommit-test-scenarios" version = "0.0.0" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", @@ -7662,7 +7862,7 @@ dependencies = [ "magicblock-magic-program-api 0.9.0", "magicblock-program", "program-schedulecommit", - "rand 0.8.5", + "rand 0.8.6", "schedulecommit-client", "serial_test", "solana-commitment-config 3.1.1", @@ -7703,9 +7903,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -7757,24 +7957,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.5.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -7783,9 +7970,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -7793,9 +7980,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "seqlock" @@ -7891,17 +8078,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.1", + "indexmap 2.14.0", "schemars 0.9.0", - "schemars 1.1.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -7910,11 +8097,11 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", "syn 2.0.117", @@ -7922,12 +8109,13 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" dependencies = [ "fslock", - "futures", + "futures-executor", + "futures-util", "log", "once_cell", "parking_lot", @@ -7937,9 +8125,9 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" dependencies = [ "proc-macro2", "quote", @@ -7953,7 +8141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -7965,7 +8153,7 @@ checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -7977,7 +8165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -7989,9 +8177,9 @@ checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" [[package]] name = "sha3" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ "digest 0.10.7", "keccak", @@ -8024,10 +8212,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -8049,9 +8238,19 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] [[package]] name = "simdutf8" @@ -8067,9 +8266,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "sized-chunks" @@ -8083,9 +8282,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -8105,12 +8304,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -8134,7 +8333,7 @@ dependencies = [ [[package]] name = "solana-account" version = "3.4.0" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#bb638243c884b9ec86cc71a2edcb8676ef974dba" dependencies = [ "bincode", "qualifier_attr", @@ -8170,7 +8369,7 @@ dependencies = [ "solana-fee-calculator 3.2.0", "solana-instruction 3.4.0", "solana-loader-v3-interface 6.1.1", - "solana-nonce 3.1.0", + "solana-nonce 3.2.0", "solana-program-option 3.1.0", "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", @@ -8243,7 +8442,7 @@ dependencies = [ "bincode", "serde_core", "solana-address 2.6.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-memory 3.1.0", ] @@ -8254,7 +8453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37ca34c37f92ee341b73d5ce7c8ef5bb38e9a87955b4bd343c63fa18b149215" dependencies = [ "solana-address 2.6.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", ] [[package]] @@ -8272,15 +8471,15 @@ dependencies = [ "bytemuck_derive", "crossbeam-channel", "dashmap", - "indexmap 2.12.1", + "indexmap 2.14.0", "itertools 0.12.1", "log", "lz4", - "memmap2 0.9.9", + "memmap2 0.9.10", "modular-bitfield", "num_cpus", "num_enum", - "rand 0.8.5", + "rand 0.8.6", "rayon", "seqlock", "serde", @@ -8309,7 +8508,7 @@ dependencies = [ "solana-time-utils 3.0.0", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "spl-generic-token 2.0.1", "static_assertions", "tempfile", @@ -8331,23 +8530,23 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1384b52c435a750cc9c538760fc7bb472fd78e65a9900a2d07312c5bb335b72" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", "five8 1.0.0", "five8_const 1.0.0", - "rand 0.9.2", + "rand 0.9.4", "serde", "serde_derive", "sha2-const-stable", "solana-atomic-u64 3.0.1", - "solana-define-syscall 5.0.0", + "solana-define-syscall 5.1.0", "solana-nullable", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-sanitize 3.0.1", "solana-sha256-hasher 3.1.0", - "wincode 0.5.1", + "wincode", ] [[package]] @@ -8409,7 +8608,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16034da9477c2ceb6bf03a04389d68f463fb9e09a7641b4517af4177976c5f59" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "futures", "solana-account 3.4.0", "solana-banks-interface", @@ -8424,7 +8623,7 @@ dependencies = [ "solana-sysvar 3.1.1", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "tarpc", "thiserror 2.0.18", "tokio", @@ -8447,7 +8646,7 @@ dependencies = [ "solana-signature 3.4.0", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "tarpc", ] @@ -8475,7 +8674,7 @@ dependencies = [ "solana-signature 3.4.0", "solana-svm", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "tarpc", "tokio", "tokio-serde", @@ -8545,7 +8744,7 @@ checksum = "7116e1d942a2432ca3f514625104757ab8a56233787e95144c93950029e31176" dependencies = [ "blake3", "solana-define-syscall 4.0.1", - "solana-hash 4.2.0", + "solana-hash 4.3.0", ] [[package]] @@ -8562,7 +8761,7 @@ dependencies = [ "ff", "group", "pairing", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "serde_with", @@ -8598,7 +8797,7 @@ dependencies = [ "ark-ff 0.5.0", "ark-serialize 0.5.0", "bytemuck", - "solana-define-syscall 5.0.0", + "solana-define-syscall 5.1.0", "thiserror 2.0.18", ] @@ -8609,7 +8808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "718333bcd0a1a7aed6655aa66bef8d7fb047944922b2d3a18f49cbc13e73d004" dependencies = [ "borsh 0.10.4", - "borsh 1.6.0", + "borsh 1.6.1", ] [[package]] @@ -8618,7 +8817,7 @@ version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c04abbae16f57178a163125805637b8a076175bb5c0002fb04f4792bea901cf7" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", ] [[package]] @@ -8659,10 +8858,10 @@ dependencies = [ "bv", "bytemuck", "bytemuck_derive", - "memmap2 0.9.9", + "memmap2 0.9.10", "modular-bitfield", "num_enum", - "rand 0.8.5", + "rand 0.8.6", "solana-clock 3.0.1", "solana-measure", "solana-pubkey 3.0.0", @@ -8719,7 +8918,7 @@ dependencies = [ "dashmap", "futures", "futures-util", - "indexmap 2.12.1", + "indexmap 2.14.0", "indicatif 0.18.4", "log", "rayon", @@ -8747,12 +8946,12 @@ dependencies = [ "solana-time-utils 3.0.0", "solana-tpu-client", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "solana-udp-client", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", ] [[package]] @@ -8773,7 +8972,7 @@ dependencies = [ "solana-signer 3.0.0", "solana-system-interface 2.0.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", ] [[package]] @@ -8819,7 +9018,7 @@ checksum = "3a494cf8eda7d98d9f0144b288bb409c88308d2e86f15cc1045aa77b83304718" dependencies = [ "serde", "serde_derive", - "solana-hash 4.2.0", + "solana-hash 4.3.0", ] [[package]] @@ -8869,7 +9068,7 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", "solana-svm-transaction", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] @@ -8889,7 +9088,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8292c436b269ad23cecc8b24f7da3ab07ca111661e25e00ce0e1d22771951ab9" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "solana-instruction 3.4.0", "solana-sdk-ids 3.1.0", ] @@ -8916,7 +9115,7 @@ dependencies = [ "solana-instruction 3.4.0", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-system-interface 2.0.0", ] @@ -8930,15 +9129,15 @@ dependencies = [ "bincode", "crossbeam-channel", "futures-util", - "indexmap 2.12.1", + "indexmap 2.14.0", "log", - "rand 0.8.5", + "rand 0.8.6", "rayon", "solana-keypair 3.1.2", "solana-measure", "solana-metrics 3.1.12", "solana-time-utils 3.0.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", ] @@ -8967,7 +9166,7 @@ dependencies = [ "solana-sdk-ids 3.1.0", "solana-svm-transaction", "solana-system-interface 2.0.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-vote-program", ] @@ -8994,7 +9193,7 @@ dependencies = [ "solana-account-info 3.1.1", "solana-define-syscall 4.0.1", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 4.2.0", "solana-stable-layout 3.0.1", ] @@ -9056,9 +9255,9 @@ checksum = "57e5b1c0bc1d4a4d10c88a4100499d954c09d3fecfae4912c1a074dff68b1738" [[package]] name = "solana-define-syscall" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03aacdd7a61e2109887a7a7f046caebafce97ddf1150f33722eeac04f9039c73" +checksum = "21e14a4f604117f379840956a8fc8695e4c84f5b0ebed192f31f60d9b85d581d" [[package]] name = "solana-derivation-path" @@ -9136,7 +9335,7 @@ checksum = "f5e7b0ba210593ba8ddd39d6d234d81795d1671cebf3026baa10d5dc23ac42f0" dependencies = [ "serde", "serde_derive", - "solana-hash 4.2.0", + "solana-hash 4.3.0", "solana-sdk-ids 3.1.0", "solana-sdk-macro 3.0.1", "solana-sysvar-id 3.1.0", @@ -9150,7 +9349,7 @@ checksum = "1ee8beac9bff4db9225e57d532d169b0be5e447f1e6601a2f50f27a01bf5518f" dependencies = [ "siphasher 0.3.11", "solana-address 2.6.0", - "solana-hash 4.2.0", + "solana-hash 4.3.0", ] [[package]] @@ -9185,7 +9384,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "027e6d0b9e7daac5b2ac7c3f9ca1b727861121d9ef05084cf435ff736051e7c2" dependencies = [ - "solana-define-syscall 5.0.0", + "solana-define-syscall 5.1.0", "solana-pubkey 4.2.0", ] @@ -9224,7 +9423,7 @@ dependencies = [ "solana-instruction 3.4.0", "solana-keccak-hasher 3.1.0", "solana-message 3.1.0", - "solana-nonce 3.1.0", + "solana-nonce 3.2.0", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", "solana-system-interface 2.0.0", @@ -9262,7 +9461,7 @@ dependencies = [ "solana-account 3.4.0", "solana-account-info 3.1.1", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 4.2.0", "solana-rent 4.2.0", "solana-sdk-ids 3.1.0", @@ -9368,7 +9567,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "five8 0.2.1", @@ -9386,16 +9585,16 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "337c246447142f660f778cf6cb582beba8e28deb05b3b24bfb9ffd7c562e5f41" dependencies = [ - "solana-hash 4.2.0", + "solana-hash 4.3.0", ] [[package]] name = "solana-hash" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8064ea1d591ec791be95245058ca40f4f5345d390c200069d0f79bbf55bfae55" +checksum = "f1b113239362cee7093bfb250467138f079a2a03673181dc15bff6ccd677912d" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "five8 1.0.0", @@ -9403,7 +9602,7 @@ dependencies = [ "serde_derive", "solana-atomic-u64 3.0.1", "solana-sanitize 3.0.1", - "wincode 0.4.4", + "wincode", ] [[package]] @@ -9429,8 +9628,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bab5682934bd1f65f8d2c16f21cb532526fcc1a09f796e2cacdb091eee5774ad" dependencies = [ "bincode", - "borsh 1.6.0", - "getrandom 0.2.16", + "borsh 1.6.1", + "getrandom 0.2.17", "js-sys", "num-traits", "serde", @@ -9448,10 +9647,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ebb0ffd19263051bc3f683fcc086134b8ff23af894dcb63f7563c7137b42f1" dependencies = [ "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "serde", "serde_derive", - "solana-define-syscall 5.0.0", + "solana-define-syscall 5.1.0", "solana-instruction-error", "solana-pubkey 4.2.0", ] @@ -9465,7 +9664,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", ] [[package]] @@ -9477,7 +9676,7 @@ dependencies = [ "solana-account-view", "solana-address 2.6.0", "solana-define-syscall 4.0.1", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", ] [[package]] @@ -9486,7 +9685,7 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0e85a6fad5c2d0c4f5b91d34b8ca47118fc593af706e523cdbedf846a954f57" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "solana-account-info 2.3.0", "solana-instruction 2.3.3", "solana-program-error 2.2.2", @@ -9503,11 +9702,11 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf67876c541aa1e21ee1acae35c95c6fbc61119814bfef70579317a5e26955" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "solana-account-info 3.1.1", "solana-instruction 3.4.0", "solana-instruction-error", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", "solana-sdk-ids 3.1.0", @@ -9535,7 +9734,7 @@ checksum = "ed1c0d16d6fdeba12291a1f068cdf0d479d9bff1141bf44afd7aa9d485f65ef8" dependencies = [ "sha3", "solana-define-syscall 4.0.1", - "solana-hash 4.2.0", + "solana-hash 4.3.0", ] [[package]] @@ -9564,7 +9763,7 @@ dependencies = [ "ed25519-dalek-bip32", "five8 1.0.0", "five8_core 1.0.0", - "rand 0.9.2", + "rand 0.9.4", "solana-address 2.6.0", "solana-derivation-path 3.0.0", "solana-seed-derivable 3.0.0", @@ -9764,12 +9963,12 @@ dependencies = [ "serde", "serde_derive", "solana-address 2.6.0", - "solana-hash 4.2.0", + "solana-hash 4.3.0", "solana-instruction 3.4.0", "solana-sanitize 3.0.1", "solana-sdk-ids 3.1.0", - "solana-short-vec 3.2.0", - "solana-transaction-error 3.1.0", + "solana-short-vec 3.2.1", + "solana-transaction-error 3.2.0", ] [[package]] @@ -9783,7 +9982,7 @@ dependencies = [ "log", "reqwest 0.12.28", "solana-cluster-type 2.2.1", - "solana-sha256-hasher 2.2.1", + "solana-sha256-hasher 2.3.0", "solana-time-utils 2.2.1", "thiserror 2.0.18", ] @@ -9819,7 +10018,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726b7cbbc6be6f1c6f29146ac824343b9415133eee8cce156452ad1db93f8008" dependencies = [ - "solana-define-syscall 5.0.0", + "solana-define-syscall 5.1.0", ] [[package]] @@ -9847,10 +10046,10 @@ dependencies = [ "dashmap", "itertools 0.12.1", "log", - "nix", - "rand 0.8.5", + "nix 0.30.1", + "rand 0.8.6", "serde", - "socket2 0.6.1", + "socket2 0.6.3", "solana-serde", "solana-svm-type-overrides", "tokio", @@ -9874,19 +10073,19 @@ dependencies = [ "solana-fee-calculator 2.2.1", "solana-hash 2.3.0", "solana-pubkey 2.4.0", - "solana-sha256-hasher 2.2.1", + "solana-sha256-hasher 2.3.0", ] [[package]] name = "solana-nonce" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc469152a63284ef959b80c59cda015262a021da55d3b8fe42171d89c4b64f8" +checksum = "d95dbc9f2e33b6c10e231df15cb2a3bff9ea7eab6347f9e316fe75c97fd67bbb" dependencies = [ "serde", "serde_derive", "solana-fee-calculator 3.2.0", - "solana-hash 4.2.0", + "solana-hash 4.3.0", "solana-pubkey 4.2.0", "solana-sha256-hasher 3.1.0", ] @@ -9899,7 +10098,7 @@ checksum = "805fd25b29e5a1a0e6c3dd6320c9da80f275fbe4ff6e392617c303a2085c435e" dependencies = [ "solana-account 3.4.0", "solana-hash 3.1.0", - "solana-nonce 3.1.0", + "solana-nonce 3.2.0", "solana-sdk-ids 3.1.0", ] @@ -9944,7 +10143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6edf2f25743c95229ac0fdc32f8f5893ef738dbf332c669e9861d33ddb0f469d" dependencies = [ "bincode", - "bitflags 2.10.0", + "bitflags 2.11.1", "cfg_eval", "serde", "serde_derive", @@ -9967,8 +10166,8 @@ dependencies = [ "fnv", "libc", "log", - "nix", - "rand 0.8.5", + "nix 0.30.1", + "rand 0.8.6", "rayon", "serde", "solana-hash 3.1.0", @@ -9978,7 +10177,7 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-rayon-threadlimit", "solana-sdk-ids 3.1.0", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-signature 3.4.0", "solana-time-utils 3.0.0", "solana-transaction-context 3.1.12", @@ -10037,19 +10236,19 @@ dependencies = [ "bincode", "blake3", "borsh 0.10.4", - "borsh 1.6.0", + "borsh 1.6.1", "bs58", "bytemuck", "console_error_panic_hook", "console_log", - "getrandom 0.2.16", + "getrandom 0.2.17", "lazy_static", "log", "memoffset", "num-bigint 0.4.6", "num-derive", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_bytes", "serde_derive", @@ -10094,7 +10293,7 @@ dependencies = [ "solana-secp256k1-recover 2.2.1", "solana-serde-varint 2.2.2", "solana-serialize-utils 2.2.1", - "solana-sha256-hasher 2.2.1", + "solana-sha256-hasher 2.3.0", "solana-short-vec 2.2.1", "solana-slot-hashes 2.2.1", "solana-slot-history 2.2.1", @@ -10136,7 +10335,7 @@ dependencies = [ "solana-msg 3.1.0", "solana-native-token 3.0.0", "solana-program-entrypoint 3.1.1", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-memory 3.1.0", "solana-program-option 3.1.0", "solana-program-pack 3.1.0", @@ -10147,7 +10346,7 @@ dependencies = [ "solana-serde-varint 3.0.1", "solana-serialize-utils 3.1.1", "solana-sha256-hasher 3.1.0", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-slot-hashes 3.0.1", "solana-slot-history 3.0.0", "solana-stable-layout 3.0.1", @@ -10191,7 +10390,7 @@ checksum = "84c9b0a1ff494e05f503a08b3d51150b73aa639544631e510279d6375f290997" dependencies = [ "solana-account-info 3.1.1", "solana-define-syscall 4.0.1", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 4.2.0", ] @@ -10201,7 +10400,7 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "num-traits", "serde", "serde_derive", @@ -10213,11 +10412,11 @@ dependencies = [ [[package]] name = "solana-program-error" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1af32c995a7b692a915bb7414d5f8e838450cf7c70414e763d8abcae7b51f28" +checksum = "4f04fa578707b3612b095f0c8e19b66a1233f7c42ca8082fcb3b745afcc0add6" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "serde", "serde_derive", ] @@ -10267,20 +10466,20 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7701cb15b90667ae1c89ef4ac35a59c61e66ce58ddee13d729472af7f41d59" dependencies = [ - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", ] [[package]] name = "solana-program-runtime" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#bb638243c884b9ec86cc71a2edcb8676ef974dba" dependencies = [ "base64 0.22.1", "bincode", "itertools 0.12.1", "log", "percentage", - "rand 0.8.5", + "rand 0.8.6", "serde", "solana-account 3.4.0", "solana-account-info 3.1.1", @@ -10354,7 +10553,7 @@ dependencies = [ "solana-poh-config", "solana-program-binaries", "solana-program-entrypoint 3.1.1", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-rent 3.1.0", @@ -10372,7 +10571,7 @@ dependencies = [ "solana-sysvar-id 3.1.0", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-vote-program", "spl-generic-token 2.0.1", "thiserror 2.0.18", @@ -10386,13 +10585,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1" dependencies = [ "borsh 0.10.4", - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", "five8 0.2.1", "five8_const 0.1.4", - "getrandom 0.2.16", + "getrandom 0.2.17", "js-sys", "num-traits", "serde", @@ -10401,7 +10600,7 @@ dependencies = [ "solana-decode-error", "solana-define-syscall 2.3.0", "solana-sanitize 2.2.1", - "solana-sha256-hasher 2.2.1", + "solana-sha256-hasher 2.3.0", "wasm-bindgen", ] @@ -10411,7 +10610,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8909d399deb0851aa524420beeb5646b115fd253ef446e35fe4504c904da3941" dependencies = [ - "rand 0.8.5", + "rand 0.8.6", "solana-address 1.1.0", ] @@ -10463,7 +10662,7 @@ dependencies = [ "futures", "itertools 0.12.1", "log", - "rustls 0.23.35", + "rustls 0.23.40", "solana-connection-cache", "solana-keypair 3.1.2", "solana-measure", @@ -10475,7 +10674,7 @@ dependencies = [ "solana-signer 3.0.0", "solana-streamer", "solana-tls-utils", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", ] @@ -10627,7 +10826,7 @@ dependencies = [ "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "solana-version 3.1.12", "solana-vote-interface 4.0.4", @@ -10672,7 +10871,7 @@ dependencies = [ "solana-clock 3.0.1", "solana-rpc-client-types 3.1.12", "solana-signer 3.0.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "thiserror 2.0.18", ] @@ -10687,7 +10886,7 @@ dependencies = [ "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-message 3.1.0", - "solana-nonce 3.1.0", + "solana-nonce 3.2.0", "solana-pubkey 3.0.0", "solana-rpc-client 3.1.12", "solana-sdk-ids 3.1.0", @@ -10740,7 +10939,7 @@ dependencies = [ "solana-inflation 3.1.0", "solana-reward-info 3.0.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "solana-version 3.1.12", "spl-generic-token 2.0.1", @@ -10779,7 +10978,7 @@ dependencies = [ "libc", "log", "lz4", - "memmap2 0.9.9", + "memmap2 0.9.10", "mockall", "modular-bitfield", "num-derive", @@ -10788,7 +10987,7 @@ dependencies = [ "num_enum", "percentage", "qualifier_attr", - "rand 0.8.5", + "rand 0.8.6", "rayon", "regex", "semver", @@ -10835,7 +11034,7 @@ dependencies = [ "solana-metrics 3.1.12", "solana-native-token 3.0.0", "solana-nohash-hasher", - "solana-nonce 3.1.0", + "solana-nonce 3.2.0", "solana-nonce-account", "solana-packet", "solana-perf", @@ -10868,7 +11067,7 @@ dependencies = [ "solana-time-utils 3.0.0", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "solana-unified-scheduler-logic", "solana-version 3.1.12", @@ -10902,7 +11101,7 @@ dependencies = [ "solana-svm-transaction", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] @@ -10929,7 +11128,7 @@ dependencies = [ "hash32", "libc", "log", - "rand 0.8.5", + "rand 0.8.6", "rustc-demangle", "thiserror 2.0.18", "winapi", @@ -10963,13 +11162,13 @@ dependencies = [ "solana-seed-phrase 3.0.0", "solana-serde", "solana-serde-varint 3.0.1", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-shred-version", "solana-signature 3.4.0", "solana-signer 3.0.0", "solana-time-utils 3.0.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] @@ -11047,7 +11246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c5f18893d62e6c73117dcba48f8f5e3266d90e5ec3d0a0a90f9785adac36c1" dependencies = [ "k256", - "solana-define-syscall 5.0.0", + "solana-define-syscall 5.1.0", "thiserror 2.0.18", ] @@ -11137,7 +11336,7 @@ dependencies = [ "solana-time-utils 3.0.0", "solana-tpu-client-next", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", ] [[package]] @@ -11191,9 +11390,9 @@ dependencies = [ [[package]] name = "solana-sha256-hasher" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0037386961c0d633421f53560ad7c80675c0447cba4d1bb66d60974dd486c7ea" +checksum = "5aa3feb32c28765f6aa1ce8f3feac30936f16c5c3f7eb73d63a5b8f6f8ecdc44" dependencies = [ "sha2 0.10.9", "solana-define-syscall 2.3.0", @@ -11208,7 +11407,7 @@ checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" dependencies = [ "sha2 0.10.9", "solana-define-syscall 4.0.1", - "solana-hash 4.2.0", + "solana-hash 4.3.0", ] [[package]] @@ -11222,9 +11421,9 @@ dependencies = [ [[package]] name = "solana-short-vec" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3bd991c2cc415291c86bb0b6b4d53e93d13bb40344e4c5a2884e0e4f5fa93f" +checksum = "2bb8cc883fc7b8ce4a7814cb1441b48c06437049ec11847005cf63bcfa85c546" dependencies = [ "serde_core", ] @@ -11236,7 +11435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6c79722e299d957958bf33695f7cd1ef6724ff55563c60fd9e3e24487cccde2" dependencies = [ "solana-hard-forks", - "solana-hash 4.2.0", + "solana-hash 4.3.0", "solana-sha256-hasher 3.1.0", ] @@ -11262,12 +11461,12 @@ checksum = "e7a73c6e97cc2108be0adf6a6ea326434f8398df9d7eed81da2a4548b69e971c" dependencies = [ "ed25519-dalek 2.2.0", "five8 1.0.0", - "rand 0.9.2", + "rand 0.9.4", "serde", "serde-big-array", "serde_derive", "solana-sanitize 3.0.1", - "wincode 0.5.1", + "wincode", ] [[package]] @@ -11289,7 +11488,7 @@ checksum = "5bfea97951fee8bae0d6038f39a5efcb6230ecdfe33425ac75196d1a1e3e3235" dependencies = [ "solana-pubkey 3.0.0", "solana-signature 3.4.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", ] [[package]] @@ -11313,7 +11512,7 @@ checksum = "2585f70191623887329dfb5078da3a00e15e3980ea67f42c2e10b07028419f43" dependencies = [ "serde", "serde_derive", - "solana-hash 4.2.0", + "solana-hash 4.3.0", "solana-sdk-ids 3.1.0", "solana-sysvar-id 3.1.0", ] @@ -11371,7 +11570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c" dependencies = [ "borsh 0.10.4", - "borsh 1.6.0", + "borsh 1.6.1", "num-traits", "serde", "serde_derive", @@ -11397,7 +11596,7 @@ dependencies = [ "solana-clock 3.0.1", "solana-cpi 3.1.0", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "solana-system-interface 2.0.0", "solana-sysvar 3.1.1", @@ -11420,7 +11619,7 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-signature 3.4.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status", "tonic-prost-build", ] @@ -11441,18 +11640,18 @@ dependencies = [ "futures-util", "governor", "histogram", - "indexmap 2.12.1", + "indexmap 2.14.0", "itertools 0.12.1", "libc", "log", - "nix", + "nix 0.30.1", "num_cpus", "pem", "percentage", - "rand 0.8.5", - "rustls 0.23.35", + "rand 0.8.6", + "rustls 0.23.40", "smallvec", - "socket2 0.6.1", + "socket2 0.6.3", "solana-keypair 3.1.2", "solana-measure", "solana-metrics 3.1.12", @@ -11465,18 +11664,18 @@ dependencies = [ "solana-signer 3.0.0", "solana-time-utils 3.0.0", "solana-tls-utils", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-metrics-tracker", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "x509-parser", ] [[package]] name = "solana-svm" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#bb638243c884b9ec86cc71a2edcb8676ef974dba" dependencies = [ "ahash 0.8.12", "log", @@ -11493,7 +11692,7 @@ dependencies = [ "solana-loader-v4-interface 3.1.0", "solana-loader-v4-program", "solana-message 3.1.0", - "solana-nonce 3.1.0", + "solana-nonce 3.2.0", "solana-nonce-account", "solana-program-entrypoint 3.1.1", "solana-program-pack 3.1.0", @@ -11511,7 +11710,7 @@ dependencies = [ "solana-system-interface 2.0.0", "solana-sysvar-id 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "spl-generic-token 2.0.1", "thiserror 2.0.18", ] @@ -11586,7 +11785,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa888be46794b88f130508f694e989fb8802c823b9048acd4d0240e9818502fe" dependencies = [ - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -11616,7 +11815,7 @@ dependencies = [ "serde_derive", "solana-instruction 3.4.0", "solana-msg 3.1.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", ] @@ -11632,7 +11831,7 @@ dependencies = [ "solana-address 2.6.0", "solana-instruction 3.4.0", "solana-msg 3.1.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", ] [[package]] @@ -11648,7 +11847,7 @@ dependencies = [ "solana-bincode 3.1.0", "solana-fee-calculator 3.2.0", "solana-instruction 3.4.0", - "solana-nonce 3.1.0", + "solana-nonce 3.2.0", "solana-nonce-account", "solana-packet", "solana-program-runtime", @@ -11732,11 +11931,11 @@ dependencies = [ "solana-epoch-rewards 3.0.1", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", - "solana-hash 4.2.0", + "solana-hash 4.3.0", "solana-instruction 3.4.0", "solana-last-restart-slot 3.0.0", "solana-program-entrypoint 3.1.1", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-memory 3.1.0", "solana-pubkey 4.2.0", "solana-rent 3.1.0", @@ -11785,7 +11984,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57a74352404ca3378d3bc6586a9a1e0d7362b687ce2218a0b646dccb767c7ba2" dependencies = [ - "rustls 0.23.35", + "rustls 0.23.40", "solana-keypair 3.1.2", "solana-pubkey 3.0.0", "solana-signer 3.0.0", @@ -11801,7 +12000,7 @@ dependencies = [ "async-trait", "bincode", "futures-util", - "indexmap 2.12.1", + "indexmap 2.14.0", "indicatif 0.18.4", "log", "rayon", @@ -11821,7 +12020,7 @@ dependencies = [ "solana-signature 3.4.0", "solana-signer 3.0.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", ] @@ -11836,7 +12035,7 @@ dependencies = [ "async-trait", "log", "lru 0.7.8", - "rustls 0.23.35", + "rustls 0.23.40", "solana-clock 3.0.1", "solana-connection-cache", "solana-keypair 3.1.2", @@ -11850,7 +12049,7 @@ dependencies = [ "solana-tpu-client", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", ] [[package]] @@ -11888,16 +12087,16 @@ dependencies = [ "serde", "serde_derive", "solana-address 2.6.0", - "solana-hash 4.2.0", + "solana-hash 4.3.0", "solana-instruction 3.4.0", "solana-instruction-error", "solana-message 3.1.0", "solana-sanitize 3.0.1", "solana-sdk-ids 3.1.0", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-signature 3.4.0", "solana-signer 3.0.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", ] [[package]] @@ -11920,7 +12119,7 @@ dependencies = [ [[package]] name = "solana-transaction-context" version = "3.1.12" -source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#50c9b0eded38105c8bf07e0a1d30bf17db15d5b3" +source = "git+https://github.com/magicblock-labs/magicblock-svm.git?branch=fix%2Fv3-compressed#bb638243c884b9ec86cc71a2edcb8676ef974dba" dependencies = [ "bincode", "qualifier_attr", @@ -11948,9 +12147,9 @@ dependencies = [ [[package]] name = "solana-transaction-error" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8396904805b0b385b9de115a652fe80fd01e5b98ce0513f4fcd8184ada9bb792" +checksum = "4a2165ad25b694c654d5395fc7a049452a192376e4c96a7fad05580f6ba5ba1c" dependencies = [ "serde", "serde_derive", @@ -11967,10 +12166,10 @@ dependencies = [ "base64 0.22.1", "bincode", "log", - "rand 0.8.5", + "rand 0.8.6", "solana-packet", "solana-perf", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-signature 3.4.0", ] @@ -11984,7 +12183,7 @@ dependencies = [ "agave-reserved-account-keys", "base64 0.22.1", "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "bs58", "log", "serde", @@ -12005,7 +12204,7 @@ dependencies = [ "solana-stake-interface 2.0.2", "solana-system-interface 2.0.0", "solana-transaction 3.1.0", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "solana-transaction-status-client-types 3.1.12", "solana-vote-interface 4.0.4", "spl-associated-token-account-interface", @@ -12060,7 +12259,7 @@ dependencies = [ "solana-signature 3.4.0", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] @@ -12075,7 +12274,7 @@ dependencies = [ "solana-keypair 3.1.2", "solana-net-utils", "solana-streamer", - "solana-transaction-error 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", ] @@ -12101,7 +12300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3324d46c7f7b7f5d34bf7dc71a2883bdc072c7b28ca81d0b2167ecec4cf8da9f" dependencies = [ "agave-feature-set 2.3.13", - "rand 0.8.5", + "rand 0.8.6", "semver", "serde", "serde_derive", @@ -12116,7 +12315,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f697aacc5aa4ac5534abdde8a91afdcf18c24d28bd52768e8001445dbda078db" dependencies = [ "agave-feature-set 3.1.12", - "rand 0.8.5", + "rand 0.8.6", "semver", "serde", "solana-sanitize 3.0.1", @@ -12196,7 +12395,7 @@ dependencies = [ "solana-sdk-ids 3.1.0", "solana-serde-varint 3.0.1", "solana-serialize-utils 3.1.1", - "solana-short-vec 3.2.0", + "solana-short-vec 3.2.1", "solana-system-interface 2.0.0", ] @@ -12238,7 +12437,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5a91404c7de468dd80658cdb5d894ec803d1092ea6e2bfdf84eee6f07559c0d" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", ] @@ -12277,7 +12476,7 @@ dependencies = [ "merlin", "num-derive", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_derive", "serde_json", @@ -12308,13 +12507,13 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "getrandom 0.2.16", + "getrandom 0.2.17", "itertools 0.12.1", "js-sys", "merlin", "num-derive", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_derive", "serde_json", @@ -12366,7 +12565,7 @@ dependencies = [ "merlin", "num-derive", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "sha3", @@ -12386,18 +12585,18 @@ dependencies = [ [[package]] name = "sonic-number" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a74044c092f4f43ca7a6cfd62854cf9fb5ac8502b131347c990bf22bef1dfe" +checksum = "3775c3390edf958191f1ab1e8c5c188907feebd0f3ce1604cb621f72961dbf32" dependencies = [ "cfg-if", ] [[package]] name = "sonic-rs" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4425ea8d66ec950e0a8f2ef52c766cc3d68d661d9a0845c353c40833179fd866" +checksum = "d971cc77a245ccf1756dbd1a87c3e7f709c0191464096510d43eec056d0f2c4f" dependencies = [ "ahash 0.8.12", "bumpalo", @@ -12406,19 +12605,19 @@ dependencies = [ "faststr", "itoa", "ref-cast", - "ryu", "serde", "simdutf8", "sonic-number", "sonic-simd", "thiserror 2.0.18", + "zmij", ] [[package]] name = "sonic-simd" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5707edbfb34a40c9f2a55fa09a49101d9fec4e0cc171ce386086bd9616f34257" +checksum = "f99e664ecd2d85a68c87e3c7a3cfe691f647ea9e835de984aba4d54a41f817d4" dependencies = [ "cfg-if", ] @@ -12457,7 +12656,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "solana-instruction 3.4.0", "solana-pubkey 3.0.0", ] @@ -12470,7 +12669,7 @@ checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ "bytemuck", "solana-program-error 2.2.2", - "solana-sha256-hasher 2.2.1", + "solana-sha256-hasher 2.3.0", "spl-discriminator-derive", ] @@ -12481,7 +12680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e597c5ff9ed7c74a54dbc47bae2f06e4db8c98f4356ad280200dc11878266db1" dependencies = [ "bytemuck", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-sha256-hasher 3.1.0", "spl-discriminator-derive", ] @@ -12573,7 +12772,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d994afaf86b779104b4a95ba9ca75b8ced3fdb17ee934e38cb69e72afbe17799" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "num-derive", @@ -12593,13 +12792,13 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f9c6e142cdf1e7e77f480053ec9f0ce989890768ddf91f619b50f39d1b456f5" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "num-derive", "num-traits", "num_enum", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-option 3.1.0", "solana-pubkey 3.0.0", "solana-zero-copy", @@ -12740,7 +12939,7 @@ dependencies = [ "num_enum", "solana-account-info 3.1.1", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-option 3.1.0", "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", @@ -12813,7 +13012,7 @@ dependencies = [ "solana-instruction 3.4.0", "solana-instructions-sysvar 3.0.0", "solana-msg 3.1.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", "solana-zk-sdk 4.0.0", @@ -12905,7 +13104,7 @@ dependencies = [ "solana-address 2.6.0", "solana-instruction 3.4.0", "solana-nullable", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-zero-copy", "spl-discriminator 0.5.2", "thiserror 2.0.18", @@ -12923,7 +13122,7 @@ dependencies = [ "num-traits", "num_enum", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-program-option 3.1.0", "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", @@ -12937,7 +13136,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb9c89dbc877abd735f05547dcf9e6e12c00c11d6d74d8817506cab4c99fdbb" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "num-derive", "num-traits", "solana-borsh 2.2.1", @@ -12958,7 +13157,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "304d6e06f0de0c13a621464b1fd5d4b1bebf60d15ca71a44d3839958e0da16ee" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "num-derive", "num-traits", "solana-borsh 2.2.1", @@ -12979,12 +13178,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c467c7c3bd056f8fe60119e7ec34ddd6f23052c2fa8f1f51999098063b72676" dependencies = [ - "borsh 1.6.0", + "borsh 1.6.1", "num-derive", "num-traits", "solana-borsh 3.0.2", "solana-instruction 3.4.0", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "spl-discriminator 0.5.2", "spl-pod 0.7.3", @@ -13064,7 +13263,7 @@ dependencies = [ "num-traits", "num_enum", "solana-account-info 3.1.1", - "solana-program-error 3.0.0", + "solana-program-error 3.0.1", "solana-zero-copy", "spl-discriminator 0.5.2", "thiserror 2.0.18", @@ -13099,11 +13298,11 @@ dependencies = [ [[package]] name = "strum" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" dependencies = [ - "strum_macros 0.27.2", + "strum_macros 0.28.0", ] [[package]] @@ -13121,9 +13320,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -13211,7 +13410,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.11.1", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", ] [[package]] @@ -13224,6 +13434,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "sysvars" version = "0.0.0" @@ -13260,7 +13480,7 @@ dependencies = [ "humantime", "opentelemetry", "pin-project", - "rand 0.8.5", + "rand 0.8.6", "serde", "static_assertions", "tarpc-plugins", @@ -13291,12 +13511,12 @@ checksum = "28768569381ae187ca3e46026f5c0786c4120e146fc74bda02ab930dc1b94bd3" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", @@ -13322,7 +13542,7 @@ name = "test-chainlink" version = "0.0.0" dependencies = [ "bincode", - "borsh 1.6.0", + "borsh 1.6.1", "compressed-delegation-client", "futures", "integration-test-tools", @@ -13600,30 +13820,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -13631,9 +13851,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -13641,9 +13861,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -13656,9 +13876,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -13666,16 +13886,16 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -13708,7 +13928,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.35", + "rustls 0.23.40", "tokio", ] @@ -13730,14 +13950,14 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", ] [[package]] @@ -13748,7 +13968,7 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "rustls 0.23.35", + "rustls 0.23.40", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", @@ -13773,9 +13993,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -13820,9 +14040,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] @@ -13833,33 +14053,33 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.14.0", "serde", "serde_spanned", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.23.9" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.12.1", - "toml_datetime 0.7.3", + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.2", ] [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.2", ] [[package]] @@ -13880,11 +14100,11 @@ dependencies = [ "base64 0.22.1", "bytes", "flate2", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-timeout", "hyper-util", "percent-encoding", @@ -13909,26 +14129,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" dependencies = [ "async-trait", - "axum 0.8.8", + "axum 0.8.9", "base64 0.22.1", "bytes", "flate2", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "rustls-native-certs", - "socket2 0.6.1", + "socket2 0.6.3", "sync_wrapper 1.0.2", "tokio", "tokio-rustls 0.26.4", "tokio-stream", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", @@ -14011,10 +14231,10 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", + "rand 0.8.6", "slab", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tower-layer", "tower-service", "tracing", @@ -14022,18 +14242,18 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.12.1", + "indexmap 2.14.0", "pin-project-lite", "slab", "sync_wrapper 1.0.2", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tower-layer", "tower-service", "tracing", @@ -14046,7 +14266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "async-compression", - "bitflags 2.10.0", + "bitflags 2.11.1", "bytes", "futures-core", "futures-util", @@ -14056,8 +14276,8 @@ dependencies = [ "iri-string", "pin-project-lite", "tokio", - "tokio-util 0.7.17", - "tower 0.5.2", + "tokio-util 0.7.18", + "tower 0.5.3", "tower-layer", "tower-service", ] @@ -14076,9 +14296,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -14099,9 +14319,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -14133,9 +14353,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -14167,8 +14387,8 @@ dependencies = [ "http 1.4.0", "httparse", "log", - "rand 0.9.2", - "rustls 0.23.35", + "rand 0.9.4", + "rustls 0.23.40", "rustls-pki-types", "sha1", "thiserror 2.0.18", @@ -14190,9 +14410,9 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "uncased" @@ -14205,21 +14425,21 @@ dependencies = [ [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -14245,7 +14465,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] @@ -14280,7 +14500,7 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls 0.23.35", + "rustls 0.23.40", "rustls-pki-types", "url", "webpki-roots 0.26.11", @@ -14288,22 +14508,22 @@ dependencies = [ [[package]] name = "ureq" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" +checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" dependencies = [ "base64 0.22.1", "log", "percent-encoding", "ureq-proto", - "utf-8", + "utf8-zero", ] [[package]] name = "ureq-proto" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" dependencies = [ "base64 0.22.1", "http 1.4.0", @@ -14323,14 +14543,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -14339,6 +14560,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-zero" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -14353,11 +14580,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.19.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", "wasm-bindgen", ] @@ -14419,18 +14646,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" dependencies = [ "cfg-if", "once_cell", @@ -14441,9 +14677,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.68" +version = "0.4.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" dependencies = [ "js-sys", "wasm-bindgen", @@ -14451,9 +14687,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -14461,9 +14697,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" dependencies = [ "bumpalo", "proc-macro2", @@ -14474,13 +14710,35 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.5.0" @@ -14494,11 +14752,23 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.2", + "indexmap 2.14.0", + "semver", +] + [[package]] name = "web-sys" -version = "0.3.95" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" dependencies = [ "js-sys", "wasm-bindgen", @@ -14516,9 +14786,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] @@ -14535,14 +14805,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.4", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -14580,22 +14850,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "wincode" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "466e67917609b2d40a838a5b972d1a6237c9749600cb8de8f65559b90d48485b" -dependencies = [ - "pastey", - "proc-macro2", - "quote", - "thiserror 2.0.18", - "wincode-derive", -] - -[[package]] -name = "wincode" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a61f8f0a55eb6cae5d7b7ad2eca536a944deb9722a948525181069064ecd1abc" +checksum = "b4c754f1fc41250f2f742a27ba0fcc9f73df1dec23f6878490770855d43c322d" dependencies = [ "pastey", "proc-macro2", @@ -14606,11 +14863,11 @@ dependencies = [ [[package]] name = "wincode-derive" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca057fc9a13dd19cdb64ef558635d43c42667c0afa1ae7915ea1fa66993fd1a" +checksum = "3e070787599c7c067b89598cd3eda440cca1b69eda9e0ff7c725fc8679ce9eb4" dependencies = [ - "darling", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.117", @@ -15036,9 +15293,18 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] @@ -15055,15 +15321,103 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wyz" @@ -15110,9 +15464,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -15121,9 +15475,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -15133,18 +15487,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -15153,18 +15507,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -15183,9 +15537,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", @@ -15194,9 +15548,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -15205,9 +15559,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -15216,9 +15570,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", @@ -15227,13 +15581,13 @@ dependencies = [ [[package]] name = "zip" -version = "7.2.0" +version = "8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ "crc32fast", "flate2", - "indexmap 2.12.1", + "indexmap 2.14.0", "memchr", "typed-path", "zopfli", @@ -15241,9 +15595,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" +checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" [[package]] name = "zmij" diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 53f4d2a36..7d9b384cb 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -38,7 +38,7 @@ color-backtrace = { version = "0.7" } compressed-delegation-api = { path = "../compressed-delegation-api" } compressed-delegation-client = { path = "../compressed-delegation-client" } ctrlc = "3.4.7" -ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "ccfc9f924dc40", default-features = false, features = [ +ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "1e2da4393273e", default-features = false, features = [ "disable-realloc", "modular-sdk", ] } From 7162fbbc0d61631d86d9c4396749875990cf0476 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 12:54:02 +0200 Subject: [PATCH 061/110] feat: simplify cleanup --- test-integration/test-runner/bin/run_tests.rs | 83 +++++++------------ test-integration/test-runner/src/cleanup.rs | 11 --- test-integration/test-runner/src/signal.rs | 11 ++- 3 files changed, 40 insertions(+), 65 deletions(-) diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index e3a1a7483..888d5d51f 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -17,8 +17,7 @@ use integration_test_tools::{ use teepee::Teepee; use test_runner::{ cleanup::{ - cleanup_devnet_only, cleanup_devnet_validator, cleanup_light_validator, - cleanup_validators, + cleanup_devnet_only, cleanup_light_validator, cleanup_validators, }, env_config::TestConfigViaEnvVars, signal::wait_for_ctrlc, @@ -156,7 +155,7 @@ fn run_restore_ledger_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, false, success_output()) + wait_for_ctrlc(devnet_validator, None, None, success_output()) } } @@ -191,7 +190,7 @@ fn run_chainlink_tests( ]); loaded_chain_accounts }; - let start_devnet_validator = || match start_validator( + let start_light_validator = || match start_validator( "chainlink-conf.devnet.toml", ValidatorCluster::Light, &loaded_chain_accounts, @@ -203,7 +202,7 @@ fn run_chainlink_tests( }; if config.run_test(TEST_NAME) { eprintln!("======== RUNNING CHAINLINK TESTS ========"); - let mut devnet_validator = start_devnet_validator(); + let mut light_validator = start_light_validator(); let test_chainlink_dir = format!("{}/../{}", manifest_dir, "test-chainlink"); eprintln!("Running chainlink tests in {}", test_chainlink_dir); @@ -211,16 +210,16 @@ fn run_chainlink_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run chainlink tests: {:?}", err); - cleanup_light_validator(&mut devnet_validator); + cleanup_light_validator(&mut light_validator); return Err(err.into()); } }; - cleanup_light_validator(&mut devnet_validator); + cleanup_light_validator(&mut light_validator); Ok(output) } else { - let devnet_validator = - config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, true, success_output()) + let light_validator = + config.setup_devnet(TEST_NAME).then(start_light_validator); + wait_for_ctrlc(None, light_validator, None, success_output()) } } @@ -241,16 +240,9 @@ fn run_table_mania_and_committor_tests( let loaded_chain_accounts = LoadedAccounts::with_delegation_program_test_authority(); - let cluster = if !config.skip_entirely(COMMITTOR_TEST) { - ValidatorCluster::Chain(None) - } else { - ValidatorCluster::Light - }; - let uses_light_validator = matches!(&cluster, ValidatorCluster::Light); - - let start_devnet_validator = || match start_validator( + let start_light_validator = || match start_validator( "committor-conf.devnet.toml", - cluster, + ValidatorCluster::Light, &loaded_chain_accounts, ) { Some(validator) => validator, @@ -266,7 +258,7 @@ fn run_table_mania_and_committor_tests( if run_table_mania || run_committor { eprintln!("======== Starting DEVNET Validator for TableMania and Committor ========"); - let mut devnet_validator = start_devnet_validator(); + let mut light_validator = start_light_validator(); // NOTE: the table mania and committor tests run directly against // a chain validator therefore no ephemeral validator needs to be started @@ -279,10 +271,7 @@ fn run_table_mania_and_committor_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run table-mania: {:?}", err); - cleanup_devnet_validator( - &mut devnet_validator, - uses_light_validator, - ); + cleanup_light_validator(&mut light_validator); return Err(err.into()); } } @@ -310,10 +299,7 @@ fn run_table_mania_and_committor_tests( Ok(output) => output, Err(err) => { eprintln!("Failed to run committor: {:?}", err); - cleanup_devnet_validator( - &mut devnet_validator, - uses_light_validator, - ); + cleanup_light_validator(&mut light_validator); return Err(err.into()); } } @@ -322,20 +308,15 @@ fn run_table_mania_and_committor_tests( success_output() }; - cleanup_devnet_validator(&mut devnet_validator, uses_light_validator); + cleanup_light_validator(&mut light_validator); Ok((table_mania_test_output, committor_test_output)) } else { let setup_needed = config.setup_devnet(TABLE_MANIA_TEST) || config.setup_devnet(COMMITTOR_TEST); - let devnet_validator = setup_needed.then(start_devnet_validator); + let light_validator = setup_needed.then(start_light_validator); Ok(( - wait_for_ctrlc( - devnet_validator, - None, - uses_light_validator, - success_output(), - )?, + wait_for_ctrlc(None, light_validator, None, success_output())?, success_output(), )) } @@ -353,7 +334,7 @@ fn run_schedule_commit_tests( let loaded_chain_accounts = LoadedAccounts::with_delegation_program_test_authority(); - let start_devnet_validator = || match start_validator( + let start_light_validator = || match start_validator( "schedulecommit-conf.devnet.toml", ValidatorCluster::Light, &loaded_chain_accounts, @@ -380,7 +361,7 @@ fn run_schedule_commit_tests( "======== Starting DEVNET Validator for Scenarios + Security ========" ); - let mut devnet_validator = start_devnet_validator(); + let mut light_validator = start_light_validator(); // These share a common config that includes the program to schedule commits // Thus they can run against the same validator instances @@ -400,7 +381,7 @@ fn run_schedule_commit_tests( eprintln!("Failed to run security: {:?}", err); cleanup_validators( &mut ephem_validator, - &mut devnet_validator, + &mut light_validator, true, ); return Err(err.into()); @@ -417,25 +398,25 @@ fn run_schedule_commit_tests( eprintln!("Failed to run scenarios: {:?}", err); cleanup_validators( &mut ephem_validator, - &mut devnet_validator, + &mut light_validator, true, ); return Err(err.into()); } }; - cleanup_validators(&mut ephem_validator, &mut devnet_validator, true); + cleanup_validators(&mut ephem_validator, &mut light_validator, true); Ok((test_security_output, test_scenarios_output)) } else { - let devnet_validator = - config.setup_devnet(TEST_NAME).then(start_devnet_validator); + let light_validator = + config.setup_devnet(TEST_NAME).then(start_light_validator); let ephem_validator = config.setup_ephem(TEST_NAME).then(start_ephem_validator); eprintln!("Setup validator(s)"); wait_for_ctrlc( - devnet_validator, + None, + light_validator, ephem_validator, - true, success_output(), )?; Ok((success_output(), success_output())) @@ -527,8 +508,8 @@ fn run_cloning_tests( config.setup_ephem(TEST_NAME).then(start_ephem_validator); wait_for_ctrlc( devnet_validator, + None, ephem_validator, - false, success_output(), ) } @@ -593,8 +574,8 @@ fn run_magicblock_api_tests( config.setup_ephem(TEST_NAME).then(start_ephem_validator); wait_for_ctrlc( devnet_validator, + None, ephem_validator, - false, success_output(), ) } @@ -661,8 +642,8 @@ fn run_magicblock_pubsub_tests( config.setup_ephem(TEST_NAME).then(start_ephem_validator); wait_for_ctrlc( devnet_validator, + None, ephem_validator, - false, success_output(), ) } @@ -711,7 +692,7 @@ fn run_config_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, false, success_output()) + wait_for_ctrlc(devnet_validator, None, None, success_output()) } } @@ -787,8 +768,8 @@ fn run_schedule_intents_tests( config.setup_ephem(TEST_NAME).then(start_ephem_validator); wait_for_ctrlc( devnet_validator, + None, ephem_validator, - false, success_output(), ) } @@ -839,7 +820,7 @@ fn run_task_scheduler_tests( } else { let devnet_validator = config.setup_devnet(TEST_NAME).then(start_devnet_validator); - wait_for_ctrlc(devnet_validator, None, false, success_output()) + wait_for_ctrlc(devnet_validator, None, None, success_output()) } } diff --git a/test-integration/test-runner/src/cleanup.rs b/test-integration/test-runner/src/cleanup.rs index e889e0e05..6390b3f3f 100644 --- a/test-integration/test-runner/src/cleanup.rs +++ b/test-integration/test-runner/src/cleanup.rs @@ -14,17 +14,6 @@ pub fn cleanup_validators( kill_validators(); } -pub fn cleanup_devnet_validator( - devnet_validator: &mut process::Child, - uses_light_validator: bool, -) { - if uses_light_validator { - cleanup_light_validator(devnet_validator); - } else { - cleanup_devnet_only(devnet_validator); - } -} - pub fn cleanup_devnet_only(devnet_validator: &mut Child) { cleanup_validator(devnet_validator, "devnet"); kill_validators(); diff --git a/test-integration/test-runner/src/signal.rs b/test-integration/test-runner/src/signal.rs index 384795daf..8881eb389 100644 --- a/test-integration/test-runner/src/signal.rs +++ b/test-integration/test-runner/src/signal.rs @@ -4,12 +4,14 @@ use std::{ sync::mpsc::channel, }; -use crate::cleanup::{cleanup_devnet_validator, cleanup_validator}; +use crate::cleanup::{ + cleanup_devnet_only, cleanup_light_validator, cleanup_validator, +}; pub fn wait_for_ctrlc( devnet_validator: Option, + light_validator: Option, ephem_validator: Option, - uses_light_validator: bool, output: Output, ) -> Result> { let (tx, rx) = channel(); @@ -24,7 +26,10 @@ pub fn wait_for_ctrlc( cleanup_validator(&mut validator, "ephemeral"); } if let Some(mut validator) = devnet_validator { - cleanup_devnet_validator(&mut validator, uses_light_validator); + cleanup_devnet_only(&mut validator); + } + if let Some(mut validator) = light_validator { + cleanup_light_validator(&mut validator); } Ok(output) From 9893d95250f3f95c7eadd2248ca5e19b6fb26019 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 12:59:21 +0200 Subject: [PATCH 062/110] fix: smaller airdrop --- .../test-committor-service/tests/utils/transactions.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index c08af12ac..30d4217a2 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -340,11 +340,11 @@ pub async fn init_and_delegate_compressed_record_on_chain( airdrop_and_confirm( &rpc_client, &counter_auth.pubkey(), - 777 * LAMPORTS_PER_SOL, + LAMPORTS_PER_SOL, "counter auth", ) .await; - debug!("Airdropped to counter auth: {} SOL", 777 * LAMPORTS_PER_SOL); + debug!("Airdropped to counter auth: {} SOL", LAMPORTS_PER_SOL); let InitAccountAndCompressedRecordIxs { init: init_counter_ix, From 093832e92e0394551c02e5547ce9f6c8a57979d2 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 13:04:17 +0200 Subject: [PATCH 063/110] fix: commit account data --- .../src/tasks/commit_finalize_compressed_task.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs index d85193b9b..0b486dc22 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs @@ -29,23 +29,12 @@ impl CommitFinalizeCompressedTask { let old_record = CompressedDelegationRecord::try_from_slice( &self.compressed_data.compressed_delegation_record_bytes, ).expect("The record should have been valid because it was already used to clone the account"); - let new_record = CompressedDelegationRecord { - pda: self.committed_account.pubkey, - authority: *validator, - last_update_nonce: self.commit_id + 1, - is_undelegatable: self.allow_undelegation, - owner: old_record.owner, - delegation_slot: old_record.delegation_slot, - lamports: self.committed_account.account.lamports, - data: self.committed_account.account.data.clone(), - }; let args = CommitAndFinalizeArgs { current_compressed_delegated_account_data: self .compressed_data .compressed_delegation_record_bytes .clone(), - new_data: borsh::to_vec(&new_record) - .expect("The serializing the new record should not fail"), + new_data: self.committed_account.account.data.clone(), account_meta: self.compressed_data.account_meta, validity_proof: self.compressed_data.proof, update_nonce: self.commit_id, From 0172a02680e2dd5b47215b3223864cbf1af7cbcb Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 13:06:20 +0200 Subject: [PATCH 064/110] style: lint --- .../src/tasks/commit_finalize_compressed_task.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs index 0b486dc22..53ed1978a 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_compressed_task.rs @@ -1,7 +1,4 @@ -use borsh::BorshDeserialize; -use compressed_delegation_api::{ - CommitAndFinalizeArgs, CompressedDelegationRecord, -}; +use compressed_delegation_api::CommitAndFinalizeArgs; use magicblock_core::intent::CommittedAccount; use solana_instruction::Instruction; use solana_pubkey::Pubkey; @@ -26,9 +23,6 @@ pub struct CommitFinalizeCompressedTask { impl CommitFinalizeCompressedTask { #[inline(always)] pub fn instruction(&self, validator: &Pubkey) -> Instruction { - let old_record = CompressedDelegationRecord::try_from_slice( - &self.compressed_data.compressed_delegation_record_bytes, - ).expect("The record should have been valid because it was already used to clone the account"); let args = CommitAndFinalizeArgs { current_compressed_delegated_account_data: self .compressed_data From a8f37328cce877d35fc3c53fc2ca4c2d54a100f5 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 14:10:25 +0200 Subject: [PATCH 065/110] fix: use confirmed transaction --- .../test-task-scheduler/src/lib.rs | 41 ++++--------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/test-integration/test-task-scheduler/src/lib.rs b/test-integration/test-task-scheduler/src/lib.rs index d52e1de23..11068e328 100644 --- a/test-integration/test-task-scheduler/src/lib.rs +++ b/test-integration/test-task-scheduler/src/lib.rs @@ -88,43 +88,16 @@ pub fn create_delegated_counter( validator: &mut Child, commit_frequency_ms: u32, ) { - // Initialize the counter - let blockhash = expect!( - ctx.try_chain_client().and_then(|client| client - .get_latest_blockhash() - .map_err(|e| anyhow::anyhow!( - "Failed to get latest blockhash: {}", - e - ))), - validator - ); - expect!( - ctx.send_transaction_chain( - &mut Transaction::new_signed_with_payer( - &[create_init_ix(payer.pubkey(), "test".to_string())], - Some(&payer.pubkey()), - &[&payer], - blockhash, - ), - &[payer] - ), - format!("Failed to send init transaction: blockhash {:?}", blockhash), - validator + let init_ix = create_init_ix(payer.pubkey(), "test".to_string()); + let delegate_ix = create_delegate_ix_with_commit_frequency_ms( + payer.pubkey(), + commit_frequency_ms, ); - // Delegate the counter to the ephem validator expect!( - ctx.send_transaction_chain( - &mut Transaction::new_signed_with_payer( - &[create_delegate_ix_with_commit_frequency_ms( - payer.pubkey(), - commit_frequency_ms - )], - Some(&payer.pubkey()), - &[&payer], - blockhash, - ), - &[payer] + ctx.send_and_confirm_instructions_with_payer_chain( + &[init_ix, delegate_ix], + payer, ), validator ); From 96453098d9f1153f67d06c481d6d5bc47d444aef Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 14:33:30 +0200 Subject: [PATCH 066/110] feat: use MagicIntentBundleBuilder --- test-integration/Cargo.lock | 12 +-- test-integration/Cargo.toml | 2 +- .../programs/schedulecommit/src/lib.rs | 75 +++++++------------ 3 files changed, 34 insertions(+), 55 deletions(-) diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 3e1b4651f..2b41b07cc 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -2481,7 +2481,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk" version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" dependencies = [ "base64ct", "bincode", @@ -2508,7 +2508,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-action" version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" dependencies = [ "quote", "syn 1.0.109", @@ -2517,7 +2517,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-commit" version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" dependencies = [ "quote", "syn 1.0.109", @@ -2526,7 +2526,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-delegate" version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" dependencies = [ "proc-macro2", "quote", @@ -2536,7 +2536,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-ephemeral" version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" dependencies = [ "proc-macro2", "quote", @@ -2546,7 +2546,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-ephemeral-accounts" version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=1e2da4393273e#1e2da4393273e1f0ea8e21a2fc98e060621ef9ca" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" dependencies = [ "proc-macro2", "quote", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 7d9b384cb..8cf543303 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -38,7 +38,7 @@ color-backtrace = { version = "0.7" } compressed-delegation-api = { path = "../compressed-delegation-api" } compressed-delegation-client = { path = "../compressed-delegation-client" } ctrlc = "3.4.7" -ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "1e2da4393273e", default-features = false, features = [ +ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "e864ea09d0", default-features = false, features = [ "disable-realloc", "modular-sdk", ] } diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 787dae545..2043cb968 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -9,6 +9,7 @@ use ephemeral_rollups_sdk::{ ephem::{ commit_accounts, commit_and_undelegate_accounts, commit_finalize_accounts, commit_finalize_and_undelegate_accounts, + FoldableIntentBuilder, MagicIntentBundleBuilder, }, }; use magicblock_magic_program_api::{ @@ -256,56 +257,34 @@ impl ScheduleCommitType { ) } ScheduleCommitType::CommitFinalizeCompressed => { - let ix = Instruction::new_with_bincode( - *magic_program.key, - &magicblock_magic_program_api::instruction::MagicBlockInstruction::ScheduleCommitCompressed, - [vec![ - AccountMeta { - pubkey: *payer.key, - is_signer: true, - is_writable: true, - }, - AccountMeta { - pubkey: *magic_context.key, - is_signer: false, - is_writable: true, - }, - ], accounts.iter().map(|account| AccountMeta { - pubkey: *account.key, - is_signer: account.is_signer, - is_writable: account.is_writable, - }).collect()].concat(), - ); - let mut all_accounts = - vec![payer.clone(), magic_context.clone()]; - all_accounts.extend(accounts.into_iter().cloned()); - invoke(&ix, &all_accounts) + MagicIntentBundleBuilder::new( + payer.clone(), + magic_context.clone(), + magic_program.clone(), + ) + .commit( + &accounts + .into_iter() + .map(|account| account.clone()) + .collect::>(), + ) + .compressed() + .build_and_invoke() } ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { - let ix = Instruction::new_with_bincode( - *magic_program.key, - &magicblock_magic_program_api::instruction::MagicBlockInstruction::ScheduleCommitAndUndelegateCompressed, - [vec![ - AccountMeta { - pubkey: *payer.key, - is_signer: true, - is_writable: true, - }, - AccountMeta { - pubkey: *magic_context.key, - is_signer: false, - is_writable: true, - }, - ], accounts.iter().map(|account| AccountMeta { - pubkey: *account.key, - is_signer: account.is_signer, - is_writable: account.is_writable, - }).collect()].concat(), - ); - let mut all_accounts = - vec![payer.clone(), magic_context.clone()]; - all_accounts.extend(accounts.into_iter().cloned()); - invoke(&ix, &all_accounts) + MagicIntentBundleBuilder::new( + payer.clone(), + magic_context.clone(), + magic_program.clone(), + ) + .commit_and_undelegate( + &accounts + .into_iter() + .map(|account| account.clone()) + .collect::>(), + ) + .compressed() + .build_and_invoke() } } } From 1cc48ed1347f1f7ff4225fd13e213a222ad0a6a9 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 30 Apr 2026 15:05:29 +0200 Subject: [PATCH 067/110] style: lint --- test-integration/programs/schedulecommit/src/lib.rs | 12 ++---------- test-integration/test-task-scheduler/src/lib.rs | 4 +--- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 2043cb968..d0cdfa4d4 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -262,12 +262,7 @@ impl ScheduleCommitType { magic_context.clone(), magic_program.clone(), ) - .commit( - &accounts - .into_iter() - .map(|account| account.clone()) - .collect::>(), - ) + .commit(&accounts.into_iter().cloned().collect::>()) .compressed() .build_and_invoke() } @@ -278,10 +273,7 @@ impl ScheduleCommitType { magic_program.clone(), ) .commit_and_undelegate( - &accounts - .into_iter() - .map(|account| account.clone()) - .collect::>(), + &accounts.into_iter().cloned().collect::>(), ) .compressed() .build_and_invoke() diff --git a/test-integration/test-task-scheduler/src/lib.rs b/test-integration/test-task-scheduler/src/lib.rs index 11068e328..20e2372ff 100644 --- a/test-integration/test-task-scheduler/src/lib.rs +++ b/test-integration/test-task-scheduler/src/lib.rs @@ -32,9 +32,7 @@ use program_flexi_counter::{ state::FlexiCounter, }; use program_schedulecommit::MainAccount; -use solana_sdk::{ - signature::Keypair, signer::Signer, transaction::Transaction, -}; +use solana_sdk::{signature::Keypair, signer::Signer}; use tempfile::TempDir; pub const TASK_SCHEDULER_TICK_MILLIS: u64 = 50; From 8063aa95579867886e76356a35fff70e605e09f0 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 6 May 2026 18:15:41 +0200 Subject: [PATCH 068/110] fix: disable regular compressed commits + guard --- .../process_schedule_commit.rs | 20 ++-------------- .../process_schedule_commit_finalize.rs | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs index d75f03ad6..7abe04056 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs @@ -26,7 +26,6 @@ use crate::{ }, instruction_utils::InstructionUtils, }, - validator::is_compression_enabled, MagicContext, }; @@ -41,11 +40,8 @@ pub(crate) fn process_schedule_commit( invoke_context: &mut InvokeContext, opts: ProcessScheduleCommitOptions, ) -> Result<(), InstructionError> { - if opts.compressed && !is_compression_enabled() { - ic_msg!( - invoke_context, - "ScheduleCommit: compression is not enabled, but compressed accounts are being committed" - ); + if opts.compressed { + ic_msg!(invoke_context, "ScheduleCommit: compressed accounts are not supported for regular commits"); return Err(InstructionError::InvalidInstructionData); } @@ -237,18 +233,6 @@ pub(crate) fn process_schedule_commit( committed_accounts.push(committed); } - if opts.compressed - && committed_accounts - .iter() - .any(|acc| acc.account.lamports > 0) - { - ic_msg!( - invoke_context, - "ScheduleCommit: compressed accounts with lamports > 0 are not supported", - ); - return Err(InstructionError::InvalidAccountData); - } - if opts.request_undelegation { // If the account is scheduled to be undelegated then we need to lock it // immediately in order to prevent the following actions: diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs index 389fc73c5..7102bddea 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs @@ -29,6 +29,7 @@ use crate::{ }, instruction_utils::InstructionUtils, }, + validator::is_compression_enabled, MagicContext, }; @@ -37,6 +38,14 @@ pub(crate) fn process_schedule_commit_finalize( invoke_context: &mut InvokeContext, opts: ProcessScheduleCommitOptions, ) -> Result<(), InstructionError> { + if opts.compressed && !is_compression_enabled() { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: compression is not enabled, but compressed accounts are being committed" + ); + return Err(InstructionError::InvalidInstructionData); + } + const PAYER_IDX: u16 = 0; const MAGIC_CONTEXT_IDX: u16 = PAYER_IDX + 1; @@ -220,6 +229,21 @@ pub(crate) fn process_schedule_commit_finalize( committed_accounts.push(committed); } + if opts.compressed + && committed_accounts + .iter() + .any(|acc| acc.account.lamports > 0) + { + // The reason here is that the delegated account no longer exists. + // The undelegation is triggered by the user, which pays the rent. + // Intents can be used to pay for the undelegation and previous lamports. + ic_msg!( + invoke_context, + "ScheduleCommit: compressed accounts with lamports > 0 are not supported", + ); + return Err(InstructionError::InvalidAccountData); + } + if opts.request_undelegation { // If the account is scheduled to be undelegated then we need to lock it // immediately in order to prevent the following actions: From aa486d6db760ebc8ae68118a395807908239c85a Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 7 May 2026 11:33:36 +0200 Subject: [PATCH 069/110] feat: surface compressed data errors --- .../src/intent_executor/task_info_fetcher.rs | 7 ++---- .../src/tasks/task_builder.rs | 24 ++++++++----------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 63701fcf1..7c1b01245 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -95,12 +95,9 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { &self, pubkeys: &[Pubkey], min_context_slot: Option, - ) -> TaskInfoFetcherResult>> { + ) -> TaskInfoFetcherResult>> { try_join_all(pubkeys.iter().map(|pubkey| async move { - Ok(self - .get_compressed_data(pubkey, min_context_slot) - .await - .ok()) + Ok(self.get_compressed_data(pubkey, min_context_slot).await) })) .await } diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 59069ccd4..89a19b853 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -156,7 +156,9 @@ impl TaskBuilderImpl { task_info_fetcher: &Arc, accounts: &[(bool, bool, bool, CommittedAccount)], min_context_slot: u64, - ) -> TaskInfoFetcherResult> { + ) -> TaskInfoFetcherResult< + HashMap>, + > { let pubkeys = accounts .iter() .filter(|(_, _, compressed, _)| *compressed) @@ -172,7 +174,7 @@ impl TaskBuilderImpl { ) .await?, ) - .filter_map(|(pk, data)| data.map(|data| (*pk, data))) + .map(|(pk, data)| (*pk, data)) .collect()) } @@ -297,7 +299,7 @@ impl TasksBuilder for TaskBuilderImpl { tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); Default::default() }); - let compressed_data = + let mut compressed_data = compressed_data.map_err(TaskBuilderError::CommitTasksBuildError)?; // Persist commit ids for commitees @@ -328,19 +330,13 @@ impl TasksBuilder for TaskBuilderImpl { if compressed { let compressed_data = compressed_data - .get(&account.pubkey) - .cloned() + .remove(&account.pubkey) .ok_or_else(|| { TaskBuilderError::CommitFinalizeCompressedTasksBuildError( - std::io::Error::new( - std::io::ErrorKind::NotFound, - format!( - "compressed data absent for pubkey {}", - account.pubkey - ), - ), + TaskInfoFetcherError::CompressedAccountNotFound(account.pubkey), ) - })?; + })? + .map_err(TaskBuilderError::CommitFinalizeCompressedTasksBuildError)?; Ok(Self::create_commit_finalize_compressed_task( commit_id, allow_undelegation, @@ -475,7 +471,7 @@ pub enum TaskBuilderError { #[error("FinalizedTasksBuildError: {0}")] FinalizedTasksBuildError(#[source] TaskInfoFetcherError), #[error("CommitFinalizeCompressedTasksBuildError: {0}")] - CommitFinalizeCompressedTasksBuildError(#[from] std::io::Error), + CommitFinalizeCompressedTasksBuildError(#[from] TaskInfoFetcherError), } impl TaskBuilderError { From 5f46206d21dad51cab417a437b4b25aa79fac488 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 7 May 2026 11:39:48 +0200 Subject: [PATCH 070/110] feat: never fetch from photon when disabled --- magicblock-chainlink/src/chainlink/errors.rs | 3 -- .../src/remote_account_provider/mod.rs | 48 ++++++++++--------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/errors.rs b/magicblock-chainlink/src/chainlink/errors.rs index bcacd8e0d..259dacf03 100644 --- a/magicblock-chainlink/src/chainlink/errors.rs +++ b/magicblock-chainlink/src/chainlink/errors.rs @@ -50,7 +50,4 @@ pub enum ChainlinkError { #[error("Photon client error: {0}")] PhotonClientError(#[from] magicblock_core::traits::PhotonClientError), - - #[error("Compression is not enabled")] - CompressionNotEnabled, } diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 806261d1f..c2411117b 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -75,7 +75,7 @@ use remote_account::{ pub use remote_account::{ResolvedAccount, ResolvedAccountSharedData}; use crate::{ - errors::{ChainlinkError, ChainlinkResult}, + errors::ChainlinkResult, remote_account_provider::{ chain_updates_client::ChainUpdatesClient, photon_client::PhotonClientImpl, pubsub_common::SubscriptionUpdate, @@ -1163,23 +1163,34 @@ impl mark_empty_if_not_found.unwrap_or(&[]).to_vec(); let program_ids = program_ids.map(|ids| ids.to_vec()); tokio::spawn(async move { - // Fetch accounts from RPC - // If any are owned by the compressed delegation program then we also fetch from Photon with retries - let (rpc_accounts, photon_accounts) = tokio::join!( - Self::fetch_from_rpc( + let results = if let Some(photon_client) = photon_client { + let (rpc_accounts, photon_accounts) = tokio::join!( + Self::fetch_from_rpc( + rpc_client, + pubkeys.clone(), + &mark_empty_if_not_found, + min_context_slot, + ), + Self::fetch_from_photon( + photon_client, + pubkeys.clone(), + &mark_empty_if_not_found, + min_context_slot, + ) + ); + trace!(rpc_accounts = ?rpc_accounts, photon_accounts = ?photon_accounts, "Fetched accounts from RPC and Photon"); + vec![rpc_accounts, photon_accounts] + } else { + let rpc_accounts = Self::fetch_from_rpc( rpc_client, pubkeys.clone(), &mark_empty_if_not_found, min_context_slot, - ), - Self::fetch_from_photon( - photon_client, - pubkeys.clone(), - &mark_empty_if_not_found, - min_context_slot, ) - ); - trace!(rpc_accounts = ?rpc_accounts, photon_accounts = ?photon_accounts, "Fetched accounts from RPC and Photon"); + .await; + trace!(rpc_accounts = ?rpc_accounts, "Fetched accounts from RPC"); + vec![rpc_accounts] + }; let mut remote_accounts_results = Vec::with_capacity(2); let mut rpc_fetch_success = false; @@ -1188,8 +1199,6 @@ impl let mut compressed_found_count = 0; let mut compressed_not_found_count = 0; - let results = vec![rpc_accounts, photon_accounts]; - for result in results { match result { Ok((FetchedRemoteAccounts::Rpc(accs), fc, nfc)) => { @@ -1205,10 +1214,6 @@ impl compressed_found_count += fc; compressed_not_found_count += nfc; } - Err(ChainlinkError::CompressionNotEnabled) => { - // Not an error, just skip - continue; - } Err(err) => { error!("Failed to fetch accounts: {err:?}"); } @@ -1530,14 +1535,11 @@ impl } async fn fetch_from_photon( - photon_client: Option

, + photon_client: P, pubkeys: Vec, mark_empty_if_not_found: &[Pubkey], min_context_slot: u64, ) -> ChainlinkResult<(FetchedRemoteAccounts, u64, u64)> { - let Some(photon_client) = photon_client else { - return Err(ChainlinkError::CompressionNotEnabled); - }; if tracing::enabled!(tracing::Level::TRACE) { trace!( pubkeys = pubkeys_str(&pubkeys), From ec00ec1d86c766c3793bad50ca3adf070d9ceb09 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 7 May 2026 15:02:32 +0200 Subject: [PATCH 071/110] feat: surface error when fetch photon failed --- .../src/remote_account_provider/mod.rs | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index c2411117b..d992b8e0c 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -1198,6 +1198,7 @@ impl let mut not_found_cnt = 0; let mut compressed_found_count = 0; let mut compressed_not_found_count = 0; + let mut fetch_errors = vec![]; for result in results { match result { @@ -1216,9 +1217,35 @@ impl } Err(err) => { error!("Failed to fetch accounts: {err:?}"); + fetch_errors.push(err.to_string()); } } } + + if !fetch_errors.is_empty() { + let msg = format!( + "failed to fetch accounts: {}", + fetch_errors.join(", ") + ); + let mut fetching = fetching_accounts + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + for pubkey in &pubkeys { + if let Some((_, requests)) = fetching.remove(pubkey) { + for request in requests { + let _ = request.send(Err( + RemoteAccountProviderError::AccountResolutionsFailed( + msg.clone(), + ), + )); + } + } + } + return Err( + RemoteAccountProviderError::AccountResolutionsFailed(msg), + ); + } + let remote_accounts = Self::consolidate_fetched_remote_accounts( &pubkeys, remote_accounts_results, @@ -1808,6 +1835,11 @@ fn pubkeys_str(pubkeys: &[Pubkey]) -> String { #[cfg(test)] mod test { + use light_client::indexer::IndexerError; + use magicblock_core::{ + traits::{PhotonClientError, PhotonClientResult}, + Slot, + }; use solana_system_interface::program as system_program; use super::*; @@ -1823,6 +1855,45 @@ mod test { }, }; + #[derive(Clone)] + struct FailingPhotonClient { + fail_pubkey: Pubkey, + } + + #[tonic::async_trait] + impl PhotonClient for FailingPhotonClient { + async fn get_account( + &self, + pubkey: &Pubkey, + _min_context_slot: Option, + ) -> PhotonClientResult> { + if *pubkey == self.fail_pubkey { + Err(photon_failure()) + } else { + Ok(None) + } + } + + async fn get_multiple_accounts( + &self, + pubkeys: &[Pubkey], + min_context_slot: Option, + ) -> PhotonClientResult<(Vec>, Slot)> { + if pubkeys.contains(&self.fail_pubkey) { + Err(photon_failure()) + } else { + Ok((vec![None; pubkeys.len()], min_context_slot.unwrap_or(0))) + } + } + } + + fn photon_failure() -> PhotonClientError { + PhotonClientError::IndexerError(IndexerError::PhotonError { + context: "test".to_string(), + message: "forced photon failure".to_string(), + }) + } + #[tokio::test] async fn test_get_non_existing_account() { init_logger(); @@ -1861,6 +1932,50 @@ mod test { assert!(!remote_account.is_found()); } + #[tokio::test] + async fn test_photon_failure_is_returned_instead_of_rpc_not_found() { + init_logger(); + let pubkey = random_pubkey(); + + let remote_account_provider = { + let (tx, rx) = mpsc::channel(1); + let rpc_client = ChainRpcClientMockBuilder::new() + .slot(1) + .clock_sysvar_for_slot(1) + .build(); + let pubsub_client = + chain_pubsub_client::mock::ChainPubsubClientMock::new(tx, rx); + let (fwd_tx, _fwd_rx) = mpsc::channel(100); + let (subscribed_accounts, config) = create_test_lru_cache(1000); + let chain_slot = Arc::::default(); + + RemoteAccountProvider::new( + rpc_client, + pubsub_client, + Some(FailingPhotonClient { + fail_pubkey: pubkey, + }), + fwd_tx, + &config, + subscribed_accounts, + ChainSlot::new(chain_slot), + ) + .await + .unwrap() + }; + + let err = remote_account_provider + .try_get(pubkey, AccountFetchOrigin::GetAccount) + .await + .expect_err("Photon failure should not fall back to RPC NotFound"); + + assert!(matches!( + err, + RemoteAccountProviderError::AccountResolutionsFailed(_) + )); + assert!(err.to_string().contains("forced photon failure")); + } + #[tokio::test] async fn test_get_existing_account_for_valid_slot() { init_logger(); From 3d0934a42b762bcbdea225d4d92f19e3f082ec98 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 7 May 2026 15:04:24 +0200 Subject: [PATCH 072/110] fix: cpi limit catches compressed commits --- magicblock-committor-service/src/intent_executor/utils.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/magicblock-committor-service/src/intent_executor/utils.rs b/magicblock-committor-service/src/intent_executor/utils.rs index ea24005a3..33708bc4c 100644 --- a/magicblock-committor-service/src/intent_executor/utils.rs +++ b/magicblock-committor-service/src/intent_executor/utils.rs @@ -170,7 +170,9 @@ pub(in crate::intent_executor) fn handle_cpi_limit_error( let last_commit_ind = strategy.optimized_tasks.iter().rposition(|el| { matches!( el, - BaseTaskImpl::Commit(_) | BaseTaskImpl::CommitFinalize(_) + BaseTaskImpl::Commit(_) + | BaseTaskImpl::CommitFinalize(_) + | BaseTaskImpl::CommitFinalizeCompressed(_) ) }); let (mut commit_stage_tasks, mut finalize_stage_tasks) = (vec![], vec![]); From ffcf47b7e07a8e29245eb8acfd455d56bb11a9e2 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 7 May 2026 18:43:22 +0200 Subject: [PATCH 073/110] fix: intent bundle fee --- .../src/magic_scheduled_base_intent.rs | 57 +++++++++++++++++++ .../process_schedule_intent_bundle.rs | 22 +++++-- .../tests/utils/transactions.rs | 2 +- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 2c1b29c52..13e81f2a2 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -127,6 +127,20 @@ impl ScheduledIntentBundle { self.intent_bundle.get_all_committed_accounts() } + /// Returns all regular accounts that will be committed on Base layer, + /// including the one scheduled for undelegation + pub fn get_all_regular_committed_accounts(&self) -> Vec { + self.intent_bundle.get_all_regular_committed_accounts() + } + + /// Returns all compressed accounts that will be committed on Base layer, + /// including the one scheduled for undelegation + pub fn get_all_compressed_committed_accounts( + &self, + ) -> Vec { + self.intent_bundle.get_all_compressed_committed_accounts() + } + /// Returns pubkeys of all accounts that will be committed on Base layer, /// including the one scheduled for undelegation pub fn get_all_committed_pubkeys(&self) -> Vec { @@ -573,6 +587,49 @@ impl MagicIntentBundle { .collect() } + /// Returns all the compressed accounts that will be committed, + /// including the ones that will be undelegated as well + pub fn get_all_regular_committed_accounts(&self) -> Vec { + let committed = self.get_commit_intent_accounts(); + let undelegated = self.get_undelegate_intent_accounts(); + let commit_finalize = self.get_commit_finalize_intent_accounts(); + let commit_finalize_and_undelegate = + self.get_commit_finalize_and_undelegate_intent_accounts(); + + [ + committed, + undelegated, + commit_finalize, + commit_finalize_and_undelegate, + ] + .into_iter() + .flatten() + .flatten() + .cloned() + .collect() + } + + /// Returns all the compressed accounts that will be committed, + /// including the ones that will be undelegated as well + pub fn get_all_compressed_committed_accounts( + &self, + ) -> Vec { + let commit_finalize_compressed = + self.get_commit_finalize_compressed_intent_accounts(); + let commit_finalize_compressed_and_unde = self + .get_commit_finalize_compressed_and_undelegate_intent_accounts(); + + [ + commit_finalize_compressed, + commit_finalize_compressed_and_unde, + ] + .into_iter() + .flatten() + .flatten() + .cloned() + .collect() + } + pub fn get_all_committed_pubkeys(&self) -> Vec { [ self.get_commit_intent_pubkeys(), diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index 67653fa79..9087dfe47 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -94,6 +94,7 @@ pub(crate) fn process_schedule_intent_bundle( let undelegated_accounts_ref = [ args.commit_and_undelegate.as_ref(), args.commit_finalize_and_undelegate.as_ref(), + args.commit_finalize_compressed_and_undelegate.as_ref(), ] .into_iter() .flatten() @@ -142,17 +143,26 @@ pub(crate) fn process_schedule_intent_bundle( PAYER_IDX, MAGIC_CONTEXT_IDX + 1, )?; - let is_compressed = scheduled_intent.intent_bundle.is_compressed(); if let Some(magic_fee_vault) = magic_fee_vault { - let chargable_accounts = scheduled_intent.get_all_committed_accounts(); - let nonces = - fetch_current_commit_nonces(&chargable_accounts, is_compressed)?; - let fee = scheduled_intent.calculate_fee(&nonces)?; + let regular_chargable_accounts = + scheduled_intent.get_all_regular_committed_accounts(); + let regular_nonces = + fetch_current_commit_nonces(®ular_chargable_accounts, false)?; + let compressed_chargable_accounts = + scheduled_intent.get_all_compressed_committed_accounts(); + let compressed_nonces = + fetch_current_commit_nonces(&compressed_chargable_accounts, true)?; + let fee = scheduled_intent.calculate_fee(®ular_nonces)? + + scheduled_intent.calculate_fee(&compressed_nonces)?; charge_delegated_payer(&payer_account, &magic_fee_vault, fee)?; } else if let Some(commit_accounts) = scheduled_intent.get_commit_intent_accounts() { - check_commit_limits(commit_accounts, is_compressed, invoke_context)?; + check_commit_limits( + commit_accounts, + scheduled_intent.intent_bundle.is_compressed(), + invoke_context, + )?; } let action_sent_signature = scheduled_intent.sent_transaction.signatures[0]; diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index 30d4217a2..480a089ca 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -92,7 +92,7 @@ pub async fn fetch_tx_logs( // line: 0, column: 0)) // } // Therefore we retry a few times. - const MAX_RETRIES: usize = 10; + const MAX_RETRIES: usize = 50; let mut retries = MAX_RETRIES; let tx = loop { match rpc_client From b2c1f0a59a5fe6b63f0277f7db4781b4aeaca93c Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Thu, 7 May 2026 18:55:12 +0200 Subject: [PATCH 074/110] fix: use min context slot --- .../tests/test_ix_commit_local.rs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index e14eced94..ad5a8d35a 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -6,7 +6,9 @@ use std::{ use borsh::{to_vec, BorshDeserialize}; use compressed_delegation_client::CompressedDelegationRecord; -use light_client::indexer::{photon_indexer::PhotonIndexer, Indexer}; +use light_client::indexer::{ + photon_indexer::PhotonIndexer, Indexer, IndexerRpcConfig, +}; use magicblock_committor_service::{ config::ChainConfig, intent_executor::{error::IntentExecutorError, ExecutionOutput}, @@ -28,6 +30,7 @@ use solana_account::{Account, ReadableAccount}; use solana_commitment_config::CommitmentConfig; use solana_pubkey::Pubkey; use solana_rpc_client::nonblocking::rpc_client::RpcClient; +use solana_rpc_client_api::config::RpcTransactionConfig; use solana_sdk::{ hash::Hash, signature::Keypair, signer::Signer, transaction::Transaction, }; @@ -1290,9 +1293,25 @@ async fn ix_commit_local( } ); } else { + let min_context_slot = rpc_client + .get_transaction_with_config( + &commit_signature, + RpcTransactionConfig { + commitment: Some(CommitmentConfig::confirmed()), + max_supported_transaction_version: Some(0), + ..Default::default() + }, + ) + .await + .unwrap() + .slot; + let cda = derive_cda_from_pda(&account.pubkey); let compressed_account = photon_indexer - .get_compressed_account(cda.to_bytes(), None) + .get_compressed_account( + cda.to_bytes(), + Some(IndexerRpcConfig::new(min_context_slot)), + ) .await .unwrap() .value From 8ec8cb22e0794f08fa7133e6792a6645b1e0f8b6 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 8 May 2026 11:12:48 +0200 Subject: [PATCH 075/110] fix: light validator --- test-integration/test-runner/bin/run_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-integration/test-runner/bin/run_tests.rs b/test-integration/test-runner/bin/run_tests.rs index daa02cafb..487d388ed 100644 --- a/test-integration/test-runner/bin/run_tests.rs +++ b/test-integration/test-runner/bin/run_tests.rs @@ -571,7 +571,7 @@ fn run_table_mania_and_committor_tests( } Err(err) => { eprintln!("Failed to run {}: {:?}", label, err); - cleanup_devnet_only(&mut devnet_validator); + cleanup_light_validator(&mut light_validator); return Err(err.into()); } } From 9001180fe9a002f2daf1bcaf3a25312f8fa24c09 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 8 May 2026 11:28:26 +0200 Subject: [PATCH 076/110] fix: merge nonces --- .../magicblock/src/magic_scheduled_base_intent.rs | 10 ---------- .../process_schedule_intent_bundle.rs | 14 +++++++------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 13e81f2a2..fae26e426 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -771,16 +771,6 @@ impl MagicIntentBundle { self.standalone_actions.get_mut(index.checked_sub(offset)?) } - - pub fn is_compressed(&self) -> bool { - self.has_committed_accounts() - && (self.commit_finalize_compressed_and_undelegate.is_some() - || self.commit_finalize_compressed.is_some()) - && self.commit_finalize_and_undelegate.is_none() - && self.commit_finalize.is_none() - && self.commit_and_undelegate.is_none() - && self.commit.is_none() - } } impl MagicBaseIntent { diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index 9087dfe47..89c82b301 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -152,17 +152,17 @@ pub(crate) fn process_schedule_intent_bundle( scheduled_intent.get_all_compressed_committed_accounts(); let compressed_nonces = fetch_current_commit_nonces(&compressed_chargable_accounts, true)?; - let fee = scheduled_intent.calculate_fee(®ular_nonces)? - + scheduled_intent.calculate_fee(&compressed_nonces)?; + let mut commit_nonces = regular_nonces; + commit_nonces.extend(compressed_nonces); + let fee = scheduled_intent.calculate_fee(&commit_nonces)?; charge_delegated_payer(&payer_account, &magic_fee_vault, fee)?; } else if let Some(commit_accounts) = scheduled_intent.get_commit_intent_accounts() { - check_commit_limits( - commit_accounts, - scheduled_intent.intent_bundle.is_compressed(), - invoke_context, - )?; + // TODO(dode): Add commit limits for compressed commits + // Cost for compressed commits is small (~5000 lamports) + // but since compressed accounts have 0 lamports, we never take fees for them + check_commit_limits(commit_accounts, false, invoke_context)?; } let action_sent_signature = scheduled_intent.sent_transaction.signatures[0]; From 2550a77d962c082e2e01faa415b4d6b9d8a624ee Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 8 May 2026 12:01:27 +0200 Subject: [PATCH 077/110] feat: reduce retries --- .../test-committor-service/tests/utils/transactions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index 480a089ca..2f9aa79da 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -92,7 +92,7 @@ pub async fn fetch_tx_logs( // line: 0, column: 0)) // } // Therefore we retry a few times. - const MAX_RETRIES: usize = 50; + const MAX_RETRIES: usize = 5; let mut retries = MAX_RETRIES; let tx = loop { match rpc_client From 46953b491031d242e568d7aabb17e5ea0a22951f Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 8 May 2026 14:59:21 +0200 Subject: [PATCH 078/110] fix: setup light --- .github/workflows/ci-test-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-test-integration.yml b/.github/workflows/ci-test-integration.yml index b6bb47094..1aad8a9be 100644 --- a/.github/workflows/ci-test-integration.yml +++ b/.github/workflows/ci-test-integration.yml @@ -356,7 +356,7 @@ jobs: runs-on: ${{ matrix.runner || 'ubuntu-latest-m' }} env: SOLANA_VERSION: v3.1.5 - NEEDS_COMPRESSION_TOOLS: ${{ contains(fromJSON('["schedulecommit","chainlink","table_mania","committor"]'), matrix.batch_tests) }} + NEEDS_COMPRESSION_TOOLS: ${{ contains(fromJSON('["schedulecommit","chainlink","table_mania"]'), matrix.batch_tests) || startsWith(matrix.batch_tests, 'committor') }} strategy: matrix: include: From 1993af16353d4fb76eda79280172d5ccd98a52b6 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Sun, 10 May 2026 16:09:04 +0200 Subject: [PATCH 079/110] feat: update cdlp --- compressed-delegation-api/src/instruction.rs | 2 -- .../configs/schedulecommit-conf.devnet.toml | 4 ++++ .../compressed_delegation.so | Bin 172232 -> 173360 bytes 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compressed-delegation-api/src/instruction.rs b/compressed-delegation-api/src/instruction.rs index 64d95d4d3..819879e63 100644 --- a/compressed-delegation-api/src/instruction.rs +++ b/compressed-delegation-api/src/instruction.rs @@ -135,8 +135,6 @@ pub struct DelegateArgs { pub owner_program_id: Pubkey, /// Validator pub validator: Pubkey, - /// Original lamports of the account - pub lamports: u64, /// Account data before delegation pub account_data: Vec, /// PDA seeds diff --git a/test-integration/configs/schedulecommit-conf.devnet.toml b/test-integration/configs/schedulecommit-conf.devnet.toml index 2d3084f36..4f34d5b04 100644 --- a/test-integration/configs/schedulecommit-conf.devnet.toml +++ b/test-integration/configs/schedulecommit-conf.devnet.toml @@ -50,6 +50,10 @@ path = "../target/deploy/program_schedulecommit.so" id = "4RaQH3CUBMSMQsSHPVaww2ifeNEEuaDZjF9CUdFwr3xr" path = "../target/deploy/program_schedulecommit_security.so" +[[programs]] +id = "DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT" +path = "../programs/compressed_delegation/compressed_delegation.so" + [compression] photon-url = "http://localhost:8784" diff --git a/test-integration/programs/compressed_delegation/compressed_delegation.so b/test-integration/programs/compressed_delegation/compressed_delegation.so index 701b36fa3a6219791625073fff1a64f9022fd28c..7fe9c26a5b548fa572bdfd41510647ffc5c63676 100755 GIT binary patch delta 34456 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 delta 33507 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 Date: Sun, 10 May 2026 16:10:40 +0200 Subject: [PATCH 080/110] feat: prevent bundles without compression --- .../process_schedule_intent_bundle.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index 89c82b301..7d21994d6 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -24,6 +24,7 @@ use crate::{ get_instruction_account_with_idx, get_instruction_pubkey_with_idx, }, }, + validator::is_compression_enabled, MagicContext, }; @@ -33,6 +34,17 @@ pub(crate) fn process_schedule_intent_bundle( args: MagicIntentBundleArgs, secure: bool, ) -> Result<(), InstructionError> { + if !is_compression_enabled() + && (args.commit_finalize_compressed.is_some() + || args.commit_finalize_compressed_and_undelegate.is_some()) + { + ic_msg!( + invoke_context, + "ScheduleIntentBundle: compression is not enabled" + ); + return Err(InstructionError::InvalidInstructionData); + } + check_magic_context_id(invoke_context, MAGIC_CONTEXT_IDX)?; let parent_program_id = get_parent_program_id(invoke_context)?; From febfda46883e7c171f42af2ffb0925a7a60cfe29 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Sun, 10 May 2026 16:22:38 +0200 Subject: [PATCH 081/110] fix: unused parameter --- test-integration/programs/flexi-counter/src/processor.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/test-integration/programs/flexi-counter/src/processor.rs b/test-integration/programs/flexi-counter/src/processor.rs index 61fc02a2d..f7555759f 100644 --- a/test-integration/programs/flexi-counter/src/processor.rs +++ b/test-integration/programs/flexi-counter/src/processor.rs @@ -690,7 +690,6 @@ fn process_delegate_compressed( validator: args.validator.unwrap_or(DEFAULT_VALIDATOR_IDENTITY), validity_proof: args.validity_proof, account_meta: args.account_meta, - lamports: 0, account_data, pda_seeds: pda_seeds .iter() From f3a1b2203e5ba5513f8e3317566edd967c539725 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 18 May 2026 20:20:07 +0200 Subject: [PATCH 082/110] feat: update address derivation --- Cargo.lock | 2 -- compressed-delegation-client/Cargo.toml | 1 - magicblock-core/Cargo.toml | 1 - magicblock-core/src/compression.rs | 15 +++++---------- test-integration/Cargo.lock | 4 ---- test-integration/Cargo.toml | 1 - .../compressed_delegation.so | Bin 173360 -> 181216 bytes test-integration/test-chainlink/Cargo.toml | 1 - .../test-committor-service/Cargo.toml | 1 - 9 files changed, 5 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d6d4f338..4c7035b87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1314,7 +1314,6 @@ version = "0.9.0" dependencies = [ "borsh 1.6.1", "compressed-delegation-api", - "light-compressed-account", "light-hasher", "light-sdk", "light-sdk-types", @@ -4743,7 +4742,6 @@ dependencies = [ "console-subscriber", "flume", "light-client", - "light-compressed-account", "light-sdk", "magicblock-magic-program-api", "serde", diff --git a/compressed-delegation-client/Cargo.toml b/compressed-delegation-client/Cargo.toml index 306f195ac..1b674c20f 100644 --- a/compressed-delegation-client/Cargo.toml +++ b/compressed-delegation-client/Cargo.toml @@ -23,7 +23,6 @@ borsh = { workspace = true } light-hasher = { workspace = true } light-sdk = { workspace = true, features = ["v2"] } light-sdk-types = { workspace = true } -light-compressed-account = { workspace = true } num-derive = { workspace = true } num-traits = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } diff --git a/magicblock-core/Cargo.toml b/magicblock-core/Cargo.toml index ce1450cf2..ed44f561c 100644 --- a/magicblock-core/Cargo.toml +++ b/magicblock-core/Cargo.toml @@ -10,7 +10,6 @@ edition.workspace = true [dependencies] async-trait = { workspace = true } light-client = { workspace = true } -light-compressed-account = { workspace = true } light-sdk = { workspace = true, features = ["v2"] } compressed-delegation-client = { workspace = true } console-subscriber = { workspace = true, optional = true } diff --git a/magicblock-core/src/compression.rs b/magicblock-core/src/compression.rs index 3af81d64b..52cbee6eb 100644 --- a/magicblock-core/src/compression.rs +++ b/magicblock-core/src/compression.rs @@ -1,5 +1,4 @@ -use light_compressed_account::address::derive_address; -use light_sdk::light_hasher::hash_to_field_size::hashv_to_bn254_field_size_be_const_array; +use light_sdk::address::v2::derive_address; use solana_pubkey::Pubkey; // Light protocol V2 accounts: @@ -14,14 +13,10 @@ pub const OUTPUT_QUEUE: Pubkey = pub fn derive_cda_from_pda(pda: &Pubkey) -> Pubkey { // Since the PDA is already unique we use the delegation program's id // as a program id. - // SAFETY: BN254 hash of PDA must succeed for a 32-byte PDA seed - let seed = - hashv_to_bn254_field_size_be_const_array::<3>(&[&pda.to_bytes()]) - .expect("BN254 hash of PDA must succeed for a 32-byte PDA seed"); - let address = derive_address( - &seed, - &ADDRESS_TREE.to_bytes(), - &compressed_delegation_client::ID.to_bytes(), + let (address, _seed) = derive_address( + &[pda.as_array()], + &ADDRESS_TREE.to_bytes().into(), + &compressed_delegation_client::ID.to_bytes().into(), ); Pubkey::new_from_array(address) } diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 2b41b07cc..c63ae54b4 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -1617,7 +1617,6 @@ version = "0.9.0" dependencies = [ "borsh 1.6.1", "compressed-delegation-api", - "light-compressed-account", "light-hasher", "light-sdk", "light-sdk-types", @@ -5354,7 +5353,6 @@ dependencies = [ "compressed-delegation-client", "flume", "light-client", - "light-compressed-account", "light-sdk", "magicblock-magic-program-api 0.9.0", "serde", @@ -7823,7 +7821,6 @@ dependencies = [ "compressed-delegation-client", "futures", "light-client", - "light-compressed-account", "light-sdk", "light-sdk-types", "magicblock-committor-program", @@ -13547,7 +13544,6 @@ dependencies = [ "futures", "integration-test-tools", "light-client", - "light-compressed-account", "light-hasher", "light-sdk", "magicblock-chainlink", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 8cf543303..3d37b4295 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -47,7 +47,6 @@ integration-test-tools = { path = "test-tools" } isocountry = "0.3.2" lazy_static = "1.4.0" light-client = "0.23" -light-compressed-account = "0.11" light-hasher = "5" light-sdk = "0.23" light-sdk-types = "0.23" diff --git a/test-integration/programs/compressed_delegation/compressed_delegation.so b/test-integration/programs/compressed_delegation/compressed_delegation.so index 7fe9c26a5b548fa572bdfd41510647ffc5c63676..999850eadd7cd4b03982e0c002f568268fd9b366 100755 GIT binary patch delta 52962 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 V;oa4D!GBQhVJ??J@7qh_{y%1&GR*)0 delta 46120 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%0AWJWD>vE!U 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 diff --git a/test-integration/test-chainlink/Cargo.toml b/test-integration/test-chainlink/Cargo.toml index 626c74f1d..8bc22cc21 100644 --- a/test-integration/test-chainlink/Cargo.toml +++ b/test-integration/test-chainlink/Cargo.toml @@ -10,7 +10,6 @@ compressed-delegation-client = { workspace = true } futures = { workspace = true } tracing = { workspace = true } light-client = { workspace = true, features = ["v2"] } -light-compressed-account = { workspace = true } light-hasher = { workspace = true } light-sdk = { workspace = true, features = ["v2"] } magicblock-chainlink = { workspace = true } diff --git a/test-integration/test-committor-service/Cargo.toml b/test-integration/test-committor-service/Cargo.toml index b39e180b0..c7f07c7c6 100644 --- a/test-integration/test-committor-service/Cargo.toml +++ b/test-integration/test-committor-service/Cargo.toml @@ -10,7 +10,6 @@ compressed-delegation-client = { workspace = true } tracing = { workspace = true } futures = { workspace = true } light-client = { workspace = true, features = ["v2"] } -light-compressed-account = { workspace = true } light-sdk = { workspace = true, features = ["v2"] } light-sdk-types = { workspace = true, features = ["v2"] } magicblock-core = { workspace = true } From 5f2c72f41f3a83e3c7d5e1fc40fc3bfc1f9764f6 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 22 May 2026 18:00:02 +0200 Subject: [PATCH 083/110] fix: merge conflicts --- Cargo.lock | 1261 +++++++++++------ .../src/chainlink/fetch_cloner/delegation.rs | 24 - .../src/chainlink/fetch_cloner/mod.rs | 45 +- .../src/chainlink/fetch_cloner/pipeline.rs | 7 +- .../chainlink/fetch_cloner/subscription.rs | 22 +- .../src/chainlink/fetch_cloner/tests.rs | 97 +- .../src/chainlink/fetch_cloner/types.rs | 5 +- magicblock-chainlink/src/chainlink/mod.rs | 19 +- .../src/remote_account_provider/mod.rs | 38 +- .../src/remote_account_provider/tests.rs | 27 +- .../src/tasks/task_builder.rs | 142 +- .../src/instruction.rs | 32 - .../magicblock/src/magicblock_processor.rs | 22 +- .../process_schedule_commit.rs | 15 +- .../magicblock/src/utils/instruction_utils.rs | 70 - programs/magicblock/src/validator.rs | 5 +- test-integration/Cargo.lock | 857 ++++++----- .../programs/schedulecommit/src/lib.rs | 45 +- .../tests/02_commit_and_undelegate.rs | 8 +- .../tests/test_ix_commit_local.rs | 42 +- 20 files changed, 1550 insertions(+), 1233 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dac64e36b..6c9b4e357 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,10 +95,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d93caf9e6dd35ba4193fe778c1e52ee69433ba53b9eaeebc00c7bcd4d699081" dependencies = [ "log", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-signature 3.4.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-status", "thiserror 2.0.18", ] @@ -149,10 +149,10 @@ dependencies = [ "solana-account-info 3.1.1", "solana-big-mod-exp 3.0.0", "solana-blake3-hasher 3.1.0", - "solana-bn254", - "solana-clock 3.0.1", + "solana-bn254 3.2.1", + "solana-clock 3.1.0", "solana-cpi 3.1.0", - "solana-curve25519", + "solana-curve25519 3.1.12", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-keccak-hasher 3.1.0", @@ -175,7 +175,7 @@ dependencies = [ "solana-svm-type-overrides", "solana-sysvar 3.1.1", "solana-sysvar-id 3.1.0", - "solana-transaction-context", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", ] @@ -289,7 +289,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -300,7 +300,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -370,7 +370,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "itertools 0.13.0", "num-bigint 0.4.6", "num-integer", @@ -489,7 +489,7 @@ dependencies = [ "ark-std 0.5.0", "educe", "fnv", - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -557,6 +557,7 @@ checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ "num-traits", "rand 0.8.6", + "rayon", ] [[package]] @@ -682,9 +683,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "autotools" @@ -697,9 +698,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.16.3" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" dependencies = [ "aws-lc-sys", "zeroize", @@ -707,9 +708,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.40.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" dependencies = [ "cc", "cmake", @@ -926,7 +927,7 @@ dependencies = [ "cfg-if", "constant_time_eq", "cpufeatures 0.3.0", - "digest 0.11.2", + "digest 0.11.3", ] [[package]] @@ -1155,9 +1156,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.61" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -1165,12 +1166,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cexpr" version = "0.6.0" @@ -1338,7 +1333,7 @@ dependencies = [ [[package]] name = "compressed-delegation-api" -version = "0.9.0" +version = "0.11.1" dependencies = [ "borsh 1.6.1", "light-compressed-account", @@ -1349,7 +1344,7 @@ dependencies = [ [[package]] name = "compressed-delegation-client" -version = "0.9.0" +version = "0.11.1" dependencies = [ "borsh 1.6.1", "compressed-delegation-api", @@ -1386,6 +1381,19 @@ version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width 0.2.0", + "windows-sys 0.59.0", +] + [[package]] name = "console" version = "0.16.3" @@ -1407,7 +1415,7 @@ dependencies = [ "futures-core", "prost 0.14.3", "prost-types 0.14.3", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", "tracing-core", ] @@ -1432,7 +1440,7 @@ dependencies = [ "thread_local", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "tracing-core", "tracing-subscriber", @@ -1632,9 +1640,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", ] @@ -1896,12 +1904,12 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer 0.12.0", - "crypto-common 0.2.1", + "crypto-common 0.2.2", "ctutils", ] @@ -2038,9 +2046,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "elliptic-curve" @@ -2129,7 +2137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2231,13 +2239,12 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", - "libredox", ] [[package]] @@ -2252,7 +2259,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75b8549488b4715defcb0d8a8a1c1c76a80661b5fa106b4ca0e7fce59d7d875" dependencies = [ - "five8_core", + "five8_core 0.1.2", ] [[package]] @@ -2261,7 +2268,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23f76610e969fa1784327ded240f1e28a3fd9520c9cec93b636fcf62dd37f772" dependencies = [ - "five8_core", + "five8_core 1.0.0", ] [[package]] @@ -2270,7 +2277,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26dec3da8bc3ef08f2c04f61eab298c3ab334523e55f076354d6d6f613799a7b" dependencies = [ - "five8_core", + "five8_core 0.1.2", ] [[package]] @@ -2279,7 +2286,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a0f1728185f277989ca573a402716ae0beaaea3f76a8ff87ef9dd8fb19436c5" dependencies = [ - "five8_core", + "five8_core 1.0.0", ] [[package]] @@ -2288,6 +2295,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2551bf44bc5f776c15044b9b94153a00198be06743e262afaaa61f11ac7523a5" +[[package]] +name = "five8_core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059c31d7d36c43fe39d89e55711858b4da8be7eb6dabac23c7289b1a19489406" + [[package]] name = "fixedbitset" version = "0.4.2" @@ -2643,9 +2656,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", @@ -2689,9 +2702,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -2711,9 +2724,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hashlink" @@ -2721,7 +2734,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -2901,9 +2914,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" dependencies = [ "typenum", ] @@ -2942,7 +2955,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.13", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -3208,7 +3221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -3302,16 +3315,6 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" -[[package]] -name = "iri-string" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -3352,21 +3355,72 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ - "cesu8", + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ "cfg-if", "combine 4.6.7", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", ] [[package]] name = "jni-sys" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] [[package]] name = "jobserver" @@ -3380,9 +3434,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.97" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ "cfg-if", "futures-util", @@ -3454,11 +3508,11 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.4" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.1", "libc", ] @@ -3472,7 +3526,7 @@ dependencies = [ "futures", "laserstream-core-proto", "thiserror 1.0.69", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-health", ] @@ -3489,17 +3543,17 @@ dependencies = [ "protobuf-src", "solana-account 3.4.0", "solana-account-decoder", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signature 3.4.0", - "solana-transaction", - "solana-transaction-context", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "solana-transaction-error 3.2.0", "solana-transaction-status", - "tonic 0.14.5", - "tonic-build 0.14.5", + "tonic 0.14.6", + "tonic-build 0.14.6", "tonic-prost", "tonic-prost-build", ] @@ -3533,7 +3587,7 @@ dependencies = [ "num-format", "pretty-hex", "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signature 3.4.0", @@ -3589,7 +3643,7 @@ dependencies = [ "bitflags 2.11.1", "libc", "plain", - "redox_syscall 0.7.4", + "redox_syscall 0.7.5", ] [[package]] @@ -3830,7 +3884,7 @@ dependencies = [ "light-token-interface", "num-bigint 0.4.6", "photon-api", - "rand 0.8.5", + "rand 0.8.6", "reqwest 0.12.28", "serde_json", "smallvec", @@ -4374,7 +4428,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -4458,9 +4512,9 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-sysvar 3.1.1", - "solana-transaction", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -4480,7 +4534,7 @@ dependencies = [ "magicblock-program", "solana-hash 3.1.0", "solana-pubkey 3.0.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", @@ -4559,15 +4613,15 @@ dependencies = [ "solana-account 3.4.0", "solana-account-decoder", "solana-fee-structure", - "solana-keypair", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-pubsub-client", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", "solana-system-transaction", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "solana-transaction-status", "sonic-rs", @@ -4609,15 +4663,15 @@ dependencies = [ "num_cpus", "paste", "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cluster-type 3.1.0", - "solana-commitment-config", + "solana-commitment-config 3.1.1", "solana-feature-gate-interface 3.1.0", "solana-fee-calculator 3.2.0", "solana-genesis-config", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-native-token 3.0.0", "solana-program 3.0.0", @@ -4625,14 +4679,14 @@ dependencies = [ "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-rent 3.1.0", - "solana-rpc-client", + "solana-rpc-client 3.1.12", "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-system-program", "solana-sysvar 3.1.1", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "spl-token-interface", "thiserror 2.0.18", @@ -4654,6 +4708,7 @@ dependencies = [ "compressed-delegation-client", "futures-util", "helius-laserstream", + "light-client", "lru 0.16.4", "magicblock-accounts-db", "magicblock-aml", @@ -4664,17 +4719,17 @@ dependencies = [ "magicblock-magic-program-api", "magicblock-metrics", "parking_lot", - "rustls 0.23.38", + "rustls 0.23.40", "scc", "solana-account 3.4.0", "solana-account-decoder", - "solana-account-decoder-client-types", + "solana-account-decoder-client-types 3.1.12", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", - "solana-commitment-config", + "solana-clock 3.1.0", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", "solana-message 3.1.0", @@ -4682,21 +4737,21 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-pubsub-client", "solana-rent 3.1.0", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-sdk-ids 3.1.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-system-interface 3.2.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", - "spl-token-2022-interface", + "spl-token-2022-interface 2.1.0", "spl-token-interface", "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "url", ] @@ -4728,6 +4783,8 @@ dependencies = [ "compressed-delegation-client", "futures-util", "lazy_static", + "light-client", + "light-sdk", "lru 0.16.4", "magicblock-committor-program", "magicblock-core", @@ -4742,22 +4799,22 @@ dependencies = [ "solana-account 3.4.0", "solana-account-decoder", "solana-address-lookup-table-interface 3.1.0", - "solana-commitment-config", - "solana-compute-budget-interface", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-program 3.0.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-system-program", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", + "solana-transaction-status-client-types 3.1.12", "static_assertions", "tempfile", "test-kit", @@ -4781,7 +4838,7 @@ dependencies = [ "serde", "serde_with", "serial_test", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-pubkey 3.0.0", "solana-signer 3.0.0", "tempfile", @@ -4796,6 +4853,7 @@ dependencies = [ "async-trait", "bincode", "bytes", + "compressed-delegation-client", "console-subscriber", "flume", "light-client", @@ -4804,17 +4862,17 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-account-decoder", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-message 3.1.0", "solana-program 3.0.0", "solana-pubkey 3.0.0", "solana-signature 3.4.0", - "solana-transaction", - "solana-transaction-context", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", - "spl-token-2022-interface", + "solana-transaction-status-client-types 3.1.12", + "spl-token-2022-interface 2.1.0", "spl-token-interface", "thiserror 2.0.18", "tokio", @@ -4871,20 +4929,20 @@ dependencies = [ "rocksdb", "serde", "solana-account-decoder", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-metrics", "solana-pubkey 3.0.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-storage-proto", "solana-svm-measure", "solana-system-transaction", - "solana-transaction", - "solana-transaction-context", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "solana-transaction-error 3.2.0", "solana-transaction-status", "tempfile", @@ -4949,7 +5007,7 @@ dependencies = [ "solana-feature-gate-interface 3.1.0", "solana-fee-structure", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-program", "solana-precompile-error", @@ -4958,13 +5016,13 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-svm", "solana-svm-callback", "solana-svm-transaction", "solana-system-program", - "solana-transaction", - "solana-transaction-context", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "solana-transaction-error 3.2.0", "solana-transaction-status", "solana-zk-elgamal-proof-program", @@ -4992,23 +5050,23 @@ dependencies = [ "serial_test", "solana-account 3.4.0", "solana-account-info 3.1.1", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", - "solana-seed-derivable", + "solana-seed-derivable 3.0.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-svm-log-collector", "solana-sysvar 3.1.1", - "solana-transaction", - "solana-transaction-context", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "test-kit", "thiserror 2.0.18", ] @@ -5029,7 +5087,7 @@ dependencies = [ "notify", "serde", "solana-hash 3.1.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "tempfile", "thiserror 2.0.18", @@ -5045,18 +5103,18 @@ version = "0.11.1" dependencies = [ "futures-util", "solana-account 3.4.0", - "solana-account-decoder-client-types", + "solana-account-decoder-client-types 3.1.12", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", - "solana-commitment-config", + "solana-clock 3.1.0", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", + "solana-transaction-status-client-types 3.1.12", "thiserror 2.0.18", "tokio", "tracing", @@ -5071,13 +5129,13 @@ dependencies = [ "magicblock-core", "magicblock-magic-program-api", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", + "solana-rpc-client 3.1.12", "solana-signature 3.4.0", - "solana-signer", - "solana-transaction", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -5093,17 +5151,17 @@ dependencies = [ "rand 0.9.4", "sha3", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", - "solana-commitment-config", - "solana-compute-budget-interface", + "solana-clock 3.1.0", + "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signature 3.4.0", - "solana-signer", - "solana-slot-hashes 3.0.1", - "solana-transaction", + "solana-signer 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", "tracing", @@ -5124,10 +5182,10 @@ dependencies = [ "solana-instruction 3.4.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client", - "solana-rpc-client-api", + "solana-rpc-client 3.1.12", + "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", @@ -5180,11 +5238,11 @@ dependencies = [ "magicblock-delegation-program-api", "magicblock-program", "magicblock-rpc-client", - "solana-commitment-config", - "solana-rpc-client", + "solana-commitment-config 3.1.1", + "solana-rpc-client 3.1.12", "solana-signature 3.4.0", - "solana-signer", - "solana-transaction", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", "tokio", "tokio-util", "tracing", @@ -5389,9 +5447,9 @@ dependencies = [ [[package]] name = "no_std_io2" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" dependencies = [ "memchr", ] @@ -5448,7 +5506,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5508,9 +5566,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-derive" @@ -5632,15 +5690,14 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.78" +version = "0.10.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" dependencies = [ "bitflags 2.11.1", "cfg-if", "foreign-types", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -5679,9 +5736,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.114" +version = "0.9.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" +checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" dependencies = [ "cc", "libc", @@ -5721,9 +5778,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" [[package]] name = "pbkdf2" @@ -5798,7 +5855,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset 0.5.7", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "indexmap 2.14.0", ] @@ -5809,25 +5866,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95609d4f08f2cf86d6e41f5b483cfbbfd914099eb0f7c6ea15e98b358f4614f8" dependencies = [ "progenitor-client", - "reqwest 0.13.2", + "reqwest 0.13.3", "serde", "serde_json", ] [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", @@ -6029,7 +6086,7 @@ dependencies = [ "bytes", "futures-core", "percent-encoding", - "reqwest 0.13.2", + "reqwest 0.13.3", "serde", "serde_json", "serde_urlencoded", @@ -6107,7 +6164,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ "heck", - "itertools 0.13.0", + "itertools 0.14.0", "log", "multimap", "petgraph 0.8.3", @@ -6141,7 +6198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -6222,9 +6279,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" +checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ "bitflags 2.11.1", "memchr", @@ -6504,9 +6561,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" dependencies = [ "bitflags 2.11.1", ] @@ -6645,7 +6702,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.13", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -6679,6 +6736,47 @@ dependencies = [ "webpki-roots 1.0.7", ] +[[package]] +name = "reqwest" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.9.0", + "hyper-rustls 0.27.9", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.40", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tokio-rustls 0.26.4", + "tokio-util", + "tower 0.5.3", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "reqwest-middleware" version = "0.4.2" @@ -6743,7 +6841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73389e0c99e664f919275ab5b5b0471391fe9a8de61e1dff9b1eaf56a90f16e3" dependencies = [ "bytes", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "indexmap 2.14.0", "munge", "ptr_meta 0.3.1", @@ -6855,7 +6953,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6941,20 +7039,20 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.23.38", - "rustls-native-certs", + "rustls 0.23.40", + "rustls-native-certs 0.8.3", "rustls-platform-verifier-android", - "rustls-webpki 0.103.11", - "security-framework", + "rustls-webpki 0.103.13", + "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -6992,6 +7090,7 @@ version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -7195,9 +7294,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -7249,11 +7348,12 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ "base64 0.22.1", + "bs58", "chrono", "hex", "indexmap 1.9.3", @@ -7268,9 +7368,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -7446,6 +7546,16 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + [[package]] name = "simdutf8" version = "0.1.5" @@ -7487,7 +7597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7496,11 +7606,16 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f949fe4edaeaea78c844023bfc1c898e0b1f5a100f8a8d2d0f85d0a7b090258" dependencies = [ + "bincode", + "serde", + "serde_bytes", + "serde_derive", "solana-account-info 2.3.0", "solana-clock 2.2.3", "solana-instruction 2.3.3", "solana-pubkey 2.4.0", "solana-sdk-ids 2.2.1", + "solana-sysvar 2.3.0", ] [[package]] @@ -7513,7 +7628,7 @@ dependencies = [ "serde", "serde_bytes", "solana-account-info 3.1.1", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-instruction 3.4.0", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", @@ -7534,9 +7649,9 @@ dependencies = [ "serde", "serde_json", "solana-account 3.4.0", - "solana-account-decoder-client-types", + "solana-account-decoder-client-types 3.1.12", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-config-interface", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", @@ -7548,14 +7663,14 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", - "solana-slot-hashes 3.0.1", - "solana-slot-history 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-slot-history 3.0.1", "solana-stake-interface 2.0.2", "solana-sysvar 3.1.1", "solana-vote-interface 4.0.4", - "spl-generic-token", - "spl-token-2022-interface", - "spl-token-group-interface", + "spl-generic-token 2.0.1", + "spl-token-2022-interface 2.1.0", + "spl-token-group-interface 0.7.2", "spl-token-interface", "spl-token-metadata-interface 0.8.0", "thiserror 2.0.18", @@ -7690,12 +7805,12 @@ dependencies = [ "bytemuck", "serde", "serde_derive", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-instruction 3.4.0", "solana-instruction-error", "solana-pubkey 4.2.0", "solana-sdk-ids 3.1.0", - "solana-slot-hashes 3.0.1", + "solana-slot-hashes 3.0.2", ] [[package]] @@ -7843,7 +7958,7 @@ dependencies = [ "qualifier_attr", "solana-account 3.4.0", "solana-bincode 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-instruction 3.4.0", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", @@ -7853,12 +7968,12 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sbpf", "solana-sdk-ids 3.1.0", - "solana-svm-feature-set", + "solana-svm-feature-set 3.1.12", "solana-svm-log-collector", "solana-svm-measure", "solana-svm-type-overrides", "solana-system-interface 2.0.0", - "solana-transaction-context", + "solana-transaction-context 3.1.12", ] [[package]] @@ -7876,9 +7991,9 @@ dependencies = [ [[package]] name = "solana-clock" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95cf11109c3b6115cc510f1e31f06fdd52f504271bc24ef5f1249fbbcae5f9f3" +checksum = "5ea35d8f69b67daddb921a9da7f78ca591b533cf5e98833cd9ae62fdc2e4652c" dependencies = [ "serde", "serde_derive", @@ -7905,6 +8020,16 @@ dependencies = [ "solana-hash 4.3.0", ] +[[package]] +name = "solana-commitment-config" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac49c4dde3edfa832de1697e9bcdb7c3b3f7cb7a1981b7c62526c8bb6700fb73" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "solana-commitment-config" version = "3.1.1" @@ -7999,6 +8124,20 @@ dependencies = [ "solana-stable-layout 3.0.1", ] +[[package]] +name = "solana-curve25519" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae4261b9a8613d10e77ac831a8fa60b6fa52b9b103df46d641deff9f9812a23" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-define-syscall 2.3.0", + "subtle", + "thiserror 2.0.18", +] + [[package]] name = "solana-curve25519" version = "3.1.12" @@ -8046,6 +8185,17 @@ version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21e14a4f604117f379840956a8fc8695e4c84f5b0ebed192f31f60d9b85d581d" +[[package]] +name = "solana-derivation-path" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "939756d798b25c5ec3cca10e06212bdca3b1443cb9bb740a38124f58b258737b" +dependencies = [ + "derivation-path", + "qstring", + "uriparse", +] + [[package]] name = "solana-derivation-path" version = "3.0.0" @@ -8071,17 +8221,27 @@ dependencies = [ [[package]] name = "solana-epoch-info" -version = "3.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e093c84f6ece620a6b10cd036574b0cd51944231ab32d81f80f76d54aba833e6" +checksum = "90ef6f0b449290b0b9f32973eefd95af35b01c5c0c34c569f936c34c5b20d77b" dependencies = [ "serde", "serde_derive", ] [[package]] -name = "solana-epoch-rewards" -version = "2.2.1" +name = "solana-epoch-info" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e093c84f6ece620a6b10cd036574b0cd51944231ab32d81f80f76d54aba833e6" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-epoch-rewards" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" dependencies = [ @@ -8095,9 +8255,9 @@ dependencies = [ [[package]] name = "solana-epoch-rewards" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e7b0ba210593ba8ddd39d6d234d81795d1671cebf3026baa10d5dc23ac42f0" +checksum = "1cddf2388b28291210d9aa60690740733cab527531f06ed153c4d388951e407c" dependencies = [ "serde", "serde_derive", @@ -8184,7 +8344,7 @@ dependencies = [ "serde", "serde_derive", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-keccak-hasher 3.1.0", @@ -8268,9 +8428,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b04663357817fddb4755c6359005038c12e110ab04d1ac5048482551f95b160" +checksum = "4efd54c3f198403955addf2160af0ccc30294a04cf34e155c775d69960e1f0f6" dependencies = [ "proc-macro2", "quote", @@ -8287,20 +8447,20 @@ dependencies = [ "chrono", "memmap2 0.5.10", "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cluster-type 3.1.0", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", - "solana-inflation", - "solana-keypair", + "solana-inflation 3.1.0", + "solana-keypair 3.1.0", "solana-poh-config", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-shred-version", - "solana-signer", + "solana-signer 3.0.0", "solana-time-utils 3.0.0", ] @@ -8316,6 +8476,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63" dependencies = [ + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "five8 0.2.1", @@ -8376,6 +8537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bab5682934bd1f65f8d2c16f21cb532526fcc1a09f796e2cacdb091eee5774ad" dependencies = [ "bincode", + "borsh 1.6.1", "getrandom 0.2.17", "js-sys", "num-traits", @@ -8445,19 +8607,18 @@ dependencies = [ [[package]] name = "solana-instructions-sysvar" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddf67876c541aa1e21ee1acae35c95c6fbc61119814bfef70579317a5e26955" +checksum = "9e0732294560e88ecdb2bbc656e67383e9f88c78ec09469cef172f0d28cd1bcd" dependencies = [ "bitflags 2.11.1", "solana-account-info 3.1.1", "solana-instruction 3.4.0", "solana-instruction-error", "solana-program-error 3.0.1", - "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", "solana-sdk-ids 3.1.0", - "solana-serialize-utils 3.1.1", + "solana-serialize-utils 3.1.2", "solana-sysvar-id 3.1.0", ] @@ -8484,6 +8645,22 @@ dependencies = [ "solana-hash 4.3.0", ] +[[package]] +name = "solana-keypair" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd3f04aa1a05c535e93e121a95f66e7dcccf57e007282e8255535d24bf1e98bb" +dependencies = [ + "ed25519-dalek 1.0.1", + "five8 0.2.1", + "rand 0.7.3", + "solana-pubkey 2.4.0", + "solana-seed-phrase 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "wasm-bindgen", +] + [[package]] name = "solana-keypair" version = "3.1.0" @@ -8495,11 +8672,11 @@ dependencies = [ "five8 1.0.0", "rand 0.8.6", "solana-address 2.6.0", - "solana-derivation-path", - "solana-seed-derivable", - "solana-seed-phrase", + "solana-derivation-path 3.0.0", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", ] [[package]] @@ -8517,9 +8694,9 @@ dependencies = [ [[package]] name = "solana-last-restart-slot" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcda154ec827f5fc1e4da0af3417951b7e9b8157540f81f936c4a8b1156134d0" +checksum = "426711c6564b790026e45cabec3c64b971864c48b6b2d83c0ebf52a118bb4cda" dependencies = [ "serde", "serde_derive", @@ -8637,7 +8814,7 @@ dependencies = [ "solana-svm-log-collector", "solana-svm-measure", "solana-svm-type-overrides", - "solana-transaction-context", + "solana-transaction-context 3.1.12", ] [[package]] @@ -8769,11 +8946,20 @@ dependencies = [ "solana-sdk-ids 3.1.0", ] +[[package]] +name = "solana-nostd-keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ced70920435b1baa58f76e6f84bbc1110ddd1d6161ec76b6d731ae8431e9c4" +dependencies = [ + "sha3", +] + [[package]] name = "solana-nullable" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da028344c595c7416769ff648d206de7962571291a4cea24c38a60b6f40d53bb" +checksum = "a0f95d3028ef0f682bb174b77379c19d5dae2904a649f4a103fe29be7a139980" dependencies = [ "bytemuck", ] @@ -8791,7 +8977,7 @@ dependencies = [ "solana-sanitize 3.0.1", "solana-sha256-hasher 3.1.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", ] [[package]] @@ -8840,7 +9026,7 @@ checksum = "0f704eaf825be3180832445b9e4983b875340696e8e7239bf2d535b0f86c14a2" dependencies = [ "solana-pubkey 3.0.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", ] [[package]] @@ -8851,6 +9037,8 @@ checksum = "98eca145bd3545e2fbb07166e895370576e47a00a7d824e325390d33bf467210" dependencies = [ "bincode", "blake3", + "borsh 0.10.4", + "borsh 1.6.1", "bs58", "bytemuck", "console_error_panic_hook", @@ -8872,6 +9060,7 @@ dependencies = [ "solana-big-mod-exp 2.2.1", "solana-bincode 2.2.1", "solana-blake3-hasher 2.2.1", + "solana-borsh 2.2.1", "solana-clock 2.2.3", "solana-cpi 2.2.1", "solana-decode-error", @@ -8930,11 +9119,11 @@ dependencies = [ "solana-account-info 3.1.1", "solana-big-mod-exp 3.0.0", "solana-blake3-hasher 3.1.0", - "solana-borsh", - "solana-clock 3.0.1", + "solana-borsh 3.0.2", + "solana-clock 3.1.0", "solana-cpi 3.1.0", "solana-define-syscall 3.0.0", - "solana-epoch-rewards 3.0.1", + "solana-epoch-rewards 3.0.2", "solana-epoch-schedule 3.1.0", "solana-epoch-stake", "solana-example-mocks 3.0.0", @@ -8942,9 +9131,9 @@ dependencies = [ "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-instruction-error", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-keccak-hasher 3.1.0", - "solana-last-restart-slot 3.0.0", + "solana-last-restart-slot 3.0.1", "solana-msg 3.1.0", "solana-native-token 3.0.0", "solana-program-entrypoint 3.1.1", @@ -8957,11 +9146,11 @@ dependencies = [ "solana-sdk-ids 3.1.0", "solana-secp256k1-recover 3.1.1", "solana-serde-varint 3.0.1", - "solana-serialize-utils 3.1.1", + "solana-serialize-utils 3.1.2", "solana-sha256-hasher 3.1.0", "solana-short-vec 3.2.1", - "solana-slot-hashes 3.0.1", - "solana-slot-history 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-slot-history 3.0.1", "solana-stable-layout 3.0.1", "solana-sysvar 3.1.1", "solana-sysvar-id 3.1.0", @@ -8997,6 +9186,7 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" dependencies = [ + "borsh 1.6.1", "num-traits", "serde", "serde_derive", @@ -9079,20 +9269,20 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-account-info 3.1.1", - "solana-clock 3.0.1", - "solana-epoch-rewards 3.0.1", + "solana-clock 3.1.0", + "solana-epoch-rewards 3.0.2", "solana-epoch-schedule 3.1.0", "solana-fee-structure", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-last-restart-slot 3.0.0", + "solana-last-restart-slot 3.0.1", "solana-loader-v3-interface 6.1.1", "solana-program-entrypoint 3.1.1", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", "solana-sdk-ids 3.1.0", - "solana-slot-hashes 3.0.1", + "solana-slot-hashes 3.0.2", "solana-stable-layout 3.0.1", "solana-stake-interface 2.0.2", "solana-svm-callback", @@ -9105,7 +9295,7 @@ dependencies = [ "solana-system-interface 2.0.0", "solana-sysvar 3.1.1", "solana-sysvar-id 3.1.0", - "solana-transaction-context", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", ] @@ -9115,6 +9305,8 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1" dependencies = [ + "borsh 0.10.4", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", @@ -9165,10 +9357,10 @@ dependencies = [ "semver", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-clock 3.0.1", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client-types", + "solana-rpc-client-types 3.1.12", "solana-signature 3.4.0", "thiserror 2.0.18", "tokio", @@ -9213,6 +9405,16 @@ dependencies = [ "solana-sdk-macro 3.0.1", ] +[[package]] +name = "solana-reward-info" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18205b69139b1ae0ab8f6e11cdcb627328c0814422ad2482000fa2ca54ae4a2f" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "solana-reward-info" version = "3.0.0" @@ -9283,22 +9485,22 @@ dependencies = [ "serde_json", "solana-account 3.4.0", "solana-account-decoder", - "solana-account-decoder-client-types", - "solana-clock 3.0.1", - "solana-commitment-config", - "solana-epoch-info", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.1.0", + "solana-commitment-config 3.1.1", + "solana-epoch-info 3.1.0", "solana-epoch-schedule 3.1.0", "solana-feature-gate-interface 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-rpc-client-api", + "solana-rpc-client-api 3.1.12", "solana-signature 3.4.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", - "solana-version", + "solana-transaction-status-client-types 3.1.12", + "solana-version 3.1.12", "solana-vote-interface 4.0.4", "tokio", ] @@ -9337,12 +9539,38 @@ dependencies = [ "reqwest-middleware", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-clock 3.0.1", - "solana-rpc-client-types", - "solana-signer", + "solana-account-decoder-client-types 3.1.12", + "solana-clock 3.1.0", + "solana-rpc-client-types 3.1.12", + "solana-signer 3.0.0", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", + "solana-transaction-status-client-types 3.1.12", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-rpc-client-types" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea428a81729255d895ea47fba9b30fd4dacbfe571a080448121bd0592751676" +dependencies = [ + "base64 0.22.1", + "bs58", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account 2.2.1", + "solana-account-decoder-client-types 2.3.13", + "solana-clock 2.2.3", + "solana-commitment-config 2.2.1", + "solana-fee-calculator 2.2.1", + "solana-inflation 2.2.1", + "solana-pubkey 2.4.0", + "solana-transaction-error 2.2.1", + "solana-transaction-status-client-types 2.3.13", + "solana-version 2.3.13", + "spl-generic-token 1.0.1", "thiserror 2.0.18", ] @@ -9358,18 +9586,18 @@ dependencies = [ "serde", "serde_json", "solana-account 3.4.0", - "solana-account-decoder-client-types", + "solana-account-decoder-client-types 3.1.12", "solana-address 1.1.0", - "solana-clock 3.0.1", - "solana-commitment-config", + "solana-clock 3.1.0", + "solana-commitment-config 3.1.1", "solana-fee-calculator 3.2.0", - "solana-inflation", - "solana-reward-info", - "solana-transaction", + "solana-inflation 3.1.0", + "solana-reward-info 3.0.0", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", - "solana-version", - "spl-generic-token", + "solana-transaction-status-client-types 3.1.12", + "solana-version 3.1.12", + "spl-generic-token 2.0.1", "thiserror 2.0.18", ] @@ -9412,11 +9640,11 @@ dependencies = [ "bs58", "serde", "solana-account 3.4.0", - "solana-epoch-info", + "solana-epoch-info 3.1.0", "solana-epoch-rewards-hasher", "solana-fee-structure", - "solana-inflation", - "solana-keypair", + "solana-inflation 3.1.0", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-offchain-message", "solana-presigner", @@ -9426,16 +9654,16 @@ dependencies = [ "solana-sanitize 3.0.1", "solana-sdk-ids 3.1.0", "solana-sdk-macro 3.0.1", - "solana-seed-derivable", - "solana-seed-phrase", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", "solana-serde", "solana-serde-varint 3.0.1", "solana-short-vec 3.2.1", "solana-shred-version", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-time-utils 3.0.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] @@ -9530,6 +9758,21 @@ dependencies = [ "solana-sdk-ids 3.1.0", ] +[[package]] +name = "solana-security-txt" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94a02d486b28f219a4f8f5d7dd93cbfbb93c9f466cb7871c22e50cd5ae9a7a2" + +[[package]] +name = "solana-seed-derivable" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beb82b5adb266c6ea90e5cf3967235644848eac476c5a1f2f9283a143b7c97f" +dependencies = [ + "solana-derivation-path 2.2.1", +] + [[package]] name = "solana-seed-derivable" version = "3.0.0" @@ -9601,9 +9844,9 @@ dependencies = [ [[package]] name = "solana-serialize-utils" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7cc401931d178472358e6b78dc72d031dc08f752d7410f0e8bd259dd6f02fa" +checksum = "761357b0853c9623bf12c1d2314b3d6160a85b087b84c45224fb85766d22616b" dependencies = [ "solana-instruction-error", "solana-pubkey 4.2.0", @@ -9667,6 +9910,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c" dependencies = [ + "ed25519-dalek 1.0.1", "five8 0.2.1", "serde", "serde-big-array", @@ -9727,9 +9971,9 @@ dependencies = [ [[package]] name = "solana-slot-hashes" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2585f70191623887329dfb5078da3a00e15e3980ea67f42c2e10b07028419f43" +checksum = "0a57c158c35629f9e302ab385f16b15813f4927a31c27dda72f3df828bb08d93" dependencies = [ "serde", "serde_derive", @@ -9753,9 +9997,9 @@ dependencies = [ [[package]] name = "solana-slot-history" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f914f6b108f5bba14a280b458d023e3621c9973f27f015a4d755b50e88d89e97" +checksum = "0622d03a823770f7763afd866e012b296d5a3cbbbe51e110b5bd9ab3441efdca" dependencies = [ "bv", "serde", @@ -9790,6 +10034,8 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c" dependencies = [ + "borsh 0.10.4", + "borsh 1.6.1", "num-traits", "serde", "serde_derive", @@ -9812,7 +10058,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cpi 3.1.0", "solana-instruction 3.4.0", "solana-program-error 3.0.1", @@ -9838,7 +10084,7 @@ dependencies = [ "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signature 3.4.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "solana-transaction-status", "tonic-prost-build", @@ -9855,11 +10101,11 @@ dependencies = [ "qualifier_attr", "serde", "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-fee-structure", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", "solana-loader-v4-program", @@ -9881,9 +10127,9 @@ dependencies = [ "solana-svm-type-overrides", "solana-system-interface 2.0.0", "solana-sysvar-id 3.1.0", - "solana-transaction-context", + "solana-transaction-context 3.1.12", "solana-transaction-error 3.2.0", - "spl-generic-token", + "spl-generic-token 2.0.1", "thiserror 2.0.18", ] @@ -9894,7 +10140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb521c7f62db21661267a933f0d311a76b2b744a766b46f5a9a9395ce70f687c" dependencies = [ "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-precompile-error", "solana-pubkey 3.0.0", ] @@ -9948,7 +10194,7 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", "solana-signature 3.4.0", - "solana-transaction", + "solana-transaction 3.1.0", ] [[package]] @@ -10029,7 +10275,7 @@ dependencies = [ "solana-svm-type-overrides", "solana-system-interface 2.0.0", "solana-sysvar 3.1.1", - "solana-transaction-context", + "solana-transaction-context 3.1.12", ] [[package]] @@ -10039,12 +10285,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31b5699ec533621515e714f1533ee6b3b0e71c463301d919eb59b8c1e249d30" dependencies = [ "solana-hash 3.1.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signer 3.0.0", "solana-system-interface 2.0.0", - "solana-transaction", + "solana-transaction 3.1.0", ] [[package]] @@ -10098,14 +10344,14 @@ dependencies = [ "serde", "serde_derive", "solana-account-info 3.1.1", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-define-syscall 4.0.1", - "solana-epoch-rewards 3.0.1", + "solana-epoch-rewards 3.0.2", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", "solana-hash 4.3.0", "solana-instruction 3.4.0", - "solana-last-restart-slot 3.0.0", + "solana-last-restart-slot 3.0.1", "solana-program-entrypoint 3.1.1", "solana-program-error 3.0.1", "solana-program-memory 3.1.0", @@ -10113,8 +10359,8 @@ dependencies = [ "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", "solana-sdk-macro 3.0.1", - "solana-slot-hashes 3.0.1", - "solana-slot-history 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-slot-history 3.0.1", "solana-sysvar-id 3.1.0", ] @@ -10193,10 +10439,27 @@ dependencies = [ "solana-sdk-ids 3.1.0", "solana-short-vec 3.2.1", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "solana-transaction-error 3.2.0", ] +[[package]] +name = "solana-transaction-context" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a312304361987a85b2ef2293920558e6612876a639dd1309daf6d0d59ef2fe" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account 2.2.1", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-pubkey 2.4.0", + "solana-rent 2.2.1", + "solana-sdk-ids 2.2.1", +] + [[package]] name = "solana-transaction-context" version = "3.1.12" @@ -10207,7 +10470,7 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-instruction 3.4.0", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", @@ -10220,6 +10483,8 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "222a9dc8fdb61c6088baab34fc3a8b8473a03a7a5fd404ed8dd502fa79b67cb1" dependencies = [ + "serde", + "serde_derive", "solana-instruction 2.3.3", "solana-sanitize 2.2.1", ] @@ -10253,7 +10518,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-loader-v2-interface 3.0.0", @@ -10261,14 +10526,14 @@ dependencies = [ "solana-message 3.1.0", "solana-program-option 3.1.0", "solana-pubkey 3.0.0", - "solana-reward-info", + "solana-reward-info 3.0.0", "solana-sdk-ids 3.1.0", "solana-signature 3.4.0", "solana-stake-interface 2.0.2", "solana-system-interface 2.0.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", + "solana-transaction-status-client-types 3.1.12", "solana-vote-interface 4.0.4", "spl-associated-token-account-interface", "spl-memo-interface", @@ -10313,15 +10578,15 @@ dependencies = [ "bs58", "serde", "serde_json", - "solana-account-decoder-client-types", - "solana-commitment-config", + "solana-account-decoder-client-types 3.1.12", + "solana-commitment-config 3.1.1", "solana-instruction 3.4.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", - "solana-reward-info", + "solana-reward-info 3.0.0", "solana-signature 3.4.0", - "solana-transaction", - "solana-transaction-context", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "solana-transaction-error 3.2.0", "thiserror 2.0.18", ] @@ -10333,7 +10598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3324d46c7f7b7f5d34bf7dc71a2883bdc072c7b28ca81d0b2167ecec4cf8da9f" dependencies = [ "agave-feature-set 2.3.13", - "rand 0.8.5", + "rand 0.8.6", "semver", "serde", "serde_derive", @@ -10347,7 +10612,7 @@ version = "3.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f697aacc5aa4ac5534abdde8a91afdcf18c24d28bd52768e8001445dbda078db" dependencies = [ - "agave-feature-set", + "agave-feature-set 3.1.12", "rand 0.8.6", "semver", "serde", @@ -10392,7 +10657,7 @@ dependencies = [ "serde", "serde_derive", "serde_with", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-instruction-error", @@ -10400,16 +10665,16 @@ dependencies = [ "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", "solana-serde-varint 3.0.1", - "solana-serialize-utils 3.1.1", + "solana-serialize-utils 3.1.2", "solana-short-vec 3.2.1", "solana-system-interface 2.0.0", ] [[package]] name = "solana-zero-copy" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a91404c7de468dd80658cdb5d894ec803d1092ea6e2bfdf84eee6f07559c0d" +checksum = "8ea15126ebdc7e270c50d43884369af9f51d2308156d46a18e351522a164844d" dependencies = [ "borsh 1.6.1", "bytemuck", @@ -10450,7 +10715,7 @@ dependencies = [ "merlin", "num-derive", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_derive", "serde_json", @@ -10492,14 +10757,14 @@ dependencies = [ "serde_derive", "serde_json", "sha3", - "solana-derivation-path", + "solana-derivation-path 3.0.0", "solana-instruction 3.4.0", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", - "solana-seed-derivable", - "solana-seed-phrase", + "solana-seed-derivable 3.0.0", + "solana-seed-phrase 3.0.0", "solana-signature 3.4.0", - "solana-signer", + "solana-signer 3.0.0", "subtle", "thiserror 2.0.18", "wasm-bindgen", @@ -10570,7 +10835,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" dependencies = [ - "borsh", + "borsh 1.6.1", "solana-instruction 3.4.0", "solana-pubkey 3.0.0", ] @@ -10672,12 +10937,12 @@ dependencies = [ [[package]] name = "spl-memo-interface" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4e2aedd58f858337fa609af5ad7100d4a243fdaf6a40d6eb4c28c5f19505d3" +checksum = "3745d384b0afee980d43d62b66c27bdcbbd03507732b8d3626d3413cb72084f2" dependencies = [ "solana-instruction 3.4.0", - "solana-pubkey 3.0.0", + "solana-pubkey 4.2.0", ] [[package]] @@ -10858,13 +11123,59 @@ dependencies = [ "solana-program-pack 3.1.0", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", - "solana-zk-sdk", - "spl-pod", - "spl-token-confidential-transfer-proof-extraction", - "spl-token-confidential-transfer-proof-generation", - "spl-token-group-interface", - "spl-token-metadata-interface", - "spl-type-length-value", + "solana-zk-sdk 4.0.0", + "spl-pod 0.7.3", + "spl-token-confidential-transfer-proof-extraction 0.5.1", + "spl-token-confidential-transfer-proof-generation 0.5.1", + "spl-token-group-interface 0.7.2", + "spl-token-metadata-interface 0.8.0", + "spl-type-length-value 0.9.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-ciphertext-arithmetic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170378693c5516090f6d37ae9bad2b9b6125069be68d9acd4865bbe9fc8499fd" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "solana-curve25519 2.3.13", + "solana-zk-sdk 2.3.13", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff2d6a445a147c9d6dd77b8301b1e116c8299601794b558eafa409b342faf96" +dependencies = [ + "bytemuck", + "solana-curve25519 2.3.13", + "solana-program 2.3.0", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512c85bdbbb4cbcc2038849a9e164c958b16541f252b53ea1a3933191c0a4a1a" +dependencies = [ + "bytemuck", + "solana-account-info 2.3.0", + "solana-curve25519 2.3.13", + "solana-instruction 2.3.3", + "solana-instructions-sysvar 2.2.2", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "solana-sdk-ids 2.2.1", + "solana-zk-sdk 2.3.13", + "spl-pod 0.5.1", "thiserror 2.0.18", ] @@ -10876,15 +11187,37 @@ checksum = "879a9ebad0d77383d3ea71e7de50503554961ff0f4ef6cbca39ad126e6f6da3a" dependencies = [ "bytemuck", "solana-account-info 3.1.1", - "solana-curve25519", + "solana-curve25519 3.1.12", "solana-instruction 3.4.0", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-msg 3.1.0", "solana-program-error 3.0.1", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", - "solana-zk-sdk", - "spl-pod", + "solana-zk-sdk 4.0.0", + "spl-pod 0.7.3", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3597628b0d2fe94e7900fd17cdb4cfbb31ee35c66f82809d27d86e44b2848b" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk 2.3.13", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa27b9174bea869a7ebf31e0be6890bce90b1a4288bc2bbf24bd413f80ae3fde" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk 2.3.13", "thiserror 2.0.18", ] @@ -10976,6 +11309,48 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "spl-token-metadata-interface" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb9c89dbc877abd735f05547dcf9e6e12c00c11d6d74d8817506cab4c99fdbb" +dependencies = [ + "borsh 1.6.1", + "num-derive", + "num-traits", + "solana-borsh 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-type-length-value 0.7.0", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304d6e06f0de0c13a621464b1fd5d4b1bebf60d15ca71a44d3839958e0da16ee" +dependencies = [ + "borsh 1.6.1", + "num-derive", + "num-traits", + "solana-borsh 2.2.1", + "solana-decode-error", + "solana-instruction 2.3.3", + "solana-msg 2.2.1", + "solana-program-error 2.2.2", + "solana-pubkey 2.4.0", + "spl-discriminator 0.4.1", + "spl-pod 0.5.1", + "spl-type-length-value 0.8.0", + "thiserror 2.0.18", +] + [[package]] name = "spl-token-metadata-interface" version = "0.8.0" @@ -10985,7 +11360,7 @@ dependencies = [ "borsh 1.6.1", "num-derive", "num-traits", - "solana-borsh", + "solana-borsh 3.0.2", "solana-instruction 3.4.0", "solana-program-error 3.0.1", "solana-pubkey 3.0.0", @@ -11253,9 +11628,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.45" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -11272,7 +11647,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -11286,14 +11661,15 @@ dependencies = [ "magicblock-processor", "solana-account 3.4.0", "solana-instruction 3.4.0", - "solana-keypair", + "solana-keypair 3.1.0", "solana-program 3.0.0", - "solana-rpc-client", + "solana-pubkey 3.0.0", + "solana-rpc-client 3.1.12", "solana-signature 3.4.0", - "solana-signer", - "solana-transaction", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", - "solana-transaction-status-client-types", + "solana-transaction-status-client-types 3.1.12", "tempfile", "tokio", "tokio-util", @@ -11409,9 +11785,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -11505,7 +11881,7 @@ dependencies = [ "futures-io", "futures-sink", "futures-util", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "pin-project-lite", "slab", "tokio", @@ -11532,6 +11908,15 @@ dependencies = [ "webpki-roots 0.26.11", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.23" @@ -11585,7 +11970,7 @@ dependencies = [ "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.2", + "winnow 1.0.3", ] [[package]] @@ -11594,7 +11979,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.2", + "winnow 1.0.3", ] [[package]] @@ -11615,7 +12000,7 @@ dependencies = [ "base64 0.22.1", "bytes", "flate2", - "h2 0.4.13", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -11639,16 +12024,16 @@ dependencies = [ [[package]] name = "tonic" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum 0.8.9", "base64 0.22.1", "bytes", "flate2", - "h2 0.4.13", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -11685,9 +12070,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -11697,33 +12082,33 @@ dependencies = [ [[package]] name = "tonic-health" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ff0636fef47afb3ec02818f5bceb4377b8abb9d6a386aeade18bd6212f8eb7" +checksum = "fcfab99db777fba2802f0dfa861d1628d1ae916fb199d29819941f139ae85082" dependencies = [ "prost 0.14.3", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", ] [[package]] name = "tonic-prost" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost 0.14.3", - "tonic 0.14.5", + "tonic 0.14.6", ] [[package]] name = "tonic-prost-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -11732,7 +12117,7 @@ dependencies = [ "quote", "syn 2.0.117", "tempfile", - "tonic-build 0.14.5", + "tonic-build 0.14.6", ] [[package]] @@ -11776,9 +12161,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", "bitflags 2.11.1", @@ -11788,13 +12173,13 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "iri-string", "pin-project-lite", "tokio", "tokio-util", "tower 0.5.3", "tower-layer", "tower-service", + "url", ] [[package]] @@ -12176,9 +12561,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -12189,9 +12574,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.70" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ "js-sys", "wasm-bindgen", @@ -12199,9 +12584,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12209,9 +12594,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -12222,9 +12607,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -12278,9 +12663,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.97" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", @@ -12362,7 +12747,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -12373,9 +12758,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "wincode" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c754f1fc41250f2f742a27ba0fcc9f73df1dec23f6878490770855d43c322d" +checksum = "37095eb18dd6254c66217edc61a29d83d51f8818de8a2ffe88e4584ad73fb5f9" dependencies = [ "pastey", "proc-macro2", @@ -12386,9 +12771,9 @@ dependencies = [ [[package]] name = "wincode-derive" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e070787599c7c067b89598cd3eda440cca1b69eda9e0ff7c725fc8679ce9eb4" +checksum = "e262d55d1261f31e2cfe49cc6385a421d14d99faa0526bbe3cc1bda0d3005c62" dependencies = [ "darling 0.21.3", "proc-macro2", @@ -12541,15 +12926,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -12595,21 +12971,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -12667,12 +13028,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -12691,12 +13046,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -12715,12 +13064,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -12751,12 +13094,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -12775,12 +13112,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -12799,12 +13130,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -12823,12 +13148,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -12858,9 +13177,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] @@ -13069,9 +13388,9 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index d4921764b..29801418a 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use dlp_api::{ args::PostDelegationActions, decrypt::Decrypt, pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, @@ -186,12 +184,6 @@ where { let delegation_record_pubkey = delegation_record_pda_from_delegated_account(&account_pubkey); - let was_watching_deleg_record = this - .remote_account_provider - .is_watching(&delegation_record_pubkey); - let deleg_record_generation = this - .remote_account_provider - .subscription_generation(&delegation_record_pubkey); let acquired_delegation_record_reason = this .acquire_subscription_reason( @@ -239,22 +231,6 @@ where Err(_) => None, }; - if !was_watching_deleg_record { - // We only subscribed to fetch the delegation record, so unsubscribe now. - // Use the shared cancellation path so a concurrent explicit fetch can keep - // the subscription while its request is still pending. - cancel_subs( - &this.remote_account_provider, - CancelStrategy::OnlyIfUnchanged { - pubkeys: HashMap::from([( - delegation_record_pubkey, - deleg_record_generation, - )]), - }, - ) - .await; - } - let mut releases = Vec::new(); // Handle edge case where it was cloned in the meantime. // The small possibility of a fetch + clone of this delegation record being in process diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index e2c566997..c2f96909c 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -65,9 +65,8 @@ use self::{ }, subscription::{release_subs, SubscriptionRelease}, types::{ - AccountWithCompanion, ClassifiedAccounts, ExistingSubs, - PartitionedNotFound, RefreshDecision, ResolvedDelegatedAccounts, - ResolvedPrograms, + AccountWithCompanion, ClassifiedAccounts, PartitionedNotFound, + RefreshDecision, ResolvedDelegatedAccounts, ResolvedPrograms, }, }; use super::errors::{ChainlinkError, ChainlinkResult}; @@ -90,12 +89,6 @@ use crate::{ }, }; -type RemoteAccountRequests = Vec>; - -use self::pending_clone_guard::{ - CloneClaim, CloneCompletion, CloneKey, PendingCloneGuard, -}; - pub struct FetchCloner where T: ChainRpcClient, @@ -296,6 +289,13 @@ where .insert(pubkey); } + fn clear_post_undelegation_photon_merge_pending(&self, pubkey: Pubkey) { + self.post_undelegation_photon_merge_pending + .lock() + .expect("post_undelegation_photon_merge_pending lock poisoned") + .remove(&pubkey); + } + pub fn cloner(&self) -> &Arc { &self.cloner } @@ -1081,6 +1081,7 @@ where } async fn unsubscribe_from_delegated_account(&self, pubkey: Pubkey) { + self.clear_post_undelegation_photon_merge_pending(pubkey); self.release_subscription_reason_all( &pubkey, SubscriptionReason::UndelegationTracking, @@ -2030,6 +2031,11 @@ where record_subs, program_data_subs, ); + let delegated_cloned_pubkeys = accounts_to_clone + .iter() + .filter(|request| request.account.delegated()) + .map(|request| request.pubkey) + .collect::>(); pipeline::clone_accounts_and_programs( self, @@ -2039,6 +2045,26 @@ where .await?; release_subs(&self.remote_account_provider, releases).await; + for pubkey in delegated_cloned_pubkeys { + self.unsubscribe_from_delegated_account(pubkey).await; + } + + { + let mut pending = self + .post_undelegation_photon_merge_pending + .lock() + .expect("post_undelegation_photon_merge_pending lock poisoned"); + for pubkey in pubkeys { + if !pending.contains(pubkey) { + continue; + } + if self.accounts_bank.get_account(pubkey).is_some_and(|in_bank| { + !in_bank.delegated() && !in_bank.compressed() + }) { + pending.remove(pubkey); + } + } + } Ok(FetchAndCloneResult { not_found_on_chain: not_found, @@ -2614,6 +2640,7 @@ where pubkey: &Pubkey, ) -> ChainlinkResult<()> { trace!(pubkey = %pubkey, "Subscribing to account"); + self.mark_post_undelegation_photon_merge_pending(*pubkey); self.acquire_subscription_reason( pubkey, SubscriptionReason::UndelegationTracking, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index fc4eb1eb3..e31adef8e 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -1,7 +1,4 @@ -use std::{ - collections::{HashMap, HashSet}, - sync::atomic::Ordering, -}; +use std::{collections::HashSet, sync::atomic::Ordering}; use dlp_api::pda::delegation_record_pda_from_delegated_account; use magicblock_accounts_db::traits::AccountsBank; @@ -31,7 +28,7 @@ use crate::{ LOADER_V3, }, ChainPubsubClient, ChainRpcClient, MatchSlotsConfig, RemoteAccount, - ResolvedAccount, SubscriptionReason, + RemoteAccountUpdateSource, ResolvedAccount, SubscriptionReason, }, }; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs index 256b80c5c..87bb7eb5f 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs @@ -17,13 +17,14 @@ pub(crate) enum SubscriptionRelease { pubkey: Pubkey, reason: SubscriptionReason, }, - /// Cancel subscriptions for accounts that are explicitly subscribed to - /// and have not changed since the last snapshot. - OnlyIfUnchanged { pubkeys: HashMap }, } -pub(crate) async fn acquire_subs( - provider: &Arc>, +pub(crate) async fn acquire_subs< + T: ChainRpcClient, + U: ChainPubsubClient, + P: PhotonClient, +>( + provider: &Arc>, pubkeys: impl IntoIterator, reason: SubscriptionReason, ) -> ChainlinkResult<()> { @@ -49,8 +50,12 @@ pub(crate) async fn acquire_subs( } #[instrument(skip(provider, releases))] -pub(crate) async fn release_subs( - provider: &Arc>, +pub(crate) async fn release_subs< + T: ChainRpcClient, + U: ChainPubsubClient, + P: PhotonClient, +>( + provider: &Arc>, releases: impl IntoIterator, ) { for release in releases { @@ -66,8 +71,9 @@ pub(crate) async fn release_subs( pub(crate) async fn release_program_data_subs< T: ChainRpcClient, U: ChainPubsubClient, + P: PhotonClient, >( - provider: &Arc>, + provider: &Arc>, program_data_pubkey: Pubkey, ) { release_subs( diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index b3d928ba0..069303de2 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -276,6 +276,7 @@ async fn wait_for_pending_request( ChainPubsubClientMock, AccountsBankStub, ClonerStub, + PhotonClientMock, >, >, pubkey: Pubkey, @@ -300,6 +301,7 @@ async fn wait_for_pending_waiter_count( ChainPubsubClientMock, AccountsBankStub, ClonerStub, + PhotonClientMock, >, >, pubkey: Pubkey, @@ -551,7 +553,12 @@ async fn test_get_account_releases_delegation_record_direct_ref_when_already_wat .await .unwrap(); - let (resolved_account, delegation_record, _actions) = fetch_cloner + let ( + resolved_account, + delegation_record, + _actions, + _compressed_delegation_slot, + ) = fetch_cloner .resolve_account_to_clone_from_forwarded_sub_with_unsubscribe( ForwardedSubscriptionUpdate { pubkey: account_pubkey, @@ -1368,7 +1375,7 @@ async fn test_post_undelegation_plain_refresh_clears_photon_merge_marker() { accounts_bank .insert(account_pubkey, AccountSharedData::from(account.clone())); fetch_cloner - .subscribe_to_account(&account_pubkey) + .subscribe_to_account_to_track_undelegation(&account_pubkey) .await .expect("failed to subscribe to account"); assert_subscribed!(remote_account_provider, &[&account_pubkey]); @@ -1473,92 +1480,6 @@ async fn test_empty_compressed_subscription_update_skips_when_refetch_cannot_dec ); } -#[tokio::test] -async fn test_only_if_unchanged_cancellation_preserves_newer_subscription() { - init_logger(); - let validator_keypair = Keypair::new(); - const CURRENT_SLOT: u64 = 100; - - let FetcherTestCtx { - remote_account_provider, - .. - } = setup( - Vec::<(Pubkey, Account)>::new(), - CURRENT_SLOT, - validator_keypair.insecure_clone(), - ) - .await; - - use super::subscription::{cancel_subs, CancelStrategy}; - - let pubkey = random_pubkey(); - let generation_before_temporary_subscription = - remote_account_provider.subscription_generation(&pubkey); - - remote_account_provider - .subscribe_for_fetch(&pubkey) - .await - .expect("temporary subscription should succeed"); - remote_account_provider - .subscribe(&pubkey) - .await - .expect("newer subscription should succeed"); - - cancel_subs( - &remote_account_provider, - CancelStrategy::OnlyIfUnchanged { - pubkeys: HashMap::from([( - pubkey, - generation_before_temporary_subscription, - )]), - }, - ) - .await; - - assert_subscribed!(remote_account_provider, &[&pubkey]); -} - -#[tokio::test] -async fn test_only_if_unchanged_cancellation_removes_temporary_subscription() { - init_logger(); - let validator_keypair = Keypair::new(); - const CURRENT_SLOT: u64 = 100; - - let FetcherTestCtx { - remote_account_provider, - .. - } = setup( - Vec::<(Pubkey, Account)>::new(), - CURRENT_SLOT, - validator_keypair.insecure_clone(), - ) - .await; - - use super::subscription::{cancel_subs, CancelStrategy}; - - let pubkey = random_pubkey(); - let generation_before_temporary_subscription = - remote_account_provider.subscription_generation(&pubkey); - - remote_account_provider - .subscribe_for_fetch(&pubkey) - .await - .expect("temporary subscription should succeed"); - - cancel_subs( - &remote_account_provider, - CancelStrategy::OnlyIfUnchanged { - pubkeys: HashMap::from([( - pubkey, - generation_before_temporary_subscription, - )]), - }, - ) - .await; - - assert_not_subscribed!(remote_account_provider, &[&pubkey]); -} - #[tokio::test] async fn test_delegated_authoritative_skip_unsubscribes_subscription() { init_logger(); diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs index 44461f87a..00cae5229 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/types.rs @@ -1,7 +1,4 @@ -use std::{ - collections::{HashMap, HashSet}, - fmt, -}; +use std::{collections::HashSet, fmt}; use solana_account::AccountSharedData; use solana_pubkey::Pubkey; diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index 891e6ac56..c6c50876d 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -30,7 +30,10 @@ use crate::{ ChainRpcClientImpl, Endpoints, RemoteAccountProvider, }, submux::SubMuxClient, - testing::{cloner_stub::ClonerStub, rpc_client_mock::ChainRpcClientMock}, + testing::{ + cloner_stub::ClonerStub, photon_client_mock::PhotonClientMock, + rpc_client_mock::ChainRpcClientMock, + }, }; mod account_still_undelegating_on_chain; @@ -42,8 +45,18 @@ pub mod fetch_cloner; pub use blacklisted_accounts::*; /// A type alias for chainlink with only accountsdb being real impl -pub type StubbedChainlink = - Chainlink; +pub type StubbedChainlink = Chainlink< + ChainRpcClientMock, + ChainPubsubClientMock, + V, + ClonerStub, + PhotonClientMock, +>; + +type OptionalFetchCloner = + Option>>; +type OptionalFetchClonerRef<'a, T, U, V, C, P> = + Option<&'a Arc>>; // ----------------- // Chainlink diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 5e5911c95..65b0c6851 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -678,6 +678,7 @@ impl deferred_pubsubs, commitment, rpc_client.clone(), + photon_client.clone(), chain_slot.clone(), subscription_forwarder.clone(), config, @@ -713,6 +714,7 @@ impl Vec::new(), commitment, rpc_client, + photon_client, chain_slot, subscription_forwarder, config, @@ -723,11 +725,13 @@ impl } } + #[allow(clippy::too_many_arguments)] async fn try_new_from_pubsubs( startup_pubsubs: Vec, mut deferred_pubsubs: Vec, commitment: CommitmentConfig, rpc_client: ChainRpcClientImpl, + photon_client: Option, chain_slot: Arc, subscription_forwarder: mpsc::Sender, config: &RemoteAccountProviderConfig, @@ -735,6 +739,7 @@ impl RemoteAccountProvider< ChainRpcClientImpl, SubMuxClient, + PhotonClientImpl, >, Vec, )> { @@ -1391,34 +1396,6 @@ impl self.lrucache_subscribed_accounts.contains(pubkey) } - /// Returns the current explicit-watcher generation for `pubkey`. - /// - /// Callers that create temporary fetch subscriptions can snapshot this - /// value and later cancel only if it is unchanged, preserving any explicit - /// watcher that subscribed concurrently. - pub(crate) fn subscription_generation(&self, pubkey: &Pubkey) -> u64 { - self.subscription_generations - .lock() - .expect("subscription_generations lock poisoned") - .get(pubkey) - .copied() - .unwrap_or_default() - } - - /// Marks that an explicit watcher subscribed or renewed interest in - /// `pubkey`. - /// - /// This is deliberately separate from fetch-owned subscriptions: fetches may - /// subscribe only to resolve an account and should not prevent their own - /// cleanup from removing that temporary subscription. - fn bump_subscription_generation(&self, pubkey: &Pubkey) { - let mut generations = self - .subscription_generations - .lock() - .expect("subscription_generations lock poisoned"); - *generations.entry(*pubkey).or_default() += 1; - } - /// Check if an account is currently pending (being fetched) pub fn is_pending(&self, pubkey: &Pubkey) -> bool { let fetching = self.fetching_accounts.lock().unwrap(); @@ -1475,7 +1452,6 @@ impl existing.acquire(reason); } self.lrucache_subscribed_accounts.add(*pubkey); - self.bump_subscription_generation(pubkey); return Ok(()); } drop(ownership); @@ -1709,7 +1685,7 @@ impl { for sender in state.waiters { let error = RemoteAccountProviderError::AccountResolutionsFailed( - format!("{}: {}", pubkey, error_msg) + format!("{}: {}", pubkey, msg) ); let _ = sender.send(Err(error)); } @@ -1744,7 +1720,7 @@ impl generation, ) { - for request in waiters { + for request in state.waiters { let _ = request.send(Err( RemoteAccountProviderError::AccountResolutionsFailed(msg.clone()) )); diff --git a/magicblock-chainlink/src/remote_account_provider/tests.rs b/magicblock-chainlink/src/remote_account_provider/tests.rs index 81a59e1e4..958a64b08 100644 --- a/magicblock-chainlink/src/remote_account_provider/tests.rs +++ b/magicblock-chainlink/src/remote_account_provider/tests.rs @@ -15,6 +15,7 @@ use crate::{ }, testing::{ init_logger, + photon_client_mock::PhotonClientMock, rpc_client_mock::{ AccountAtSlot, ChainRpcClientMock, ChainRpcClientMockBuilder, }, @@ -23,8 +24,13 @@ use crate::{ }; struct ProviderTestCtx { - provider: - Arc>, + provider: Arc< + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, + >, rpc_client: ChainRpcClientMock, _pubsub_client: ChainPubsubClientMock, _forward_rx: mpsc::Receiver, @@ -60,6 +66,7 @@ async fn setup_provider_with_lru_capacity( RemoteAccountProvider::new( rpc_client.clone(), pubsub_client.clone(), + None, forward_tx, &config, subscribed_accounts, @@ -88,7 +95,11 @@ async fn setup_matching_slots( pubkey1: Pubkey, pubkey2: Pubkey, ) -> ( - RemoteAccountProvider, + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, mpsc::Receiver, ) { init_logger(); @@ -129,6 +140,7 @@ async fn setup_matching_slots( RemoteAccountProvider::new( rpc_client, pubsub_client, + None, forward_tx, &config, subscribed_accounts, @@ -765,6 +777,7 @@ async fn test_get_non_existing_account() { RemoteAccountProvider::new( rpc_client, pubsub_client, + None::, fwd_tx, &config, subscribed_accounts, @@ -816,6 +829,7 @@ async fn test_get_existing_account_for_valid_slot() { RemoteAccountProvider::new( rpc_client.clone(), pubsub_client, + None::, fwd_tx, &config, subscribed_accounts, @@ -1008,7 +1022,11 @@ async fn setup_with_accounts( pubkeys: &[Pubkey], accounts_capacity: usize, ) -> ( - RemoteAccountProvider, + RemoteAccountProvider< + ChainRpcClientMock, + ChainPubsubClientMock, + PhotonClientMock, + >, mpsc::Receiver, mpsc::Receiver, ) { @@ -1040,6 +1058,7 @@ async fn setup_with_accounts( let provider = RemoteAccountProvider::new( rpc_client, pubsub_client, + None, forward_tx, &config, subscribed_accounts, diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 8fa912c7c..a3f4e95e9 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -49,7 +49,8 @@ pub struct CommitStageTaskInfo { /// Base account state for diff calculation base_accounts: HashMap, /// Data used for compressed accounts - compressed_data: HashMap, + compressed_data: + HashMap>, } /// Task builder @@ -161,15 +162,15 @@ impl TaskBuilderImpl { async fn fetch_compressed_data( task_info_fetcher: &Arc, - accounts: &[(bool, bool, bool, CommittedAccount)], + accounts: &[(CommittedAccount, bool)], min_context_slot: u64, ) -> TaskInfoFetcherResult< HashMap>, > { let pubkeys = accounts .iter() - .filter(|(_, _, compressed, _)| *compressed) - .map(|(_, _, _, account)| account.pubkey) + .filter(|(_, compressed)| *compressed) + .map(|(account, _)| account.pubkey) .collect::>(); Ok(pubkeys .iter() @@ -192,6 +193,19 @@ impl TaskBuilderImpl { ) -> TaskBuilderResult { // Fetch necessary data for BaseTasks creation let all_committed_accounts = intent_bundle.get_all_committed_accounts(); + let all_regular_committed_accounts = + intent_bundle.get_all_regular_committed_accounts(); + let all_compressed_committed_accounts = + intent_bundle.get_all_compressed_committed_accounts(); + let flagged_accounts = all_regular_committed_accounts + .into_iter() + .map(|acc| (acc, false)) + .chain( + all_compressed_committed_accounts + .into_iter() + .map(|acc| (acc, true)), + ) + .collect::>(); // Get commit nonces and base accounts let min_context_slot = all_committed_accounts .iter() @@ -201,14 +215,14 @@ impl TaskBuilderImpl { let (commit_ids, base_accounts, compressed_data) = tokio::join!( Self::fetch_commit_nonces( task_info_fetcher, - &all_committed_accounts, + &flagged_accounts, min_context_slot ), Self::fetch_diffable_accounts( task_info_fetcher, - &all_committed_accounts, + &flagged_accounts, min_context_slot - ) + ), Self::fetch_compressed_data( task_info_fetcher, &flagged_accounts, @@ -221,7 +235,7 @@ impl TaskBuilderImpl { tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); Default::default() }); - let mut compressed_data = + let compressed_data = compressed_data.map_err(TaskBuilderError::CommitTasksBuildError)?; // Persist commit ids for commitees @@ -270,13 +284,13 @@ impl TaskBuilderImpl { pub fn create_commit_finalize_compressed_task( commit_id: u64, allow_undelegation: bool, - committed_account: CommittedAccount, + account: CommittedAccount, compressed_data: CompressedData, ) -> CommitFinalizeCompressedTask { CommitFinalizeCompressedTask { commit_id, allow_undelegation, - committed_account, + committed_account: account, compressed_data, } } @@ -358,19 +372,20 @@ impl TasksBuilder for TaskBuilderImpl { base_accounts: &mut base_accounts, compressed_data: &mut compressed_data, } - .build(value), + .build(value)?, ); } - if let Some(ref value) = - intent_bundle.intent_bundle.commit_and_undelegate_compressed + if let Some(ref value) = intent_bundle + .intent_bundle + .commit_finalize_compressed_and_undelegate { tasks.extend( - CommitAndUndelegateCompressedBuilder { + CommitFinalizeAndUndelegateCompressedBuilder { commit_nonces: &mut commit_nonces, base_accounts: &mut base_accounts, compressed_data: &mut compressed_data, } - .build(value), + .build(value)?, ); } @@ -605,6 +620,103 @@ impl<'a> CommitFinalizeAndUndelegateBuilder<'a> { } } +struct CommitFinalizeCompressedBuilder<'a> { + commit_nonces: &'a mut HashMap, + base_accounts: &'a mut HashMap, + compressed_data: + &'a mut HashMap>, +} + +impl<'a> CommitFinalizeCompressedBuilder<'a> { + fn build( + &mut self, + commit_type: &CommitType, + ) -> TaskBuilderResult> { + let mut tasks: Vec = commit_type + .get_committed_accounts() + .iter() + .map(|account| -> TaskBuilderResult { + let nonce = + take_commit_nonce(self.commit_nonces, account.pubkey); + let _base = self.base_accounts.remove(&account.pubkey); + let compressed_data = self + .compressed_data + .remove(&account.pubkey) + .ok_or( + TaskBuilderError::CommitFinalizeCompressedTasksBuildError( + TaskInfoFetcherError::MissingCompressedData, + ), + )??; + Ok( + TaskBuilderImpl::create_commit_finalize_compressed_task( + nonce, + false, + account.clone(), + compressed_data, + ) + .into(), + ) + }) + .collect::, _>>()?; + if let CommitType::WithBaseActions { + ref base_actions, .. + } = commit_type + { + tasks.extend(TaskBuilderImpl::create_action_tasks(base_actions)); + } + Ok(tasks) + } +} + +struct CommitFinalizeAndUndelegateCompressedBuilder<'a> { + commit_nonces: &'a mut HashMap, + base_accounts: &'a mut HashMap, + compressed_data: + &'a mut HashMap>, +} + +impl<'a> CommitFinalizeAndUndelegateCompressedBuilder<'a> { + fn build( + &mut self, + commit_and_undelegate: &CommitAndUndelegate, + ) -> TaskBuilderResult> { + let commit_type = &commit_and_undelegate.commit_action; + let mut tasks: Vec = commit_type + .get_committed_accounts() + .iter() + .map(|account| -> TaskBuilderResult { + let nonce = + take_commit_nonce(self.commit_nonces, account.pubkey); + let _base = self.base_accounts.remove(&account.pubkey); + let compressed_data = self + .compressed_data + .remove(&account.pubkey) + .ok_or( + TaskBuilderError::CommitFinalizeCompressedTasksBuildError( + TaskInfoFetcherError::MissingCompressedData, + ), + )??; + Ok( + TaskBuilderImpl::create_commit_finalize_compressed_task( + nonce, + true, + account.clone(), + compressed_data, + ) + .into(), + ) + }) + .collect::, _>>()?; + if let CommitType::WithBaseActions { + ref base_actions, .. + } = commit_type + { + tasks.extend(TaskBuilderImpl::create_action_tasks(base_actions)); + } + Ok(tasks) + } +} + fn take_commit_nonce( commit_nonces: &mut HashMap, pubkey: Pubkey, diff --git a/magicblock-magic-program-api/src/instruction.rs b/magicblock-magic-program-api/src/instruction.rs index bac7f2051..6e4c6b01b 100644 --- a/magicblock-magic-program-api/src/instruction.rs +++ b/magicblock-magic-program-api/src/instruction.rs @@ -311,38 +311,6 @@ pub enum MagicBlockInstruction { authority: Pubkey, instructions: Vec, }, - - /// Schedules the accounts provided at end of accounts Vec to be committed using compression. - /// It should be invoked from the program whose PDA accounts are to be - /// committed. - /// - /// This is the first part of scheduling a commit. - /// A second transaction [MagicBlockInstruction::AcceptScheduleCommits] has to run in order - /// to finish scheduling the commit. - /// - /// # Account references - /// - **0.** `[WRITE, SIGNER]` Payer requesting the commit to be scheduled - /// - **1.** `[WRITE]` Magic Context Account containing to which we store - /// the scheduled commits - /// - **2..n** `[]` Accounts to be committed - ScheduleCommitCompressed, - - /// This is the exact same instruction as [MagicBlockInstruction::ScheduleCommitCompressed] except - /// that the [ScheduledCommit] is flagged such that when accounts are committed, - /// they can later be undelegated. - /// Additionally the validator will refuse anymore transactions for the specific account - /// since they are no longer considered delegated to it. - /// - /// This is the first part of scheduling a commit. - /// A second transaction [MagicBlockInstruction::AcceptScheduleCommits] has to run in order - /// to finish scheduling the commit. - /// - /// # Account references - /// - **0.** `[WRITE, SIGNER]` Payer requesting the commit to be scheduled - /// - **1.** `[WRITE]` Magic Context Account containing to which we store - /// the scheduled commits - /// - **2..n** `[]` Accounts to be committed and undelegated - ScheduleCommitAndUndelegateCompressed, } impl MagicBlockInstruction { diff --git a/programs/magicblock/src/magicblock_processor.rs b/programs/magicblock/src/magicblock_processor.rs index b0f7992b4..6e1a2ac1f 100644 --- a/programs/magicblock/src/magicblock_processor.rs +++ b/programs/magicblock/src/magicblock_processor.rs @@ -74,7 +74,6 @@ declare_process_instruction!( invoke_context, ProcessScheduleCommitOptions { request_undelegation: false, - compressed: false, }, ), ScheduleCommitAndUndelegate => process_schedule_commit( @@ -82,7 +81,6 @@ declare_process_instruction!( invoke_context, ProcessScheduleCommitOptions { request_undelegation: true, - compressed: false, }, ), Unused => { @@ -234,24 +232,6 @@ declare_process_instruction!( &authority, instructions, ), - ScheduleCommitCompressed => process_schedule_commit_finalize( - signers, - invoke_context, - ProcessScheduleCommitOptions { - request_undelegation: false, - compressed: true, - }, - ), - ScheduleCommitAndUndelegateCompressed => { - process_schedule_commit_finalize( - signers, - invoke_context, - ProcessScheduleCommitOptions { - request_undelegation: true, - compressed: true, - }, - ) - } } } ); @@ -305,12 +285,14 @@ mod test { use magicblock_magic_program_api::args::ScheduleTaskArgs; use solana_instruction::AccountMeta; use solana_program_runtime::invoke_context::mock_process_instruction; + use solana_pubkey::Pubkey; use super::*; #[test] fn crank_entrypoint_decodes_execute_crank_before_account_validation() { let data = bincode::serialize(&MagicBlockInstruction::ExecuteCrank { + authority: Pubkey::new_unique(), instructions: vec![], }) .unwrap(); diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs index b5d811248..751c6ea45 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs @@ -32,7 +32,6 @@ use crate::{ #[derive(Default)] pub(crate) struct ProcessScheduleCommitOptions { pub request_undelegation: bool, - pub compressed: bool, } pub(crate) fn process_schedule_commit( @@ -40,11 +39,6 @@ pub(crate) fn process_schedule_commit( invoke_context: &mut InvokeContext, opts: ProcessScheduleCommitOptions, ) -> Result<(), InstructionError> { - if opts.compressed { - ic_msg!(invoke_context, "ScheduleCommit: compressed accounts are not supported for regular commits"); - return Err(InstructionError::InvalidInstructionData); - } - const PAYER_IDX: u16 = 0; const MAGIC_CONTEXT_IDX: u16 = PAYER_IDX + 1; @@ -257,18 +251,13 @@ pub(crate) fn process_schedule_commit( } if let Some(fee_vault) = magic_fee_vault { - let nonces = - fetch_current_commit_nonces(&committed_accounts, opts.compressed)?; + let nonces = fetch_current_commit_nonces(&committed_accounts, false)?; let fee = calculate_commit_fee(&committed_accounts, &nonces)?; charge_delegated_payer(&payer_account, &fee_vault, fee)?; } else if !opts.request_undelegation { // We validate commit nonces only for plain commits. // If accounts are undelegated we don't want to fail. - check_commit_limits( - &committed_accounts, - opts.compressed, - invoke_context, - )?; + check_commit_limits(&committed_accounts, false, invoke_context)?; } // NOTE: this is only protected by all the above checks however if the diff --git a/programs/magicblock/src/utils/instruction_utils.rs b/programs/magicblock/src/utils/instruction_utils.rs index e8c638051..ed9f06dfb 100644 --- a/programs/magicblock/src/utils/instruction_utils.rs +++ b/programs/magicblock/src/utils/instruction_utils.rs @@ -112,76 +112,6 @@ impl InstructionUtils { ) } - // ----------------- - // Schedule Commit and Undelegate Compressed - // ----------------- - #[cfg(test)] - pub fn schedule_commit_and_undelegate_compressed( - payer: &Keypair, - pubkeys: Vec, - recent_blockhash: Hash, - ) -> Transaction { - let ix = Self::schedule_commit_and_undelegate_compressed_instruction( - &payer.pubkey(), - pubkeys, - ); - Self::into_transaction(payer, ix, recent_blockhash) - } - - #[cfg(test)] - pub(crate) fn schedule_commit_and_undelegate_compressed_instruction( - payer: &Pubkey, - pdas: Vec, - ) -> Instruction { - let mut account_metas = vec![ - AccountMeta::new(*payer, true), - AccountMeta::new(MAGIC_CONTEXT_PUBKEY, false), - ]; - for pubkey in &pdas { - account_metas.push(AccountMeta::new(*pubkey, true)); - } - Instruction::new_with_bincode( - crate::id(), - &MagicBlockInstruction::ScheduleCommitAndUndelegateCompressed, - account_metas, - ) - } - - // ----------------- - // Schedule Commit Compressed - // ----------------- - #[cfg(test)] - pub fn schedule_commit_compressed( - payer: &Keypair, - pubkeys: Vec, - recent_blockhash: Hash, - ) -> Transaction { - let ix = Self::schedule_commit_compressed_instruction( - &payer.pubkey(), - pubkeys, - ); - Self::into_transaction(payer, ix, recent_blockhash) - } - - #[cfg(test)] - pub(crate) fn schedule_commit_compressed_instruction( - payer: &Pubkey, - pdas: Vec, - ) -> Instruction { - let mut account_metas = vec![ - AccountMeta::new(*payer, true), - AccountMeta::new(MAGIC_CONTEXT_PUBKEY, false), - ]; - for pubkey in &pdas { - account_metas.push(AccountMeta::new_readonly(*pubkey, true)); - } - Instruction::new_with_bincode( - crate::id(), - &MagicBlockInstruction::ScheduleCommitCompressed, - account_metas, - ) - } - // ----------------- // Scheduled Commit Sent // ----------------- diff --git a/programs/magicblock/src/validator.rs b/programs/magicblock/src/validator.rs index 94d34a6ab..9b7b6ac8c 100644 --- a/programs/magicblock/src/validator.rs +++ b/programs/magicblock/src/validator.rs @@ -1,4 +1,7 @@ -use std::sync::OnceLock; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + OnceLock, +}; use solana_keypair::Keypair; use solana_pubkey::Pubkey; diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 5f337c8e4..7a79d8765 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -118,7 +118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d93caf9e6dd35ba4193fe778c1e52ee69433ba53b9eaeebc00c7bcd4d699081" dependencies = [ "log", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-signature 3.4.0", "solana-transaction 3.1.0", @@ -200,7 +200,7 @@ dependencies = [ "regex", "semver", "solana-accounts-db", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-genesis-config", "solana-hash 3.1.0", "solana-lattice-hash", @@ -228,7 +228,7 @@ dependencies = [ "solana-big-mod-exp 3.0.0", "solana-blake3-hasher 3.1.0", "solana-bn254 3.2.1", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cpi 3.1.0", "solana-curve25519 3.1.12", "solana-hash 3.1.0", @@ -283,7 +283,7 @@ dependencies = [ "agave-logger", "serde", "solana-bls-signatures", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", ] @@ -397,7 +397,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -408,7 +408,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -535,7 +535,7 @@ dependencies = [ "ark-std 0.5.0", "educe 0.6.0", "fnv", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "itertools 0.13.0", "num-bigint 0.4.6", "num-integer", @@ -654,7 +654,7 @@ dependencies = [ "ark-std 0.5.0", "educe 0.6.0", "fnv", - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -826,7 +826,7 @@ dependencies = [ "once_cell", "pin-project", "portable-atomic", - "rand 0.8.5", + "rand 0.8.6", "regex", "ring", "rustls-native-certs 0.7.3", @@ -841,7 +841,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tokio-stream", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tokio-websockets", "tracing", "tryhard", @@ -898,9 +898,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "autotools" @@ -913,9 +913,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.16.3" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" dependencies = [ "aws-lc-sys", "zeroize", @@ -923,9 +923,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.40.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" dependencies = [ "cc", "cmake", @@ -1169,7 +1169,7 @@ dependencies = [ "cfg-if", "constant_time_eq", "cpufeatures 0.3.0", - "digest 0.11.2", + "digest 0.11.3", ] [[package]] @@ -1337,9 +1337,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bv" @@ -1445,9 +1445,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.61" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -1639,7 +1639,7 @@ dependencies = [ [[package]] name = "compressed-delegation-api" -version = "0.9.0" +version = "0.11.1" dependencies = [ "borsh 1.6.1", "light-compressed-account", @@ -1650,7 +1650,7 @@ dependencies = [ [[package]] name = "compressed-delegation-client" -version = "0.9.0" +version = "0.11.1" dependencies = [ "borsh 1.6.1", "compressed-delegation-api", @@ -1888,9 +1888,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", ] @@ -1943,7 +1943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix 0.31.2", + "nix 0.31.3", "windows-sys 0.61.2", ] @@ -2198,12 +2198,12 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer 0.12.0", - "crypto-common 0.2.1", + "crypto-common 0.2.2", "ctutils", ] @@ -2402,9 +2402,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "elliptic-curve" @@ -2532,12 +2532,12 @@ dependencies = [ "getrandom 0.2.17", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade)", "magicblock-magic-program-api 0.9.0", - "solana-account", - "solana-account-info", - "solana-cpi", - "solana-instruction", - "solana-program-error", - "solana-program-memory", + "solana-account 3.4.0", + "solana-account-info 3.1.1", + "solana-cpi 3.1.0", + "solana-instruction 3.4.0", + "solana-program-error 3.0.1", + "solana-program-memory 3.1.0", "solana-pubkey 3.0.0", "solana-system-interface 3.2.0", "solana-sysvar 3.1.1", @@ -2604,7 +2604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2649,7 +2649,7 @@ dependencies = [ "getrandom 0.3.4", "libm", "rand 0.9.4", - "siphasher 1.0.2", + "siphasher 1.0.3", ] [[package]] @@ -2740,13 +2740,12 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", - "libredox", ] [[package]] @@ -2761,7 +2760,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75b8549488b4715defcb0d8a8a1c1c76a80661b5fa106b4ca0e7fce59d7d875" dependencies = [ - "five8_core", + "five8_core 0.1.2", ] [[package]] @@ -2770,7 +2769,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23f76610e969fa1784327ded240f1e28a3fd9520c9cec93b636fcf62dd37f772" dependencies = [ - "five8_core", + "five8_core 1.0.0", ] [[package]] @@ -2779,7 +2778,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26dec3da8bc3ef08f2c04f61eab298c3ab334523e55f076354d6d6f613799a7b" dependencies = [ - "five8_core", + "five8_core 0.1.2", ] [[package]] @@ -2788,7 +2787,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a0f1728185f277989ca573a402716ae0beaaea3f76a8ff87ef9dd8fb19436c5" dependencies = [ - "five8_core", + "five8_core 1.0.0", ] [[package]] @@ -2797,6 +2796,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2551bf44bc5f776c15044b9b94153a00198be06743e262afaaa61f11ac7523a5" +[[package]] +name = "five8_core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059c31d7d36c43fe39d89e55711858b4da8be7eb6dabac23c7289b1a19489406" + [[package]] name = "fixedbitset" version = "0.4.2" @@ -2996,9 +3001,9 @@ checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" [[package]] name = "futures-util" @@ -3200,9 +3205,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", @@ -3252,12 +3257,11 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", - "equivalent", "foldhash 0.1.5", ] @@ -3274,9 +3278,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hashlink" @@ -3284,7 +3288,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -3463,9 +3467,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" dependencies = [ "typenum", ] @@ -3504,7 +3508,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.13", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -3580,7 +3584,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "native-tls", "tokio", @@ -3605,8 +3609,8 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", - "system-configuration", + "socket2 0.6.3", + "system-configuration 0.7.0", "tokio", "tower-service", "tracing", @@ -3805,7 +3809,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -3848,7 +3852,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "inotify-sys", "libc", ] @@ -3915,16 +3919,6 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" -[[package]] -name = "iri-string" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -4093,9 +4087,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.97" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ "cfg-if", "futures-util", @@ -4159,11 +4153,11 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.4" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.1", "libc", ] @@ -4177,7 +4171,7 @@ dependencies = [ "futures", "laserstream-core-proto", "thiserror 1.0.69", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-health", ] @@ -4194,7 +4188,7 @@ dependencies = [ "protobuf-src", "solana-account 3.4.0", "solana-account-decoder", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", @@ -4203,8 +4197,8 @@ dependencies = [ "solana-transaction-context 3.1.12", "solana-transaction-error 3.2.0", "solana-transaction-status", - "tonic 0.14.5", - "tonic-build 0.14.5", + "tonic 0.14.6", + "tonic-build 0.14.6", "tonic-prost", "tonic-prost-build", ] @@ -4282,7 +4276,7 @@ dependencies = [ "bitflags 2.11.1", "libc", "plain", - "redox_syscall 0.7.4", + "redox_syscall 0.7.5", ] [[package]] @@ -5249,7 +5243,7 @@ dependencies = [ "solana-account 3.4.0", "solana-account-decoder", "solana-fee-structure", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-rpc-client-api 3.1.12", @@ -5295,16 +5289,16 @@ dependencies = [ "magicblock-validator-admin", "num_cpus", "paste", - "solana-account", - "solana-clock", + "solana-account 3.4.0", + "solana-clock 3.1.0", "solana-cluster-type 3.1.0", - "solana-commitment-config", - "solana-feature-gate-interface", - "solana-fee-calculator", + "solana-commitment-config 3.1.1", + "solana-feature-gate-interface 3.1.0", + "solana-fee-calculator 3.2.0", "solana-genesis-config", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-native-token 3.0.0", "solana-program 3.0.0", @@ -5356,11 +5350,11 @@ dependencies = [ "solana-account-decoder", "solana-account-decoder-client-types 3.1.12", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", "solana-message 3.1.0", @@ -5382,7 +5376,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util 0.7.18", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "url", ] @@ -5431,7 +5425,7 @@ dependencies = [ "solana-compute-budget-interface 3.0.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-program 3.0.0", "solana-pubkey 3.0.0", @@ -5461,7 +5455,7 @@ dependencies = [ "isocountry", "serde", "serde_with", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-pubkey 3.0.0", "solana-signer 3.0.0", "toml 0.8.23", @@ -5475,12 +5469,15 @@ dependencies = [ "async-trait", "bincode", "bytes", + "compressed-delegation-client", "flume", + "light-client", + "light-sdk", "magicblock-magic-program-api 0.11.1", "serde", "solana-account 3.4.0", "solana-account-decoder", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-message 3.1.0", "solana-program 3.0.0", @@ -5575,7 +5572,7 @@ dependencies = [ "rocksdb", "serde", "solana-account-decoder", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-message 3.1.0", @@ -5598,9 +5595,10 @@ dependencies = [ [[package]] name = "magicblock-magic-program-api" version = "0.9.0" -source = "git+https://github.com/magicblock-labs/magicblock-validator.git?branch=bmuddha%2Fepic%2Fmigration-solana-v3#ef8ebb18879f0a3c41c11159eb5a5358dd3c89c0" +source = "git+https://github.com/magicblock-labs/magicblock-validator.git?branch=dode%2Fcompression-3x#febfda46883e7c171f42af2ffb0925a7a60cfe29" dependencies = [ "bincode", + "const-crypto", "serde", "solana-program 3.0.0", "solana-signature 3.4.0", @@ -5691,11 +5689,11 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-account-info 3.1.1", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", "solana-program-runtime", @@ -5705,14 +5703,10 @@ dependencies = [ "solana-signature 3.4.0", "solana-signer 3.0.0", "solana-svm-log-collector", - "solana-sysvar", - "solana-transaction", - "solana-transaction-context", + "solana-sysvar 3.1.1", + "solana-transaction 3.1.0", + "solana-transaction-context 3.1.12", "thiserror 2.0.18", - "tokio", - "tokio-util 0.7.17", - "tracing", - "url", ] [[package]] @@ -5731,11 +5725,11 @@ dependencies = [ "notify", "serde", "solana-hash 3.1.0", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", "url", ] @@ -5745,11 +5739,11 @@ name = "magicblock-rpc-client" version = "0.11.1" dependencies = [ "futures-util", - "solana-account", - "solana-account-decoder-client-types", - "solana-address-lookup-table-interface", - "solana-clock", - "solana-commitment-config", + "solana-account 3.4.0", + "solana-account-decoder-client-types 3.1.12", + "solana-address-lookup-table-interface 3.1.0", + "solana-clock 3.1.0", + "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-pubkey 3.0.0", @@ -5771,9 +5765,9 @@ dependencies = [ "futures-util", "magicblock-core", "magicblock-magic-program-api 0.11.1", - "solana-instruction", - "solana-keypair", - "solana-message", + "solana-instruction 3.4.0", + "solana-keypair 3.1.0", + "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-rpc-client 3.1.12", "solana-signature 3.4.0", @@ -5794,16 +5788,16 @@ dependencies = [ "rand 0.9.4", "sha3", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-compute-budget-interface 3.0.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signature 3.4.0", "solana-signer 3.0.0", - "solana-slot-hashes 3.0.1", + "solana-slot-hashes 3.0.2", "solana-transaction 3.1.0", "thiserror 2.0.18", "tokio", @@ -6075,10 +6069,10 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "openssl-sys", "schannel", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "tempfile", ] @@ -6096,6 +6090,18 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nkeys" version = "0.4.5" @@ -6105,9 +6111,9 @@ dependencies = [ "data-encoding", "ed25519 2.2.3", "ed25519-dalek 2.2.0", - "getrandom 0.2.16", + "getrandom 0.2.17", "log", - "rand 0.8.5", + "rand 0.8.6", "signatory", ] @@ -6119,9 +6125,9 @@ checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" [[package]] name = "no_std_io2" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" dependencies = [ "memchr", ] @@ -6154,7 +6160,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "fsevent-sys", "inotify", "kqueue", @@ -6172,7 +6178,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", ] [[package]] @@ -6190,7 +6196,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6199,7 +6205,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc895af95856f929163a0aa20c26a78d26bfdc839f51b9d5aa7a5b79e52b7e83" dependencies = [ - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -6250,9 +6256,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-derive" @@ -6407,15 +6413,14 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.78" +version = "0.10.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" dependencies = [ "bitflags 2.11.1", "cfg-if", "foreign-types", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -6431,6 +6436,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + [[package]] name = "openssl-probe" version = "0.2.1" @@ -6448,9 +6459,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.114" +version = "0.9.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" +checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" dependencies = [ "cc", "libc", @@ -6524,9 +6535,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" [[package]] name = "pbkdf2" @@ -6610,7 +6621,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset 0.5.7", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "indexmap 2.14.0", ] @@ -6628,18 +6639,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", @@ -6910,6 +6921,9 @@ dependencies = [ "compressed-delegation-api", "compressed-delegation-client", "ephemeral-rollups-sdk", + "light-hasher", + "light-sdk", + "light-sdk-types", "magicblock-magic-program-api 0.11.1", "serde", "solana-program 3.0.0", @@ -6936,8 +6950,8 @@ dependencies = [ "ephemeral-rollups-sdk", "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", "magicblock-magic-program-api 0.11.1", - "rkyv 0.7.45", - "solana-program", + "rkyv 0.7.46", + "solana-program 3.0.0", "solana-system-interface 3.2.0", "static_assertions", ] @@ -7139,9 +7153,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" +checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ "bitflags 2.11.1", "memchr", @@ -7442,9 +7456,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" dependencies = [ "bitflags 2.11.1", ] @@ -7583,12 +7597,12 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.12", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", - "hyper-rustls 0.27.8", + "hyper 1.9.0", + "hyper-rustls 0.27.9", "hyper-tls 0.6.0", "hyper-util", "js-sys", @@ -7722,7 +7736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73389e0c99e664f919275ab5b5b0471391fe9a8de61e1dff9b1eaf56a90f16e3" dependencies = [ "bytes", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "indexmap 2.14.0", "munge", "ptr_meta 0.3.1", @@ -7830,7 +7844,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7867,7 +7881,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", @@ -7876,15 +7890,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe", - "rustls-pemfile 2.2.0", + "openssl-probe 0.2.1", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework 3.7.0", ] [[package]] @@ -7926,14 +7939,14 @@ dependencies = [ "jni 0.21.1", "log", "once_cell", - "rustls 0.23.35", - "rustls-native-certs 0.8.2", + "rustls 0.23.40", + "rustls-native-certs 0.8.3", "rustls-platform-verifier-android", - "rustls-webpki 0.103.8", - "security-framework 3.5.1", + "rustls-webpki 0.103.13", + "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7948,13 +7961,13 @@ dependencies = [ "log", "once_cell", "rustls 0.23.40", - "rustls-native-certs", + "rustls-native-certs 0.8.3", "rustls-platform-verifier-android", "rustls-webpki 0.103.13", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7985,10 +7998,11 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -8192,6 +8206,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.11.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework" version = "3.7.0" @@ -8281,14 +8308,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", "serde", "serde_core", + "zmij", ] [[package]] @@ -8334,11 +8362,12 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ "base64 0.22.1", + "bs58", "chrono", "hex", "indexmap 1.9.3", @@ -8353,9 +8382,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -8397,7 +8426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -8545,9 +8574,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "sized-chunks" @@ -8619,7 +8648,7 @@ dependencies = [ "serde", "serde_bytes", "solana-account-info 3.1.1", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-instruction 3.4.0", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", @@ -8642,7 +8671,7 @@ dependencies = [ "solana-account 3.4.0", "solana-account-decoder-client-types 3.1.12", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-config-interface", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", @@ -8654,8 +8683,8 @@ dependencies = [ "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", - "solana-slot-hashes 3.0.1", - "solana-slot-history 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-slot-history 3.0.1", "solana-stake-interface 2.0.2", "solana-sysvar 3.1.1", "solana-vote-interface 4.0.4", @@ -8766,7 +8795,7 @@ dependencies = [ "solana-account 3.4.0", "solana-address-lookup-table-interface 3.1.0", "solana-bucket-map", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", "solana-genesis-config", @@ -8780,7 +8809,7 @@ dependencies = [ "solana-rayon-threadlimit", "solana-reward-info 3.0.0", "solana-sha256-hasher 3.1.0", - "solana-slot-hashes 3.0.1", + "solana-slot-hashes 3.0.2", "solana-svm-transaction", "solana-system-interface 2.0.0", "solana-sysvar 3.1.1", @@ -8855,12 +8884,12 @@ dependencies = [ "bytemuck", "serde", "serde_derive", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-instruction 3.4.0", "solana-instruction-error", "solana-pubkey 4.2.0", "solana-sdk-ids 3.1.0", - "solana-slot-hashes 3.0.1", + "solana-slot-hashes 3.0.2", ] [[package]] @@ -8891,7 +8920,7 @@ dependencies = [ "futures", "solana-account 3.4.0", "solana-banks-interface", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-message 3.1.0", @@ -8917,7 +8946,7 @@ checksum = "aeed8b00c1b30e10cada0de485c4c7aa2805bc54587d7fbfd4c89b9a6a2b7bb5" dependencies = [ "serde", "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-message 3.1.0", @@ -8942,7 +8971,7 @@ dependencies = [ "solana-account 3.4.0", "solana-banks-interface", "solana-client", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-hash 3.1.0", "solana-message 3.1.0", @@ -9110,7 +9139,7 @@ dependencies = [ "qualifier_attr", "solana-account 3.4.0", "solana-bincode 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-instruction 3.4.0", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", @@ -9141,7 +9170,7 @@ dependencies = [ "modular-bitfield", "num_enum", "rand 0.8.6", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-measure", "solana-pubkey 3.0.0", "tempfile", @@ -9208,7 +9237,7 @@ dependencies = [ "solana-epoch-info 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-measure", "solana-message 3.1.0", "solana-net-utils", @@ -9244,7 +9273,7 @@ dependencies = [ "solana-epoch-info 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signature 3.4.0", @@ -9269,9 +9298,9 @@ dependencies = [ [[package]] name = "solana-clock" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95cf11109c3b6115cc510f1e31f06fdd52f504271bc24ef5f1249fbbcae5f9f3" +checksum = "5ea35d8f69b67daddb921a9da7f78ca591b533cf5e98833cd9ae62fdc2e4652c" dependencies = [ "serde", "serde_derive", @@ -9412,7 +9441,7 @@ dependencies = [ "log", "rand 0.8.6", "rayon", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-measure", "solana-metrics 3.1.12", "solana-time-utils 3.0.0", @@ -9433,7 +9462,7 @@ dependencies = [ "solana-bincode 3.1.0", "solana-borsh 3.0.2", "solana-builtins-default-costs", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-compute-budget", "solana-compute-budget-instruction", "solana-compute-budget-interface 3.0.0", @@ -9608,9 +9637,9 @@ dependencies = [ [[package]] name = "solana-epoch-rewards" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e7b0ba210593ba8ddd39d6d234d81795d1671cebf3026baa10d5dc23ac42f0" +checksum = "1cddf2388b28291210d9aa60690740733cab527531f06ed153c4d388951e407c" dependencies = [ "serde", "serde_derive", @@ -9697,7 +9726,7 @@ dependencies = [ "serde", "serde_derive", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-keccak-hasher 3.1.0", @@ -9792,9 +9821,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b04663357817fddb4755c6359005038c12e110ab04d1ac5048482551f95b160" +checksum = "4efd54c3f198403955addf2160af0ccc30294a04cf34e155c775d69960e1f0f6" dependencies = [ "proc-macro2", "quote", @@ -9813,13 +9842,13 @@ dependencies = [ "serde", "serde_derive", "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cluster-type 3.1.0", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", "solana-hash 3.1.0", "solana-inflation 3.1.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-poh-config", "solana-pubkey 3.0.0", "solana-rent 3.1.0", @@ -9977,19 +10006,18 @@ dependencies = [ [[package]] name = "solana-instructions-sysvar" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddf67876c541aa1e21ee1acae35c95c6fbc61119814bfef70579317a5e26955" +checksum = "9e0732294560e88ecdb2bbc656e67383e9f88c78ec09469cef172f0d28cd1bcd" dependencies = [ "bitflags 2.11.1", "solana-account-info 3.1.1", "solana-instruction 3.4.0", "solana-instruction-error", "solana-program-error 3.0.1", - "solana-pubkey 3.0.0", "solana-sanitize 3.0.1", "solana-sdk-ids 3.1.0", - "solana-serialize-utils 3.1.1", + "solana-serialize-utils 3.1.2", "solana-sysvar-id 3.1.0", ] @@ -10013,7 +10041,23 @@ checksum = "ed1c0d16d6fdeba12291a1f068cdf0d479d9bff1141bf44afd7aa9d485f65ef8" dependencies = [ "sha3", "solana-define-syscall 4.0.1", - "solana-hash 4.2.0", + "solana-hash 4.3.0", +] + +[[package]] +name = "solana-keypair" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd3f04aa1a05c535e93e121a95f66e7dcccf57e007282e8255535d24bf1e98bb" +dependencies = [ + "ed25519-dalek 1.0.1", + "five8 0.2.1", + "rand 0.7.3", + "solana-pubkey 2.4.0", + "solana-seed-phrase 2.2.1", + "solana-signature 2.3.0", + "solana-signer 2.2.1", + "wasm-bindgen", ] [[package]] @@ -10025,7 +10069,7 @@ dependencies = [ "ed25519-dalek 2.2.0", "ed25519-dalek-bip32", "five8 1.0.0", - "rand 0.8.5", + "rand 0.8.6", "solana-address 2.6.0", "solana-derivation-path 3.0.0", "solana-seed-derivable 3.0.0", @@ -10049,9 +10093,9 @@ dependencies = [ [[package]] name = "solana-last-restart-slot" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcda154ec827f5fc1e4da0af3417951b7e9b8157540f81f936c4a8b1156134d0" +checksum = "426711c6564b790026e45cabec3c64b971864c48b6b2d83c0ebf52a118bb4cda" dependencies = [ "serde", "serde_derive", @@ -10375,9 +10419,9 @@ dependencies = [ [[package]] name = "solana-nullable" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da028344c595c7416769ff648d206de7962571291a4cea24c38a60b6f40d53bb" +checksum = "a0f95d3028ef0f682bb174b77379c19d5dae2904a649f4a103fe29be7a139980" dependencies = [ "bytemuck", ] @@ -10580,10 +10624,10 @@ dependencies = [ "solana-big-mod-exp 3.0.0", "solana-blake3-hasher 3.1.0", "solana-borsh 3.0.2", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cpi 3.1.0", "solana-define-syscall 3.0.0", - "solana-epoch-rewards 3.0.1", + "solana-epoch-rewards 3.0.2", "solana-epoch-schedule 3.1.0", "solana-epoch-stake", "solana-example-mocks 3.0.0", @@ -10591,9 +10635,9 @@ dependencies = [ "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-instruction-error", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-keccak-hasher 3.1.0", - "solana-last-restart-slot 3.0.0", + "solana-last-restart-slot 3.0.1", "solana-msg 3.1.0", "solana-native-token 3.0.0", "solana-program-entrypoint 3.1.1", @@ -10606,11 +10650,11 @@ dependencies = [ "solana-sdk-ids 3.1.0", "solana-secp256k1-recover 3.1.1", "solana-serde-varint 3.0.1", - "solana-serialize-utils 3.1.1", + "solana-serialize-utils 3.1.2", "solana-sha256-hasher 3.1.0", "solana-short-vec 3.2.1", - "solana-slot-hashes 3.0.1", - "solana-slot-history 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-slot-history 3.0.1", "solana-stable-layout 3.0.1", "solana-sysvar 3.1.1", "solana-sysvar-id 3.1.0", @@ -10745,20 +10789,20 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-account-info 3.1.1", - "solana-clock 3.0.1", - "solana-epoch-rewards 3.0.1", + "solana-clock 3.1.0", + "solana-epoch-rewards 3.0.2", "solana-epoch-schedule 3.1.0", "solana-fee-structure", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-last-restart-slot 3.0.0", + "solana-last-restart-slot 3.0.1", "solana-loader-v3-interface 6.1.1", "solana-program-entrypoint 3.1.1", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", "solana-sdk-ids 3.1.0", - "solana-slot-hashes 3.0.1", + "solana-slot-hashes 3.0.2", "solana-stable-layout 3.0.1", "solana-stake-interface 2.0.2", "solana-svm-callback", @@ -10797,17 +10841,17 @@ dependencies = [ "solana-banks-client", "solana-banks-interface", "solana-banks-server", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cluster-type 3.1.0", "solana-commitment-config 3.1.1", "solana-compute-budget", - "solana-epoch-rewards 3.0.1", + "solana-epoch-rewards 3.0.2", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", "solana-genesis-config", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-loader-v3-interface 6.1.1", "solana-message 3.1.0", "solana-msg 3.1.0", @@ -10899,7 +10943,7 @@ dependencies = [ "serde", "serde_json", "solana-account-decoder-client-types 3.1.12", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-pubkey 3.0.0", "solana-rpc-client-types 3.1.12", "solana-signature 3.4.0", @@ -10926,7 +10970,7 @@ dependencies = [ "log", "rustls 0.23.40", "solana-connection-cache", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-measure", "solana-metrics 3.1.12", "solana-net-utils", @@ -10947,7 +10991,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15319accf7d3afd845817aeffa6edd8cc185f135cefbc6b985df29cfd8c09609" dependencies = [ - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", ] [[package]] @@ -11076,7 +11120,7 @@ dependencies = [ "solana-account 3.4.0", "solana-account-decoder", "solana-account-decoder-client-types 3.1.12", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-epoch-info 3.1.0", "solana-epoch-schedule 3.1.0", @@ -11130,7 +11174,7 @@ dependencies = [ "serde", "serde_json", "solana-account-decoder-client-types 3.1.12", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-rpc-client-types 3.1.12", "solana-signer 3.0.0", "solana-transaction-error 3.2.0", @@ -11195,7 +11239,7 @@ dependencies = [ "solana-account 3.4.0", "solana-account-decoder-client-types 3.1.12", "solana-address 1.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-fee-calculator 3.2.0", "solana-inflation 3.1.0", @@ -11265,7 +11309,7 @@ dependencies = [ "solana-bucket-map", "solana-builtins", "solana-client-traits", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cluster-type 3.1.0", "solana-commitment-config 3.1.1", "solana-compute-budget", @@ -11287,7 +11331,7 @@ dependencies = [ "solana-hash 3.1.0", "solana-inflation 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-lattice-hash", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", @@ -11315,8 +11359,8 @@ dependencies = [ "solana-sha256-hasher 3.1.0", "solana-signature 3.4.0", "solana-signer 3.0.0", - "solana-slot-hashes 3.0.1", - "solana-slot-history 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-slot-history 3.0.1", "solana-stake-interface 2.0.2", "solana-svm", "solana-svm-callback", @@ -11410,7 +11454,7 @@ dependencies = [ "solana-epoch-rewards-hasher", "solana-fee-structure", "solana-inflation 3.1.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-offchain-message", "solana-presigner", @@ -11526,12 +11570,9 @@ dependencies = [ [[package]] name = "solana-security-txt" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "156bb61a96c605fa124e052d630dba2f6fb57e08c7d15b757e1e958b3ed7b3fe" -dependencies = [ - "hashbrown 0.15.2", -] +checksum = "c94a02d486b28f219a4f8f5d7dd93cbfbb93c9f466cb7871c22e50cd5ae9a7a2" [[package]] name = "solana-seed-derivable" @@ -11584,10 +11625,10 @@ dependencies = [ "itertools 0.12.1", "log", "solana-client", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-connection-cache", "solana-hash 3.1.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-measure", "solana-metrics 3.1.12", "solana-nonce-account", @@ -11641,9 +11682,9 @@ dependencies = [ [[package]] name = "solana-serialize-utils" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7cc401931d178472358e6b78dc72d031dc08f752d7410f0e8bd259dd6f02fa" +checksum = "761357b0853c9623bf12c1d2314b3d6160a85b087b84c45224fb85766d22616b" dependencies = [ "solana-instruction-error", "solana-pubkey 4.2.0", @@ -11768,9 +11809,9 @@ dependencies = [ [[package]] name = "solana-slot-hashes" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2585f70191623887329dfb5078da3a00e15e3980ea67f42c2e10b07028419f43" +checksum = "0a57c158c35629f9e302ab385f16b15813f4927a31c27dda72f3df828bb08d93" dependencies = [ "serde", "serde_derive", @@ -11794,9 +11835,9 @@ dependencies = [ [[package]] name = "solana-slot-history" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f914f6b108f5bba14a280b458d023e3621c9973f27f015a4d755b50e88d89e97" +checksum = "0622d03a823770f7763afd866e012b296d5a3cbbbe51e110b5bd9ab3441efdca" dependencies = [ "bv", "serde", @@ -11855,7 +11896,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-cpi 3.1.0", "solana-instruction 3.4.0", "solana-program-error 3.0.1", @@ -11914,7 +11955,7 @@ dependencies = [ "rustls 0.23.40", "smallvec", "socket2 0.6.3", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-measure", "solana-metrics 3.1.12", "solana-net-utils", @@ -11945,11 +11986,11 @@ dependencies = [ "qualifier_attr", "serde", "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-fee-structure", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-loader-v3-interface 6.1.1", "solana-loader-v4-interface 3.1.0", "solana-loader-v4-program", @@ -11984,7 +12025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb521c7f62db21661267a933f0d311a76b2b744a766b46f5a9a9395ce70f687c" dependencies = [ "solana-account 3.4.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-precompile-error", "solana-pubkey 3.0.0", ] @@ -12129,7 +12170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31b5699ec533621515e714f1533ee6b3b0e71c463301d919eb59b8c1e249d30" dependencies = [ "solana-hash 3.1.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-message 3.1.0", "solana-pubkey 3.0.0", "solana-signer 3.0.0", @@ -12188,14 +12229,14 @@ dependencies = [ "serde", "serde_derive", "solana-account-info 3.1.1", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-define-syscall 4.0.1", - "solana-epoch-rewards 3.0.1", + "solana-epoch-rewards 3.0.2", "solana-epoch-schedule 3.1.0", "solana-fee-calculator 3.2.0", "solana-hash 4.3.0", "solana-instruction 3.4.0", - "solana-last-restart-slot 3.0.0", + "solana-last-restart-slot 3.0.1", "solana-program-entrypoint 3.1.1", "solana-program-error 3.0.1", "solana-program-memory 3.1.0", @@ -12203,8 +12244,8 @@ dependencies = [ "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", "solana-sdk-macro 3.0.1", - "solana-slot-hashes 3.0.1", - "solana-slot-history 3.0.0", + "solana-slot-hashes 3.0.2", + "solana-slot-history 3.0.1", "solana-sysvar-id 3.1.0", ] @@ -12247,7 +12288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57a74352404ca3378d3bc6586a9a1e0d7362b687ce2218a0b646dccb767c7ba2" dependencies = [ "rustls 0.23.40", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-pubkey 3.0.0", "solana-signer 3.0.0", "x509-parser", @@ -12267,7 +12308,7 @@ dependencies = [ "log", "rayon", "solana-client-traits", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-commitment-config 3.1.1", "solana-connection-cache", "solana-epoch-schedule 3.1.0", @@ -12298,9 +12339,9 @@ dependencies = [ "log", "lru 0.7.8", "rustls 0.23.40", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-connection-cache", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-measure", "solana-metrics 3.1.12", "solana-quic-definitions", @@ -12388,7 +12429,7 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-instruction 3.4.0", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sbpf", @@ -12452,7 +12493,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-address-lookup-table-interface 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-loader-v2-interface 3.0.0", @@ -12533,7 +12574,7 @@ checksum = "b32651092f28c7fa9fb622a055f21fcfb1a109e6851d964ce043336a0035a629" dependencies = [ "async-trait", "solana-connection-cache", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-net-utils", "solana-streamer", "solana-transaction-error 3.2.0", @@ -12595,14 +12636,14 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-bincode 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-packet", "solana-pubkey 3.0.0", "solana-sdk-ids 3.1.0", - "solana-serialize-utils 3.1.1", + "solana-serialize-utils 3.1.2", "solana-signature 3.4.0", "solana-signer 3.0.0", "solana-svm-transaction", @@ -12648,7 +12689,7 @@ dependencies = [ "serde", "serde_derive", "serde_with", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", "solana-instruction-error", @@ -12656,7 +12697,7 @@ dependencies = [ "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", "solana-serde-varint 3.0.1", - "solana-serialize-utils 3.1.1", + "solana-serialize-utils 3.1.2", "solana-short-vec 3.2.1", "solana-system-interface 2.0.0", ] @@ -12675,18 +12716,18 @@ dependencies = [ "serde", "solana-account 3.4.0", "solana-bincode 3.1.0", - "solana-clock 3.0.1", + "solana-clock 3.1.0", "solana-epoch-schedule 3.1.0", "solana-hash 3.1.0", "solana-instruction 3.4.0", - "solana-keypair 3.1.2", + "solana-keypair 3.1.0", "solana-packet", "solana-program-runtime", "solana-pubkey 3.0.0", "solana-rent 3.1.0", "solana-sdk-ids 3.1.0", "solana-signer 3.0.0", - "solana-slot-hashes 3.0.1", + "solana-slot-hashes 3.0.2", "solana-transaction 3.1.0", "solana-transaction-context 3.1.12", "solana-vote-interface 4.0.4", @@ -12695,9 +12736,9 @@ dependencies = [ [[package]] name = "solana-zero-copy" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a91404c7de468dd80658cdb5d894ec803d1092ea6e2bfdf84eee6f07559c0d" +checksum = "8ea15126ebdc7e270c50d43884369af9f51d2308156d46a18e351522a164844d" dependencies = [ "borsh 1.6.1", "bytemuck", @@ -13020,12 +13061,12 @@ dependencies = [ [[package]] name = "spl-memo-interface" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4e2aedd58f858337fa609af5ad7100d4a243fdaf6a40d6eb4c28c5f19505d3" +checksum = "3745d384b0afee980d43d62b66c27bdcbbd03507732b8d3626d3413cb72084f2" dependencies = [ "solana-instruction 3.4.0", - "solana-pubkey 3.0.0", + "solana-pubkey 4.2.0", ] [[package]] @@ -13272,7 +13313,7 @@ dependencies = [ "solana-account-info 3.1.1", "solana-curve25519 3.1.12", "solana-instruction 3.4.0", - "solana-instructions-sysvar 3.0.0", + "solana-instructions-sysvar 3.0.1", "solana-msg 3.1.0", "solana-program-error 3.0.1", "solana-pubkey 3.0.0", @@ -13736,9 +13777,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.45" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -13796,7 +13837,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -13898,19 +13939,20 @@ dependencies = [ "magicblock-core", "magicblock-ledger", "magicblock-processor", - "solana-account", - "solana-instruction", - "solana-keypair", - "solana-program", - "solana-rpc-client", - "solana-signature", - "solana-signer", - "solana-transaction", - "solana-transaction-error", - "solana-transaction-status-client-types", + "solana-account 3.4.0", + "solana-instruction 3.4.0", + "solana-keypair 3.1.0", + "solana-program 3.0.0", + "solana-pubkey 3.0.0", + "solana-rpc-client 3.1.12", + "solana-signature 3.4.0", + "solana-signer 3.0.0", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", + "solana-transaction-status-client-types 3.1.12", "tempfile", "tokio", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "tracing", "tracing-log", "tracing-subscriber", @@ -14155,9 +14197,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -14281,7 +14323,7 @@ dependencies = [ "futures-io", "futures-sink", "futures-util", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "pin-project-lite", "slab", "tokio", @@ -14299,15 +14341,24 @@ dependencies = [ "futures-sink", "http 1.4.0", "httparse", - "rand 0.8.5", + "rand 0.8.6", "ring", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", - "tokio-util 0.7.17", + "tokio-util 0.7.18", "webpki-roots 0.26.11", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.23" @@ -14361,7 +14412,7 @@ dependencies = [ "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.2", + "winnow 1.0.3", ] [[package]] @@ -14370,7 +14421,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.2", + "winnow 1.0.3", ] [[package]] @@ -14391,7 +14442,7 @@ dependencies = [ "base64 0.22.1", "bytes", "flate2", - "h2 0.4.13", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -14415,16 +14466,16 @@ dependencies = [ [[package]] name = "tonic" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum 0.8.9", "base64 0.22.1", "bytes", "flate2", - "h2 0.4.13", + "h2 0.4.14", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -14433,8 +14484,8 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "rustls-native-certs 0.8.2", - "socket2 0.6.1", + "rustls-native-certs 0.8.3", + "socket2 0.6.3", "sync_wrapper 1.0.2", "tokio", "tokio-rustls 0.26.4", @@ -14461,9 +14512,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -14473,33 +14524,33 @@ dependencies = [ [[package]] name = "tonic-health" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ff0636fef47afb3ec02818f5bceb4377b8abb9d6a386aeade18bd6212f8eb7" +checksum = "fcfab99db777fba2802f0dfa861d1628d1ae916fb199d29819941f139ae85082" dependencies = [ "prost 0.14.3", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", ] [[package]] name = "tonic-prost" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost 0.14.3", - "tonic 0.14.5", + "tonic 0.14.6", ] [[package]] name = "tonic-prost-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -14508,7 +14559,7 @@ dependencies = [ "quote", "syn 2.0.117", "tempfile", - "tonic-build 0.14.5", + "tonic-build 0.14.6", ] [[package]] @@ -14552,9 +14603,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", "bitflags 2.11.1", @@ -14564,13 +14615,13 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "iri-string", "pin-project-lite", "tokio", "tokio-util 0.7.18", "tower 0.5.3", "tower-layer", "tower-service", + "url", ] [[package]] @@ -14971,9 +15022,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -14984,9 +15035,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.70" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ "js-sys", "wasm-bindgen", @@ -14994,9 +15045,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -15004,9 +15055,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -15017,9 +15068,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.120" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -15066,16 +15117,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags 2.11.1", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "indexmap 2.14.0", "semver", ] [[package]] name = "web-sys" -version = "0.3.97" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", @@ -15157,7 +15208,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -15168,9 +15219,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "wincode" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "466e67917609b2d40a838a5b972d1a6237c9749600cb8de8f65559b90d48485b" +checksum = "37095eb18dd6254c66217edc61a29d83d51f8818de8a2ffe88e4584ad73fb5f9" dependencies = [ "pastey", "proc-macro2", @@ -15179,25 +15230,13 @@ dependencies = [ "wincode-derive", ] -[[package]] -name = "wincode" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a61f8f0a55eb6cae5d7b7ad2eca536a944deb9722a948525181069064ecd1abc" -dependencies = [ - "darling 0.21.3", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "wincode-derive" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca057fc9a13dd19cdb64ef558635d43c42667c0afa1ae7915ea1fa66993fd1a" +checksum = "e262d55d1261f31e2cfe49cc6385a421d14d99faa0526bbe3cc1bda0d3005c62" dependencies = [ - "darling", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.117", @@ -15665,9 +15704,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] @@ -15696,7 +15735,95 @@ dependencies = [ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "wmi" @@ -15806,9 +15933,9 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 7869e43dc..724d8f5d7 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -6,10 +6,7 @@ use ephemeral_rollups_sdk::{ cpi::{ delegate_account, undelegate_account, DelegateAccounts, DelegateConfig, }, - ephem::{ - commit_accounts, commit_and_undelegate_accounts, CallHandler, - FoldableIntentBuilder, MagicIntentBundleBuilder, - }, + ephem::{commit_accounts, commit_and_undelegate_accounts}, }; use magicblock_magic_program_api::{ args::{ @@ -213,10 +210,6 @@ pub enum ScheduleCommitInstruction { pub enum ScheduleCommitType { Commit, CommitAndUndelegate, - CommitFinalize, - CommitFinalizeAndUndelegate, - CommitFinalizeCompressed, - CommitFinalizeCompressedAndUndelegate, } impl ScheduleCommitType { @@ -245,42 +238,6 @@ impl ScheduleCommitType { magic_fee_vault, ) } - ScheduleCommitType::CommitFinalize => commit_finalize_accounts( - payer, - accounts, - magic_context, - magic_program, - ), - ScheduleCommitType::CommitFinalizeAndUndelegate => { - commit_finalize_and_undelegate_accounts( - payer, - accounts, - magic_context, - magic_program, - ) - } - ScheduleCommitType::CommitFinalizeCompressed => { - MagicIntentBundleBuilder::new( - payer.clone(), - magic_context.clone(), - magic_program.clone(), - ) - .commit(&accounts.into_iter().cloned().collect::>()) - .compressed() - .build_and_invoke() - } - ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { - MagicIntentBundleBuilder::new( - payer.clone(), - magic_context.clone(), - magic_program.clone(), - ) - .commit_and_undelegate( - &accounts.into_iter().cloned().collect::>(), - ) - .compressed() - .build_and_invoke() - } } } } diff --git a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs index eebc525aa..dbf3e8515 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs @@ -377,14 +377,10 @@ fn run_test_for_commit_huge_order_book_account( assert_one_committee_was_committed(&ctx, &res, true); match commit_type { - ScheduleCommitType::Commit - | ScheduleCommitType::CommitFinalize - | ScheduleCommitType::CommitFinalizeCompressed => { + ScheduleCommitType::Commit => { assert_one_committee_account_was_not_undelegated_on_chain(&ctx); } - ScheduleCommitType::CommitAndUndelegate - | ScheduleCommitType::CommitFinalizeAndUndelegate - | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + ScheduleCommitType::CommitAndUndelegate => { assert_one_committee_account_was_undelegated_on_chain(&ctx); } } diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index ce214eeb5..b1f13da78 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -68,6 +68,8 @@ enum CommitIntentKind { CommitAndUndelegate, CommitFinalize, CommitFinalizeAndUndelegate, + CommitFinalizeCompressed, + CommitFinalizeCompressedAndUndelegate, } fn expect_strategies( @@ -264,8 +266,8 @@ async fn commit_single_account( let counter_auth = Keypair::new(); let (pubkey, mut account) = match commit_type { - ScheduleCommitType::CommitFinalizeCompressed - | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + CommitIntentKind::CommitFinalizeCompressed + | CommitIntentKind::CommitFinalizeCompressedAndUndelegate => { let (pubkey, _address, account) = init_and_delegate_compressed_record_on_chain(&counter_auth) .await; @@ -317,12 +319,12 @@ async fn commit_single_account( undelegate_action: UndelegateType::Standalone, }) } - ScheduleCommitType::CommitFinalizeCompressed => { + CommitIntentKind::CommitFinalizeCompressed => { MagicBaseIntent::CommitFinalizeCompressed(CommitType::Standalone( vec![account], )) } - ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + CommitIntentKind::CommitFinalizeCompressedAndUndelegate => { MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( CommitAndUndelegate { commit_action: CommitType::Standalone(vec![account]), @@ -410,8 +412,8 @@ async fn commit_book_order_account( undelegate_action: UndelegateType::Standalone, }) } - ScheduleCommitType::CommitFinalizeCompressed - | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + CommitIntentKind::CommitFinalizeCompressed + | CommitIntentKind::CommitFinalizeCompressedAndUndelegate => { unimplemented!("Order book compressed delegation not yet supported") } }; @@ -754,7 +756,7 @@ async fn test_ix_commit_single_compressed_account_100_bytes() { commit_n_accounts_x_bytes::<1, 100>( 1, expect_strategies(&[(CommitStrategy::StateArgs, 1)]), - ScheduleCommitType::CommitFinalizeCompressed, + CommitIntentKind::CommitFinalizeCompressed, ) .await; } @@ -764,7 +766,7 @@ async fn test_ix_commit_single_compressed_account_100_bytes_and_undelegate() { commit_n_accounts_x_bytes::<1, 100>( 1, expect_strategies(&[(CommitStrategy::StateArgs, 1)]), - ScheduleCommitType::CommitFinalizeCompressedAndUndelegate, + CommitIntentKind::CommitFinalizeCompressedAndUndelegate, ) .await; } @@ -774,7 +776,7 @@ async fn test_ix_commit_single_compressed_account_500_bytes() { commit_n_accounts_x_bytes::<1, 500>( 1, expect_strategies(&[(CommitStrategy::StateArgs, 1)]), - ScheduleCommitType::CommitFinalizeCompressed, + CommitIntentKind::CommitFinalizeCompressed, ) .await; } @@ -784,7 +786,7 @@ async fn test_ix_commit_single_compressed_account_500_bytes_and_undelegate() { commit_n_accounts_x_bytes::<1, 500>( 1, expect_strategies(&[(CommitStrategy::StateArgs, 1)]), - ScheduleCommitType::CommitFinalizeCompressedAndUndelegate, + CommitIntentKind::CommitFinalizeCompressedAndUndelegate, ) .await; } @@ -794,7 +796,7 @@ async fn test_ix_commit_two_compressed_accounts_512_bytes() { commit_n_accounts_x_bytes::<2, 512>( 1, expect_strategies(&[(CommitStrategy::StateArgs, 2)]), - ScheduleCommitType::CommitFinalizeCompressed, + CommitIntentKind::CommitFinalizeCompressed, ) .await; } @@ -804,7 +806,7 @@ async fn test_ix_commit_three_compressed_accounts_512_bytes() { commit_n_accounts_x_bytes::<3, 512>( 1, expect_strategies(&[(CommitStrategy::StateArgs, 3)]), - ScheduleCommitType::CommitFinalizeCompressed, + CommitIntentKind::CommitFinalizeCompressed, ) .await; } @@ -814,7 +816,7 @@ async fn test_ix_commit_six_compressed_accounts_512_bytes() { commit_n_accounts_x_bytes::<6, 512>( 1, expect_strategies(&[(CommitStrategy::StateArgs, 6)]), - ScheduleCommitType::CommitFinalizeCompressed, + CommitIntentKind::CommitFinalizeCompressed, ) .await; } @@ -824,7 +826,7 @@ async fn test_commit_20_compressed_accounts_100bytes_bundle_size_2() { commit_n_accounts_x_bytes::<20, 100>( 2, expect_strategies(&[(CommitStrategy::StateArgs, 20)]), - ScheduleCommitType::CommitFinalizeCompressed, + CommitIntentKind::CommitFinalizeCompressed, ) .await; } @@ -835,7 +837,7 @@ async fn test_commit_5_compressed_accounts_100bytes_bundle_size_2_undelegate_all commit_n_accounts_x_bytes::<5, 100>( 2, expect_strategies(&[(CommitStrategy::StateArgs, 5)]), - ScheduleCommitType::CommitFinalizeCompressedAndUndelegate, + CommitIntentKind::CommitFinalizeCompressedAndUndelegate, ) .await; } @@ -885,7 +887,7 @@ async fn commit_n_accounts_x_bytes< >( bundle_size: usize, expected_strategies: ExpectedStrategies, - commit_type: ScheduleCommitType, + commit_type: CommitIntentKind, ) { init_logger!(); let accs = (0..ACCOUNTS).map(|_| BYTES).collect::>(); @@ -972,8 +974,8 @@ async fn commit_multiple_accounts( bytess, matches!( commit_type, - ScheduleCommitType::CommitFinalizeCompressed - | ScheduleCommitType::CommitFinalizeCompressedAndUndelegate + CommitIntentKind::CommitFinalizeCompressed + | CommitIntentKind::CommitFinalizeCompressedAndUndelegate ), ) .await; @@ -1003,12 +1005,12 @@ async fn commit_multiple_accounts( }, ) } - ScheduleCommitType::CommitFinalizeCompressed => { + CommitIntentKind::CommitFinalizeCompressed => { MagicBaseIntent::CommitFinalizeCompressed( CommitType::Standalone(committees), ) } - ScheduleCommitType::CommitFinalizeCompressedAndUndelegate => { + CommitIntentKind::CommitFinalizeCompressedAndUndelegate => { MagicBaseIntent::CommitFinalizeAndUndelegateCompressed( CommitAndUndelegate { commit_action: CommitType::Standalone(committees), From fa75ce99012751dc6c14ad5dd7145cd8ec771c4d Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 22 May 2026 18:04:31 +0200 Subject: [PATCH 084/110] feat: use try from --- compressed-delegation-api/src/instruction.rs | 26 +++++++++----------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/compressed-delegation-api/src/instruction.rs b/compressed-delegation-api/src/instruction.rs index 819879e63..35aaa99b2 100644 --- a/compressed-delegation-api/src/instruction.rs +++ b/compressed-delegation-api/src/instruction.rs @@ -19,14 +19,18 @@ pub enum CompressedDelegationInstructionDiscriminator { Undelegate = 3, } -impl CompressedDelegationInstructionDiscriminator { - pub fn from_u64(value: u64) -> Option { +impl TryFrom for CompressedDelegationInstructionDiscriminator { + type Error = std::io::Error; + fn try_from(value: u64) -> Result { match value { - 0 => Some(Self::InitDelegationRecord), - 1 => Some(Self::Delegate), - 2 => Some(Self::CommitAndFinalize), - 3 => Some(Self::Undelegate), - _ => None, + 0 => Ok(Self::InitDelegationRecord), + 1 => Ok(Self::Delegate), + 2 => Ok(Self::CommitAndFinalize), + 3 => Ok(Self::Undelegate), + _ => Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Invalid CompressedDelegationInstructionDiscriminator value", + )), } } } @@ -77,13 +81,7 @@ impl BorshSerialize for CompressedDelegationProgramInstruction { impl BorshDeserialize for CompressedDelegationProgramInstruction { fn deserialize_reader(reader: &mut R) -> std::io::Result { let raw = u64::deserialize_reader(reader)?; - let disc = CompressedDelegationInstructionDiscriminator::from_u64(raw) - .ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "Invalid CompressedDelegationProgramInstruction discriminant", - ) - })?; + let disc = CompressedDelegationInstructionDiscriminator::try_from(raw)?; Ok(match disc { CompressedDelegationInstructionDiscriminator::InitDelegationRecord => { Self::InitDelegationRecord { From 24191181b54daba11605ded0afc660f6a0badc2b Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 22 May 2026 18:19:20 +0200 Subject: [PATCH 085/110] feat: explicit cdp types --- compressed-delegation-api/src/instruction.rs | 166 ++++++++++++------ compressed-delegation-client/src/mod.rs | 9 - compressed-delegation-client/src/shared.rs | 16 -- .../compressed_delegation.so | Bin 181216 -> 184936 bytes 4 files changed, 112 insertions(+), 79 deletions(-) delete mode 100644 compressed-delegation-client/src/mod.rs delete mode 100644 compressed-delegation-client/src/shared.rs diff --git a/compressed-delegation-api/src/instruction.rs b/compressed-delegation-api/src/instruction.rs index 35aaa99b2..848269502 100644 --- a/compressed-delegation-api/src/instruction.rs +++ b/compressed-delegation-api/src/instruction.rs @@ -178,101 +178,159 @@ pub struct ExternalUndelegateArgs { pub delegation_record: CompressedDelegationRecord, } -/// Reimplementations of the types from light-sdk for borsh compatibility +// ------------------------------------------------------------------------------------------------ +// Reimplementations of the types from light-sdk for borsh compatibility +// ------------------------------------------------------------------------------------------------ +/// Reimplements [ValidityProof] compatible with borsh 1. +/// It is a wrapper around a [CompressedProof] [Option] that is compatible with borsh 1. #[derive( BorshSerialize, BorshDeserialize, Clone, Copy, Debug, Default, PartialEq, )] -pub struct CdpValidityProof(pub Option<[u8; 128]>); +pub struct CdpValidityProof(pub Option); + +#[derive(BorshSerialize, BorshDeserialize, Clone, Copy, Debug, PartialEq)] +pub struct CdpCompressedProof { + pub a: [u8; 32], + pub b: [u8; 64], + pub c: [u8; 32], +} + +impl From for CompressedProof { + fn from(cp: CdpCompressedProof) -> Self { + Self { + a: cp.a, + b: cp.b, + c: cp.c, + } + } +} + +impl From for CdpCompressedProof { + fn from(cp: CompressedProof) -> Self { + Self { + a: cp.a, + b: cp.b, + c: cp.c, + } + } +} impl TryFrom for ValidityProof { type Error = light_compressed_account::CompressedAccountError; fn try_from( cdp_validity_proof: CdpValidityProof, ) -> Result { - let Some(bytes) = cdp_validity_proof.0 else { + let Some(proof) = cdp_validity_proof.0 else { return Ok(Self(None)); }; - let proof = CompressedProof::try_from(&bytes[..])?; + let proof = CompressedProof::from(proof); Ok(Self(Some(proof))) } } impl From for CdpValidityProof { fn from(vp: ValidityProof) -> Self { - Self(vp.0.map(|proof| proof.to_array())) + Self(vp.0.map(CdpCompressedProof::from)) } } -#[derive(BorshSerialize, BorshDeserialize, Clone, Copy, Debug, PartialEq)] -pub struct CdpCompressedAccountMeta(pub [u8; 42]); +/// Reimplements [CompressedAccountMeta] compatible with borsh 1. +/// It is a wrapper around a [CompressedAccountMeta] that is compatible with borsh 1. +#[derive( + BorshSerialize, BorshDeserialize, Clone, Copy, Debug, PartialEq, Default, +)] +pub struct CdpCompressedAccountMeta { + pub tree_info: CdpPackedStateTreeInfo, + pub address: [u8; 32], + pub output_state_tree_index: u8, +} impl From for CdpCompressedAccountMeta { fn from(cam: CompressedAccountMeta) -> Self { - let mut bytes = [0u8; 42]; - bytes[0..2].copy_from_slice(&cam.tree_info.root_index.to_le_bytes()); - bytes[2] = cam.tree_info.prove_by_index as u8; - bytes[3] = cam.tree_info.merkle_tree_pubkey_index; - bytes[4] = cam.tree_info.queue_pubkey_index; - bytes[5..9].copy_from_slice(&cam.tree_info.leaf_index.to_le_bytes()); - bytes[9..41].copy_from_slice(&cam.address); - bytes[41] = cam.output_state_tree_index; - Self(bytes) + Self { + tree_info: cam.tree_info.into(), + address: cam.address, + output_state_tree_index: cam.output_state_tree_index, + } } } -impl TryFrom for CompressedAccountMeta { - type Error = core::array::TryFromSliceError; - fn try_from(cam: CdpCompressedAccountMeta) -> Result { - Ok(Self { - tree_info: PackedStateTreeInfo { - root_index: u16::from_le_bytes(cam.0[0..2].try_into()?), - prove_by_index: cam.0[2] != 0, - merkle_tree_pubkey_index: cam.0[3], - queue_pubkey_index: cam.0[4], - leaf_index: u32::from_le_bytes(cam.0[5..9].try_into()?), - }, - address: cam.0[9..41].try_into()?, - output_state_tree_index: cam.0[41], - }) +impl From for CompressedAccountMeta { + fn from(cam: CdpCompressedAccountMeta) -> Self { + Self { + tree_info: cam.tree_info.into(), + address: cam.address, + output_state_tree_index: cam.output_state_tree_index, + } } } -impl Default for CdpCompressedAccountMeta { - fn default() -> Self { - Self([0u8; 42]) +#[derive( + BorshSerialize, BorshDeserialize, Clone, Copy, Debug, PartialEq, Default, +)] +pub struct CdpPackedStateTreeInfo { + pub root_index: u16, + pub prove_by_index: bool, + pub merkle_tree_pubkey_index: u8, + pub queue_pubkey_index: u8, + pub leaf_index: u32, +} + +impl From for CdpPackedStateTreeInfo { + fn from(psti: PackedStateTreeInfo) -> Self { + Self { + root_index: psti.root_index, + prove_by_index: psti.prove_by_index, + merkle_tree_pubkey_index: psti.merkle_tree_pubkey_index, + queue_pubkey_index: psti.queue_pubkey_index, + leaf_index: psti.leaf_index, + } } } +impl From for PackedStateTreeInfo { + fn from(psti: CdpPackedStateTreeInfo) -> Self { + Self { + root_index: psti.root_index, + prove_by_index: psti.prove_by_index, + merkle_tree_pubkey_index: psti.merkle_tree_pubkey_index, + queue_pubkey_index: psti.queue_pubkey_index, + leaf_index: psti.leaf_index, + } + } +} + +/// Reimplements [PackedAddressTreeInfo] compatible with borsh 1. +/// It is a wrapper around a [PackedAddressTreeInfo] that is compatible with borsh 1. #[derive( BorshSerialize, BorshDeserialize, Clone, Copy, Debug, Default, PartialEq, )] -pub struct CdpPackedAddressTreeInfo(pub [u8; 4]); +pub struct CdpPackedAddressTreeInfo { + pub address_merkle_tree_pubkey_index: u8, + pub address_queue_pubkey_index: u8, + pub root_index: u16, +} impl From for CdpPackedAddressTreeInfo { fn from(pati: PackedAddressTreeInfo) -> Self { - let mut bytes = [0u8; 4]; - bytes[0..1].copy_from_slice( - &pati.address_merkle_tree_pubkey_index.to_le_bytes(), - ); - bytes[1..2] - .copy_from_slice(&pati.address_queue_pubkey_index.to_le_bytes()); - bytes[2..4].copy_from_slice(&pati.root_index.to_le_bytes()); - Self(bytes) + Self { + address_merkle_tree_pubkey_index: pati + .address_merkle_tree_pubkey_index, + address_queue_pubkey_index: pati.address_queue_pubkey_index, + root_index: pati.root_index, + } } } -impl TryFrom for PackedAddressTreeInfo { - type Error = core::array::TryFromSliceError; - fn try_from( - cdp_packed_address_tree_info: CdpPackedAddressTreeInfo, - ) -> Result { - Ok(Self { - address_merkle_tree_pubkey_index: cdp_packed_address_tree_info.0[0], - address_queue_pubkey_index: cdp_packed_address_tree_info.0[1], - root_index: u16::from_le_bytes( - cdp_packed_address_tree_info.0[2..4].try_into()?, - ), - }) +impl From for PackedAddressTreeInfo { + fn from(cdp_packed_address_tree_info: CdpPackedAddressTreeInfo) -> Self { + Self { + address_merkle_tree_pubkey_index: cdp_packed_address_tree_info + .address_merkle_tree_pubkey_index, + address_queue_pubkey_index: cdp_packed_address_tree_info + .address_queue_pubkey_index, + root_index: cdp_packed_address_tree_info.root_index, + } } } diff --git a/compressed-delegation-client/src/mod.rs b/compressed-delegation-client/src/mod.rs deleted file mode 100644 index 500c4f924..000000000 --- a/compressed-delegation-client/src/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Legacy client module layout (`accounts`, `instructions`, `types`). - -pub mod accounts; -pub mod instructions; -pub mod programs; -pub mod shared; -pub mod types; - -pub(crate) use programs::*; diff --git a/compressed-delegation-client/src/shared.rs b/compressed-delegation-client/src/shared.rs deleted file mode 100644 index 69c049e3d..000000000 --- a/compressed-delegation-client/src/shared.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Shared account decoding helpers for optional `fetch` integration. - -#[cfg(feature = "fetch")] -#[derive(Debug, Clone)] -pub struct DecodedAccount { - pub address: solana_pubkey::Pubkey, - pub account: solana_account::Account, - pub data: T, -} - -#[cfg(feature = "fetch")] -#[derive(Debug, Clone)] -pub enum MaybeAccount { - Exists(DecodedAccount), - NotFound(solana_pubkey::Pubkey), -} diff --git a/test-integration/programs/compressed_delegation/compressed_delegation.so b/test-integration/programs/compressed_delegation/compressed_delegation.so index 999850eadd7cd4b03982e0c002f568268fd9b366..99b506cf36d2a126929642bc94c0ad08c6de5d92 100755 GIT binary patch delta 57171 zcmeFadwf;J)i=IpLP!V#NiZR7NJv0Kh!BEuiIGb{g@6J<1R@IL5H5+_atL5{j&j01 z-Y~kWlhR6a5|G#`jUpskCDB$It73fWB|fb*)@tJoV=o#-;kRbi+UM-OsXTq#=Xu`W zAMgGsE8m$lGi%nYS+i#LoO3$%^zJ;+yDA~JiZe|Tq@|M4OmXIXe8n0{`f~k zn5K<{KYiKV=VVF(;3C7ET#>=Gx#s$ccs^W&t9+lH zrf3A{BUzTyBNZ->%IO*axI8MkD?(ANtC#uRv;n+*j+qfQU<9cRvb0^%niij6|@uoOX8RO?DsA`F-d zBE%0ZnH%b_l;LlndP@e<&f#qtJgwY3wJn}UmYYdD9$GT{Zja}khB*gNt6{F<K!iC!1K9TkdQkCnwZIb36zIkCB2y6~`_?JX{g2`C_CIU@qt2 z@s=U>O*8j}CHpt1QH+aBQmG3fr)kn8kFsbr4n~R8x~6$I_fxcVajW9@MYSl}9H)}C zh;U8&15|!Ayq5;u*NlVDBj4f#MGXU`@opaNtY_4|NMziH6)plPJD{QkJ!WeKz}ioa zK0FB^RZF=!$B6g0jDx|UPLxMtr^B_WHa4fSo&o-FZIa3_-7R~kX`b35)ofuZ@)p;w zRd`LRoEw@}IvxfR9$!4x-|SIP1N$^D>lx!O0TCO)a3(;q9P{7gLZ1WJS6}>0#a#Lj zB*J3^a^9bh>zDZ$kAWz}acx=QI$Wpj4e!0po4op;dP5deVoW1GgK#ooufmO}3s8=?dIg@(d_Gg)V^Cp$8Nqdt@^v&u%D^u+0DS$&J(xvhZW3^<{eET#drFZiN zg)NiwZ1xOM35APMKgF9@D!gVf>c_XwTpT`net;}bk5<)q#waGOP!A|vJO<=~XN`Uk z^QT(*Xc5Izt$ehI=8c+W{=PCHIOMXv=3ZDx4t)uXvQbBU2t=w%OZ9w3ec3lDYSf|* z4B2sbd^(zhHD`S~nuIq6&8}2OlQ6s`#GgDBE27y8{!(GDw?Z)(hfryyI-0<3V4GQx zV+2r;aBb(gBP)6qgz?X3m?wHIWZ#*IQH$7L%*|2D*oWqu@b~Y`QN0(jHgi|+W$ahx z2k`gP=A?_}vY(sxUbKwW9r^5{+gMDC%Mo35WOLsQEY_Xed#w3ozoc|`a`;&2`W_`P z7~OAF59Gv7^97A=JzHnK8$E!T=HH|J>}TfYm>E3gq9ey+K4xZgpMica8sDWXLiwqF z30NDt2j{%M=Za8kI>KYEbE(~ z$&Sbh|51VUwjPITs2aC^`CH@URF3)fQm7oAowl)On#RTKOZfo*8R+EE9>>o~Y3-f= zN~Qne+z?3j?!vx!s{p{`*$Lhs9^b5L)n{WTE*9Q9(Rr8dYgOsKSuKh#U|bsk{IV;O zhHFo#^wnJRYsru>_j33Lp4CvVoDg$wP*9T&LiWm9aGQ5wx?Fug|1b@4?#n3REfCmS zA*%<$2GC$_Q&4(wEnTG}E}lnoKHiUic+gX8h1S}-4VCGO$DSG6l2u7xJoeDLEluIl z_#sGp$`A<}PQ64?BY>JIj89hBH$Fnq(&;z?;o3>10prM{{jX*$!~E>x)hq@69c+5z z=Cl6hi*d_Xgn4QFXudSjJid6M`9S<#Y}1j%0TC>=$cH8=Ym^S@%dzJ8gjD|2h$BlA z;u-&DFcio(8wRe8&2w=!jy;m0kMF@gJhC!rSs2W@SBEB=e@wZY-D$2Hda0Q`^m4Wp z{#wR1Le5-PWF`(<#Fz9m=cElj^1!f-Vf>SDv*++R{Jn55gDh2*sZC-lST(-pA4FAqIU%YBA zpBZMJ96H#%eB$MNN|{E)@SC`K;-31InM zcbFMh4-!w$WS6lQ&Bw2q5L;x6)nz-=$C_K`W%Rli9JyNW%~ux>h%JEP_U%B`9cnvp zdA`~Xl-v<&%)T8MlaJd0=XT-z?LdyK-L@ToxvOGvq*@nKv3OFxI6R%j$7b5PCI$Y} zc&QkEZlrlSXZp}9CQEOF-b?15oG7uZ2?zWy6V0CUGMMil_Wj!{WZ(JKV^vizKtO4) zYPqYbT@%fWoH_ivJacPKe0sHO=G`_ymPWVPoTA#-5M@R}Y>3I&{%jj;7jNk6n}=zZ)F06;3yA zr>?`0xJ_+7EN0DKQ=dL0|OOg}JUExn^8YuFFWS3v&%4 zxh~8#h~&C3SAUW#_kwcuCb=%m6-IJhnClEI(=bB+d10=l@kz5z%DkZsQUr??!B-iXA{tI}MLg0#k&`d^gLEq&; zA9W#Lb&IT>_~g2B2yk#eOfh700P8UePV_JbUmM9^9&hf>o1WtKd$ULe2J8zW{&p_M z>~rk^{=ntt$r~r1xBnV`ByquQjK@zlA6ht`?K<-6!bP0FIY}H}&qkUz+?0KJmTTcT z2Z5<2sXUx==bssA9>3|WSa=$1cpec4vE&JsXzsdM#JJr|aHKH1r4agSA8WCkxD; z>oWKU3(fKC#`B{K%=JJXU1&bCE|p)i&^!rb-XinMbxHa=3qrjM*YE^Hh8J%yG&9yu zA5mt@mhqq5gd{*P((Y=u-h6od0KRsid2D@>US}&5t_@VWlXX@vG*7Qj;$aKTz8jKw z&qZbikj#bV93WE`nd>*i^F<5I-GCM^GLv@3$4&uxtjQrOxOahhaziTLxzPL)m|7Q@ z@g+(8D0H%9I)@{_ttIiS$$YTn=X`vud2-=Z<~HvR{#f>ro*Oe5-<@raFFnOqWgm&( z^avZ;?HX|d_J8t}D^7M0nwof{d1`Y!Y-;|#c@cZ?$m}imv6xJkB^)(ByKRVUxNliJ zJ7Hd0=8s8mu?#kkmMw~jc4_N&Gtn3=3&J5K+i$Kk{CsE(NId8WEB}P?%-hY=zIc{r zhTksEtMOs;@!MC&x{Y#gnt5t@5vhr zg-udlc8!`+a+<>dbCN%aMVpi0Xt`S*Gru8^nFl@vn(<}VD@OYf|4#E^{{WuG%&k4* z%~$-H{N+XFS$}+bi>(1UZ&ETtgK0l-&%`}InA!vIirdZI@PgojMR?2((wwY_hn?LA z6%+W|U=`cqW1q4%^&pU}*gx7_&oZ(r^I+KMk){ec%2e}gy9&vkYm-BExMZtR66|~A zp}Xup9J7NM^3WYrmbyKacWUNje>^LY+Awe5p2@n*$G6YmeQpwG;WdT7YHO%v*}@BO za&4Kdy{Gm`cv@MRa>94xTZ zQ6N8QKQs&sCz zw(D!BW@IyV&2Z3+Z(rFrs`dbu_vs}H`|c`2THc9c8K5za&6MnB^R7WRbg7&rWAQ}H z7zP5vV;tzFbUcxhEvodP(&A*krfN>S1cy`R%fF1;j<3y;yA%8ccI~H=_H8C2yWvYG z?So3&kA&>Pm)@n6WjBaUP=hbMQ>DwL#4%dws9c}kuJU2DW(J2#3ND9B4x3%Ca`^2H zNE?=;HCBxl4!=>`aMrwN&-i(fs$Zet5SEi0lQ+<%rTMg{6PSy7%{qe}u8^~1o zaSU}Kr}g_cnU7Q^`4bjPUE|XTe?sMO)N(?tao*v#s0>d^o}xazN!ghP#Ayo^ z_KwI`v^eEP%0GXGxV(>FleQv(C~B z*?&fSAR6;${Xt=$Zt+`uR=#E9e$|fhgGw?FVkyw-K~fX9;%XltK2TiIH{d60dyya& zO0h<54B<+`0|{3VP9a=PnEdrM!!lLPzU%;I3A1X@xgN)qKOu zckdeK?^5aTPD`aPkBa zs4SwHL~%sQqjD7v)}II!xtwZnXg~ehJa+dbv1kn7ba1Q!?PttS?@sgQB}+YzR(dw- z&}sOxX~5EH!2ZFK@O`b#P=&b zp?)LfXDRB_Zy}sRcm-j6De2SkO{hWdseSq;mA^bH|6CgA*c14c>b+g1HwXMu^$^MY z1O4SgG$bwY378EAs7vzs^h30=Pf^rTr!Rd5;-CiSBA@kgJ{6}voZza4edYCP?)nz* zYrsG5I)AdJftxjIzrcpm={0NJM~Jhr$Hsy85YIx57zf`$yg18z|K2hF?;EBc!@ReI zw>l?7KHF1~IOeDl);NS=k34RWZy=3&TpH~!2n(R#KQJG^GE<1koaPGJZiRX5UQ?P6 zVDs{Qd=2DFfihij*vx@23gso($$dpg?sI+8nr;Duf1ou!_pnu=XZ% z^1gWgTjMb*k_^TH^atK)1&V(Wut5nej?*GE^=Xyv)A8MyG4%<;Rj8n;j}opV93Whw zaPu?;m7nv#pD=CxDn*)I4QNz`1UWKehDugp+zTL};eB2u`1B5}*!vRUPQtGf?jrmS zVLZ&1VITabmC|Y-^cM_PrguOgBJ*Z8*#9In)r?)xB6?AbY8wk>ME9$j)!ww$6*J4W zGKw@fN*3w(9s)3d><~#m49ZXIJcd)o9wZ-)sq0)VKB`a){;dWnDu7gbJ zQJ|K3TPP{}z7CFDi~!cxPq5RhKcD-JdFltLGt`L#wP4gDhrPx;xtB9lFSOj(KsS>akw)gPm_7(HZq5h|f}Ibjds#e{Dnd;{Tm z3d8LiOn;P=et)JC!;qU^c#JyCUos5C@oNmViswjSm!7Gp%y(>R z^fZ-juP+Zq55gmr4l~W#wB*wsv*^4{OQ&noA_q$j&V);$Hvzf?1(%)7>qRPmnVFkJ zuD{A<8hwG+Yv!v?#)aLksHF*CI!=2_bG~$R3zmj`>Et$IR537Fax30XRf12~$Y=kF za5p(Z@9!yrg!H~axDzL)2ZsXYfYOHH!J+f%s7=Fzu?AecqI^{x1VHUMv`R|(p)QpY zi^CYlYMGoxa7*wT^Ofo(f4&+;V^cTEF{=x0Zj+kt^41*TNHzC-voz%>j04zV->eeM zKY$AH%_<{|3iHjXAdCw2&8j4f{q^~0RZ#*e1TOCo?p6x%&8i`c8uiVpSJ;=`f$4SF zabGq@?M59c#+Us(<)h+!*)I_$^UQu-;f20^k?0E3qmk+fif)W*QViu$4MaN?y)`PC z@`oyF*Z44J7*aY8EX?~D4RC@g?)CnZFivW(_h*EoRlaA-0fi0kk14%HHDh>xK)8wU zJ%k$w?<8EWu-9l9}o4Xs7B*@3{_M`owut$)pdsjY#644F`;k5>uRI=U!u~(wS&R@7TbLNM@~rk zfb*Qta%>Cc1DR7g+8KBiW#{ElA*Uh@+CF;HtJ$Mg%c(pFvcYy4=UZ*2>HE>}m=S6= zH1@#e7W6n}zC2(Ed)NGAKw{W){kNMh#}A>IRUU3c zT3FyF6hv<$>>=DvnATNmrO`Vm9Zlb-cS<|~dWdrajDZ+%?!d7*VVqmwtyPbtV9SE0 zJPT$oJaIiB2!rQ*Q-+Hr@K_;^T<7d2{apVn%-O*TvGm9%w_(6WiM`XF#^d- zU^yxeD|4w=Jqk^_-^fWf;w6k&(Xo8*aE$8TYW7YT=y$&@{t(Lj>jsF1CwF4<@oq#K z+F}k+35NG3MPZ9cMT_ zYin6dc)GQ>#N7tW42n|>VsP&*&krk7z)j-Taw9Zl-_|Jib3j$3uH7q#O4}OTorC=J z$k`IYB@p>n_zB6fV5=F-pgU zwN!tUFfP2M^lHNh6j43TQ+^5Imk5^;ew{F`lRo{LcT_@o6ox_@qgu|&!6}bwQt7uw zJ*8;#BT_7I4zNd38mS`;8mKsHo(&}VCn*J>6Y}XJa7gHw%%`UiMknUe2NG6Z4pzDt z!mT7{KH)aP1%%rP7ZFC|g?A)ql+uG7J(f3IO1H#&$E)B*mHaY&(#FeQlj*11BA&LE zR+)b9W6fPMz2W(<9|W%&_LOU!F?v-Ia@UUyh=( z0p|f~mP+3k6@3n}K+%y3pJ#$L1$Uk`x6~y~CTPV1a?4DUOj_j6;T+cp zM4B(x4e_HF@}_uFvT%K^9u=iHZ(@-_DI&6WK ztVVNH69v^6H6)gdV&M7y>iq8N5?s}tg?(3ZuB-$oI!N330gu`DWYoJ-IWRtoEqwcER_w#sFUsjupc)9INRuq;m>Ext%p*l?17rB77RLavDa8-J7bUo_T6B4 zws61Fu(!4qPx~o^-=|lpp4in_0J9ig!>e>zzGt~M^nx9QN{4Nqs<%9li|gryR$Iq0%B+l{GBPY z{hfi-we@ygdMWkpz>oYYiuevp6|P30z3Vw@6pa8{NANf$P)+%CoD#fnK-;?jjyk;5 zpz=+`k6s;)Q3<2>_roYtLb56l3a2K54%BkxNOwih7x-&4r83*ZpS7g$r%uN<>MkeiOrnI^D=^qhB z>+tDc5T-LD{cFN#T|OOO_`w@nrAv6TOVp2%N_kYKO4u0HNugl}Re)AueZI0hDuD_{ z6HTTFCrx4dTL+~%TTGyQ&^9%uniaw{%FmBMXVtvu1{E3sG*1ZjRE2Q*r_2@hWQ5Va z!TS+L`-k^4glm);uhGjDF1^*Dbo3vkdYQtvM%}IiPqYWUYV2(i=bP)E7;-}~h~?W? zqQrn{i|$BAr!3!A$R1hF7~cIUK6v-1sNLp#U`e)De|Jj53!plr7t57~W@}ujZ#m{m zSDo^ujP!COfcS^BC+8_u6}}U-3n0hm`xhy+SYI|; zv}@5(YYw#G=#c6_Eeawhy|w1N3^EykUZlX<67%k#4fkUVDt8`oS!kwy`_hqXc~rr- za(%b&yzLWH>Ss0lAB!bdFCBnS<=nz(8`i>5V zf9sBp;WZWJTSqg7I^zkn5nnmZeL42fe(JG>Y`l5Lv9bR0d{uq(1Zpn5T4B#rjAX5= zXx^#KiovIsseJF$?R1+O$m|}w07=*Di@S1}#_7+})D7-Ohz!^C) zynzV{LtKlE1V$?i@6-toC)`eW2;z(NHcA*k46Wa2=Ip13M6|;l7uckkrB830FhEB9 zVdvjdcpWx%a4xHAfTpm9@^(expu)WD884@+2se(Atd)v&5r{0MZbXyTWVj}u1?r6q z@YUiN!~7)SsucCcv?@NUd>l(s*f@mwhBrl43+}Q^4T<3$NVo+3k>QP@1l)WY-d==p zOs#c8`jeNSBD+mgfK6Ce7^FkUmL2lqcEqP+IAnOoP<J;P#O4O(n>d(?*UZ!xV{xsnV z!gvk@A)>;t<)r*J!dCQwwh4xW`TYZEyw(AXH_-Wwx#_vosc1#^)vO9MVhx_PrIMQY z7!1^|NvSz_M``}crGa>JgQigJtN?W8IqZZpR>aY*?I>%frlCI!MF>Np@tTts^ zcbF@WUoyt}WV&9Dfx$M&fd^JT!syO}w`{hV&m14hZ_hVR9gmOLu8v!(%rnRDi$MXr zvAI}2y~6xa^Bnld%E!&=YvcX~O}j;R8HhE|cAKq*F8l5R(~}bIBa@^%D{u~oCQ6gk zTC2^fUnPXg{`D{)ZkZ5q5Vm6B+A8yREyLlee%SLyO8#HLQPj6!_X16d!s(?NTUqY3 z`SA1C@I%$+`_E7Azftu@S#gyVBE14$3TzqN+n@~N0IWhUOlPG>YG0VZdOb?)z05!U za(LqXh>SWifSrhCBdZ3QXP?tWdk(wEUn#W{ppr0`WMp8}<_87Z>B?_W`8d$Bt_oMa zG#cw3N%Ib@R~iJ&Ts8f&U~^{#=+KXA=F7ht5#g0L-N6H%`PDL3W#0Va2;L*p-2LL% zn3t52WpVi!pq7_k^uVXlN1d4Bp9Y1(wIet@@gNC2a((Ts{!;%`glmT}e;X#s{1`|6 zPgQ>KYl!A)T{7ERXN?8;O-{bW*x^gV!`15=sK*cA=mTDX9;u1LgJFvF!h~?Gx61To zqb7Z`3Y13Wmp#ZmwRIcAw-~3d3_7K)!zFAro$Vtc@3+eOCxEjv4xt+{0+$!53Pau< zg=xl(7g(KI>a>*+Pbv?&AmSy>ynRQqza7R$*7n4Qa&@j$-H&5msKvw+xJTha{jbU} zJ%Kw3cagz9uW)E%i~|HWxKt=-1YW0n410{gJA^URGajW-*IQq$GK|_EBCQJ`J%A@w z#=$2L*F3GLC-6r_3vmMrw>Cc@yn_V&lyE8Gj|k(=1@18`wU+AsPU?xK5`x$00^O!g1`l+M@W<^OV}HuV9fob5Q8HIR4BzIRI9=TzF(06UQ4>`J?>Uxnw!M z{(T9m0$)@v(#4rbXJsMH&Qa7`+Y1Fu*AzBtyHG&7OXaP7k8m>Oqv3dmK`XMMZ2V|~ zcNkcf!uelI>MtIKhT_ZaR0-Z;IJ@9G5EM2p!3pFYhG)>F*;T3`X`#P^9(n2B5PbSa z@q32JO@eGNm+Au(S2z+oL<3iSeo zi&N-$NY7K)lafUF(WtqUO9*!m|4_p1fX%Htl7e&K?!UuKd=&c!imMt6@Ac0nf#5KzxV&nmY{=;qj#-HfnJW!L1`z57egw^kR2`uTrIZYH{+yahozl zPpuzkcVYT3RYK`quPF-m+0-odrRNf+0}Jb-aV>3T=-kk#r43vC6{=iedXA!= zTAZAP=~pYf8Z@FbK#Mxb#eidPy-G%8{3VUmDa+juO zDh#)o6@~kUgmH2&@ueqI0@|n?f-F$2B@lRRC6KgvFnL%HTamx61uLWri@tp|iZ5K7 zqHJVA1boQXykp0ZT+7Q2h1D@=VdQNSFsM<33I9|iZkwb^!?p&ea`3n@?;Gi|Gp)*G zAY;^$xl(0IwjET3n@3=M;cx-O;paO)u>1Kmm!JQI>QBheH(@^m|E8Z0ke|1@=3}k!2{_ur7mv(!xT7JCrn|Fo~dwgP)!XAdjbbk{XRX~PkKY&;Hi5G zGsszc>K-GE2Jfx=8Q~&Tkx}h2_gDzV=F_?=d;+~N54$30ph zeZgn5pM1$8a6TP!K@K~1HW>u)EzZM=XH_A+D-SKI{~#$JEN96o-P>Odh{Orl;Kiv5 zd;4c78tO>0!oF;DDc=6*hW)FRK!3DLh9x)8Pb6Lp@@~QRc zK!aZ;oVVh_sjz%PD=ykVuz`bUBXeT2?|Uc7x&zt=N96A(Yrti+(t? zWTT(9R%}?0R0XB!|4l2mzZU&xXz51xX)WE>LKr-4sI4XeD%8+;YSF!hR%Uds|Ln@_ z2UVzwLMt=QXJ2{=HPEeSVS1UO-ddbRrRjYYF0RE{v?l!`%12`_P5*(yo?0~GvoqgP1fZGNmtK!n2al=qT`*6guQ}xiOZBZ0HUyN%s$#6b;o4IvoQvY1(U3CnaWpdv2n)&vs#DQh% za|F3cDEYo#iUs$czhh>f$^r02e4p(c(C?x|7=Zxoa%*$VBfn1ZKMng5>m^5M=lnbD zY;fn?u5d9qyfySH%^Sdlv{c_n{J3IU8(c3%0Hrz&O7N94EiZu|Ss$e9Qc5xcv{KWB zO>ZzH=%jorvg%gY8^B1QRDXs9d{T9Mjow58eXMYyj@IA_d`9?}D&HIMW26IbBWdr? z&@1cK-v4V=AapkH1!3G}7y&DkYbOD%n6rcMOT^zs_;tcfh_4DBF0>GX6`D0D>!RBJ{p9$&ckrc3A}I?Y$gw&YRcy-F%y zdKNmFU|3CCMF^uEL1~rjI_)I9)b$0CH>;qud7xD(-t@CRr3KeUl;pmO%TnVNc*ssz9NR`$i+sL>1(sLpq3KWE{Y`YSh)B zmV&y)P|n&ac>^6(9%FV-!2by~a1{yANjOVkZy-XMvh{t$M&KM(kVZZD%Bqm?=T^QF z&=ZKZrh?LxH*hiGGQ|Es93@n!gyKLF;XH+nns|jh0rVz?I=RpQdXqx>dT4I|y+^4| zt6%_K@EV;~!2o)XQk_=80J?C0pznUy#bs@r8+GlfiBfhp`Jjh#lw!< zz+cN9I$S+K4FykQ_9-iEgnW37s9x0Ix0(2}bvYph(#VkM1UFWe(?ZjM{UkXtYob^O zn%3+@r{y89S{U?_=tT?lUnp^H$F}C(J7R(dO|QQnTA|=os5(jvEg3sVw;0GZ^|rOGB`)F=xWbtv&%3d;Wdv%n_Mq+f1Bb8t**afVnsiqK&p`rOcAA^K!* zEn0QxEDxxlM=R9WF9JSUku0Y+00RNQ(=6Xn$wwBH@%3EF zFaibGu#VTW4EmaVh>htkLLTK;5ypibUQ;UUp`U~RM@1Od=|X)6VI0yz_!vDU;FuQb zK84}iZ&U-NdWpjDF*$0mh;TCD0^-LpE!A&P*h9ZnQK;t=#vv`#=M%;uh54UH72x_< zs?SllIDqTp8vT08$MvyP&!q~glmLbLHI$FbW2ruk%H#65M$aLBTpkPcs|XjV^03Zk zsRTGyq#k7w?nb{5ys6SfIGOTsc?{ijsZr^0phx*QRB+>za24figw;^_VZH2D#^(v( z*ua}T!WD`U;#$HuG==&ngmLH!>57auP@?!tgI8p5sNf}z;s=`|0ooMy2INrr<(2qX zs6rg8LcNtRj#Z)lOTu|1PzzOnLshCDSGYKUL$yYKmhy3^O6dZVCxAm$s6R#dFjUY! z2=F9TkfRz{qcOUilLsh8PD{KTZsYf-0(+F1+P9|JMIDv2_;pj86eHemF ziY+3EA&sy`IGHdG6^yyUo&XLN1b>8as37`fV^=(eVGuhz;rxVL^oQu&|5ErHYG`CVh(wkj~0S znr(%XdBlg|q~Dir#gPe=fpKK$CT$4~4cY+QJ0OfU0=I7nqYZ%zw)jB*1|LxvTmw_`r=%SV<=2D(On1@og? z6$KYg9sCL5d{72CjB+uZeJ#(lJChglhUf!H||uz8vUeV@C0zW6zV@B9I0rbUQHErDcgYWbt2qN_~#0H1Dc|x zdLv<+Ev5Q7g+265R)zW*bxl^?NxA!GbLodkTvG>8Gx0O%7~QLbD2Upu$J!~`FDzxj zO#)vzt_bHHQ1RSz=INdB(KWg}ZNQZq?(dv4Km9tv9Qi;WbLOA>`^R4f@qh>0urBu) z^t~Rn4dYishqmwkpE7>adf3sVz4FA8F z-D;Qd-!;4I$vYI#Y;Pd%kWaXUa30|%dU>YjQbHRsp&VE}XR-=e=Sv`E`&aY}>5P3He`XkiTe-q51A_;xvq z^!NKGJ(|i$OIQlsl&O z|91z~|72WYg%y7INYDR`xWWo6VEq66xZ+>%JTMe+c>kTYRE^31nCCIibYGep{5Ydt zLY}Lh_C-ZO&-B5~X6o198wj=U`fu<>Z^GS$@7d<`o|XsRQ3gV5M*MSuP=B@E!NUUS zS>dNV;i5n+e6YZAQJ_`*pzIBgspPJ6vKNkRn8G#qmG-vJnY07H{ewuA@&iWnkr{OZ zKSBPMWyITX)E}-@n1jxw@MC?=$!C_r&+Zsz~x2O}zFF8}VQZo5;Ty@ZedN z>d%6Uan@}Gi>~DO`*GF}hA!Zd>fFQnh*=}_Oh!lH@*~^u#L@48F5qG6^Bi_QxrYtc z@Y9jj$0=-Y<(6y7x7d~~;Le5uQVp-bdpj#?l@(%x@LmEQDS&*!)f;KRRE12JfBG1{ zC-J2KXxtpeUgK}0^8K8)`p7OO0wx2KFjR5}7#CH+w zP)xOpdxtn0$^H=2;7VR84)$WNu@dMU)-$k+4Vme&ON#fn!?DN=eSMu53 z;?za#WNbA3I;$nvAA2_*@5A~sp0-__?91ZWbB!PLW$+6>IorkAek_SS)R-8}mNA~c zU2Kg3ysGix7&bbLR|5aVEQx;`B~D+=md2L2D()H}mc}vo&F)lj0%%IIOP~T65xa)& z60_sMxQ2Y!xIUi2@782(6Z;3SR5qyb#R2RmoEL2qt8~CGh>F!mMWc}qpcb1a@W z?GVQ=Wf^?Eu711l<)P9Z@W@1tX9A49{bvxfQ^cuUHY3Hw*4xE4Dn%SmWpjAZVD+0! zH7*@}G(i0(Q)Yr}GsUk8huREJcD9)&J{!)aq}=0b^Bou488JJJEn?q@gK2CEzjBE< zd<~no*`dZ-c*e;T$ z1N~E|-2QZ^_O)Bok4p0QpnN(@<*`e|>FGc(Un1sQ2K2>S#N-)3wH;#rWx)UUTjZ~` z$Mjj^oG#CbJ|o%iU@JE1wvL2S)1eda)0IP8T++P)F=M!fvsk`5OIsq&jszRNQ^bv8 zxA9Hz`cfcOg4c3 z06Mn_s!hlfb25Rx3!MOVrZ?W3$zJQh(i@kIWBnLUUMjy?DW$?zi~O>Y8XJ})c3I=W z@zO(eh|O2Bx7n1&+1c!K&WgmONo)qI6R+mL?7p(`;YlolaXm%s-N;t4>7vgR5asG< zk+Fd#iEE~?dX_Feo5B|Hh;ETFkL_mJsw8jwN}Qa>t`;Mvvb*^g{lxyM(9_fX#L21b zB!2_&G&Y?*DL$CS=Ju$EmCr1=WibEfE7A8U=#pQoyPD07&D!Z4k3aVjC$9$Aa#(zJ zHCVwtUx_(Svc;n08dz9nFGKt7+^OvMjiqS6FE6FvN!p3_+prYv_r;~os{as=_S?A= z?YBErPTBAKOVNJ+4&|l&rY=MKoxTk1_noC^zmdDpetRvG_8XhB%-PJ<@uKfYC~h@l z6HgiNV(5i5;5S_2&4=54b_1TcOc^kbj#pl2U6RZWd4y*MJ3Yeh2P?-hBhktB>L4du zmw0?8o51@dC?{0q(*EB5$_c&MUo|<&)#P2SCLbFtwn#r&S%7}CeHZ%8U&V>NPk?uF z72n`0e*a)GCygy+RpRg0v1UGFNaL~VSw^dwAlP;$#k((~-tk=Ygl=cO?aX&2LPDt9MU9uwX6x^7HcU{08ydeD-#%JK5|b zl18!hmJ5kVa|!g4n6!Y6=KGhS2Z3={9;9_AdXV>*Di0DKj~?Vdm!St)3)Uq)2w0W! zAa^ZO9wes7Rr`IS&mx$P&o4s<;)7PeBgE#q*tW)rzL_xn>cP6~9^?zKBI!X!h`4^S3-5*sHkW$@#;gA>K{WneP#iDJt#@DAR_=axY^{>#Cl z?{c=34>~K>FK1hN%!1I>?CN!~+U@fLgByDmvXhL(i8oiUpNaf5meAO~lKqMC>3?lJ zzM4G}&L8-T@=g53zbJ#?Hv^r=ritA3Y!jb8s1bhSaSP`O#C08Uz4rxjC2Rz)SM)~k zfcqJ*25-L!;+3r3;-O6tfP5@o+yoJuzwv`ju$1tk-D2r&Y`4A}zJozVoUrJsKv9N< zQb~iq5NB^=OWAE=Nf``XpD!A>l*urrVt3;s2HOjP#_q=PKGwGfA2(1;_rsD~y<6<} zgF1GLQQIK!8Pp|uR@8MNm(h*?qHL7rbkTP3AAgs4A^4xQEucTkD5QimYh2o^7_iwl+<3=5?B`+Z4l$|<^xglom|n#W z^H$Ja74VhiiTL|L*0ked`u*_T`d^8055Q>tRV;Xb&EVP|vHtzR8*{Lew! zggs*N&)Et7#!C4kiehjBtKq31i{lL-(a?{@sRp*2uj(x(KLNZeFH%26ogzOfZujw( z@L3~!r1_Zm>SJ7jYs9-pz;S^g$rV`_P;DH2IdEwK@WCTDsrAs4r@)*) z7k!?Bcwv_~`V_m5KU5^99|cSKTK!}<&#Dv;9fhvlS0s)}T2?9EItml|-XgIyjmL}Y zkFjL_1@b0TirvQ?Mc+EclJo=6zMM|-)3(;WOp2TRk?7mVw&?d2g%mEoHbL&Fq>sw4 z6#E;&mUBK5ryF4;t1CrP6VO1Bn9~HdnN=xPHGx)sR3r{d{B@o<(ZuEq{JZ_f62bS$ z*ip7uEJi&IlMsr{c^YO6D0A=A(EXdlXHT=?19QGd%D2R*XV@~{1l-R+1WtO>{YSr7vK@W7Ek>Gvb&FpzR!XRT5c8VpJjtDYEqkgsqM~6nX*+jd-_>uK6))K zu32}f#Z_#2j%D$^w~E8hLGjAF#fQ(a$+`ib^|SWa)=Nhj1Q)CmlaE7lO?Nl0KQ67g z^=`4Sg?%XLV6pz2~ccM!(qf0>oWIJH?kTfC5KHp_!%j603d* zl|bure#IW)9e0Z_e+A~YWt~WR5!R;eyF&vd2PoklG5tkwW4{%5ya*GoNId)^IIQcV z8+)DrC&#bsBfe|}S)MHsha>o4G3_Nblwa1Tan(yuhG+I`-2WTcl*YE(hD+Ako+pmK z%%RNkV<=2qXmdAEo%9l!!MPZuYD%l7iG zO2pDPV9sprD~`Vb`YpIeoX+Os#qZx_(Y$J!IQ=FtRoo-Cz6Evx^!Qs~_0fjt`!*;) z^FI0G9%A0x>@r>hJa0n-UDt{eZ-bdY183i6>!Z#=03>a!P32D%&kW*GlIeImFx7l6 zzHEn?i_GK2_3yAe9(}La{|<-^Pt673)6$*9!H0DJj&m^+R@w z&-03TTBvpGH4 z!;Q1QV0(J9R~p~^irv@4CSv3MZ^2R65(Fe%(O7(z-F#lEfYcrQqch_4S!ec+ED{5$`No$Dmy>thOBToW5-a}Ha_Icjj?#o92QFGm2Z zI9~idjOWT>$cW%qh?{!wLOB-4d+_ygEHc9RbU79~6iaTE zg}^H;lmn)`!_Y{+Jy`8Kk$k=~m0o;~tZu8M%`n8hphT~EA~lMq@}!N@3C6?bd1VwI z9tIoUd;9RW!+68JVpR#r^|^7 z9wAk{lFXxd(W~NAGIXM3py-QX?n>c+5EZ0B2geT|^Y!30r1y^47m7evFo5jgXcoKiCR5EAqof}2cr97Vh zeq-bKOL=M-zY$CT7Jc?WYE#F8j*F_HKMRfBhW)<2ccd^hy0{6@3kc1 zVv_J0DVCHlB%rjjxG?04WB6S&@`k!hSp@&UDTVsg3`YYrq!G|Cyi{>~Uln-Vb3^-0 zg;MZ%uaMP1gVaMAze)`ZnJS{vxZX=LD_*f=1Ro~SF6S5XmM_KR%lSk6aYYA-myR=d zt9?0d;`e_kj$HvB39M}YSeQ^ikB#N0fHpofPMR|$93IcVWc|g#3H&wPA#$}6L`#6s z2H5sy@#B(x&XxQTDmF;OWb>QZNU<&(X8KMzILU@d+_qN+8Plc1IC~XX`0T%ky>CL4 z+~rCiOX<<~IrzbSkDA06#qKN%`3h-|JIlmFllX29G-)za3-q*$Li#LGGlgFyGY?PU zXZb7Z8V~32-|*;78&|GeR=j@I2G5EW8&{T=il1N22P9m*q9o5#xMt;wshD~raLoiJ z@l`ILdJVBITeouKnzbvJsVYh~FJH6LfSOjUEVJ^xn^$gLxy+ukal?j9$Rnz*=0l{x zG@iJcFJp}b*Yf+r8nb5d{IED^{ptR3=POk-8KSQjSIBSkLxegYh>qQ2@KHa;m0#IDMek1SCbGRxQWqosb z%Um(1gva}9RwJwYwR-#-4#Y12jtSKQpA_L5yd(=gMG)%4k{f(F0fSiwpSXFPPWmy4 z-^jHgl&hvQ{vD>J+$h$s=NUu0XJShF4Ix1eK$6vH`VDYu$m3%dLPc@IVC(eU6z+pMhNUWcQ3A>=4p}|@-?T{2uyk5eG@y_d%c85mi zV!mCZpO8C}IUv%h4LpA6+C`zh$@IHj7@D5rgTwnwnF$Ygtl*Q3&Pi*T3ocHKDdiUz zufk0Ci2M|4wQNFixJTd^8|B-3s_Biy7!az+fbyuP}_CFHUXb@!2pcXg-RG*W@x` z(aV_ld@WB5>ljIYw89_$^}qo+KiR;OdW}Te$j=ZbrKwN|_51na^cEh!@^AD$IGo;( z{g__#zDV>nqJJkEOZ;g>FDH5>(dk6vslKk63{38eGJbK?uTc<45pzp;+*NIqP){_0 zULYmULdGnj6_jtKXU@W|M&;qpw`jO-jOO#0m;&xk%qfHQbFNq~$t2*4{GE$zn_fo%Ds|m67ziW+2f9>dQMs-zVCO-bJPook(;#(b+^76HTZ3 z#=+$3E#BJzet8_sKWI`{Nigj4c^ss%mO98kDf17){9Az8+Rq^0T7Rvc5FOeHO;}|m z`)>=m+7nPwjrjCtFn7yy$*+ALPYliT#ny5jpZ?s+&~%bncKLP#w!9+9cO3Y`D~`E` z8B)|RPje4*C7tAVKoR+L6SaofO7Eg{5E+)-jId;=aKk#D*r)n=EZCshO!4xIS)(}a z<4Iv{N6|8P%~5gI2X5^VIK&QlTliK~z*tx{t)PXg{Ge30l7 zMg5xgJSChY`eRrX*X z+&B*=K(Z=<|9lPnu_~m#wf$P`XSXW`jQ2WS#wft{mDEWO)dl(<-mJ9f?CCLp3Mu6=;Wg1|s4Vk|a?7<%E7D0YbnSsyE+W7yX!u61E_u+2- zZ*B;6Q0`$yQqBGw#OZC&K|kbM0?G3rE7TcP=89$k52dn_?Y?tdc!1ma$ zHw+*=y|q60ht>}cMz(W3w&Q-Z7;DkcCW~jb^Q72c(4nNIo$mX@$B@o5?-x-!_`*T0 z5vcc8SuH$r!HR{ksN$^Aw}U^5>$K_x}A7S5GtQZ|9gT)4)C+Z^}`O)I1L z#;UL+#aUs;6erFVBP#ijn66xRaxo;&YnK5vJXUS_bZ%hbRu}Ge;ppp}<NlaF+{bF0^$(F774v1i%e0+~vZVi)%H@?G}-{8Wz;)nNwjdyKzvQ=$! z;+*YH+~mU6XB{o)k-yW)U*f`*PAn$e$74J#&P2F@>8zy5g*#k0dbg85&4u&D%=`F| zs(q~_l%Pshx^T4%x4Ceq3wOJ4$IqPt)ihWb+t-?&uo94Vx^U!^ z&ipPH&U?z4pLxuQE1R4+`f0+{zLsMpV7k`&jI%(u3+F%U%&&Ce1{bb=&dJ|On10F; zt}(h8s-AZi$b7+xyMO7#MJJrN?4%QSpK{`~KPc=EhSW75I2p43;>7tbT2TrbTbvc zEU+-PuO$Q%WdGq@!G#kHs{rPA_?$Rxs}nc*oj7@?6PN8GOzmq~l}?5V7jAK3?M^3u zrVCfNaDxkX5)Q^@$#*#`%yr=s7p`*Q1{dyd;cgdByIZvvip?4@A?T^vT)4}HqwjGF zoaw@OE?nZmRSJXtt!dNXVrX;WZWm6t*C{}j3zt3U%&&IgR*B{KTLL5tXMvg@I&r59 zcRlIMFFE4G)h^uP!j(@ke7kN5(9|eq{e&k?ZGGBVk@k!eC%ABy3+Ia;{)7)1)8$Hz z{Drfc92d?PFF~=CIt!Gzu=YD=evS)Qxp0#UYrl7v&$VOe zf-39@fV*8d=Urz7WiDLp!pZa&+_LRF7p|~j*}j%Qugk3hT`nB?fm48F7jAdq{12V{ z9WI>p=V1N-*}m2gN>DhzQ)C~2v&)2!f{ZFX(}lZSxa?ymzxIg}cerrgr_TI@&m7pV zH8>NrtkVt#t;L0N>B51f$qE$+K_;x97v)G&vG9Ew_iA0c^*GOL{u< z>s`1i!kM2#@4YPn%IsJgN2fhO${yvcpu~mST(}5-1v|LTw!3ihMb7%VZCDv+Q6DEm zy9?*{b>=s?a9%%We!B~&MLYA$LRhu0wS^MY*mb*bbb_;jZWm4)=*%xmapEo)&Khdv zWBXc3FhRAib+~ZaFslIOm$`83rOy1w;ZB_A!j%@L_O&J}0qfT~UAQ9MSz)~kx43ZT zWlsJA7cL{LTUJ@^VracgMAd_Th#c*#C^OTE^T#-G#pO=iaD@|hjCEpdyb~u+aA0`1 zait?cOUriRDi?0O%9-Ep!u1oK`H_>HI6B9UVSLgY2@uXswKHg1@-!#zyxNJiYn-^n zg^TFMlr<6s({23HKI-iWfYWB!7yy^JaF+{b4Gr!7)r%QY6wk1ehFw0q> z)rFIw#P@F`wbZ(OD<&wxGjXO-|4wp`6i2?^v@WwmO_WURLt-m*Kch=*zt+RJ$i1Y}~ z;fcL`H@Xn5Z`f;hWvBAHvQtwDZ>L{|y?5XNJhq4TWVfbBuk2+>AH?=ES=juZ+q?@) z7h3nD#1363?hEHGtX+r;2@MxA7jhStF4RsWbX>??Sf0qb@dLTna3OP{=fcQ^!iBjD zwNt6fPUT+Dg^>$|g!7B9!be%L&rf9(lYW@4!%aA~7az($GhL(y@R7YLW#=bI&+K(c z+x%fvJuvn}?jO|cGq*_XbGJfo5bn;hk;K80<|7N(CaL(Z|ynxMj;fN$~6K?Ok>E8@?3D>{TS;TZi zj?rGg6L=0U;N{k3|7NvKZ2C8A*xU*qVFj+jF`U3PweR25HBt6&8gL4C-~l{>$MDp9 z`!(YN1uNKmAC5o_*WnhN!G1!f-PeqIUB~u0#|k+-fv4~cp2LfcW&E|nB??yX8aBgl zMCxz~XK>fqJ^#7`M<^J>Q+N(9;T61w&24{)gYG~@67El3g=08@Yj7QIz|GrHdHidK zEfl112Djl3+=YAa;5I(qhbTCLNANM6!(+IBCw(NQ@C=^A3wQ~y;5FPgKZMVD1+Ky| zoWM1>4mU#gO*2fG7M#Kv+=e@F7w!d?<8Kfop3pa2;;!T=w7GCEWXuX~8L+!ELw$cj4aFW&dWdO>Fu% zL--iZ;W1pmQ+T2F{hR7f;ZqR9O*n18%{YvwQw^gB=v~;32HD zLh1Si+Gp?rUWqrypKie12@k?5oWOOs0XN~;|L%289<=+eynU_ge{+ekyOyczPtSD) z&Yhnn$e%j*XV({r_Bh;N{#WSKpNFXR zmA}LG+@E)-?d^ZU_F>9z$;Z7v*O5+Fue*zSz~varcgy z-P$G2N66H$6cb`U=4)qE} gU7GjGZJx1zej2@QkDo^I*~K5_zP0T8PooR}1CRrTCIA2c delta 55624 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 Date: Fri, 22 May 2026 18:29:44 +0200 Subject: [PATCH 086/110] feat: simplify photon errors --- .../src/intent_executor/task_info_fetcher.rs | 78 +++++++------------ .../src/tasks/task_builder.rs | 8 +- 2 files changed, 32 insertions(+), 54 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index 7c1b01245..3644847cf 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -15,7 +15,7 @@ use compressed_delegation_api::{ use dlp_api::{ delegation_metadata_seeds_from_delegated_account, state::DelegationMetadata, }; -use futures_util::future::try_join_all; +use futures_util::{future::try_join_all, TryFutureExt}; use light_client::indexer::{ photon_indexer::PhotonIndexer, Indexer, IndexerRpcConfig, RetryConfig, }; @@ -127,7 +127,7 @@ impl RpcTaskInfoFetcher { fn photon_client(&self) -> TaskInfoFetcherResult<&PhotonIndexer> { self.photon_client .as_deref() - .ok_or(TaskInfoFetcherError::CompressionNotConfigured) + .ok_or(PhotonFetcherError::CompressionNotConfigured.into()) } /// Fetches [`DelegationMetadata`]s with some num of retries @@ -218,31 +218,7 @@ impl RpcTaskInfoFetcher { TaskInfoFetcherError::MagicBlockRpcClientError(ref err) => { warn!(error = ?err, attempt = i, "Fetch account error"); } - TaskInfoFetcherError::IndexerError(_) => { - break Err(err); - } - TaskInfoFetcherError::CompressionNotConfigured => { - break Err(err); - } - TaskInfoFetcherError::CompressedAccountNotFound(_) => { - break Err(err); - } - TaskInfoFetcherError::EmptyCompressedAccount => { - break Err(err); - } - TaskInfoFetcherError::MissingStateTrees => { - break Err(err); - } - TaskInfoFetcherError::MissingAddress => { - break Err(err); - } - TaskInfoFetcherError::MissingCompressedData => { - break Err(err); - } - TaskInfoFetcherError::LightSdkError(_) => { - break Err(err); - } - TaskInfoFetcherError::PhotonItemsMismatch(_, _) => { + TaskInfoFetcherError::PhotonFetcherError(_) => { break Err(err); } } @@ -341,15 +317,17 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { None, Some(IndexerRpcConfig::new(min_context_slot)), ) + .map_err(PhotonFetcherError::from) .await? .value .items; if items.len() != pubkeys.len() { - return Err(TaskInfoFetcherError::PhotonItemsMismatch( + return Err(PhotonFetcherError::PhotonItemsMismatch( items.len(), pubkeys.len(), - )); + ) + .into()); } let mut result = HashMap::with_capacity(pubkeys.len()); @@ -361,7 +339,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .ok() }) .map(|record| record.last_update_nonce + 1) - .ok_or(TaskInfoFetcherError::CompressedAccountNotFound( + .ok_or(PhotonFetcherError::CompressedAccountNotFound( *pubkey, ))?; result.insert(*pubkey, nonce); @@ -403,15 +381,17 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { None, Some(IndexerRpcConfig::new(min_context_slot)), ) + .map_err(PhotonFetcherError::from) .await? .value .items; if items.len() != pubkeys.len() { - return Err(TaskInfoFetcherError::PhotonItemsMismatch( + return Err(PhotonFetcherError::PhotonItemsMismatch( items.len(), pubkeys.len(), - )); + ) + .into()); } let mut result = HashMap::with_capacity(pubkeys.len()); @@ -423,7 +403,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .ok() }) .map(|record| record.last_update_nonce) - .ok_or(TaskInfoFetcherError::CompressedAccountNotFound( + .ok_or(PhotonFetcherError::CompressedAccountNotFound( *pubkey, ))?; result.insert(*pubkey, nonce); @@ -479,9 +459,10 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { retry_config: RetryConfig::default(), }), ) + .map_err(PhotonFetcherError::from) .await? .value - .ok_or(TaskInfoFetcherError::EmptyCompressedAccount)?; + .ok_or(PhotonFetcherError::EmptyCompressedAccount)?; let proof_result = self .photon_client()? .get_validity_proof( @@ -492,6 +473,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { retry_config: RetryConfig::default(), }), ) + .map_err(PhotonFetcherError::from) .await? .value; @@ -501,32 +483,30 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { let mut remaining_accounts = PackedAccounts::default(); remaining_accounts .add_system_accounts_v2(system_account_meta_config) - .map_err(|err| { - TaskInfoFetcherError::LightSdkError(Box::new(err)) - })?; + .map_err(|err| PhotonFetcherError::LightSdkError(Box::new(err)))?; let packed_tree_accounts = proof_result .pack_tree_infos(&mut remaining_accounts) .state_trees - .ok_or(TaskInfoFetcherError::MissingStateTrees)?; + .ok_or(PhotonFetcherError::MissingStateTrees)?; let tree_info = packed_tree_accounts .packed_tree_infos .first() .copied() - .ok_or(TaskInfoFetcherError::MissingStateTrees)?; + .ok_or(PhotonFetcherError::MissingStateTrees)?; let account_meta = CompressedAccountMeta { tree_info, address: compressed_delegation_record .address - .ok_or(TaskInfoFetcherError::MissingAddress)?, + .ok_or(PhotonFetcherError::MissingAddress)?, output_state_tree_index: packed_tree_accounts.output_tree_index, } .into(); let compressed_delegation_record_bytes = compressed_delegation_record .data - .ok_or(TaskInfoFetcherError::MissingCompressedData)? + .ok_or(PhotonFetcherError::MissingCompressedData)? .data; CompressedDelegationRecord::try_from_slice( &compressed_delegation_record_bytes, @@ -923,6 +903,12 @@ pub enum TaskInfoFetcherError { MinContextSlotNotReachedError(u64, Box), #[error("MagicBlockRpcClientError: {0}")] MagicBlockRpcClientError(Box), + #[error("Photon fetcher error: {0}")] + PhotonFetcherError(#[from] PhotonFetcherError), +} + +#[derive(thiserror::Error, Debug)] +pub enum PhotonFetcherError { #[error("Indexer error: {0}")] IndexerError(#[from] light_client::indexer::IndexerError), #[error("Compression is not configured")] @@ -991,15 +977,7 @@ impl TaskInfoFetcherError { Self::InvalidAccountDataError(_) => None, Self::MinContextSlotNotReachedError(_, err) => err.signature(), Self::MagicBlockRpcClientError(err) => err.signature(), - Self::IndexerError(_) => None, - Self::CompressionNotConfigured => None, - Self::CompressedAccountNotFound(_) => None, - Self::EmptyCompressedAccount => None, - Self::LightSdkError(_) => None, - Self::MissingStateTrees => None, - Self::MissingAddress => None, - Self::MissingCompressedData => None, - Self::PhotonItemsMismatch(_, _) => None, + Self::PhotonFetcherError(_) => None, } } } diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index a3f4e95e9..e9a4ee1b5 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -14,8 +14,8 @@ use tracing::error; use crate::{ intent_executor::task_info_fetcher::{ - CompressedData, TaskInfoFetcher, TaskInfoFetcherError, - TaskInfoFetcherResult, + CompressedData, PhotonFetcherError, TaskInfoFetcher, + TaskInfoFetcherError, TaskInfoFetcherResult, }, persist::IntentPersister, tasks::{ @@ -644,7 +644,7 @@ impl<'a> CommitFinalizeCompressedBuilder<'a> { .remove(&account.pubkey) .ok_or( TaskBuilderError::CommitFinalizeCompressedTasksBuildError( - TaskInfoFetcherError::MissingCompressedData, + PhotonFetcherError::MissingCompressedData.into(), ), )??; Ok( @@ -693,7 +693,7 @@ impl<'a> CommitFinalizeAndUndelegateCompressedBuilder<'a> { .remove(&account.pubkey) .ok_or( TaskBuilderError::CommitFinalizeCompressedTasksBuildError( - TaskInfoFetcherError::MissingCompressedData, + PhotonFetcherError::MissingCompressedData.into(), ), )??; Ok( From 0fe4eb02487c840f5f173fc193cf8779fd65d9a3 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Fri, 22 May 2026 19:53:22 +0200 Subject: [PATCH 087/110] style: format --- magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index c2f96909c..f662faeeb 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -2058,9 +2058,9 @@ where if !pending.contains(pubkey) { continue; } - if self.accounts_bank.get_account(pubkey).is_some_and(|in_bank| { - !in_bank.delegated() && !in_bank.compressed() - }) { + if self.accounts_bank.get_account(pubkey).is_some_and( + |in_bank| !in_bank.delegated() && !in_bank.compressed(), + ) { pending.remove(pubkey); } } From a9fc5a3aa93f56938d92c92ed3608d8e4e7e3f94 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 14:34:11 +0200 Subject: [PATCH 088/110] feat: paid compressed commits --- .../src/magic_scheduled_base_intent.rs | 42 ++- .../process_schedule_commit.rs | 2 +- .../process_schedule_intent_bundle.rs | 16 +- test-integration/Cargo.lock | 87 +++-- test-integration/Cargo.toml | 3 +- .../schedulecommit-conf-fees.ephem.toml | 3 + .../configs/schedulecommit-conf.devnet.toml | 4 + .../programs/flexi-counter/Cargo.toml | 2 +- .../programs/flexi-counter/src/instruction.rs | 13 +- .../programs/flexi-counter/src/processor.rs | 37 +- .../schedulecommit/test-scenarios/Cargo.toml | 6 + .../tests/04_compressed_commits.rs | 315 ++++++++++++++++++ .../tests/test_ix_commit_local.rs | 1 - test-integration/test-tools/Cargo.toml | 1 + .../src/integration_test_context.rs | 10 + 15 files changed, 461 insertions(+), 81 deletions(-) create mode 100644 test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index fae26e426..d32bd9cb3 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -36,6 +36,9 @@ pub const ACTUAL_COMMIT_LIMIT: u64 = 25; /// Fixed fee per commit. /// https://github.com/magicblock-labs/delegation-program/blob/main/src/consts.rs#L11 pub const COMMIT_FEE_LAMPORTS: u64 = 100_000; +/// Fixed fee per compressed commit. +/// Cost = 2 * (tx cost(5k) + light protocol fee(5k)) = 20k +pub const COMPRESSED_COMMIT_FEE_LAMPORTS: u64 = 20_000; /// Price per compute unit for a BaseAction executed on Solana base chain, /// denominated in micro-lamports per CU (mirrors Solana's priority fee model). pub const COMPUTE_UNIT_PRICE_MICRO_LAMPORTS: u64 = 50_000; @@ -441,16 +444,16 @@ impl MagicIntentBundle { ) -> Result { let mut fee = 0; if let Some(ref commit) = self.commit { - fee += commit.calculate_fee(commit_nonces)?; + fee += commit.calculate_fee(commit_nonces, false)?; } if let Some(ref cau) = self.commit_and_undelegate { - fee += cau.calculate_fee(commit_nonces)?; + fee += cau.calculate_fee(commit_nonces, false)?; } if let Some(ref commit) = self.commit_finalize_compressed { - fee += commit.calculate_fee(commit_nonces)?; + fee += commit.calculate_fee(commit_nonces, true)?; } if let Some(ref cau) = self.commit_finalize_compressed_and_undelegate { - fee += cau.calculate_fee(commit_nonces)?; + fee += cau.calculate_fee(commit_nonces, true)?; } fee += calculate_actions_fee(&self.standalone_actions); Ok(fee) @@ -969,9 +972,12 @@ impl CommitAndUndelegate { pub fn calculate_fee( &self, commit_nonces: &HashMap, + compressed: bool, ) -> Result { let mut fee = 0; - fee += self.commit_action.calculate_fee(commit_nonces)?; + fee += self + .commit_action + .calculate_fee(commit_nonces, compressed)?; fee += self.undelegate_action.calculate_fee(commit_nonces)?; Ok(fee) } @@ -1236,17 +1242,26 @@ impl CommitType { pub fn calculate_fee( &self, commit_nonces: &HashMap, + compressed: bool, ) -> Result { let mut fee = 0; match self { CommitType::Standalone(ref committed_accounts) => { - fee += calculate_commit_fee(committed_accounts, commit_nonces)?; + fee += calculate_commit_fee( + committed_accounts, + commit_nonces, + compressed, + )?; } CommitType::WithBaseActions { committed_accounts, base_actions, } => { - fee += calculate_commit_fee(committed_accounts, commit_nonces)?; + fee += calculate_commit_fee( + committed_accounts, + commit_nonces, + compressed, + )?; fee += calculate_actions_fee(base_actions); } } @@ -1423,10 +1438,13 @@ pub(crate) fn validate_commit_schedule_permissions( pub(crate) fn calculate_commit_fee( accounts: &[CommittedAccount], commit_nonces: &HashMap, + compressed: bool, ) -> Result { accounts.iter().try_fold(0u64, |fee, account| { if let Some(nonce) = commit_nonces.get(&account.pubkey) { - if nonce >= &ACTUAL_COMMIT_LIMIT { + if compressed { + Ok(fee + COMPRESSED_COMMIT_FEE_LAMPORTS) + } else if nonce >= &ACTUAL_COMMIT_LIMIT { Ok(fee + COMMIT_FEE_LAMPORTS) } else { Ok(fee) @@ -1490,8 +1508,9 @@ mod tests { // nonce is commits done so far; nonce+1 is the next commit number. // ACTUAL_COMMIT_LIMIT - 1 means the next commit is exactly at the limit → free. let nonces = HashMap::from([(pk, ACTUAL_COMMIT_LIMIT - 1)]); - let fee = calculate_commit_fee(&[make_committed_account(pk)], &nonces) - .unwrap(); + let fee = + calculate_commit_fee(&[make_committed_account(pk)], &nonces, false) + .unwrap(); assert_eq!(fee, 0); } @@ -1506,6 +1525,7 @@ mod tests { let fee = calculate_commit_fee( &[make_committed_account(pk1), make_committed_account(pk2)], &nonces, + false, ) .unwrap(); assert_eq!(fee, COMMIT_FEE_LAMPORTS * 2); @@ -1525,6 +1545,7 @@ mod tests { make_committed_account(pk_above), ], &nonces, + false, ) .unwrap(); assert_eq!(fee, COMMIT_FEE_LAMPORTS); @@ -1536,6 +1557,7 @@ mod tests { let err = calculate_commit_fee( &[make_committed_account(pk)], &HashMap::new(), + false, ) .unwrap_err(); assert_eq!(err, InstructionError::Custom(MISSING_COMMIT_NONCE_ERR)); diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs index 751c6ea45..45202aa98 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit.rs @@ -252,7 +252,7 @@ pub(crate) fn process_schedule_commit( if let Some(fee_vault) = magic_fee_vault { let nonces = fetch_current_commit_nonces(&committed_accounts, false)?; - let fee = calculate_commit_fee(&committed_accounts, &nonces)?; + let fee = calculate_commit_fee(&committed_accounts, &nonces, false)?; charge_delegated_payer(&payer_account, &fee_vault, fee)?; } else if !opts.request_undelegation { // We validate commit nonces only for plain commits. diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index 7d21994d6..e451554e6 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -11,7 +11,7 @@ use crate::{ magic_scheduled_base_intent::{ CommitType, ConstructionContext, ScheduledIntentBundle, }, - magic_sys::fetch_current_commit_nonces, + magic_sys::{fetch_current_commit_nonces, COMMIT_LIMIT_ERR}, schedule_transactions::{ check_commit_limits, check_magic_context_id, get_clock, get_parent_program_id, try_get_fee_vault, MAGIC_CONTEXT_IDX, PAYER_IDX, @@ -171,10 +171,18 @@ pub(crate) fn process_schedule_intent_bundle( } else if let Some(commit_accounts) = scheduled_intent.get_commit_intent_accounts() { - // TODO(dode): Add commit limits for compressed commits - // Cost for compressed commits is small (~5000 lamports) - // but since compressed accounts have 0 lamports, we never take fees for them check_commit_limits(commit_accounts, false, invoke_context)?; + } else if scheduled_intent + .get_commit_finalize_compressed_intent_accounts() + .is_some() + { + // Compressed accounts are free to delegate and don't have rents. + // Committing them must be paid for. + ic_msg!( + invoke_context, + "ScheduleCommit ERR: compressed accounts need to be paid for", + ); + return Err(InstructionError::Custom(COMMIT_LIMIT_ERR)); } let action_sent_signature = scheduled_intent.sent_transaction.signatures[0]; diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 7a79d8765..0d70c9bb9 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -2518,35 +2518,41 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk" -version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" +version = "0.14.3" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=01abca6e74631a10376c014bcc843ab168a8ba95#01abca6e74631a10376c014bcc843ab168a8ba95" dependencies = [ "base64ct", "bincode", - "borsh 1.6.1", + "bytemuck", "ephemeral-rollups-sdk-attribute-action", "ephemeral-rollups-sdk-attribute-commit", "ephemeral-rollups-sdk-attribute-delegate", "ephemeral-rollups-sdk-attribute-ephemeral", "ephemeral-rollups-sdk-attribute-ephemeral-accounts", + "five8 0.2.1", "getrandom 0.2.17", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade)", + "magicblock-delegation-program-api 3.0.0", "magicblock-magic-program-api 0.9.0", "solana-account 3.4.0", + "solana-account-info 2.3.0", "solana-account-info 3.1.1", + "solana-address 2.6.0", "solana-cpi 3.1.0", "solana-instruction 3.4.0", + "solana-program 2.3.0", + "solana-program 3.0.0", + "solana-program-error 2.2.2", "solana-program-error 3.0.1", "solana-program-memory 3.1.0", "solana-pubkey 3.0.0", - "solana-system-interface 3.2.0", + "solana-system-interface 2.0.0", "solana-sysvar 3.1.1", ] [[package]] name = "ephemeral-rollups-sdk-attribute-action" -version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" +version = "0.14.3" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=01abca6e74631a10376c014bcc843ab168a8ba95#01abca6e74631a10376c014bcc843ab168a8ba95" dependencies = [ "quote", "syn 1.0.109", @@ -2554,17 +2560,18 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-commit" -version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" +version = "0.14.3" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=01abca6e74631a10376c014bcc843ab168a8ba95#01abca6e74631a10376c014bcc843ab168a8ba95" dependencies = [ + "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "ephemeral-rollups-sdk-attribute-delegate" -version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" +version = "0.14.3" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=01abca6e74631a10376c014bcc843ab168a8ba95#01abca6e74631a10376c014bcc843ab168a8ba95" dependencies = [ "proc-macro2", "quote", @@ -2573,8 +2580,8 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-ephemeral" -version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" +version = "0.14.3" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=01abca6e74631a10376c014bcc843ab168a8ba95#01abca6e74631a10376c014bcc843ab168a8ba95" dependencies = [ "proc-macro2", "quote", @@ -2583,8 +2590,8 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-ephemeral-accounts" -version = "0.12.0" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=e864ea09d0#e864ea09d01fb88b1cf246a1450ea1ba6c3ba7fc" +version = "0.14.3" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=01abca6e74631a10376c014bcc843ab168a8ba95#01abca6e74631a10376c014bcc843ab168a8ba95" dependencies = [ "proc-macro2", "quote", @@ -3882,8 +3889,9 @@ dependencies = [ "anyhow", "borsh 1.6.1", "color-backtrace", + "light-client", "magicblock-config", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "rand 0.8.6", "rayon", "serde", @@ -5277,7 +5285,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-ledger", "magicblock-magic-program-api 0.11.1", "magicblock-metrics", @@ -5340,7 +5348,7 @@ dependencies = [ "magicblock-aml", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-magic-program-api 0.11.1", "magicblock-metrics", "parking_lot", @@ -5412,7 +5420,7 @@ dependencies = [ "lru 0.16.4", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -5499,12 +5507,13 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "0.3.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fupgrade#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" dependencies = [ "bincode", "borsh 1.6.1", "bytemuck", "const-crypto", + "libsodium-rs", "num_enum", "pinocchio 0.10.2", "pinocchio-log", @@ -5516,6 +5525,7 @@ dependencies = [ "solana-instruction 3.4.0", "solana-loader-v3-interface 6.1.1", "solana-program 3.0.0", + "solana-sdk", "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-system-interface 2.0.0", @@ -5526,14 +5536,15 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" -version = "0.3.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288904a9950bd20f27f0ef934f320ab1410bd35a6d5c9cf138eca276442b6b2e" dependencies = [ "bincode", + "borsh 0.10.4", "borsh 1.6.1", "bytemuck", "const-crypto", - "libsodium-rs", "num_enum", "pinocchio 0.10.2", "pinocchio-log", @@ -5545,7 +5556,7 @@ dependencies = [ "solana-instruction 3.4.0", "solana-loader-v3-interface 6.1.1", "solana-program 3.0.0", - "solana-sdk", + "solana-pubkey 2.4.0", "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", "solana-system-interface 2.0.0", @@ -5834,7 +5845,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.11.1" dependencies = [ - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config 3.1.1", @@ -6948,7 +6959,7 @@ version = "0.0.0" dependencies = [ "borsh 1.6.1", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-magic-program-api 0.11.1", "rkyv 0.7.46", "solana-program 3.0.0", @@ -8054,7 +8065,7 @@ dependencies = [ "anyhow", "borsh 1.6.1", "integration-test-tools", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "program-schedulecommit", "solana-commitment-config 3.1.1", "solana-compute-budget-interface 3.0.0", @@ -8080,7 +8091,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -8106,22 +8117,28 @@ name = "schedulecommit-test-scenarios" version = "0.0.0" dependencies = [ "borsh 1.6.1", + "compressed-delegation-client", "ephemeral-rollups-sdk", "integration-test-tools", + "light-client", + "light-sdk", "magicblock-core", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-magic-program-api 0.11.1", "magicblock-program", + "program-flexi-counter", "program-schedulecommit", "rand 0.8.6", "schedulecommit-client", "serial_test", "solana-commitment-config 3.1.1", + "solana-compute-budget-interface 3.0.0", "solana-program 3.0.0", "solana-rpc-client 3.1.12", "solana-rpc-client-api 3.1.12", "solana-sdk", "test-kit", + "tokio", "tracing", ] @@ -8130,7 +8147,7 @@ name = "schedulecommit-test-security" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-magic-program-api 0.11.1", "program-schedulecommit", "program-schedulecommit-security", @@ -13870,7 +13887,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "program-flexi-counter", "program-mini", "solana-account 3.4.0", @@ -13896,7 +13913,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -13967,7 +13984,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "program-flexi-counter", "solana-commitment-config 3.1.1", "solana-rpc-client 3.1.12", @@ -13990,7 +14007,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-program", "magicblock-validator-admin", "solana-commitment-config 3.1.1", @@ -14035,7 +14052,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "log", - "magicblock-delegation-program-api 0.3.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b)", + "magicblock-delegation-program-api 0.3.0", "magicblock-magic-program-api 0.11.1", "program-flexi-counter", "solana-rpc-client-api 3.1.12", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index dae0b8f74..40e5bc4ea 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -38,8 +38,7 @@ color-backtrace = { version = "0.7" } compressed-delegation-api = { path = "../compressed-delegation-api" } compressed-delegation-client = { path = "../compressed-delegation-client" } ctrlc = "3.4.7" -ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "e864ea09d0", default-features = false, features = [ - "disable-realloc", +ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "01abca6e74631a10376c014bcc843ab168a8ba95", features = [ "modular-sdk", ] } futures = "0.3.31" diff --git a/test-integration/configs/schedulecommit-conf-fees.ephem.toml b/test-integration/configs/schedulecommit-conf-fees.ephem.toml index 04a62c568..8f7265759 100644 --- a/test-integration/configs/schedulecommit-conf-fees.ephem.toml +++ b/test-integration/configs/schedulecommit-conf-fees.ephem.toml @@ -36,5 +36,8 @@ path = "test-integration/target/deploy/program_schedulecommit.so" id = "4RaQH3CUBMSMQsSHPVaww2ifeNEEuaDZjF9CUdFwr3xr" path = "test-integration/target/deploy/program_schedulecommit_security.so" +[compression] +photon-url = "http://localhost:8784" + [metrics] address = "0.0.0.0:9000" diff --git a/test-integration/configs/schedulecommit-conf.devnet.toml b/test-integration/configs/schedulecommit-conf.devnet.toml index 1bef3df83..95e792e3c 100644 --- a/test-integration/configs/schedulecommit-conf.devnet.toml +++ b/test-integration/configs/schedulecommit-conf.devnet.toml @@ -48,6 +48,10 @@ path = "../target/deploy/program_schedulecommit.so" id = "4RaQH3CUBMSMQsSHPVaww2ifeNEEuaDZjF9CUdFwr3xr" path = "../target/deploy/program_schedulecommit_security.so" +[[programs]] +id = "f1exzKGtdeVX3d6UXZ89cY7twiNJe9S5uq84RTA4Rq4" +path = "../target/deploy/program_flexi_counter.so" + [[programs]] id = "DEL2rPzhFaS5qzo8XY9ZNxSzuunWueySq3p2dxJfwPbT" path = "../programs/compressed_delegation/compressed_delegation.so" diff --git a/test-integration/programs/flexi-counter/Cargo.toml b/test-integration/programs/flexi-counter/Cargo.toml index fcd46c6ad..cbdf5cd36 100644 --- a/test-integration/programs/flexi-counter/Cargo.toml +++ b/test-integration/programs/flexi-counter/Cargo.toml @@ -15,7 +15,7 @@ light-sdk-types = { workspace = true, features = ["v2"] } magicblock-magic-program-api = { workspace = true } serde = { workspace = true } solana-program = { workspace = true } -solana-system-interface = { workspace = true } +solana-system-interface = { workspace = true, features = ["bincode"] } [lib] crate-type = ["cdylib", "lib"] diff --git a/test-integration/programs/flexi-counter/src/instruction.rs b/test-integration/programs/flexi-counter/src/instruction.rs index 9b12003d8..b8182fd85 100644 --- a/test-integration/programs/flexi-counter/src/instruction.rs +++ b/test-integration/programs/flexi-counter/src/instruction.rs @@ -776,14 +776,21 @@ pub fn create_delegate_compressed_ix( ) } -pub fn create_schedule_commit_compressed_ix(payer: Pubkey) -> Instruction { +pub fn create_schedule_commit_compressed_ix( + payer: &Pubkey, + validator: &Pubkey, +) -> Instruction { let program_id = &crate::id(); - let (pda, _) = FlexiCounter::pda(&payer); + let (pda, _) = FlexiCounter::pda(payer); let accounts = vec![ - AccountMeta::new(payer, true), + AccountMeta::new(*payer, true), AccountMeta::new(pda, false), AccountMeta::new(MAGIC_CONTEXT_ID, false), AccountMeta::new_readonly(MAGIC_PROGRAM_ID, false), + AccountMeta::new( + dlp_api::pda::magic_fee_vault_pda_from_validator(validator), + false, + ), ]; Instruction::new_with_borsh( *program_id, diff --git a/test-integration/programs/flexi-counter/src/processor.rs b/test-integration/programs/flexi-counter/src/processor.rs index f7555759f..605a590ab 100644 --- a/test-integration/programs/flexi-counter/src/processor.rs +++ b/test-integration/programs/flexi-counter/src/processor.rs @@ -15,7 +15,10 @@ use ephemeral_rollups_sdk::{ cpi::{ delegate_account, undelegate_account, DelegateAccounts, DelegateConfig, }, - ephem::{commit_accounts, commit_and_undelegate_accounts}, + ephem::{ + commit_accounts, commit_and_undelegate_accounts, FoldableIntentBuilder, + MagicIntentBundleBuilder, + }, }; use magicblock_magic_program_api::{ args::ScheduleTaskArgs, instruction::MagicBlockInstruction, @@ -709,7 +712,9 @@ fn process_schedule_commit_compressed( ) -> ProgramResult { msg!("ScheduleCommitCompressed"); - let [payer, counter, magic_context, magic_program] = accounts else { + let [payer, counter, magic_context, magic_program, magic_fee_vault] = + accounts + else { return Err(ProgramError::NotEnoughAccountKeys); }; @@ -725,31 +730,15 @@ fn process_schedule_commit_compressed( format!("Invalid counter PDA {}, should be {}", counter.key, pda) })?; - let instruction_data = MagicBlockInstruction::ScheduleCommitAndUndelegate - .try_to_vec() - .map_err(|_| ProgramError::BorshIoError)?; - - let account_metas = vec![ - AccountMeta::new(*payer.key, true), - AccountMeta::new(*magic_context.key, false), - AccountMeta::new(*counter.key, false), - AccountMeta::new_readonly(*magic_program.key, false), - ]; - - let account_refs = vec![ + MagicIntentBundleBuilder::new( payer.clone(), magic_context.clone(), - counter.clone(), magic_program.clone(), - ]; - - let ix = Instruction { - program_id: *magic_program.key, - data: instruction_data, - accounts: account_metas, - }; - - invoke(&ix, &account_refs)?; + ) + .magic_fee_vault(magic_fee_vault.clone()) + .commit(&[counter.clone()]) + .compressed() + .build_and_invoke()?; Ok(()) } diff --git a/test-integration/schedulecommit/test-scenarios/Cargo.toml b/test-integration/schedulecommit/test-scenarios/Cargo.toml index e3f29c57e..77e735c04 100644 --- a/test-integration/schedulecommit/test-scenarios/Cargo.toml +++ b/test-integration/schedulecommit/test-scenarios/Cargo.toml @@ -5,20 +5,26 @@ version.workspace = true [dev-dependencies] borsh = { workspace = true } +compressed-delegation-client = { workspace = true } ephemeral-rollups-sdk = { workspace = true } integration-test-tools = { workspace = true } +light-client = { workspace = true, features = ["v2"] } +light-sdk = { workspace = true, features = ["v2"] } magicblock-core = { workspace = true } magicblock-delegation-program-api = { workspace = true } magicblock-magic-program-api = { workspace = true } magicblock-program = { workspace = true } +program-flexi-counter = { workspace = true, features = ["no-entrypoint"] } program-schedulecommit = { workspace = true, features = ["no-entrypoint"] } rand = { workspace = true } schedulecommit-client = { workspace = true } serial_test = { workspace = true } solana-commitment-config = { workspace = true } +solana-compute-budget-interface = { workspace = true } solana-program = { workspace = true } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } solana-sdk = { workspace = true } test-kit = { workspace = true } +tokio = { workspace = true, features = ["full"] } tracing = { workspace = true } diff --git a/test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs b/test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs new file mode 100644 index 000000000..bf4c921cd --- /dev/null +++ b/test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs @@ -0,0 +1,315 @@ +#![allow(clippy::result_large_err)] + +use borsh::BorshDeserialize; +use compressed_delegation_client::CompressedDelegationRecord; +use integration_test_tools::{ + loaded_accounts::DLP_TEST_AUTHORITY_BYTES, + scheduled_commits::{ + extract_scheduled_commit_sent_signature_from_logs, + extract_sent_commit_info_from_logs, + }, + IntegrationTestContext, +}; +use light_client::indexer::{ + photon_indexer::PhotonIndexer, AddressWithTree, Indexer, + ValidityProofWithContext, +}; +use light_sdk::{ + instruction::{ + account_meta::CompressedAccountMeta, PackedAccounts, + SystemAccountMetaConfig, + }, + sdk_types::PackedAddressTreeInfo, +}; +use magicblock_core::compression::{ + derive_cda_from_pda, ADDRESS_TREE, OUTPUT_QUEUE, +}; +use program_flexi_counter::{ + instruction::{ + create_delegate_compressed_ix, + create_init_compressed_delegation_record_ix, create_init_ix, + create_schedule_commit_compressed_ix, DelegateCompressedArgs, + InitDelegationRecordArgs, + }, + state::FlexiCounter, +}; +use solana_compute_budget_interface::ComputeBudgetInstruction; +use solana_rpc_client::rpc_client::RpcClient; +use solana_rpc_client_api::config::RpcSendTransactionConfig; +use solana_sdk::{ + native_token::LAMPORTS_PER_SOL, + signature::{Keypair, Signer}, + transaction::Transaction, +}; + +#[tokio::test(flavor = "multi_thread")] +async fn test_schedule_compressed_commit() { + test_kit::init_logger!(); + + let ctx = IntegrationTestContext::try_new().unwrap(); + let chain_client = ctx.chain_client.as_ref().unwrap(); + let ephem_client = ctx.ephem_client.as_ref().unwrap(); + let photon_indexer = ctx.photon_client.as_ref().unwrap(); + + let payer_chain = Keypair::new(); + let counter_auth = Keypair::new(); + let validator_identity = ctx.ephem_validator_identity.unwrap(); + + ctx.airdrop_chain(&payer_chain.pubkey(), LAMPORTS_PER_SOL * 10) + .unwrap(); + ctx.airdrop_chain(&counter_auth.pubkey(), LAMPORTS_PER_SOL * 10) + .unwrap(); + + let validator_keypair = + Keypair::try_from(&DLP_TEST_AUTHORITY_BYTES[..]).unwrap(); + ctx.ensure_magic_fee_vault_delegated_on_chain(&validator_keypair) + .unwrap(); + + let (counter_pda, compressed_record_address) = + init_and_delegate_compressed_counter( + &chain_client, + &photon_indexer, + &counter_auth, + validator_identity, + ) + .await; + + let (_deleg_sig, confirmed) = + ctx.delegate_account(&payer_chain, &counter_auth).unwrap(); + assert!(confirmed, "failed to delegate ephemeral fee payer"); + + let schedule_sig = ephem_client + .send_and_confirm_transaction(&mut Transaction::new_signed_with_payer( + &[create_schedule_commit_compressed_ix( + &counter_auth.pubkey(), + &validator_identity, + )], + Some(&counter_auth.pubkey()), + &[&counter_auth], + ephem_client.get_latest_blockhash().unwrap(), + )) + .unwrap(); + + let schedule_logs = ctx.fetch_ephemeral_logs(schedule_sig).unwrap(); + let scheduled_commit_sent_sig = + extract_scheduled_commit_sent_signature_from_logs(&schedule_logs) + .unwrap(); + let sent_logs = + ctx.fetch_ephemeral_logs(scheduled_commit_sent_sig).unwrap(); + let (included, excluded, _feepayers, chain_sigs) = + extract_sent_commit_info_from_logs(&sent_logs); + for sig in &chain_sigs { + assert!( + ctx.confirm_transaction_chain(sig, None).unwrap(), + "chain commit transaction {sig} should confirm" + ); + } + + assert!( + included.contains(&counter_pda), + "compressed counter should be included in scheduled commit result: {included:#?}" + ); + assert!( + excluded.is_empty(), + "compressed counter should not be excluded from scheduled commit result: {excluded:#?}" + ); + + let compressed_account = photon_indexer + .get_compressed_account(compressed_record_address, None) + .await + .unwrap() + .value + .unwrap(); + let compressed_record = CompressedDelegationRecord::try_from_slice( + &compressed_account.data.unwrap().data, + ) + .unwrap(); + + let committed_counter = + FlexiCounter::try_from_slice(&compressed_record.data).unwrap(); + assert_eq!( + committed_counter.count, 0, + "compressed delegation record should contain committed counter state" + ); +} + +async fn init_and_delegate_compressed_counter( + chain_client: &RpcClient, + photon_indexer: &PhotonIndexer, + counter_auth: &Keypair, + validator_identity: solana_sdk::pubkey::Pubkey, +) -> (solana_sdk::pubkey::Pubkey, [u8; 32]) { + let (counter_pda, _) = FlexiCounter::pda(&counter_auth.pubkey()); + let compressed_record_address = + derive_cda_from_pda(&counter_pda).to_bytes(); + + let init_counter_ix = + create_init_ix(counter_auth.pubkey(), "COUNTER".to_string()); + let init_record_ix = create_init_compressed_record_ix( + counter_auth.pubkey(), + compressed_record_address, + photon_indexer, + ) + .await; + + send_chain_ixs( + &chain_client, + counter_auth, + &[ + ComputeBudgetInstruction::set_compute_unit_limit(300_000), + init_counter_ix, + init_record_ix, + ], + ) + .await; + + let delegate_ix = create_delegate_compressed_counter_ix( + counter_auth.pubkey(), + compressed_record_address, + &photon_indexer, + validator_identity, + ) + .await; + send_chain_ixs( + &chain_client, + counter_auth, + &[ + ComputeBudgetInstruction::set_compute_unit_limit(300_000), + delegate_ix, + ], + ) + .await; + + (counter_pda, compressed_record_address) +} + +async fn create_init_compressed_record_ix( + payer: solana_sdk::pubkey::Pubkey, + compressed_record_address: [u8; 32], + photon_indexer: &PhotonIndexer, +) -> solana_sdk::instruction::Instruction { + let mut remaining_accounts = packed_accounts(); + let rpc_result: ValidityProofWithContext = photon_indexer + .get_validity_proof( + vec![], + vec![AddressWithTree { + address: compressed_record_address, + tree: ADDRESS_TREE.to_bytes().into(), + }], + None, + ) + .await + .unwrap() + .value; + + let address_merkle_tree_pubkey_index = + remaining_accounts.insert_or_get(ADDRESS_TREE.to_bytes().into()); + let state_queue_pubkey_index = + remaining_accounts.insert_or_get(OUTPUT_QUEUE.to_bytes().into()); + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + create_init_compressed_delegation_record_ix( + payer, + &remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + InitDelegationRecordArgs { + validity_proof: rpc_result.proof.into(), + address_tree_info: PackedAddressTreeInfo { + root_index: rpc_result.addresses[0].root_index, + address_merkle_tree_pubkey_index, + address_queue_pubkey_index: address_merkle_tree_pubkey_index, + } + .into(), + output_state_tree_index: state_queue_pubkey_index, + }, + ) +} + +async fn create_delegate_compressed_counter_ix( + payer: solana_sdk::pubkey::Pubkey, + compressed_record_address: [u8; 32], + photon_indexer: &PhotonIndexer, + validator_identity: solana_sdk::pubkey::Pubkey, +) -> solana_sdk::instruction::Instruction { + let compressed_account = photon_indexer + .get_compressed_account(compressed_record_address, None) + .await + .unwrap() + .value + .unwrap(); + let mut remaining_accounts = packed_accounts(); + let rpc_result: ValidityProofWithContext = photon_indexer + .get_validity_proof(vec![compressed_account.hash], vec![], None) + .await + .unwrap() + .value; + + let state_queue_pubkey_index = + remaining_accounts.insert_or_get(OUTPUT_QUEUE.to_bytes().into()); + let packed_trees_info = rpc_result.pack_tree_infos(&mut remaining_accounts); + let packed_state_tree_info = packed_trees_info.state_trees.unwrap(); + let (remaining_accounts_metas, _, _) = + remaining_accounts.to_account_metas(); + + create_delegate_compressed_ix( + payer, + &remaining_accounts_metas + .iter() + .map(|meta| solana_sdk::message::AccountMeta { + pubkey: meta.pubkey.to_bytes().into(), + is_signer: meta.is_signer, + is_writable: meta.is_writable, + }) + .collect::>(), + DelegateCompressedArgs { + validator: Some(validator_identity), + validity_proof: rpc_result.proof.into(), + account_meta: CompressedAccountMeta { + tree_info: packed_state_tree_info.packed_tree_infos[0], + address: compressed_account.address.unwrap(), + output_state_tree_index: state_queue_pubkey_index, + } + .into(), + }, + ) +} + +fn packed_accounts() -> PackedAccounts { + let mut remaining_accounts = PackedAccounts::default(); + remaining_accounts + .add_system_accounts_v2(SystemAccountMetaConfig::new( + compressed_delegation_client::ID.to_bytes().into(), + )) + .unwrap(); + remaining_accounts +} + +async fn send_chain_ixs( + rpc_client: &RpcClient, + payer: &Keypair, + ixs: &[solana_sdk::instruction::Instruction], +) { + let latest_blockhash = rpc_client.get_latest_blockhash().unwrap(); + rpc_client + .send_and_confirm_transaction_with_spinner_and_config( + &Transaction::new_signed_with_payer( + ixs, + Some(&payer.pubkey()), + &[payer], + latest_blockhash, + ), + rpc_client.commitment(), + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ) + .unwrap(); +} diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index b1f13da78..f34a21372 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -889,7 +889,6 @@ async fn commit_n_accounts_x_bytes< expected_strategies: ExpectedStrategies, commit_type: CommitIntentKind, ) { - init_logger!(); let accs = (0..ACCOUNTS).map(|_| BYTES).collect::>(); commit_multiple_accounts( &accs, diff --git a/test-integration/test-tools/Cargo.toml b/test-integration/test-tools/Cargo.toml index 3474c8392..3817a0d01 100644 --- a/test-integration/test-tools/Cargo.toml +++ b/test-integration/test-tools/Cargo.toml @@ -13,6 +13,7 @@ rayon = { workspace = true } serde = { workspace = true } ureq = { workspace = true } url = { workspace = true } +light-client = { workspace = true, features = ["v2"] } magicblock-config = { workspace = true } magicblock-delegation-program-api = { workspace = true, features = [ "instruction", diff --git a/test-integration/test-tools/src/integration_test_context.rs b/test-integration/test-tools/src/integration_test_context.rs index f1246007d..d1cb2e7b7 100644 --- a/test-integration/test-tools/src/integration_test_context.rs +++ b/test-integration/test-tools/src/integration_test_context.rs @@ -4,6 +4,7 @@ use std::{str::FromStr, thread::sleep, time::Duration}; use anyhow::{Context, Result}; use borsh::BorshDeserialize; +use light_client::indexer::photon_indexer::PhotonIndexer; use solana_commitment_config::CommitmentConfig; use solana_rpc_client::{ nonblocking, @@ -45,6 +46,7 @@ use crate::{ const URL_CHAIN: &str = "http://localhost:7799"; const WS_URL_CHAIN: &str = "ws://localhost:7800"; const URL_EPHEM: &str = "http://localhost:8899"; +const URL_PHOTON: &str = "http://localhost:8784"; fn async_rpc_client( rpc_client: &RpcClient, @@ -83,6 +85,7 @@ pub struct IntegrationTestContext { pub commitment: CommitmentConfig, pub chain_client: Option, pub ephem_client: Option, + pub photon_client: Option, pub ephem_validator_identity: Option, } @@ -100,6 +103,7 @@ impl IntegrationTestContext { commitment, chain_client: None, ephem_client: Some(ephem_client), + photon_client: None, ephem_validator_identity: Some(validator_identity), }) } @@ -116,6 +120,7 @@ impl IntegrationTestContext { commitment, chain_client: Some(chain_client), ephem_client: None, + photon_client: None, ephem_validator_identity: None, }) } @@ -137,12 +142,14 @@ impl IntegrationTestContext { Self::url_local_ephem_at_port(port).to_string(), commitment, ); + let photon_client = PhotonIndexer::new(Self::url_photon().to_string()); let validator_identity = ephem_client.get_identity()?; Ok(Self { commitment, chain_client: Some(chain_client), ephem_client: Some(ephem_client), + photon_client: Some(photon_client), ephem_validator_identity: Some(validator_identity), }) } @@ -1371,6 +1378,9 @@ impl IntegrationTestContext { pub fn ws_url_chain() -> &'static str { WS_URL_CHAIN } + pub fn url_photon() -> &'static str { + URL_PHOTON + } // ----------------- // Prometheus Metrics From ff3acd6ee54f8fc98e54056c6a19de35ffe665eb Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 14:45:40 +0200 Subject: [PATCH 089/110] feat: prevent compressed commits misuse --- .../process_schedule_intent_bundle.rs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index e451554e6..bdf796e1f 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -45,6 +45,31 @@ pub(crate) fn process_schedule_intent_bundle( return Err(InstructionError::InvalidInstructionData); } + // User may be trying to do compressed commits for uncompressed accounts. + let mut compressed_account_indices = Vec::::new(); + if let Some(ref args_cau) = args.commit_finalize_compressed_and_undelegate { + compressed_account_indices + .extend(args_cau.committed_accounts_indices()); + } + if let Some(ref args_cc) = args.commit_finalize_compressed { + compressed_account_indices.extend(args_cc.committed_accounts_indices()); + } + if !compressed_account_indices.is_empty() { + for idx in compressed_account_indices { + let account = get_instruction_account_with_idx( + invoke_context.transaction_context, + idx as u16, + )?; + if !account.borrow()?.compressed() { + ic_msg!( + invoke_context, + "ScheduleIntentBundle: compressed commits are not supported for uncompressed accounts" + ); + return Err(InstructionError::InvalidInstructionData); + } + } + } + check_magic_context_id(invoke_context, MAGIC_CONTEXT_IDX)?; let parent_program_id = get_parent_program_id(invoke_context)?; From 759acdb46ccddba1e4a97f8fbc12facbd1b72ff3 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 14:51:08 +0200 Subject: [PATCH 090/110] fix: map borsh error --- .../src/builders/commit_finalize.rs | 7 +++++-- compressed-delegation-client/src/builders/delegate.rs | 7 +++++-- .../src/builders/init_delegation_record.rs | 7 +++++-- compressed-delegation-client/src/builders/undelegate.rs | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/compressed-delegation-client/src/builders/commit_finalize.rs b/compressed-delegation-client/src/builders/commit_finalize.rs index c6e35a1c7..f18a2e2d2 100644 --- a/compressed-delegation-client/src/builders/commit_finalize.rs +++ b/compressed-delegation-client/src/builders/commit_finalize.rs @@ -1,4 +1,5 @@ use solana_instruction::{AccountMeta, Instruction}; +use solana_program_error::ProgramError; use solana_pubkey::Pubkey; use crate::{CommitAndFinalizeArgs, DelegationProgramDiscriminator}; @@ -18,7 +19,7 @@ pub struct CommitAndFinalizeBuilder { } impl CommitAndFinalizeBuilder { - pub fn instruction(&self) -> Result { + pub fn instruction(&self) -> Result { Ok(Instruction { program_id: crate::COMPRESSED_DELEGATION_ID, accounts: [ @@ -32,7 +33,9 @@ impl CommitAndFinalizeBuilder { data: [ &(DelegationProgramDiscriminator::CommitAndFinalize as u64) .to_le_bytes(), - borsh::to_vec(&self.args)?.as_slice(), + borsh::to_vec(&self.args) + .map_err(|_| ProgramError::BorshIoError)? + .as_slice(), ] .concat(), }) diff --git a/compressed-delegation-client/src/builders/delegate.rs b/compressed-delegation-client/src/builders/delegate.rs index 479828792..04bc954b0 100644 --- a/compressed-delegation-client/src/builders/delegate.rs +++ b/compressed-delegation-client/src/builders/delegate.rs @@ -1,4 +1,5 @@ use solana_instruction::{AccountMeta, Instruction}; +use solana_program_error::ProgramError; use solana_pubkey::Pubkey; use crate::{DelegateArgs, DelegationProgramDiscriminator}; @@ -18,7 +19,7 @@ pub struct DelegateBuilder { } impl DelegateBuilder { - pub fn instruction(&self) -> Result { + pub fn instruction(&self) -> Result { Ok(Instruction { program_id: crate::COMPRESSED_DELEGATION_ID, accounts: [ @@ -32,7 +33,9 @@ impl DelegateBuilder { data: [ &(DelegationProgramDiscriminator::Delegate as u64) .to_le_bytes(), - borsh::to_vec(&self.args)?.as_slice(), + borsh::to_vec(&self.args) + .map_err(|_| ProgramError::BorshIoError)? + .as_slice(), ] .concat(), }) diff --git a/compressed-delegation-client/src/builders/init_delegation_record.rs b/compressed-delegation-client/src/builders/init_delegation_record.rs index 76f56d044..8c9fb34bc 100644 --- a/compressed-delegation-client/src/builders/init_delegation_record.rs +++ b/compressed-delegation-client/src/builders/init_delegation_record.rs @@ -1,4 +1,5 @@ use solana_instruction::{AccountMeta, Instruction}; +use solana_program_error::ProgramError; use solana_pubkey::Pubkey; use crate::{DelegationProgramDiscriminator, InitDelegationRecordArgs}; @@ -18,7 +19,7 @@ pub struct InitDelegationRecordBuilder { } impl InitDelegationRecordBuilder { - pub fn instruction(&self) -> Result { + pub fn instruction(&self) -> Result { Ok(Instruction { program_id: crate::COMPRESSED_DELEGATION_ID, accounts: [ @@ -32,7 +33,9 @@ impl InitDelegationRecordBuilder { data: [ &(DelegationProgramDiscriminator::InitDelegationRecord as u64) .to_le_bytes(), - borsh::to_vec(&self.args)?.as_slice(), + borsh::to_vec(&self.args) + .map_err(|_| ProgramError::BorshIoError)? + .as_slice(), ] .concat(), }) diff --git a/compressed-delegation-client/src/builders/undelegate.rs b/compressed-delegation-client/src/builders/undelegate.rs index 8c1a53830..5d0734c37 100644 --- a/compressed-delegation-client/src/builders/undelegate.rs +++ b/compressed-delegation-client/src/builders/undelegate.rs @@ -1,4 +1,5 @@ use solana_instruction::{AccountMeta, Instruction}; +use solana_program_error::ProgramError; use solana_pubkey::Pubkey; use crate::{DelegationProgramDiscriminator, UndelegateArgs}; @@ -22,7 +23,7 @@ pub struct UndelegateBuilder { } impl UndelegateBuilder { - pub fn instruction(&self) -> Result { + pub fn instruction(&self) -> Result { Ok(Instruction { program_id: crate::COMPRESSED_DELEGATION_ID, accounts: [ @@ -38,7 +39,9 @@ impl UndelegateBuilder { data: [ &(DelegationProgramDiscriminator::Undelegate as u64) .to_le_bytes(), - borsh::to_vec(&self.args)?.as_slice(), + borsh::to_vec(&self.args) + .map_err(|_| ProgramError::BorshIoError)? + .as_slice(), ] .concat(), }) From 801cb22e3705349865952293aab52ab08fc369e4 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 14:57:50 +0200 Subject: [PATCH 091/110] fix: ensure zero lamports --- .../process_schedule_intent_bundle.rs | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index bdf796e1f..caa988d69 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -34,10 +34,9 @@ pub(crate) fn process_schedule_intent_bundle( args: MagicIntentBundleArgs, secure: bool, ) -> Result<(), InstructionError> { - if !is_compression_enabled() - && (args.commit_finalize_compressed.is_some() - || args.commit_finalize_compressed_and_undelegate.is_some()) - { + let contains_compressed_commits = args.commit_finalize_compressed.is_some() + || args.commit_finalize_compressed_and_undelegate.is_some(); + if !is_compression_enabled() && contains_compressed_commits { ic_msg!( invoke_context, "ScheduleIntentBundle: compression is not enabled" @@ -45,27 +44,40 @@ pub(crate) fn process_schedule_intent_bundle( return Err(InstructionError::InvalidInstructionData); } - // User may be trying to do compressed commits for uncompressed accounts. - let mut compressed_account_indices = Vec::::new(); - if let Some(ref args_cau) = args.commit_finalize_compressed_and_undelegate { - compressed_account_indices - .extend(args_cau.committed_accounts_indices()); - } - if let Some(ref args_cc) = args.commit_finalize_compressed { - compressed_account_indices.extend(args_cc.committed_accounts_indices()); - } - if !compressed_account_indices.is_empty() { - for idx in compressed_account_indices { - let account = get_instruction_account_with_idx( - invoke_context.transaction_context, - idx as u16, - )?; - if !account.borrow()?.compressed() { - ic_msg!( + if contains_compressed_commits { + let mut compressed_account_indices = Vec::::new(); + if let Some(ref args_cau) = + args.commit_finalize_compressed_and_undelegate + { + compressed_account_indices + .extend(args_cau.committed_accounts_indices()); + } + if let Some(ref args_cc) = args.commit_finalize_compressed { + compressed_account_indices + .extend(args_cc.committed_accounts_indices()); + } + if !compressed_account_indices.is_empty() { + for idx in compressed_account_indices { + let account = get_instruction_account_with_idx( + invoke_context.transaction_context, + idx as u16, + )?; + let account = account.borrow()?; + if !account.compressed() { + ic_msg!( invoke_context, "ScheduleIntentBundle: compressed commits are not supported for uncompressed accounts" ); - return Err(InstructionError::InvalidInstructionData); + return Err(InstructionError::InvalidInstructionData); + } + + if account.lamports() != 0 { + ic_msg!( + invoke_context, + "ScheduleIntentBundle: compressed commits are not supported for accounts with non-zero lamports" + ); + return Err(InstructionError::InvalidInstructionData); + } } } } From 088eb48165deb39fc8e385229918db5d1f43d7aa Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 15:42:29 +0200 Subject: [PATCH 092/110] feat: move trait to chainlink --- Cargo.lock | 2 -- magicblock-chainlink/src/chainlink/errors.rs | 5 +++- .../chainlink/fetch_cloner/ata_projection.rs | 13 ++++----- .../src/chainlink/fetch_cloner/compression.rs | 5 ++-- .../src/chainlink/fetch_cloner/delegation.rs | 9 ++---- .../src/chainlink/fetch_cloner/mod.rs | 10 +++---- .../src/chainlink/fetch_cloner/pipeline.rs | 3 +- .../chainlink/fetch_cloner/program_loader.rs | 2 +- .../chainlink/fetch_cloner/subscription.rs | 5 ++-- magicblock-chainlink/src/chainlink/mod.rs | 6 ++-- .../src/remote_account_provider/mod.rs | 16 +++++----- .../remote_account_provider/photon_client.rs | 29 ++++++++++++++++--- .../src/testing/photon_client_mock.rs | 10 +++---- .../tests/utils/test_context.rs | 2 +- magicblock-core/Cargo.toml | 2 -- magicblock-core/src/traits.rs | 26 ----------------- test-integration/Cargo.lock | 2 -- .../programs/flexi-counter/src/processor.rs | 2 +- .../tests/04_compressed_commits.rs | 12 ++++---- 19 files changed, 74 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c9b4e357..1a3ffe20d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4850,7 +4850,6 @@ dependencies = [ name = "magicblock-core" version = "0.11.1" dependencies = [ - "async-trait", "bincode", "bytes", "compressed-delegation-client", @@ -4874,7 +4873,6 @@ dependencies = [ "solana-transaction-status-client-types 3.1.12", "spl-token-2022-interface 2.1.0", "spl-token-interface", - "thiserror 2.0.18", "tokio", "tracing", "tracing-log", diff --git a/magicblock-chainlink/src/chainlink/errors.rs b/magicblock-chainlink/src/chainlink/errors.rs index 18dec5ecc..bdb2fe9e9 100644 --- a/magicblock-chainlink/src/chainlink/errors.rs +++ b/magicblock-chainlink/src/chainlink/errors.rs @@ -50,7 +50,10 @@ pub enum ChainlinkError { MissingDelegationActionAccounts(Vec), #[error("Photon client error: {0}")] - PhotonClientError(#[from] magicblock_core::traits::PhotonClientError), + PhotonClientError( + #[from] + crate::remote_account_provider::photon_client::PhotonClientError, + ), #[error("timeout waiting for pending request for {0}")] PendingRequestTimeout(Pubkey), diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs index df1e55d1a..487119103 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs @@ -3,12 +3,9 @@ use std::collections::HashSet; use dlp_api::state::DelegationRecord; use futures_util::future::join_all; use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::{ - token_programs::{ - is_ata, try_derive_ata_address_and_bump, - try_derive_eata_address_and_bump, AtaInfo, - }, - traits::PhotonClient, +use magicblock_core::token_programs::{ + is_ata, try_derive_ata_address_and_bump, try_derive_eata_address_and_bump, + AtaInfo, }; use magicblock_metrics::metrics; use solana_account::{AccountSharedData, ReadableAccount}; @@ -25,8 +22,8 @@ use super::{ use crate::{ cloner::{AccountCloneRequest, Cloner, DelegationActions}, remote_account_provider::{ - ChainPubsubClient, ChainRpcClient, ResolvedAccountSharedData, - SubscriptionReason, + photon_client::PhotonClient, ChainPubsubClient, ChainRpcClient, + ResolvedAccountSharedData, SubscriptionReason, }, }; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs index a22d14cf3..5bcbb58c7 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/compression.rs @@ -1,7 +1,6 @@ use borsh::BorshDeserialize; use compressed_delegation_client::CompressedDelegationRecord; use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::traits::PhotonClient; use solana_account::{AccountSharedData, ReadableAccount}; use solana_pubkey::Pubkey; use tracing::*; @@ -9,7 +8,9 @@ use tracing::*; use super::FetchCloner; use crate::{ cloner::{AccountCloneRequest, Cloner, DelegationActions}, - remote_account_provider::{ChainPubsubClient, ChainRpcClient}, + remote_account_provider::{ + photon_client::PhotonClient, ChainPubsubClient, ChainRpcClient, + }, }; /// Expand a [`CompressedDelegationRecord`] from `data` into the logical owner, payload, and diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 29801418a..a98b85b22 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -3,10 +3,7 @@ use dlp_api::{ pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::{ - token_programs::{derive_eata, EATA_PROGRAM_ID}, - traits::PhotonClient, -}; +use magicblock_core::token_programs::{derive_eata, EATA_PROGRAM_ID}; use magicblock_metrics::metrics; use solana_account::ReadableAccount; use solana_keypair::Keypair; @@ -23,8 +20,8 @@ use crate::{ chainlink::errors::{ChainlinkError, ChainlinkResult}, cloner::{Cloner, DelegationActions}, remote_account_provider::{ - ChainPubsubClient, ChainRpcClient, MatchSlotsConfig, - ResolvedAccountSharedData, SubscriptionReason, + photon_client::PhotonClient, ChainPubsubClient, ChainRpcClient, + MatchSlotsConfig, ResolvedAccountSharedData, SubscriptionReason, }, }; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index f662faeeb..46757165d 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -15,12 +15,9 @@ use lru::LruCache; use magicblock_accounts_db::traits::AccountsBank; use magicblock_aml::RiskService; use magicblock_config::config::AllowedProgram; -use magicblock_core::{ - token_programs::{ - is_ata, try_derive_ata_address_and_bump, - try_derive_eata_address_and_bump, MaybeIntoAta, EATA_PROGRAM_ID, - }, - traits::PhotonClient, +use magicblock_core::token_programs::{ + is_ata, try_derive_ata_address_and_bump, try_derive_eata_address_and_bump, + MaybeIntoAta, EATA_PROGRAM_ID, }; use magicblock_metrics::metrics::{self, AccountFetchOrigin}; use parking_lot::Mutex as PlMutex; @@ -82,6 +79,7 @@ use crate::{ AccountCloneRequest, Cloner, DelegationActions, }, remote_account_provider::{ + photon_client::PhotonClient, program_account::get_loaderv3_get_program_data_address, ChainPubsubClient, ChainRpcClient, ForwardedSubscriptionUpdate, MatchSlotsConfig, RemoteAccount, RemoteAccountProvider, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index e31adef8e..127a50b83 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -2,7 +2,7 @@ use std::{collections::HashSet, sync::atomic::Ordering}; use dlp_api::pda::delegation_record_pda_from_delegated_account; use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::{token_programs::is_ata, traits::PhotonClient}; +use magicblock_core::token_programs::is_ata; use magicblock_metrics::metrics::AccountFetchOrigin; use solana_account::{AccountSharedData, ReadableAccount}; use solana_pubkey::Pubkey; @@ -23,6 +23,7 @@ use crate::{ errors::ClonerResult, AccountCloneRequest, Cloner, DelegationActions, }, remote_account_provider::{ + photon_client::PhotonClient, program_account::{ get_loaderv3_get_program_data_address, ProgramAccountResolver, LOADER_V3, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs index 67faa3fb6..e829cc233 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/program_loader.rs @@ -1,5 +1,4 @@ use magicblock_accounts_db::traits::AccountsBank; -use magicblock_core::traits::PhotonClient; use magicblock_metrics::metrics::AccountFetchOrigin; use solana_account::{AccountSharedData, ReadableAccount}; use solana_pubkey::Pubkey; @@ -9,6 +8,7 @@ use super::{subscription::release_program_data_subs, FetchCloner}; use crate::{ cloner::Cloner, remote_account_provider::{ + photon_client::PhotonClient, program_account::{ get_loaderv3_get_program_data_address, ProgramAccountResolver, LOADER_V1, LOADER_V3, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs index 87bb7eb5f..3020b703b 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/subscription.rs @@ -1,14 +1,13 @@ use std::sync::Arc; -use magicblock_core::traits::PhotonClient; use solana_pubkey::Pubkey; use tracing::*; use crate::{ chainlink::errors::{ChainlinkError, ChainlinkResult}, remote_account_provider::{ - ChainPubsubClient, ChainRpcClient, RemoteAccountProvider, - SubscriptionReason, + photon_client::PhotonClient, ChainPubsubClient, ChainRpcClient, + RemoteAccountProvider, SubscriptionReason, }, }; diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index c6c50876d..d14366724 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -6,7 +6,6 @@ use fetch_cloner::FetchCloner; use magicblock_accounts_db::{traits::AccountsBank, AccountsDbResult}; use magicblock_aml::RiskService; use magicblock_config::config::ChainLinkConfig; -use magicblock_core::traits::PhotonClient; use magicblock_metrics::metrics::AccountFetchOrigin; use solana_account::{AccountSharedData, ReadableAccount}; use solana_commitment_config::CommitmentConfig; @@ -26,8 +25,9 @@ use crate::{ remote_account_provider::{ chain_pubsub_client::mock::ChainPubsubClientMock, chain_updates_client::ChainUpdatesClient, - photon_client::PhotonClientImpl, ChainPubsubClient, ChainRpcClient, - ChainRpcClientImpl, Endpoints, RemoteAccountProvider, + photon_client::{PhotonClient, PhotonClientImpl}, + ChainPubsubClient, ChainRpcClient, ChainRpcClientImpl, Endpoints, + RemoteAccountProvider, }, submux::SubMuxClient, testing::{ diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 65b0c6851..96d09d18c 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -22,7 +22,6 @@ use futures_util::{ }; pub use lru_cache::AccountsLruCache; use magicblock_config::config::GrpcConfig; -use magicblock_core::traits::PhotonClient; pub(crate) use remote_account::RemoteAccount; pub use remote_account::RemoteAccountUpdateSource; use solana_account::Account; @@ -85,7 +84,8 @@ use crate::{ errors::ChainlinkResult, remote_account_provider::{ chain_updates_client::ChainUpdatesClient, - photon_client::PhotonClientImpl, pubsub_common::SubscriptionUpdate, + photon_client::{PhotonClient, PhotonClientImpl}, + pubsub_common::SubscriptionUpdate, remote_account::FetchedRemoteAccounts, }, submux::SubMuxClient, @@ -2312,15 +2312,17 @@ fn pubkeys_str(pubkeys: &[Pubkey]) -> String { #[cfg(test)] mod test { use light_client::indexer::IndexerError; - use magicblock_core::{ - traits::{PhotonClientError, PhotonClientResult}, - Slot, - }; + use magicblock_core::Slot; use solana_system_interface::program as system_program; use super::*; use crate::{ - remote_account_provider::chain_pubsub_client::mock::ChainPubsubClientMock, + remote_account_provider::{ + chain_pubsub_client::mock::ChainPubsubClientMock, + photon_client::{ + PhotonClient, PhotonClientError, PhotonClientResult, + }, + }, testing::{ init_logger, photon_client_mock::PhotonClientMock, diff --git a/magicblock-chainlink/src/remote_account_provider/photon_client.rs b/magicblock-chainlink/src/remote_account_provider/photon_client.rs index 3687eac42..a91093d16 100644 --- a/magicblock-chainlink/src/remote_account_provider/photon_client.rs +++ b/magicblock-chainlink/src/remote_account_provider/photon_client.rs @@ -5,15 +5,36 @@ use light_client::indexer::{ photon_indexer::PhotonIndexer, CompressedAccount, Context, Indexer, IndexerRpcConfig, Response, }; -use magicblock_core::{ - compression::derive_cda_from_pda, - traits::{PhotonClient, PhotonClientResult}, -}; +use magicblock_core::compression::derive_cda_from_pda; use solana_account::Account; use solana_clock::Slot; use solana_pubkey::Pubkey; +use thiserror::Error; use tracing::*; +#[derive(Debug, Clone, Error)] +pub enum PhotonClientError { + #[error("Indexer error: {0}")] + IndexerError(#[from] light_client::indexer::IndexerError), +} + +pub type PhotonClientResult = Result; + +#[async_trait] +pub trait PhotonClient: Send + Sync + Clone + 'static { + async fn get_account( + &self, + pubkey: &Pubkey, + min_context_slot: Option, + ) -> PhotonClientResult>; + + async fn get_multiple_accounts( + &self, + pubkeys: &[Pubkey], + min_context_slot: Option, + ) -> PhotonClientResult<(Vec>, Slot)>; +} + #[derive(Clone)] pub struct PhotonClientImpl(Arc); diff --git a/magicblock-chainlink/src/testing/photon_client_mock.rs b/magicblock-chainlink/src/testing/photon_client_mock.rs index e341bf84d..0d7ba75f5 100644 --- a/magicblock-chainlink/src/testing/photon_client_mock.rs +++ b/magicblock-chainlink/src/testing/photon_client_mock.rs @@ -1,15 +1,15 @@ use std::{collections::HashMap, sync::Arc}; -use magicblock_core::{ - compression::derive_cda_from_pda, - traits::{PhotonClient, PhotonClientResult}, - Slot, -}; +use magicblock_core::{compression::derive_cda_from_pda, Slot}; use parking_lot::Mutex; use solana_account::Account; use solana_pubkey::Pubkey; use tonic::async_trait; +use crate::remote_account_provider::photon_client::{ + PhotonClient, PhotonClientResult, +}; + #[derive(Clone, Default)] pub struct PhotonClientMock { accounts: Arc>>, diff --git a/magicblock-chainlink/tests/utils/test_context.rs b/magicblock-chainlink/tests/utils/test_context.rs index b6ce34c99..bdb166a35 100644 --- a/magicblock-chainlink/tests/utils/test_context.rs +++ b/magicblock-chainlink/tests/utils/test_context.rs @@ -12,6 +12,7 @@ use magicblock_chainlink::{ remote_account_provider::{ chain_pubsub_client::{mock::ChainPubsubClientMock, ChainPubsubClient}, config::RemoteAccountProviderConfig, + photon_client::PhotonClient, RemoteAccountProvider, }, testing::{ @@ -25,7 +26,6 @@ use magicblock_chainlink::{ AccountFetchOrigin, Chainlink, }; use magicblock_config::config::{ChainLinkConfig, LifecycleMode}; -use magicblock_core::traits::PhotonClient; use solana_account::{Account, AccountSharedData}; use solana_keypair::Keypair; use solana_program::{clock::Slot, sysvar::clock}; diff --git a/magicblock-core/Cargo.toml b/magicblock-core/Cargo.toml index e40ee4d55..a5decb6b9 100644 --- a/magicblock-core/Cargo.toml +++ b/magicblock-core/Cargo.toml @@ -8,13 +8,11 @@ license.workspace = true edition.workspace = true [dependencies] -async-trait = { workspace = true } light-client = { workspace = true } light-sdk = { workspace = true, features = ["v2"] } compressed-delegation-client = { workspace = true } console-subscriber = { workspace = true, optional = true } tokio = { workspace = true, features = ["sync"] } -thiserror = { workspace = true } flume = { workspace = true } bincode = { workspace = true } bytes = { workspace = true } diff --git a/magicblock-core/src/traits.rs b/magicblock-core/src/traits.rs index 3bd6e215c..9c4b603c2 100644 --- a/magicblock-core/src/traits.rs +++ b/magicblock-core/src/traits.rs @@ -1,14 +1,11 @@ use std::{collections::HashMap, fmt}; -use async_trait::async_trait; -use solana_account::Account; use solana_clock::Clock; use solana_hash::Hash; use solana_program::instruction::InstructionError; use solana_pubkey::Pubkey; use solana_signature::Signature; use solana_transaction_error::TransactionError; -use thiserror::Error; use crate::{ intent::{BaseActionCallback, CommittedAccount}, @@ -108,26 +105,3 @@ impl std::error::Error for ActionError { } pub type ActionResult = Result<(), ActionError>; - -#[derive(Debug, Clone, Error)] -pub enum PhotonClientError { - #[error("Indexer error: {0}")] - IndexerError(#[from] light_client::indexer::IndexerError), -} - -pub type PhotonClientResult = Result; - -#[async_trait] -pub trait PhotonClient: Send + Sync + Clone + 'static { - async fn get_account( - &self, - pubkey: &Pubkey, - min_context_slot: Option, - ) -> PhotonClientResult>; - - async fn get_multiple_accounts( - &self, - pubkeys: &[Pubkey], - min_context_slot: Option, - ) -> PhotonClientResult<(Vec>, Slot)>; -} diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 0d70c9bb9..2838992e2 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -5474,7 +5474,6 @@ dependencies = [ name = "magicblock-core" version = "0.11.1" dependencies = [ - "async-trait", "bincode", "bytes", "compressed-delegation-client", @@ -5497,7 +5496,6 @@ dependencies = [ "solana-transaction-status-client-types 3.1.12", "spl-token-2022-interface 2.1.0", "spl-token-interface", - "thiserror 2.0.18", "tokio", "tracing", "tracing-log", diff --git a/test-integration/programs/flexi-counter/src/processor.rs b/test-integration/programs/flexi-counter/src/processor.rs index 605a590ab..754e72407 100644 --- a/test-integration/programs/flexi-counter/src/processor.rs +++ b/test-integration/programs/flexi-counter/src/processor.rs @@ -736,7 +736,7 @@ fn process_schedule_commit_compressed( magic_program.clone(), ) .magic_fee_vault(magic_fee_vault.clone()) - .commit(&[counter.clone()]) + .commit(core::slice::from_ref(counter)) .compressed() .build_and_invoke()?; diff --git a/test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs b/test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs index bf4c921cd..ead78c28b 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/04_compressed_commits.rs @@ -67,8 +67,8 @@ async fn test_schedule_compressed_commit() { let (counter_pda, compressed_record_address) = init_and_delegate_compressed_counter( - &chain_client, - &photon_indexer, + chain_client, + photon_indexer, &counter_auth, validator_identity, ) @@ -79,7 +79,7 @@ async fn test_schedule_compressed_commit() { assert!(confirmed, "failed to delegate ephemeral fee payer"); let schedule_sig = ephem_client - .send_and_confirm_transaction(&mut Transaction::new_signed_with_payer( + .send_and_confirm_transaction(&Transaction::new_signed_with_payer( &[create_schedule_commit_compressed_ix( &counter_auth.pubkey(), &validator_identity, @@ -153,7 +153,7 @@ async fn init_and_delegate_compressed_counter( .await; send_chain_ixs( - &chain_client, + chain_client, counter_auth, &[ ComputeBudgetInstruction::set_compute_unit_limit(300_000), @@ -166,12 +166,12 @@ async fn init_and_delegate_compressed_counter( let delegate_ix = create_delegate_compressed_counter_ix( counter_auth.pubkey(), compressed_record_address, - &photon_indexer, + photon_indexer, validator_identity, ) .await; send_chain_ixs( - &chain_client, + chain_client, counter_auth, &[ ComputeBudgetInstruction::set_compute_unit_limit(300_000), From 86368d3cd1dd6c86f5e2c3637111c967706feb99 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 15:50:58 +0200 Subject: [PATCH 093/110] feat: move is compression enabled to magic sys --- magicblock-api/src/magic_sys_adapter.rs | 15 +++++++++++++-- magicblock-api/src/magic_validator.rs | 11 +++++------ magicblock-core/src/traits.rs | 2 ++ programs/magicblock/src/magic_sys.rs | 9 +++++++++ .../process_schedule_intent_bundle.rs | 7 ++++--- programs/magicblock/src/test_utils/mod.rs | 4 ++++ programs/magicblock/src/validator.rs | 14 +------------- 7 files changed, 38 insertions(+), 24 deletions(-) diff --git a/magicblock-api/src/magic_sys_adapter.rs b/magicblock-api/src/magic_sys_adapter.rs index c0beb482f..493cfe27b 100644 --- a/magicblock-api/src/magic_sys_adapter.rs +++ b/magicblock-api/src/magic_sys_adapter.rs @@ -10,6 +10,7 @@ use tracing::error; #[derive(Clone)] pub struct MagicSysAdapter { committor_service: Option>, + is_compression_enabled: bool, } impl MagicSysAdapter { @@ -24,8 +25,14 @@ impl MagicSysAdapter { const FETCH_TIMEOUT: Duration = Duration::from_secs(30); - pub fn new(committor_service: Option>) -> Self { - Self { committor_service } + pub fn new( + committor_service: Option>, + is_compression_enabled: bool, + ) -> Self { + Self { + committor_service, + is_compression_enabled, + } } } @@ -76,4 +83,8 @@ impl MagicSys for MagicSysAdapter { }) .map_err(|_| InstructionError::Custom(Self::FETCH_ERR)) } + + fn is_compression_enabled(&self) -> bool { + self.is_compression_enabled + } } diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index b8cc18c0d..c9624cfe9 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -226,9 +226,14 @@ impl MagicValidator { let committor_service = Self::init_committor_service(&config, ledger.latest_block()) .await?; + let is_compression_enabled = config + .compression + .as_ref() + .is_some_and(|compression| compression.photon_url.is_some()); log_timing("startup", "committor_service_init", step_start); init_magic_sys(Arc::new(MagicSysAdapter::new( committor_service.clone(), + is_compression_enabled, ))); let step_start = Instant::now(); @@ -331,12 +336,6 @@ impl MagicValidator { } let base_fee = config.validator.basefee; - let compression_enabled = config - .compression - .as_ref() - .is_some_and(|compression| compression.photon_url.is_some()); - validator::set_compression_enabled(compression_enabled); - let svm_env = build_svm_env(&accountsdb, latest_block.blockhash, 0); let feature_set = svm_env.feature_set.clone(); let txn_scheduler_state = TransactionSchedulerState { diff --git a/magicblock-core/src/traits.rs b/magicblock-core/src/traits.rs index 9c4b603c2..c07aaa130 100644 --- a/magicblock-core/src/traits.rs +++ b/magicblock-core/src/traits.rs @@ -20,6 +20,8 @@ pub trait MagicSys: Sync + Send + 'static { commits: &[CommittedAccount], compressed: bool, ) -> Result, InstructionError>; + + fn is_compression_enabled(&self) -> bool; } /// Provides read access to the latest confirmed block's metadata. diff --git a/programs/magicblock/src/magic_sys.rs b/programs/magicblock/src/magic_sys.rs index 233d0a19e..b76a8298e 100644 --- a/programs/magicblock/src/magic_sys.rs +++ b/programs/magicblock/src/magic_sys.rs @@ -40,3 +40,12 @@ pub(crate) fn fetch_current_commit_nonces( .ok_or(InstructionError::UninitializedAccount)? .fetch_current_commit_nonces(commits, compressed) } + +pub fn is_compression_enabled() -> Result { + Ok(MAGIC_SYS + .read() + .expect(MAGIC_SYS_POISONED_MSG) + .as_ref() + .ok_or(InstructionError::UninitializedAccount)? + .is_compression_enabled()) +} diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index caa988d69..5bb2c9f2a 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -11,7 +11,9 @@ use crate::{ magic_scheduled_base_intent::{ CommitType, ConstructionContext, ScheduledIntentBundle, }, - magic_sys::{fetch_current_commit_nonces, COMMIT_LIMIT_ERR}, + magic_sys::{ + fetch_current_commit_nonces, is_compression_enabled, COMMIT_LIMIT_ERR, + }, schedule_transactions::{ check_commit_limits, check_magic_context_id, get_clock, get_parent_program_id, try_get_fee_vault, MAGIC_CONTEXT_IDX, PAYER_IDX, @@ -24,7 +26,6 @@ use crate::{ get_instruction_account_with_idx, get_instruction_pubkey_with_idx, }, }, - validator::is_compression_enabled, MagicContext, }; @@ -36,7 +37,7 @@ pub(crate) fn process_schedule_intent_bundle( ) -> Result<(), InstructionError> { let contains_compressed_commits = args.commit_finalize_compressed.is_some() || args.commit_finalize_compressed_and_undelegate.is_some(); - if !is_compression_enabled() && contains_compressed_commits { + if !is_compression_enabled()? && contains_compressed_commits { ic_msg!( invoke_context, "ScheduleIntentBundle: compression is not enabled" diff --git a/programs/magicblock/src/test_utils/mod.rs b/programs/magicblock/src/test_utils/mod.rs index b92350b4e..44147e7d6 100644 --- a/programs/magicblock/src/test_utils/mod.rs +++ b/programs/magicblock/src/test_utils/mod.rs @@ -161,4 +161,8 @@ impl MagicSys for MagicSysStub { .collect(), } } + + fn is_compression_enabled(&self) -> bool { + false + } } diff --git a/programs/magicblock/src/validator.rs b/programs/magicblock/src/validator.rs index 9b7b6ac8c..919d5ce8f 100644 --- a/programs/magicblock/src/validator.rs +++ b/programs/magicblock/src/validator.rs @@ -1,7 +1,4 @@ -use std::sync::{ - atomic::{AtomicBool, Ordering}, - OnceLock, -}; +use std::sync::OnceLock; use solana_keypair::Keypair; use solana_pubkey::Pubkey; @@ -9,7 +6,6 @@ use solana_signer::Signer; static VALIDATOR_AUTHORITY: OnceLock = OnceLock::new(); static VALIDATOR_AUTHORITY_OVERRIDE: OnceLock = OnceLock::new(); -static IS_COMPRESSION_ENABLED: AtomicBool = AtomicBool::new(false); pub fn validator_authority() -> Keypair { VALIDATOR_AUTHORITY.wait().insecure_clone() @@ -38,11 +34,3 @@ pub fn effective_validator_authority_id() -> Pubkey { pub fn generate_validator_authority_if_needed() { VALIDATOR_AUTHORITY.get_or_init(Keypair::new); } - -pub fn set_compression_enabled(enabled: bool) { - IS_COMPRESSION_ENABLED.store(enabled, Ordering::Relaxed); -} - -pub fn is_compression_enabled() -> bool { - IS_COMPRESSION_ENABLED.load(Ordering::Relaxed) -} From 2deff75481ffb826ad37788c3a3a0f6092f83d91 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 15:53:21 +0200 Subject: [PATCH 094/110] feat: remove dead code --- magicblock-committor-service/src/config.rs | 26 ---------------------- 1 file changed, 26 deletions(-) diff --git a/magicblock-committor-service/src/config.rs b/magicblock-committor-service/src/config.rs index e54ec7442..833760bcd 100644 --- a/magicblock-committor-service/src/config.rs +++ b/magicblock-committor-service/src/config.rs @@ -16,26 +16,6 @@ pub struct ChainConfig { } impl ChainConfig { - pub fn devnet(compute_budget_config: ComputeBudgetConfig) -> Self { - Self { - rpc_uri: "https://api.devnet.solana.com".to_string(), - photon_uri: Some("http://localhost:8784".to_string()), - commitment: CommitmentConfig::confirmed(), - compute_budget_config, - actions_timeout: DEFAULT_ACTIONS_TIMEOUT, - } - } - - pub fn mainnet(compute_budget_config: ComputeBudgetConfig) -> Self { - Self { - rpc_uri: "https://api.mainnet-beta.solana.com".to_string(), - photon_uri: Some("http://localhost:8784".to_string()), - commitment: CommitmentConfig::confirmed(), - compute_budget_config, - actions_timeout: DEFAULT_ACTIONS_TIMEOUT, - } - } - pub fn local(compute_budget_config: ComputeBudgetConfig) -> Self { Self { rpc_uri: "http://localhost:7799".to_string(), @@ -46,9 +26,3 @@ impl ChainConfig { } } } - -impl Default for ChainConfig { - fn default() -> Self { - Self::local(ComputeBudgetConfig::new(1_000_000)) - } -} From 434d75079b4588c7cb3e28934b9e566bf0397b45 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 15:59:30 +0200 Subject: [PATCH 095/110] feat: move has compressed intent helper --- .../src/committor_processor.rs | 13 +++---------- .../magicblock/src/magic_scheduled_base_intent.rs | 9 +++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/magicblock-committor-service/src/committor_processor.rs b/magicblock-committor-service/src/committor_processor.rs index 1f6672248..478c0100f 100644 --- a/magicblock-committor-service/src/committor_processor.rs +++ b/magicblock-committor-service/src/committor_processor.rs @@ -111,15 +111,6 @@ impl CommittorProcessor { }) } - fn requires_compression(intent_bundle: &ScheduledIntentBundle) -> bool { - intent_bundle - .get_commit_finalize_compressed_intent_accounts() - .is_some() - || intent_bundle - .get_commit_finalize_compressed_and_undelegate_intent_accounts() - .is_some() - } - pub async fn active_lookup_tables(&self) -> Vec { self.table_mania.active_table_addresses().await } @@ -172,7 +163,9 @@ impl CommittorProcessor { intent_bundles: Vec, ) -> CommittorServiceResult<()> { if !self.compression_enabled - && intent_bundles.iter().any(Self::requires_compression) + && intent_bundles + .iter() + .any(ScheduledIntentBundle::has_compressed_intent) { return Err(CommittorServiceError::CompressionNotConfigured); } diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index d32bd9cb3..b80360a97 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -220,6 +220,10 @@ impl ScheduledIntentBundle { self.intent_bundle.has_callbacks() } + pub fn has_compressed_intent(&self) -> bool { + self.intent_bundle.has_compressed_intent() + } + pub fn is_empty(&self) -> bool { self.intent_bundle.is_empty() } @@ -753,6 +757,11 @@ impl MagicIntentBundle { x || y || z } + pub fn has_compressed_intent(&self) -> bool { + self.commit_finalize_compressed.is_some() + || self.commit_finalize_compressed_and_undelegate.is_some() + } + pub fn get_action_mut(&mut self, index: usize) -> Option<&mut BaseAction> { let mut offset = 0usize; From 5dba812653956abc4274a50fea00b38e8b411cfe Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 16:06:47 +0200 Subject: [PATCH 096/110] feat: filter invalid bundles --- .../src/committor_processor.rs | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/magicblock-committor-service/src/committor_processor.rs b/magicblock-committor-service/src/committor_processor.rs index 478c0100f..8317de904 100644 --- a/magicblock-committor-service/src/committor_processor.rs +++ b/magicblock-committor-service/src/committor_processor.rs @@ -18,7 +18,7 @@ use tracing::{error, instrument}; use crate::{ config::ChainConfig, - error::{CommittorServiceError, CommittorServiceResult}, + error::CommittorServiceResult, intent_execution_manager::{ db::DummyDB, BroadcastedIntentExecutionResult, IntentExecutionManager, }, @@ -42,7 +42,7 @@ pub(crate) struct CommittorProcessor { persister: IntentPersisterImpl, commits_scheduler: IntentExecutionManager, task_info_fetcher: Arc>, - compression_enabled: bool, + is_compression_enabled: bool, } impl CommittorProcessor { @@ -66,7 +66,7 @@ impl CommittorProcessor { .photon_uri .as_ref() .map(|uri| Arc::new(PhotonIndexer::new(uri.to_string()))); - let compression_enabled = photon_client.is_some(); + let is_compression_enabled = photon_client.is_some(); // Create TableMania let gc_config = GarbageCollectorConfig::default(); @@ -107,7 +107,7 @@ impl CommittorProcessor { commits_scheduler, persister, task_info_fetcher, - compression_enabled, + is_compression_enabled, }) } @@ -162,15 +162,20 @@ impl CommittorProcessor { &self, intent_bundles: Vec, ) -> CommittorServiceResult<()> { - if !self.compression_enabled - && intent_bundles - .iter() - .any(ScheduledIntentBundle::has_compressed_intent) - { - return Err(CommittorServiceError::CompressionNotConfigured); + let (invalid_bundles, valid_bundles): (Vec<_>, Vec<_>) = + intent_bundles.into_iter().partition(|bundle| { + !self.is_compression_enabled && bundle.has_compressed_intent() + }); + if !invalid_bundles.is_empty() { + for bundle in invalid_bundles { + error!( + bundle_id = bundle.id, + "Intent bundle contains compressed intent but compression is not enabled" + ); + } } - if let Err(err) = self.persister.start_base_intents(&intent_bundles) { + if let Err(err) = self.persister.start_base_intents(&valid_bundles) { // We will still try to perform the commits, but the fact that we cannot // persist the intent is very serious and we should probably restart the // valiator @@ -178,7 +183,7 @@ impl CommittorProcessor { }; self.commits_scheduler - .schedule(intent_bundles) + .schedule(valid_bundles) .await .inspect_err(|err| { error!(error = ?err, "Failed to schedule intent"); From 09168633e952adbcdf622906fb7bf3225a6fc5e4 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 16:10:42 +0200 Subject: [PATCH 097/110] feat: reuse magic sys --- .../src/committor_processor.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/magicblock-committor-service/src/committor_processor.rs b/magicblock-committor-service/src/committor_processor.rs index 8317de904..e83a060ec 100644 --- a/magicblock-committor-service/src/committor_processor.rs +++ b/magicblock-committor-service/src/committor_processor.rs @@ -6,7 +6,10 @@ use std::{ use light_client::indexer::photon_indexer::PhotonIndexer; use magicblock_core::traits::ActionsCallbackScheduler; -use magicblock_program::magic_scheduled_base_intent::ScheduledIntentBundle; +use magicblock_program::{ + magic_scheduled_base_intent::ScheduledIntentBundle, + magic_sys::is_compression_enabled, +}; use magicblock_rpc_client::MagicblockRpcClient; use magicblock_table_mania::{GarbageCollectorConfig, TableMania}; use solana_keypair::Keypair; @@ -18,7 +21,7 @@ use tracing::{error, instrument}; use crate::{ config::ChainConfig, - error::CommittorServiceResult, + error::{CommittorServiceError, CommittorServiceResult}, intent_execution_manager::{ db::DummyDB, BroadcastedIntentExecutionResult, IntentExecutionManager, }, @@ -42,7 +45,6 @@ pub(crate) struct CommittorProcessor { persister: IntentPersisterImpl, commits_scheduler: IntentExecutionManager, task_info_fetcher: Arc>, - is_compression_enabled: bool, } impl CommittorProcessor { @@ -66,7 +68,6 @@ impl CommittorProcessor { .photon_uri .as_ref() .map(|uri| Arc::new(PhotonIndexer::new(uri.to_string()))); - let is_compression_enabled = photon_client.is_some(); // Create TableMania let gc_config = GarbageCollectorConfig::default(); @@ -107,7 +108,6 @@ impl CommittorProcessor { commits_scheduler, persister, task_info_fetcher, - is_compression_enabled, }) } @@ -162,9 +162,11 @@ impl CommittorProcessor { &self, intent_bundles: Vec, ) -> CommittorServiceResult<()> { + let is_compression_enabled = is_compression_enabled() + .map_err(|_| CommittorServiceError::CompressionNotConfigured)?; let (invalid_bundles, valid_bundles): (Vec<_>, Vec<_>) = intent_bundles.into_iter().partition(|bundle| { - !self.is_compression_enabled && bundle.has_compressed_intent() + !is_compression_enabled && bundle.has_compressed_intent() }); if !invalid_bundles.is_empty() { for bundle in invalid_bundles { From 0f0627f56651477e7f54f7507b3fe6f75a80c6b1 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 16:26:54 +0200 Subject: [PATCH 098/110] feat: source not from --- magicblock-committor-service/src/tasks/task_builder.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index e9a4ee1b5..af6703777 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -646,7 +646,8 @@ impl<'a> CommitFinalizeCompressedBuilder<'a> { TaskBuilderError::CommitFinalizeCompressedTasksBuildError( PhotonFetcherError::MissingCompressedData.into(), ), - )??; + )? + .map_err(TaskBuilderError::CommitFinalizeCompressedTasksBuildError)?; Ok( TaskBuilderImpl::create_commit_finalize_compressed_task( nonce, @@ -695,7 +696,8 @@ impl<'a> CommitFinalizeAndUndelegateCompressedBuilder<'a> { TaskBuilderError::CommitFinalizeCompressedTasksBuildError( PhotonFetcherError::MissingCompressedData.into(), ), - )??; + )? + .map_err(TaskBuilderError::CommitFinalizeCompressedTasksBuildError)?; Ok( TaskBuilderImpl::create_commit_finalize_compressed_task( nonce, @@ -737,7 +739,7 @@ pub enum TaskBuilderError { #[error("FinalizedTasksBuildError: {0}")] FinalizedTasksBuildError(#[source] TaskInfoFetcherError), #[error("CommitFinalizeCompressedTasksBuildError: {0}")] - CommitFinalizeCompressedTasksBuildError(#[from] TaskInfoFetcherError), + CommitFinalizeCompressedTasksBuildError(#[source] TaskInfoFetcherError), } impl TaskBuilderError { From 9fd45a9448c0677b57c715e7973aa3835c993efd Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 16:28:44 +0200 Subject: [PATCH 099/110] fix: wrong error variant --- magicblock-committor-service/src/tasks/task_builder.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index af6703777..914ca0949 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -235,8 +235,9 @@ impl TaskBuilderImpl { tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); Default::default() }); - let compressed_data = - compressed_data.map_err(TaskBuilderError::CommitTasksBuildError)?; + let compressed_data = compressed_data.map_err( + TaskBuilderError::CommitFinalizeCompressedTasksBuildError, + )?; // Persist commit ids for commitees commit_nonces From 72435eabeff0d2960d8ca60e04e16fc604c2788a Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 16:36:31 +0200 Subject: [PATCH 100/110] feat: join futures --- .../src/intent_executor/utils.rs | 23 +++++++++++-------- .../src/tasks/task_builder.rs | 18 ++++++++------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/magicblock-committor-service/src/intent_executor/utils.rs b/magicblock-committor-service/src/intent_executor/utils.rs index 1e37e39ed..8c56c0725 100644 --- a/magicblock-committor-service/src/intent_executor/utils.rs +++ b/magicblock-committor-service/src/intent_executor/utils.rs @@ -113,21 +113,26 @@ pub(in crate::intent_executor) async fn handle_commit_id_error< // We re-fetch them to fix out of sync tasks task_info_fetcher.reset(ResetType::Specific(committed_pubkeys)); let commit_ids = { - let regular_nonces = task_info_fetcher - .fetch_next_commit_nonces(®ular_pubkeys, false, min_context_slot) - .await - .map_err(TaskBuilderError::CommitTasksBuildError)?; - let compressed_nonces = task_info_fetcher - .fetch_next_commit_nonces( + let (regular_nonces, compressed_nonces) = tokio::join!( + task_info_fetcher.fetch_next_commit_nonces( + ®ular_pubkeys, + false, + min_context_slot + ), + task_info_fetcher.fetch_next_commit_nonces( &compressed_pubkeys, true, min_context_slot, ) - .await - .map_err(TaskBuilderError::CommitTasksBuildError)?; + ); regular_nonces + .map_err(TaskBuilderError::CommitTasksBuildError)? .into_iter() - .chain(compressed_nonces.into_iter()) + .chain( + compressed_nonces + .map_err(TaskBuilderError::CommitFinalizeCompressedTasksBuildError)? + .into_iter(), + ) .collect::>() }; diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 914ca0949..f65064cf2 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -125,19 +125,21 @@ impl TaskBuilderImpl { .map(|(account, _)| account.pubkey) .collect::>(); - let regular_nonces = task_info_fetcher - .fetch_next_commit_nonces(®ular_pubkeys, false, min_context_slot) - .await?; - let compressed_nonces = task_info_fetcher - .fetch_next_commit_nonces( + let (regular_nonces, compressed_nonces) = tokio::join!( + task_info_fetcher.fetch_next_commit_nonces( + ®ular_pubkeys, + false, + min_context_slot + ), + task_info_fetcher.fetch_next_commit_nonces( &compressed_pubkeys, true, min_context_slot, ) - .await?; - Ok(regular_nonces + ); + Ok(regular_nonces? .into_iter() - .chain(compressed_nonces.into_iter()) + .chain(compressed_nonces?.into_iter()) .collect::>()) } From c519d23cc0ec174a5368c0095f89a9b64f1d1e9c Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 18:05:07 +0200 Subject: [PATCH 101/110] feat: move rustls to photon client --- magicblock-chainlink/src/remote_account_provider/mod.rs | 8 -------- .../src/remote_account_provider/photon_client.rs | 5 +++++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 96d09d18c..4fd4277ad 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -94,10 +94,6 @@ use crate::{ const ACTIVE_SUBSCRIPTIONS_UPDATE_INTERVAL_MS: u64 = 60_000; pub(crate) const DEFAULT_SUBSCRIPTION_RETRIES: usize = 5; -fn install_default_rustls_crypto_provider() { - let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); -} - type ChainUpdatesPubsub = (Arc, mpsc::Receiver<()>); async fn connect_pubsub_client( @@ -568,8 +564,6 @@ impl lrucache_subscribed_accounts: Arc, chain_slot: ChainSlot, ) -> RemoteAccountProviderResult { - install_default_rustls_crypto_provider(); - let (removed_account_tx, removed_account_rx) = tokio::sync::mpsc::channel(100); @@ -633,8 +627,6 @@ impl PhotonClientImpl, >, > { - install_default_rustls_crypto_provider(); - if endpoints.is_empty() { return Err( RemoteAccountProviderError::AccountSubscriptionsTaskFailed( diff --git a/magicblock-chainlink/src/remote_account_provider/photon_client.rs b/magicblock-chainlink/src/remote_account_provider/photon_client.rs index a91093d16..dd3006c6f 100644 --- a/magicblock-chainlink/src/remote_account_provider/photon_client.rs +++ b/magicblock-chainlink/src/remote_account_provider/photon_client.rs @@ -12,6 +12,10 @@ use solana_pubkey::Pubkey; use thiserror::Error; use tracing::*; +fn install_default_rustls_crypto_provider() { + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); +} + #[derive(Debug, Clone, Error)] pub enum PhotonClientError { #[error("Indexer error: {0}")] @@ -47,6 +51,7 @@ impl Deref for PhotonClientImpl { impl PhotonClientImpl { pub fn new(photon_indexer: Arc) -> Self { + install_default_rustls_crypto_provider(); Self(photon_indexer) } pub fn new_from_url(url: String) -> Self { From 843a78791bb787de12578eae9dd18b3cb4df49ab Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 18:30:35 +0200 Subject: [PATCH 102/110] fix: activate bincode feature --- test-integration/programs/schedulecommit/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-integration/programs/schedulecommit/Cargo.toml b/test-integration/programs/schedulecommit/Cargo.toml index b76a09e71..3dac943dd 100644 --- a/test-integration/programs/schedulecommit/Cargo.toml +++ b/test-integration/programs/schedulecommit/Cargo.toml @@ -12,7 +12,7 @@ magicblock-delegation-program-api = { workspace = true, features = [ magicblock-magic-program-api = { workspace = true } rkyv = { workspace = true } solana-program = { workspace = true } -solana-system-interface = { workspace = true } +solana-system-interface = { workspace = true, features = ["bincode"] } static_assertions = { workspace = true } [lib] From d7bc22da79b455ad10396a5aaf5d24c6da669a1e Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Mon, 25 May 2026 18:39:36 +0200 Subject: [PATCH 103/110] fix: remove deprecated tests --- .../src/remote_account_provider/mod.rs | 631 ------------------ 1 file changed, 631 deletions(-) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index 929635b64..bfac9a6bd 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -2313,634 +2313,3 @@ fn pubkeys_str(pubkeys: &[Pubkey]) -> String { .collect::>() .join(", ") } - -#[cfg(test)] -mod test { - use light_client::indexer::IndexerError; - use magicblock_core::Slot; - use solana_system_interface::program as system_program; - - use super::*; - use crate::{ - remote_account_provider::{ - chain_pubsub_client::mock::ChainPubsubClientMock, - photon_client::{ - PhotonClient, PhotonClientError, PhotonClientResult, - }, - }, - testing::{ - init_logger, - photon_client_mock::PhotonClientMock, - rpc_client_mock::{ - AccountAtSlot, ChainRpcClientMock, ChainRpcClientMockBuilder, - }, - utils::{create_test_lru_cache, random_pubkey}, - }, - }; - - #[derive(Clone)] - struct FailingPhotonClient { - fail_pubkey: Pubkey, - } - - #[tonic::async_trait] - impl PhotonClient for FailingPhotonClient { - async fn get_account( - &self, - pubkey: &Pubkey, - _min_context_slot: Option, - ) -> PhotonClientResult> { - if *pubkey == self.fail_pubkey { - Err(photon_failure()) - } else { - Ok(None) - } - } - - async fn get_multiple_accounts( - &self, - pubkeys: &[Pubkey], - min_context_slot: Option, - ) -> PhotonClientResult<(Vec>, Slot)> { - if pubkeys.contains(&self.fail_pubkey) { - Err(photon_failure()) - } else { - Ok((vec![None; pubkeys.len()], min_context_slot.unwrap_or(0))) - } - } - } - - fn photon_failure() -> PhotonClientError { - PhotonClientError::IndexerError(IndexerError::PhotonError { - context: "test".to_string(), - message: "forced photon failure".to_string(), - }) - } - - #[tokio::test] - async fn test_get_non_existing_account() { - init_logger(); - - let remote_account_provider = { - let (tx, rx) = mpsc::channel(1); - let rpc_client = ChainRpcClientMockBuilder::new() - .slot(1) - .clock_sysvar_for_slot(1) - .build(); - let pubsub_client = - chain_pubsub_client::mock::ChainPubsubClientMock::new(tx, rx); - let photon_client = PhotonClientMock::default(); - let (fwd_tx, _fwd_rx) = mpsc::channel(100); - let (subscribed_accounts, config) = create_test_lru_cache(1000); - let chain_slot = Arc::::default(); - - RemoteAccountProvider::new( - rpc_client, - pubsub_client, - Some(photon_client), - fwd_tx, - &config, - subscribed_accounts, - ChainSlot::new(chain_slot), - ) - .await - .unwrap() - }; - - let pubkey = random_pubkey(); - let remote_account = remote_account_provider - .try_get(pubkey, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - assert!(!remote_account.is_found()); - } - - #[tokio::test] - async fn test_photon_failure_is_returned_instead_of_rpc_not_found() { - init_logger(); - let pubkey = random_pubkey(); - - let remote_account_provider = { - let (tx, rx) = mpsc::channel(1); - let rpc_client = ChainRpcClientMockBuilder::new() - .slot(1) - .clock_sysvar_for_slot(1) - .build(); - let pubsub_client = - chain_pubsub_client::mock::ChainPubsubClientMock::new(tx, rx); - let (fwd_tx, _fwd_rx) = mpsc::channel(100); - let (subscribed_accounts, config) = create_test_lru_cache(1000); - let chain_slot = Arc::::default(); - - RemoteAccountProvider::new( - rpc_client, - pubsub_client, - Some(FailingPhotonClient { - fail_pubkey: pubkey, - }), - fwd_tx, - &config, - subscribed_accounts, - ChainSlot::new(chain_slot), - ) - .await - .unwrap() - }; - - let err = remote_account_provider - .try_get(pubkey, AccountFetchOrigin::GetAccount) - .await - .expect_err("Photon failure should not fall back to RPC NotFound"); - - assert!(matches!( - err, - RemoteAccountProviderError::AccountResolutionsFailed(_) - )); - assert!(err.to_string().contains("forced photon failure")); - } - - #[tokio::test] - async fn test_get_existing_account_for_valid_slot() { - init_logger(); - - const CURRENT_SLOT: u64 = 42; - let pubkey = random_pubkey(); - - let (remote_account_provider, rpc_client) = { - let rpc_client = ChainRpcClientMockBuilder::new() - .account( - pubkey, - Account { - lamports: 555, - data: vec![], - owner: system_program::id(), - executable: false, - rent_epoch: 0, - }, - ) - .clock_sysvar_for_slot(CURRENT_SLOT) - .slot(CURRENT_SLOT) - .build(); - let (tx, rx) = mpsc::channel(1); - let pubsub_client = - chain_pubsub_client::mock::ChainPubsubClientMock::new(tx, rx); - let photon_client = PhotonClientMock::default(); - ( - { - let (fwd_tx, _fwd_rx) = mpsc::channel(100); - let (subscribed_accounts, config) = - create_test_lru_cache(1000); - let chain_slot = Arc::::default(); - - RemoteAccountProvider::new( - rpc_client.clone(), - pubsub_client, - Some(photon_client), - fwd_tx, - &config, - subscribed_accounts, - ChainSlot::new(chain_slot), - ) - .await - .unwrap() - }, - rpc_client, - ) - }; - - let remote_account = remote_account_provider - .try_get(pubkey, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - let AccountAtSlot { account, slot } = - rpc_client.get_account_at_slot(&pubkey).unwrap(); - assert_eq!( - remote_account, - RemoteAccount::from_fresh_account( - account, - slot, - RemoteAccountUpdateSource::Fetch, - ) - ); - assert_eq!(rpc_client.single_account_fetches(), 2); - assert_eq!(rpc_client.multi_account_fetches(), 0); - } - - struct TestSlotConfig { - current_slot: u64, - account1_slot: u64, - account2_slot: u64, - } - - async fn setup_matching_slots( - config: TestSlotConfig, - pubkey1: Pubkey, - pubkey2: Pubkey, - ) -> ( - RemoteAccountProvider< - ChainRpcClientMock, - ChainPubsubClientMock, - PhotonClientMock, - >, - mpsc::Receiver, - ) { - init_logger(); - - let rpc_client = ChainRpcClientMockBuilder::new() - .slot(config.current_slot) - .account( - pubkey1, - Account { - lamports: 555, - data: vec![], - owner: system_program::id(), - executable: false, - rent_epoch: 0, - }, - ) - .account( - pubkey2, - Account { - lamports: 666, - data: vec![], - owner: system_program::id(), - executable: false, - rent_epoch: 0, - }, - ) - .account_override_slot(&pubkey1, config.account1_slot) - .account_override_slot(&pubkey2, config.account2_slot) - .build(); - let (tx, rx) = mpsc::channel(1); - let pubsub_client = ChainPubsubClientMock::new(tx, rx); - let photon_client = PhotonClientMock::default(); - - let (forward_tx, forward_rx) = mpsc::channel(100); - let (subscribed_accounts, config) = create_test_lru_cache(1000); - let chain_slot = Arc::::default(); - - ( - RemoteAccountProvider::new( - rpc_client, - pubsub_client, - Some(photon_client), - forward_tx, - &config, - subscribed_accounts, - ChainSlot::new(chain_slot), - ) - .await - .unwrap(), - forward_rx, - ) - } - - #[tokio::test] - async fn test_get_accounts_until_slots_match_finding_matching_slot() { - const CURRENT_SLOT: u64 = 42; - let pubkey1 = random_pubkey(); - let pubkey2 = random_pubkey(); - let (remote_account_provider, _) = setup_matching_slots( - TestSlotConfig { - current_slot: CURRENT_SLOT, - account1_slot: CURRENT_SLOT, - account2_slot: CURRENT_SLOT + 1, - }, - pubkey1, - pubkey2, - ) - .await; - - let remote_accounts = remote_account_provider - .try_get_multi_until_slots_match( - &[pubkey1, pubkey2], - Some(MatchSlotsConfig { - max_retries: 10, - retry_interval_ms: 50, - min_context_slot: None, - }), - AccountFetchOrigin::GetAccount, - ) - .await - .unwrap(); - - assert_eq!(remote_accounts.len(), 2); - assert!(remote_accounts[0].is_found()); - assert!(remote_accounts[1].is_found()); - assert_eq!(remote_accounts[0].fresh_lamports(), Some(555)); - assert_eq!(remote_accounts[1].fresh_lamports(), Some(666)); - } - - #[tokio::test] - async fn test_get_accounts_until_slots_match_not_finding_matching_slot() { - const CURRENT_SLOT: u64 = 42; - let pubkey1 = random_pubkey(); - let pubkey2 = random_pubkey(); - let (remote_account_provider, _) = setup_matching_slots( - TestSlotConfig { - current_slot: CURRENT_SLOT, - account1_slot: CURRENT_SLOT, - account2_slot: CURRENT_SLOT - 1, - }, - pubkey1, - pubkey2, - ) - .await; - - let res = remote_account_provider - .try_get_multi_until_slots_match( - &[pubkey1, pubkey2], - Some(MatchSlotsConfig { - max_retries: 10, - retry_interval_ms: 50, - min_context_slot: None, - }), - AccountFetchOrigin::GetAccount, - ) - .await; - - debug!(result = ?res, "Result"); - assert!(res.is_ok()); - let accs = res.unwrap(); - - assert_eq!(accs.len(), 2); - assert!(accs[0].is_found()); - assert!(!accs[1].is_found()); - } - - #[tokio::test] - async fn test_get_accounts_until_slots_match_finding_matching_slot_but_chain_slot_smaller_than_min_context_slot( - ) { - const CURRENT_SLOT: u64 = 42; - let pubkey1 = random_pubkey(); - let pubkey2 = random_pubkey(); - let (remote_account_provider, _) = setup_matching_slots( - TestSlotConfig { - current_slot: CURRENT_SLOT, - account1_slot: CURRENT_SLOT, - account2_slot: CURRENT_SLOT, - }, - pubkey1, - pubkey2, - ) - .await; - - let res = remote_account_provider - .try_get_multi_until_slots_match( - &[pubkey1, pubkey2], - Some(MatchSlotsConfig { - max_retries: 10, - retry_interval_ms: 50, - min_context_slot: Some(CURRENT_SLOT + 1), - }), - AccountFetchOrigin::GetAccount, - ) - .await; - - debug!(result = ?res, "Result"); - - assert!(res.is_err()); - assert!(matches!( - res.unwrap_err(), - RemoteAccountProviderError::MatchingSlotsNotSatisfyingMinContextSlot( - _pubkeys, - _slots, - slot, - _ - ) if slot == CURRENT_SLOT + 1 - )); - } - - #[tokio::test] - async fn test_get_accounts_until_slots_match_finding_matching_slot_but_one_account_slot_smaller_than_min_context_slot( - ) { - const CURRENT_SLOT: u64 = 42; - let pubkey1 = random_pubkey(); - let pubkey2 = random_pubkey(); - let (remote_account_provider, _) = setup_matching_slots( - TestSlotConfig { - current_slot: CURRENT_SLOT, - account1_slot: CURRENT_SLOT, - account2_slot: CURRENT_SLOT - 1, - }, - pubkey1, - pubkey2, - ) - .await; - - let res = remote_account_provider - .try_get_multi_until_slots_match( - &[pubkey1, pubkey2], - Some(MatchSlotsConfig { - max_retries: 10, - retry_interval_ms: 50, - min_context_slot: Some(CURRENT_SLOT), - }), - AccountFetchOrigin::GetAccount, - ) - .await; - - debug!(result = ?res, "Result"); - - assert!(res.is_ok()); - let accs = res.unwrap(); - - assert_eq!(accs.len(), 2); - assert!(accs[0].is_found()); - assert!(!accs[1].is_found()); - } - - // ----------------- - // LRU Cache/Eviction/Removal - // ----------------- - async fn setup_with_accounts( - pubkeys: &[Pubkey], - accounts_capacity: usize, - ) -> ( - RemoteAccountProvider< - ChainRpcClientMock, - ChainPubsubClientMock, - PhotonClientMock, - >, - mpsc::Receiver, - mpsc::Receiver, - ) { - let rpc_client = { - let mut rpc_client_builder = - ChainRpcClientMockBuilder::new().slot(1); - for pubkey in pubkeys { - rpc_client_builder = rpc_client_builder.account( - *pubkey, - Account { - lamports: 555, - data: vec![], - owner: system_program::id(), - executable: false, - rent_epoch: 0, - }, - ); - } - rpc_client_builder.build() - }; - - let (tx, rx) = mpsc::channel(1); - let pubsub_client = ChainPubsubClientMock::new(tx, rx); - let photon_client = PhotonClientMock::default(); - - let (forward_tx, forward_rx) = mpsc::channel(100); - let (subscribed_accounts, config) = - create_test_lru_cache(accounts_capacity); - let chain_slot = Arc::::default(); - - let provider = RemoteAccountProvider::new( - rpc_client, - pubsub_client, - Some(photon_client), - forward_tx, - &config, - subscribed_accounts, - ChainSlot::new(chain_slot), - ) - .await - .unwrap(); - - let removed_account_tx = provider.try_get_removed_account_rx().unwrap(); - (provider, forward_rx, removed_account_tx) - } - - fn drain_removed_account_rx( - rx: &mut mpsc::Receiver, - ) -> Vec { - let mut removed_accounts = Vec::new(); - while let Ok(pubkey) = rx.try_recv() { - removed_accounts.push(pubkey); - } - removed_accounts - } - - #[tokio::test] - async fn test_add_accounts_up_to_limit_no_eviction() { - // Higher level version (including removed_rx) from - // src/remote_account_provider/lru_cache.rs: - // - test_lru_cache_add_accounts_up_to_limit_no_eviction - init_logger(); - - let pubkey1 = Pubkey::new_unique(); - let pubkey2 = Pubkey::new_unique(); - let pubkey3 = Pubkey::new_unique(); - - let pubkeys = &[pubkey1, pubkey2, pubkey3]; - - let (provider, _, mut removed_rx) = - setup_with_accounts(pubkeys, 3).await; - - // Add three accounts (up to limit) - for pk in pubkeys { - provider - .try_get(*pk, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - } - - // No evictions should occur - let removed = drain_removed_account_rx(&mut removed_rx); - debug!(removed = ?removed, "Removed accounts"); - assert!(removed.is_empty(), "Expected no removed accounts"); - } - - #[tokio::test] - async fn test_eviction_order() { - // Higher level version (including removed_rx) from - // src/remote_account_provider/lru_cache.rs: - // - test_lru_cache_lru_eviction_order - init_logger(); - - let pubkey1 = Pubkey::new_unique(); - let pubkey2 = Pubkey::new_unique(); - let pubkey3 = Pubkey::new_unique(); - let pubkey4 = Pubkey::new_unique(); - let pubkey5 = Pubkey::new_unique(); - - let pubkeys = &[pubkey1, pubkey2, pubkey3, pubkey4, pubkey5]; - let (provider, _, mut removed_rx) = - setup_with_accounts(pubkeys, 3).await; - - // Fill cache: [1, 2, 3] (1 is least recently used) - provider - .try_get(pubkey1, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - provider - .try_get(pubkey2, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - provider - .try_get(pubkey3, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - - // Access pubkey1 to make it more recently used: [2, 3, 1] - // This should just promote, making order [2, 3, 1] - provider - .try_get(pubkey1, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - - // Add pubkey4, should evict pubkey2 (now least recently used) - provider - .try_get(pubkey4, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - - // Check channel received the evicted account - - let removed_accounts = drain_removed_account_rx(&mut removed_rx); - assert_eq!(removed_accounts, [pubkey2]); - - // Add pubkey5, should evict pubkey3 (now least recently used) - provider - .try_get(pubkey5, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - - // Check channel received the second evicted account - let removed_accounts = drain_removed_account_rx(&mut removed_rx); - assert_eq!(removed_accounts, [pubkey3]); - } - - #[tokio::test] - async fn test_multiple_evictions_in_sequence() { - // Higher level version (including removed_rx) from - // src/remote_account_provider/lru_cache.rs: - // - test_lru_cache_multiple_evictions_in_sequence - init_logger(); - - // Create test pubkeys - let pubkeys: Vec = - (1..=7).map(|_| Pubkey::new_unique()).collect(); - - let (provider, _, mut removed_rx) = - setup_with_accounts(&pubkeys, 4).await; - - // Fill cache to capacity (no evictions) - for pk in pubkeys.iter().take(4) { - provider - .try_get(*pk, AccountFetchOrigin::GetAccount) - .await - .unwrap(); - } - - // Add more accounts and verify evictions happen in LRU order - for i in 4..7 { - provider - .try_get(pubkeys[i], AccountFetchOrigin::GetAccount) - .await - .unwrap(); - let expected_evicted = pubkeys[i - 4]; // Should evict the account added 4 steps ago - - // Verify the evicted account was sent over the channel - let removed_accounts = drain_removed_account_rx(&mut removed_rx); - assert_eq!(removed_accounts, vec![expected_evicted]); - } - } -} From c12e0638c143420f1d6794fcead552cc7423fd2d Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Tue, 26 May 2026 00:03:40 +0200 Subject: [PATCH 104/110] Revert "feat: move rustls to photon client" This reverts commit c519d23cc0ec174a5368c0095f89a9b64f1d1e9c. --- magicblock-chainlink/src/remote_account_provider/mod.rs | 8 ++++++++ .../src/remote_account_provider/photon_client.rs | 5 ----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/magicblock-chainlink/src/remote_account_provider/mod.rs b/magicblock-chainlink/src/remote_account_provider/mod.rs index bfac9a6bd..060e068dd 100644 --- a/magicblock-chainlink/src/remote_account_provider/mod.rs +++ b/magicblock-chainlink/src/remote_account_provider/mod.rs @@ -94,6 +94,10 @@ use crate::{ const ACTIVE_SUBSCRIPTIONS_UPDATE_INTERVAL_MS: u64 = 60_000; pub(crate) const DEFAULT_SUBSCRIPTION_RETRIES: usize = 5; +fn install_default_rustls_crypto_provider() { + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); +} + type ChainUpdatesPubsub = (Arc, mpsc::Receiver<()>); async fn connect_pubsub_client( @@ -564,6 +568,8 @@ impl lrucache_subscribed_accounts: Arc, chain_slot: ChainSlot, ) -> RemoteAccountProviderResult { + install_default_rustls_crypto_provider(); + let (removed_account_tx, removed_account_rx) = tokio::sync::mpsc::channel(100); @@ -627,6 +633,8 @@ impl PhotonClientImpl, >, > { + install_default_rustls_crypto_provider(); + if endpoints.is_empty() { return Err( RemoteAccountProviderError::AccountSubscriptionsTaskFailed( diff --git a/magicblock-chainlink/src/remote_account_provider/photon_client.rs b/magicblock-chainlink/src/remote_account_provider/photon_client.rs index dd3006c6f..a91093d16 100644 --- a/magicblock-chainlink/src/remote_account_provider/photon_client.rs +++ b/magicblock-chainlink/src/remote_account_provider/photon_client.rs @@ -12,10 +12,6 @@ use solana_pubkey::Pubkey; use thiserror::Error; use tracing::*; -fn install_default_rustls_crypto_provider() { - let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); -} - #[derive(Debug, Clone, Error)] pub enum PhotonClientError { #[error("Indexer error: {0}")] @@ -51,7 +47,6 @@ impl Deref for PhotonClientImpl { impl PhotonClientImpl { pub fn new(photon_indexer: Arc) -> Self { - install_default_rustls_crypto_provider(); Self(photon_indexer) } pub fn new_from_url(url: String) -> Self { From bc090b6d10966184566d725b951a29680ef4580f Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Tue, 26 May 2026 00:29:50 +0200 Subject: [PATCH 105/110] fix: setup magicsys --- programs/magicblock/src/test_utils/mod.rs | 2 +- .../tests/test_ix_commit_local.rs | 28 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/programs/magicblock/src/test_utils/mod.rs b/programs/magicblock/src/test_utils/mod.rs index 44147e7d6..adbfd47b9 100644 --- a/programs/magicblock/src/test_utils/mod.rs +++ b/programs/magicblock/src/test_utils/mod.rs @@ -163,6 +163,6 @@ impl MagicSys for MagicSysStub { } fn is_compression_enabled(&self) -> bool { - false + true } } diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index f34a21372..ce8c68412 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -19,9 +19,13 @@ use magicblock_committor_service::{ use magicblock_core::{ compression::derive_cda_from_pda, intent::CommittedAccount, }; -use magicblock_program::magic_scheduled_base_intent::{ - CommitAndUndelegate, CommitType, MagicBaseIntent, MagicIntentBundle, - ScheduledIntentBundle, UndelegateType, +use magicblock_program::{ + init_magic_sys, + magic_scheduled_base_intent::{ + CommitAndUndelegate, CommitType, MagicBaseIntent, MagicIntentBundle, + ScheduledIntentBundle, UndelegateType, + }, + test_utils::MagicSysStub, }; use magicblock_rpc_client::MagicblockRpcClient; use program_flexi_counter::state::FlexiCounter; @@ -82,6 +86,11 @@ fn expect_strategies( expected_strategies } +fn setup_test() { + init_logger!(); + init_magic_sys(Arc::new(MagicSysStub::default())); +} + // ----------------- // +++++ Tests +++++ // ----------------- @@ -249,7 +258,7 @@ async fn commit_single_account( expected_strategy: CommitStrategy, commit_type: CommitIntentKind, ) { - init_logger!(); + setup_test(); let validator_auth = ensure_validator_authority(); fund_validator_auth_and_ensure_validator_fees_vault(&validator_auth).await; @@ -358,7 +367,7 @@ async fn commit_book_order_account( expected_strategy: CommitStrategy, commit_type: CommitIntentKind, ) { - init_logger!(); + setup_test(); let validator_auth = ensure_validator_authority(); fund_validator_auth_and_ensure_validator_fees_vault(&validator_auth).await; @@ -445,7 +454,6 @@ async fn commit_book_order_account( #[tokio::test] async fn test_ix_commit_two_accounts_1kb_2kb() { - init_logger!(); commit_multiple_accounts( &[1024, 2048], 1, @@ -457,7 +465,6 @@ async fn test_ix_commit_two_accounts_1kb_2kb() { #[tokio::test] async fn test_ix_commit_two_accounts_512kb() { - init_logger!(); commit_multiple_accounts( &[512, 512], 1, @@ -469,7 +476,6 @@ async fn test_ix_commit_two_accounts_512kb() { #[tokio::test] async fn test_ix_commit_three_accounts_512kb() { - init_logger!(); commit_multiple_accounts( &[512, 512, 512], 1, @@ -481,7 +487,6 @@ async fn test_ix_commit_three_accounts_512kb() { #[tokio::test] async fn test_ix_commit_six_accounts_512kb() { - init_logger!(); commit_multiple_accounts( &[512, 512, 512, 512, 512, 512], 1, @@ -493,7 +498,6 @@ async fn test_ix_commit_six_accounts_512kb() { #[tokio::test] async fn test_ix_commit_four_accounts_1kb_2kb_5kb_10kb_single_bundle() { - init_logger!(); commit_multiple_accounts( &[1024, 2 * 1024, 5 * 1024, 10 * 1024], 1, @@ -953,7 +957,7 @@ async fn commit_multiple_accounts( commit_type: CommitIntentKind, expected_strategies: ExpectedStrategies, ) { - init_logger!(); + setup_test(); let validator_auth = ensure_validator_authority(); fund_validator_auth_and_ensure_validator_fees_vault(&validator_auth).await; @@ -1045,7 +1049,7 @@ async fn execute_intent_bundle( expected_strategies: ExpectedStrategies, compressed: bool, ) { - init_logger!(); + setup_test(); let validator_auth = ensure_validator_authority(); fund_validator_auth_and_ensure_validator_fees_vault(&validator_auth).await; From 695bb885f74ad6d7c83021ddd9c2896f06ca3986 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Tue, 26 May 2026 18:56:05 +0200 Subject: [PATCH 106/110] feat: update api --- compressed-delegation-api/src/instruction.rs | 4 ++-- .../compressed_delegation.so | Bin 184936 -> 185352 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compressed-delegation-api/src/instruction.rs b/compressed-delegation-api/src/instruction.rs index 848269502..9e95a8fbf 100644 --- a/compressed-delegation-api/src/instruction.rs +++ b/compressed-delegation-api/src/instruction.rs @@ -133,12 +133,12 @@ pub struct DelegateArgs { pub owner_program_id: Pubkey, /// Validator pub validator: Pubkey, + /// Bump + pub bump: u8, /// Account data before delegation pub account_data: Vec, /// PDA seeds pub pda_seeds: Vec>, - /// Bump - pub bump: u8, } #[repr(C)] diff --git a/test-integration/programs/compressed_delegation/compressed_delegation.so b/test-integration/programs/compressed_delegation/compressed_delegation.so index 99b506cf36d2a126929642bc94c0ad08c6de5d92..6b0090a5aabe779a6be3c9522b4c5756ef62496e 100755 GIT binary patch delta 36967 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 GFZ(~$qpnc^ delta 36690 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 Date: Wed, 27 May 2026 09:38:42 +0200 Subject: [PATCH 107/110] fix: cloning --- magicblock-account-cloner/src/lib.rs | 1 + magicblock-magic-program-api/src/instruction.rs | 1 + programs/magicblock/src/clone_account/common.rs | 7 +++++-- programs/magicblock/src/clone_account/tests.rs | 2 ++ .../process_schedule_intent_bundle.rs | 6 ++++-- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/magicblock-account-cloner/src/lib.rs b/magicblock-account-cloner/src/lib.rs index e39570e08..ce41dbc22 100644 --- a/magicblock-account-cloner/src/lib.rs +++ b/magicblock-account-cloner/src/lib.rs @@ -221,6 +221,7 @@ impl ChainlinkCloner { executable: request.account.executable(), delegated: request.account.delegated(), confined: request.account.confined(), + compressed: request.account.compressed(), remote_slot: request.account.remote_slot(), } } diff --git a/magicblock-magic-program-api/src/instruction.rs b/magicblock-magic-program-api/src/instruction.rs index 6e4c6b01b..7ca1daa83 100644 --- a/magicblock-magic-program-api/src/instruction.rs +++ b/magicblock-magic-program-api/src/instruction.rs @@ -346,6 +346,7 @@ pub struct AccountCloneFields { pub executable: bool, pub delegated: bool, pub confined: bool, + pub compressed: bool, pub remote_slot: u64, } diff --git a/programs/magicblock/src/clone_account/common.rs b/programs/magicblock/src/clone_account/common.rs index 26153e636..d32111c1c 100644 --- a/programs/magicblock/src/clone_account/common.rs +++ b/programs/magicblock/src/clone_account/common.rs @@ -212,24 +212,26 @@ pub fn set_account_from_fields( ) -> Result<(), InstructionError> { ic_msg!( invoke_context, - "src account state: lamports={}, owner={}, executable={}, delegated={}, confined={}, remote_slot={}, data_len={}", + "src account state: lamports={}, owner={}, executable={}, delegated={}, confined={}, compressed={}, remote_slot={}, data_len={}", fields.lamports, fields.owner, fields.executable, fields.delegated, fields.confined, + fields.compressed, fields.remote_slot, data.len() ); ic_msg!( invoke_context, - "dest account state: lamports={}, owner={}, executable={}, delegated={}, undelegating={} confined={}, remote_slot={}, data_len={}", + "dest account state: lamports={}, owner={}, executable={}, delegated={}, undelegating={}, confined={}, compressed={}, remote_slot={}, data_len={}", acc.lamports(), acc.owner(), acc.executable(), acc.delegated(), acc.undelegating(), acc.confined(), + acc.compressed(), acc.remote_slot(), acc.data().len() ); @@ -261,6 +263,7 @@ pub fn set_account_from_fields( acc.set_executable(fields.executable); acc.set_delegated(fields.delegated); acc.set_confined(fields.confined); + acc.set_compressed(fields.compressed); acc.set_remote_slot(fields.remote_slot); acc.set_undelegating(false); diff --git a/programs/magicblock/src/clone_account/tests.rs b/programs/magicblock/src/clone_account/tests.rs index 086040f9b..22a2a988b 100644 --- a/programs/magicblock/src/clone_account/tests.rs +++ b/programs/magicblock/src/clone_account/tests.rs @@ -103,6 +103,7 @@ fn test_clone_account_basic() { executable: true, delegated: true, confined: true, + compressed: true, remote_slot: 42, }; let ix = InstructionUtils::clone_account_instruction( @@ -126,6 +127,7 @@ fn test_clone_account_basic() { assert!(account.executable()); assert!(account.delegated()); assert!(account.confined()); + assert!(account.compressed()); assert_eq!(account.remote_slot(), 42); assert_eq!(account.data(), &[1, 2, 3]); } diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs index 5bb2c9f2a..647162cf0 100644 --- a/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs +++ b/programs/magicblock/src/schedule_transactions/process_schedule_intent_bundle.rs @@ -67,7 +67,8 @@ pub(crate) fn process_schedule_intent_bundle( if !account.compressed() { ic_msg!( invoke_context, - "ScheduleIntentBundle: compressed commits are not supported for uncompressed accounts" + "ScheduleIntentBundle: compressed commits are only for compressed accounts ({})", + get_instruction_pubkey_with_idx(invoke_context.transaction_context, idx as u16)? ); return Err(InstructionError::InvalidInstructionData); } @@ -75,7 +76,8 @@ pub(crate) fn process_schedule_intent_bundle( if account.lamports() != 0 { ic_msg!( invoke_context, - "ScheduleIntentBundle: compressed commits are not supported for accounts with non-zero lamports" + "ScheduleIntentBundle: compressed commits are only for accounts with zero lamports ({})", + get_instruction_pubkey_with_idx(invoke_context.transaction_context, idx as u16)? ); return Err(InstructionError::InvalidInstructionData); } From 7d7bf8c18bae1e133088aa09d672055093f0d542 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 27 May 2026 11:05:25 +0200 Subject: [PATCH 108/110] fix: update lockfile --- Cargo.lock | 64 ++++++++++++++++++++++--------------- test-integration/Cargo.lock | 33 ++----------------- 2 files changed, 41 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2eec39fe..2df5956de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1559,6 +1559,25 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -3615,18 +3634,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "libredox" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" -dependencies = [ - "bitflags 2.11.1", - "libc", - "plain", - "redox_syscall 0.7.5", -] - [[package]] name = "librocksdb-sys" version = "0.17.1+9.9.3" @@ -5046,7 +5053,7 @@ dependencies = [ "serde", "solana-hash 3.1.0", "solana-pubkey 3.0.0", - "solana-transaction", + "solana-transaction 3.1.0", "solana-transaction-error 3.2.0", "tempfile", "thiserror 2.0.18", @@ -5705,7 +5712,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", "windows-link", ] @@ -5913,12 +5920,6 @@ version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - [[package]] name = "polyval" version = "0.6.2" @@ -6471,19 +6472,30 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.5.18" +name = "rayon" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ - "bitflags 2.11.1", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", ] [[package]] name = "redox_syscall" -version = "0.7.5" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags 2.11.1", ] diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index ab55c8d35..bcff604c5 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -4275,18 +4275,6 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" -[[package]] -name = "libredox" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" -dependencies = [ - "bitflags 2.11.1", - "libc", - "plain", - "redox_syscall 0.7.5", -] - [[package]] name = "librocksdb-sys" version = "0.17.1+9.9.3" @@ -5714,8 +5702,8 @@ dependencies = [ "serde", "solana-hash 3.1.0", "solana-pubkey 3.0.0", - "solana-transaction", - "solana-transaction-error", + "solana-transaction 3.1.0", + "solana-transaction-error 3.2.0", "thiserror 2.0.18", "tokio", "tokio-util 0.7.18", @@ -6492,7 +6480,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", "windows-link", ] @@ -6709,12 +6697,6 @@ version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - [[package]] name = "polyval" version = "0.6.2" @@ -7424,15 +7406,6 @@ dependencies = [ "bitflags 2.11.1", ] -[[package]] -name = "redox_syscall" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" -dependencies = [ - "bitflags 2.11.1", -] - [[package]] name = "ref-cast" version = "1.0.25" From b73a289e1df6c59b6ccf4c71ddd1933746b8cbd2 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 27 May 2026 17:02:59 +0200 Subject: [PATCH 109/110] fix: add account --- test-integration/test-tools/src/validator.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test-integration/test-tools/src/validator.rs b/test-integration/test-tools/src/validator.rs index 1739d9576..05d01d421 100644 --- a/test-integration/test-tools/src/validator.rs +++ b/test-integration/test-tools/src/validator.rs @@ -584,6 +584,13 @@ fn devnet_accounts(loaded_accounts: &LoadedAccounts) -> [(String, String); 9] { loaded_accounts.magic_fee_vault().to_string(), "magic-fee-vault.json".to_string(), ), + ( + dlp_api::pda::delegation_record_pda_from_delegated_account( + &loaded_accounts.magic_fee_vault(), + ) + .to_string(), + "magic-fee-vault-delegation-record.json".to_string(), + ), ( "9yXjZTevvMp1XgZSZEaziPRgFiXtAQChpnP2oX9eCpvt".to_string(), "non-delegated-cloneable-account1.json".to_string(), From 18a5b75940c7bfc6100708aa8efc98582549204d Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Wed, 27 May 2026 17:15:44 +0200 Subject: [PATCH 110/110] fix: return type --- test-integration/test-tools/src/validator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-integration/test-tools/src/validator.rs b/test-integration/test-tools/src/validator.rs index 05d01d421..02505324b 100644 --- a/test-integration/test-tools/src/validator.rs +++ b/test-integration/test-tools/src/validator.rs @@ -562,7 +562,7 @@ pub fn resolve_programs( // Utilities // ----------------- -fn devnet_accounts(loaded_accounts: &LoadedAccounts) -> [(String, String); 9] { +fn devnet_accounts(loaded_accounts: &LoadedAccounts) -> [(String, String); 10] { [ ( loaded_accounts.validator_authority().to_string(),