From 1014cde1ce3101d6d001d2dff5ac397159e8db69 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Mon, 23 Feb 2026 20:18:11 +0530 Subject: [PATCH 01/16] feat: Handle post delegation actions --- Cargo.lock | 536 +++++++++------ Cargo.toml | 4 +- magicblock-account-cloner/src/lib.rs | 5 +- magicblock-chainlink/src/chainlink/errors.rs | 2 + .../chainlink/fetch_cloner/ata_projection.rs | 1 + .../src/chainlink/fetch_cloner/delegation.rs | 19 + .../src/chainlink/fetch_cloner/mod.rs | 64 +- .../src/chainlink/fetch_cloner/pipeline.rs | 41 +- magicblock-chainlink/src/cloner/mod.rs | 2 + test-integration/Cargo.lock | 620 ++++++++++++------ .../test-chainlink/src/ixtest_context.rs | 1 + 11 files changed, 869 insertions(+), 426 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 544797123..f6c69f7e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,7 +65,7 @@ dependencies = [ "solana-signature", "solana-transaction", "solana-transaction-status", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -375,7 +375,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -386,7 +386,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -564,7 +564,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -582,7 +582,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -687,7 +687,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -797,7 +797,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -878,7 +878,7 @@ checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -962,7 +962,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1279,7 +1279,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1313,7 +1313,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1326,7 +1326,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1337,7 +1337,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1348,7 +1348,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1403,7 +1403,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.111", + "syn 2.0.117", "unicode-xid", ] @@ -1435,7 +1435,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1523,7 +1523,7 @@ checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1648,6 +1648,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +[[package]] +name = "five8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f76610e969fa1784327ded240f1e28a3fd9520c9cec93b636fcf62dd37f772" +dependencies = [ + "five8_core", +] + [[package]] name = "five8_const" version = "0.1.4" @@ -1657,6 +1666,15 @@ dependencies = [ "five8_core", ] +[[package]] +name = "five8_const" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a0f1728185f277989ca573a402716ae0beaaea3f76a8ff87ef9dd8fb19436c5" +dependencies = [ + "five8_core", +] + [[package]] name = "five8_core" version = "0.1.2" @@ -1801,7 +1819,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1923,7 +1941,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2556,7 +2574,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2937,7 +2955,7 @@ dependencies = [ "magicblock-rpc-client", "rand 0.9.2", "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v3-interface", "solana-loader-v4-interface", @@ -2963,7 +2981,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-core", "magicblock-program", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", "solana-transaction", "solana-transaction-error", @@ -3076,7 +3094,7 @@ dependencies = [ "solana-feature-set", "solana-fee-calculator", "solana-genesis-config", - "solana-hash", + "solana-hash 2.2.1", "solana-inline-spl", "solana-instruction", "solana-keypair", @@ -3086,7 +3104,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-rpc-client", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", "solana-system-program", @@ -3126,7 +3144,7 @@ dependencies = [ "solana-clock", "solana-commitment-config", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-loader-v3-interface", @@ -3192,7 +3210,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-commitment-config", "solana-compute-budget-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -3245,7 +3263,7 @@ dependencies = [ "magicblock-magic-program-api", "solana-account", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-program", "solana-pubkey", "solana-signature", @@ -3264,24 +3282,27 @@ dependencies = [ [[package]] name = "magicblock-delegation-program" version = "1.1.3" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372#2cb491032f372faa4cfdb55e3f05cefd7e07351d" dependencies = [ "bincode", "borsh 1.6.0", "bytemuck", "const-crypto", "num_enum", - "pinocchio", + "pinocchio 0.10.2", "pinocchio-log", "pinocchio-pubkey", "pinocchio-system", - "rkyv 0.7.45", + "rand 0.8.5", + "rkyv 0.7.46", + "serde", + "solana-address", "solana-curve25519", "solana-program", - "solana-security-txt", + "solana-sdk", + "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", - "thiserror 2.0.17", + "thiserror 1.0.69", ] [[package]] @@ -3304,7 +3325,7 @@ dependencies = [ "serde", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-measure", @@ -3412,7 +3433,7 @@ dependencies = [ "solana-account-info", "solana-clock", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-log-collector", @@ -3438,7 +3459,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-clock", "solana-commitment-config", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rpc-client", @@ -3704,7 +3725,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3811,7 +3832,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3894,7 +3915,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3944,7 +3965,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3994,6 +4015,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" + [[package]] name = "pbkdf2" version = "0.11.0" @@ -4023,7 +4050,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4068,7 +4095,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4089,6 +4116,19 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b971851087bc3699b001954ad02389d50c41405ece3548cbcafc88b3e20017a" +[[package]] +name = "pinocchio" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06810dac15a4ef83d3dabdb4f2f22fb39c9adff669cd2781da4f716510a647c" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-define-syscall 4.0.1", + "solana-instruction-view", + "solana-program-error 3.0.0", +] + [[package]] name = "pinocchio-log" version = "0.5.1" @@ -4115,19 +4155,19 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0225638cadcbebae8932cb7f49cb5da7c15c21beb19f048f05a5ca7d93f065" dependencies = [ - "five8_const", - "pinocchio", + "five8_const 0.1.4", + "pinocchio 0.9.2", "sha2-const-stable", ] [[package]] name = "pinocchio-system" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141ed5eafb4ab04568bb0e224e3dc9a9de13c933de4c004e0d1a553498be3a7c" +checksum = "24044a0815753862b558e179e78f03f7344cb755de48617a09d7d23b50883b6c" dependencies = [ - "pinocchio", - "pinocchio-pubkey", + "pinocchio 0.10.2", + "solana-address", ] [[package]] @@ -4201,7 +4241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4248,9 +4288,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -4263,7 +4303,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "version_check", "yansi", ] @@ -4362,7 +4402,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.111", + "syn 2.0.117", "tempfile", ] @@ -4382,7 +4422,7 @@ dependencies = [ "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.111", + "syn 2.0.117", "tempfile", ] @@ -4409,7 +4449,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4422,7 +4462,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4435,7 +4475,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4526,7 +4566,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4546,14 +4586,14 @@ checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -4726,7 +4766,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4863,9 +4903,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", @@ -4873,7 +4913,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", @@ -4899,9 +4939,9 @@ dependencies = [ [[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", @@ -4916,7 +4956,7 @@ checksum = "bd83f5f173ff41e00337d97f6572e416d022ef8a19f371817259ae960324c482" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5252,7 +5292,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5317,7 +5357,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5342,7 +5382,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5550,7 +5590,7 @@ dependencies = [ "spl-token-2022 7.0.0", "spl-token-group-interface", "spl-token-metadata-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", "zstd", ] @@ -5578,11 +5618,41 @@ checksum = "e0c17d606a298a205fae325489fbed88ee6dc4463c111672172327e741c8905d" dependencies = [ "bincode", "serde", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-memory", "solana-pubkey", ] +[[package]] +name = "solana-account-view" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37ca34c37f92ee341b73d5ce7c8ef5bb38e9a87955b4bd343c63fa18b149215" +dependencies = [ + "solana-address", + "solana-program-error 3.0.0", +] + +[[package]] +name = "solana-address" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c5d02824391b072dc5cd0aaa85fb0af9784a21d23286a767994d1e8a322131" +dependencies = [ + "borsh 1.6.0", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "five8", + "five8_const 1.0.0", + "serde", + "sha2-const-stable", + "solana-define-syscall 5.0.0", + "solana-program-error 3.0.0", + "solana-sha256-hasher 3.1.0", + "wincode", +] + [[package]] name = "solana-address-lookup-table-interface" version = "2.2.2" @@ -5622,7 +5692,7 @@ dependencies = [ "solana-pubkey", "solana-system-interface", "solana-transaction-context", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -5642,7 +5712,7 @@ checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" dependencies = [ "num-bigint 0.4.6", "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -5663,8 +5733,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" dependencies = [ "blake3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -5679,8 +5749,8 @@ dependencies = [ "ark-ff", "ark-serialize", "bytemuck", - "solana-define-syscall", - "thiserror 2.0.17", + "solana-define-syscall 2.2.1", + "thiserror 2.0.18", ] [[package]] @@ -5714,7 +5784,7 @@ dependencies = [ "solana-cpi", "solana-curve25519", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-loader-v3-interface", @@ -5731,7 +5801,7 @@ dependencies = [ "solana-sbpf", "solana-sdk-ids", "solana-secp256k1-recover", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-stable-layout", "solana-system-interface", "solana-sysvar", @@ -5739,7 +5809,7 @@ dependencies = [ "solana-timings", "solana-transaction-context", "solana-type-overrides", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -5774,7 +5844,7 @@ dependencies = [ "solana-account", "solana-commitment-config", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -5807,7 +5877,7 @@ checksum = "7ace9fea2daa28354d107ea879cff107181d85cd4e0f78a2bedb10e1a428c97e" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", ] [[package]] @@ -5848,7 +5918,7 @@ dependencies = [ "solana-sdk-ids", "solana-svm-transaction", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -5905,9 +5975,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11" dependencies = [ "solana-account-info", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-stable-layout", ] @@ -5921,9 +5991,9 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "subtle", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -5941,6 +6011,18 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf784bb2cb3e02cac9801813c30187344228d2ae952534902108f6150573a33d" +[[package]] +name = "solana-define-syscall" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e5b1c0bc1d4a4d10c88a4100499d954c09d3fecfae4912c1a074dff68b1738" + +[[package]] +name = "solana-define-syscall" +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" @@ -5985,7 +6067,7 @@ checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sdk-macro", "solana-sysvar-id", @@ -5998,7 +6080,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c5fd2662ae7574810904585fd443545ed2b568dbd304b25a31e79ccc76e81b" dependencies = [ "siphasher", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", ] @@ -6025,7 +6107,7 @@ dependencies = [ "serde_derive", "solana-address-lookup-table-interface", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-message", @@ -6033,7 +6115,7 @@ dependencies = [ "solana-pubkey", "solana-sdk-ids", "solana-system-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6048,7 +6130,7 @@ dependencies = [ "solana-account", "solana-account-info", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-rent", "solana-sdk-ids", @@ -6064,9 +6146,9 @@ dependencies = [ "ahash 0.8.12", "lazy_static", "solana-epoch-schedule", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -6111,7 +6193,7 @@ checksum = "b83f88a126213cbcb57672c5e70ddb9791eff9b480e9f39fe9285fd2abca66fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6130,7 +6212,7 @@ dependencies = [ "solana-cluster-type", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-inflation", "solana-keypair", "solana-logger", @@ -6139,7 +6221,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-sdk-ids", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-shred-version", "solana-signer", "solana-time-utils", @@ -6173,6 +6255,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "solana-hash" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8064ea1d591ec791be95245058ca40f4f5345d390c200069d0f79bbf55bfae55" + [[package]] name = "solana-inflation" version = "2.2.1" @@ -6206,11 +6294,23 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-pubkey", "wasm-bindgen", ] +[[package]] +name = "solana-instruction-view" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60147e4d0a4620013df40bf30a86dd299203ff12fcb8b593cd51014fce0875d8" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-define-syscall 4.0.1", + "solana-program-error 3.0.0", +] + [[package]] name = "solana-instructions-sysvar" version = "2.2.1" @@ -6220,7 +6320,7 @@ dependencies = [ "bitflags 2.10.0", "solana-account-info", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-sanitize", "solana-sdk-ids", @@ -6235,8 +6335,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" dependencies = [ "sha3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -6382,7 +6482,7 @@ dependencies = [ "serde", "serde_derive", "solana-bincode", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-sanitize", @@ -6406,9 +6506,9 @@ dependencies = [ "reqwest", "solana-clock", "solana-cluster-type", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-time-utils", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6417,7 +6517,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092" dependencies = [ - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -6435,9 +6535,9 @@ dependencies = [ "serde", "serde_derive", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -6447,7 +6547,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde971a20b8dbf60144d6a84439dda86b5466e00e2843091fe731083cda614da" dependencies = [ "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-nonce", "solana-sdk-ids", ] @@ -6459,11 +6559,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b526398ade5dea37f1f147ce55dae49aa017a5d7326606359b0445ca8d946581" dependencies = [ "num_enum", - "solana-hash", + "solana-hash 2.2.1", "solana-packet", "solana-pubkey", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", ] @@ -6500,8 +6600,8 @@ checksum = "8ad1ea160d08dc423c35021fa3e437a5783eb256f5ab8bc3024e27db913acf42" dependencies = [ "ark-bn254", "light-poseidon", - "solana-define-syscall", - "thiserror 2.0.17", + "solana-define-syscall 2.2.1", + "thiserror 2.0.18", ] [[package]] @@ -6577,13 +6677,13 @@ dependencies = [ "solana-clock", "solana-cpi", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-example-mocks", "solana-feature-gate-interface", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-keccak-hasher", @@ -6596,7 +6696,7 @@ dependencies = [ "solana-native-token", "solana-nonce", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-memory", "solana-program-option", "solana-program-pack", @@ -6608,7 +6708,7 @@ dependencies = [ "solana-secp256k1-recover", "solana-serde-varint", "solana-serialize-utils", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-short-vec", "solana-slot-hashes", "solana-slot-history", @@ -6618,7 +6718,7 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-vote-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", ] @@ -6630,7 +6730,7 @@ checksum = "473ffe73c68d93e9f2aa726ad2985fe52760052709aaab188100a42c618060ec" dependencies = [ "solana-account-info", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", ] @@ -6650,6 +6750,12 @@ dependencies = [ "solana-pubkey", ] +[[package]] +name = "solana-program-error" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1af32c995a7b692a915bb7414d5f8e838450cf7c70414e763d8abcae7b51f28" + [[package]] name = "solana-program-memory" version = "2.2.1" @@ -6657,7 +6763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b0268f6c89825fb634a34bd0c3b8fdaeaecfc3728be1d622a8ee6dd577b60d4" dependencies = [ "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -6672,7 +6778,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "319f0ef15e6e12dc37c597faccb7d62525a509fec5f6975ecb9419efddeb277b" dependencies = [ - "solana-program-error", + "solana-program-error 2.2.2", ] [[package]] @@ -6695,7 +6801,7 @@ dependencies = [ "solana-epoch-rewards", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-last-restart-slot", "solana-log-collector", @@ -6713,7 +6819,7 @@ dependencies = [ "solana-timings", "solana-transaction-context", "solana-type-overrides", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6728,7 +6834,7 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "five8_const", + "five8_const 0.1.4", "getrandom 0.2.16", "js-sys", "num-traits", @@ -6737,9 +6843,9 @@ dependencies = [ "serde_derive", "solana-atomic-u64", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "wasm-bindgen", ] @@ -6762,7 +6868,7 @@ dependencies = [ "solana-pubkey", "solana-rpc-client-api", "solana-signature", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-tungstenite", @@ -6866,7 +6972,7 @@ dependencies = [ "solana-epoch-info", "solana-epoch-schedule", "solana-feature-gate-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -6907,7 +7013,7 @@ dependencies = [ "solana-transaction-error", "solana-transaction-status-client-types", "solana-version", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7000,7 +7106,7 @@ dependencies = [ "solana-transaction-context", "solana-transaction-error", "solana-validator-exit", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", ] @@ -7022,7 +7128,7 @@ dependencies = [ "bs58", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7051,8 +7157,8 @@ checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" dependencies = [ "borsh 1.6.0", "libsecp256k1", - "solana-define-syscall", - "thiserror 2.0.17", + "solana-define-syscall 2.2.1", + "thiserror 2.0.18", ] [[package]] @@ -7134,8 +7240,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0037386961c0d633421f53560ad7c80675c0447cba4d1bb66d60974dd486c7ea" dependencies = [ "sha2 0.10.9", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", +] + +[[package]] +name = "solana-sha256-hasher" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" +dependencies = [ + "sha2 0.10.9", + "solana-define-syscall 4.0.1", + "solana-hash 4.2.0", ] [[package]] @@ -7154,8 +7271,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afd3db0461089d1ad1a78d9ba3f15b563899ca2386351d38428faa5350c60a98" dependencies = [ "solana-hard-forks", - "solana-hash", - "solana-sha256-hasher", + "solana-hash 2.2.1", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -7192,7 +7309,7 @@ checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sysvar-id", ] @@ -7235,7 +7352,7 @@ dependencies = [ "solana-cpi", "solana-decode-error", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-system-interface", "solana-sysvar-id", @@ -7281,7 +7398,7 @@ dependencies = [ "protobuf-src", "serde", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -7311,7 +7428,7 @@ dependencies = [ "solana-compute-budget-instruction", "solana-feature-set", "solana-fee-structure", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-loader-v4-program", @@ -7335,7 +7452,7 @@ dependencies = [ "solana-transaction-context", "solana-transaction-error", "solana-type-overrides", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7353,7 +7470,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fc4392f0eed412141a376e99dfb052069b96f13697a9abb335504babe29387a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-sdk-ids", @@ -7409,7 +7526,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bd98a25e5bcba8b6be8bcbb7b84b24c2a6a8178d7fb0e3077a916855ceba91a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-keypair", "solana-message", "solana-pubkey", @@ -7433,16 +7550,16 @@ dependencies = [ "serde_derive", "solana-account-info", "solana-clock", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-last-restart-slot", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-memory", "solana-pubkey", "solana-rent", @@ -7493,7 +7610,7 @@ dependencies = [ "serde_derive", "solana-bincode", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -7556,7 +7673,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v2-interface", "solana-message", @@ -7576,7 +7693,7 @@ dependencies = [ "spl-token-2022 7.0.0", "spl-token-group-interface", "spl-token-metadata-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7599,7 +7716,7 @@ dependencies = [ "solana-transaction", "solana-transaction-context", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7645,7 +7762,7 @@ dependencies = [ "serde_derive", "solana-clock", "solana-decode-error", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rent", @@ -7673,7 +7790,7 @@ dependencies = [ "solana-clock", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-packet", @@ -7686,7 +7803,7 @@ dependencies = [ "solana-transaction", "solana-transaction-context", "solana-vote-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7721,7 +7838,7 @@ dependencies = [ "solana-signature", "solana-signer", "subtle", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", "zeroize", ] @@ -7753,7 +7870,7 @@ dependencies = [ "simdutf8", "sonic-number", "sonic-simd", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7807,8 +7924,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ "bytemuck", - "solana-program-error", - "solana-sha256-hasher", + "solana-program-error 2.2.2", + "solana-sha256-hasher 2.2.1", "spl-discriminator-derive", ] @@ -7820,7 +7937,7 @@ checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" dependencies = [ "quote", "spl-discriminator-syn", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7832,7 +7949,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.9", - "syn 2.0.111", + "syn 2.0.117", "thiserror 1.0.69", ] @@ -7859,7 +7976,7 @@ dependencies = [ "solana-instruction", "solana-msg", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", ] @@ -7876,11 +7993,11 @@ dependencies = [ "num-traits", "solana-decode-error", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-option", "solana-pubkey", "solana-zk-sdk", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7905,7 +8022,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.9", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7921,7 +8038,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -7998,7 +8115,7 @@ dependencies = [ "spl-token-metadata-interface", "spl-transfer-hook-interface", "spl-type-length-value", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8024,7 +8141,7 @@ dependencies = [ "solana-program", "solana-zk-sdk", "spl-pod", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8046,7 +8163,7 @@ checksum = "0e3597628b0d2fe94e7900fd17cdb4cfbb31ee35c66f82809d27d86e44b2848b" dependencies = [ "curve25519-dalek 4.1.3", "solana-zk-sdk", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8061,7 +8178,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -8081,7 +8198,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -8104,7 +8221,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -8126,7 +8243,7 @@ dependencies = [ "solana-account-info", "solana-decode-error", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "spl-discriminator", "spl-pod", "thiserror 1.0.69", @@ -8208,7 +8325,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8220,7 +8337,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8242,9 +8359,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -8271,7 +8388,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8385,11 +8502,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -8400,18 +8517,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8505,7 +8622,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8748,7 +8865,7 @@ dependencies = [ "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8762,7 +8879,7 @@ dependencies = [ "prost-build 0.13.5", "prost-types 0.13.5", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8859,7 +8976,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9172,7 +9289,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -9263,6 +9380,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a7a568eda854acc9945ed136a9d50b8c6d31911584624958808ae96eee3912" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "windows" version = "0.62.2" @@ -9316,7 +9458,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9327,7 +9469,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9678,7 +9820,7 @@ dependencies = [ "solana-account", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-signature", @@ -9709,7 +9851,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -9730,7 +9872,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9750,7 +9892,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -9771,7 +9913,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9804,7 +9946,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6c72a1d8d..8bc3893b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,8 +102,8 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "2cb491032f372", features = [ - "no-entrypoint", +magicblock-delegation-program = { path = "../delegation-program", default-features = false, features = [ + "sdk", ] } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } diff --git a/magicblock-account-cloner/src/lib.rs b/magicblock-account-cloner/src/lib.rs index 456ad08db..590130e4d 100644 --- a/magicblock-account-cloner/src/lib.rs +++ b/magicblock-account-cloner/src/lib.rs @@ -122,7 +122,7 @@ impl ChainlinkCloner { message, ); // Defined positive commit frequency means commits should be scheduled - let ixs = match request.commit_frequency_ms { + let mut ixs = match request.commit_frequency_ms { // TODO(GabrielePicco): Hotfix. Do not schedule frequency commits until we impose limits. // 1. Allow configuring a higher minimum. // 2. Stop committing accounts if they have been committed more than X times, @@ -162,6 +162,9 @@ impl ChainlinkCloner { } _ => vec![modify_ix], }; + if !request.delegation_actions.is_empty() { + ixs.extend(request.delegation_actions.clone()); + } let mut tx = Transaction::new_with_payer(&ixs, Some(&validator_authority_id())); diff --git a/magicblock-chainlink/src/chainlink/errors.rs b/magicblock-chainlink/src/chainlink/errors.rs index 18f3884b6..ef2832dda 100644 --- a/magicblock-chainlink/src/chainlink/errors.rs +++ b/magicblock-chainlink/src/chainlink/errors.rs @@ -20,6 +20,8 @@ pub enum ChainlinkError { #[error("Delegation record could not be decoded: {0} ({1:?})")] InvalidDelegationRecord(Pubkey, ProgramError), + #[error("Delegation actions could not be decoded: {0} ({1})")] + InvalidDelegationActions(Pubkey, String), #[error("Failed to resolve one or more accounts {0} when getting delegation records")] DelegatedAccountResolutionsFailed(String), diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs index 11bd4c322..b1483e2ab 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs @@ -147,6 +147,7 @@ where pubkey: ata_pubkey, account: account_to_clone, commit_frequency_ms, + delegation_actions: vec![], delegated_to_other, }); } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 212ab8bb2..d7663e3f1 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -5,6 +5,7 @@ use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::EATA_PROGRAM_ID; use magicblock_metrics::metrics; use solana_account::ReadableAccount; +use solana_instruction::Instruction; use solana_pubkey::Pubkey; use tracing::*; @@ -32,6 +33,24 @@ pub(crate) fn parse_delegation_record( }) } +pub(crate) fn parse_delegation_actions( + data: &[u8], + delegation_record_pubkey: Pubkey, +) -> ChainlinkResult> { + let delegation_record_size = DelegationRecord::size_with_discriminator(); + if data.len() <= delegation_record_size { + return Ok(vec![]); + } + + let actions_data = &data[delegation_record_size..]; + bincode::deserialize::>(actions_data).map_err(|err| { + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + err.to_string(), + ) + }) +} + pub(crate) fn apply_delegation_record_to_account( this: &FetchCloner, account: &mut ResolvedAccountSharedData, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index ff11fa227..081a31b06 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -167,7 +167,7 @@ where // record fetches. This allows multiple updates to be processed in parallel. let this = Arc::clone(&self); tokio::spawn(async move { - let (resolved_account, deleg_record) = + let (resolved_account, deleg_record, delegation_actions) = this.resolve_account_to_clone_from_forwarded_sub_with_unsubscribe(update) .await; if let Some(account) = resolved_account { @@ -277,6 +277,7 @@ where pubkey, account, commit_frequency_ms: None, + delegation_actions, delegated_to_other, }) .await @@ -332,7 +333,11 @@ where async fn resolve_account_to_clone_from_forwarded_sub_with_unsubscribe( &self, update: ForwardedSubscriptionUpdate, - ) -> (Option, Option) { + ) -> ( + Option, + Option, + Vec, + ) { let ForwardedSubscriptionUpdate { pubkey, account } = update; let owned_by_delegation_program = account.is_owned_by_delegation_program(); @@ -376,6 +381,32 @@ where let account = if let Some(delegation_record) = delegation_record { + let delegation_record_size = + DelegationRecord::size_with_discriminator(); + if delegation_record.data().len() + == delegation_record_size + { + // Regular delegation record layout. + } else { + // DelegateWithActions layout (DelegationRecord + trailing bytes). + } + + let delegation_actions = + match Self::parse_delegation_actions( + delegation_record.data(), + delegation_record_pubkey, + ) { + Ok(actions) => actions, + Err(err) => { + error!( + pubkey = %pubkey, + error = %err, + "Failed to parse delegation actions" + ); + vec![] + } + }; + let delegation_record = match Self::parse_delegation_record( delegation_record.data(), @@ -438,17 +469,25 @@ where ( Some(account.into_account_shared_data()), Some(delegation_record), + delegation_actions, ) } 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) + (None, None, vec![]) } } else { // If no delegation record exists we must assume the account itself is // a delegation record or metadata - (Some(account.into_account_shared_data()), None) + let delegation_record_size = + DelegationRecord::size_with_discriminator(); + if account.data().len() == delegation_record_size { + // Regular delegation record layout. + } else { + // DelegateWithActions layout (DelegationRecord + trailing bytes). + } + (Some(account.into_account_shared_data()), None, vec![]) }; if !subs_to_remove.is_empty() { @@ -467,7 +506,7 @@ where error = ?err, "Failed to fetch delegation record" ); - (None, None) + (None, None, vec![]) } Err(err) => { warn!( @@ -475,20 +514,20 @@ where error = ?err, "Failed to fetch delegation record" ); - (None, None) + (None, None, vec![]) } } } else { let (account, deleg_record) = self .maybe_project_ata_from_subscription_update(pubkey, account) .await; - (Some(account), deleg_record) + (Some(account), deleg_record, vec![]) } } 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) + (None, None, vec![]) } } @@ -547,6 +586,7 @@ where pubkey: ata_pubkey, account: projected_ata, commit_frequency_ms: None, + delegation_actions: vec![], delegated_to_other: None, }) } @@ -659,6 +699,13 @@ where delegation::parse_delegation_record(data, delegation_record_pubkey) } + fn parse_delegation_actions( + data: &[u8], + delegation_record_pubkey: Pubkey, + ) -> ChainlinkResult> { + delegation::parse_delegation_actions(data, delegation_record_pubkey) + } + /// Applies delegation record settings to an account: sets the owner, /// delegation status, and confined status based on the delegation /// record's authority field. @@ -1371,6 +1418,7 @@ where pubkey, account, commit_frequency_ms: None, + delegation_actions: vec![], delegated_to_other: None, }) .await?; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 2fd9c59ba..2ba7e10b5 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -143,6 +143,7 @@ fn classify_single_account( pubkey, account: account_shared_data, commit_frequency_ms: None, + delegation_actions: vec![], delegated_to_other: None, }); } @@ -292,15 +293,48 @@ where 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) = if let Some( + let (commit_frequency_ms, delegated_to_other, delegation_actions) = if let Some( delegation_record_data, ) = delegation_record { + let delegation_record_size = + dlp::state::DelegationRecord::size_with_discriminator(); + if delegation_record_data.data().len() == delegation_record_size + { + // Regular delegation record layout. + } else { + // DelegateWithActions layout (DelegationRecord + trailing bytes). + } + // NOTE: failing here is fine when resolving all accounts for a transaction // since if something is off we better not run it anyways // However we may consider a different behavior when user is getting // multiple accounts. + let delegation_actions = + match FetchCloner::::parse_delegation_actions( + delegation_record_data.data(), + delegation_record_pubkey, + ) { + Ok(x) => x, + Err(err) => { + // Cancel all new subs since we won't clone any accounts + cancel_subs( + &this.remote_account_provider, + CancelStrategy::New { + new_subs: pubkeys + .iter() + .cloned() + .chain(record_subs.iter().cloned()) + .collect(), + existing_subs: existing_subs.clone(), + }, + ) + .await; + return Err(err); + } + }; + let delegation_record = match FetchCloner::::parse_delegation_record( delegation_record_data.data(), @@ -340,15 +374,16 @@ where owner_programs_to_subscribe.insert(delegation_record.owner); } - (commit_freq, delegated_to_other) + (commit_freq, delegated_to_other, delegation_actions) } else { missing_delegation_record.push((pubkey, account.remote_slot())); - (None, None) + (None, None, vec![]) }; accounts_to_clone.push(AccountCloneRequest { pubkey, account: account.into_account_shared_data(), commit_frequency_ms, + delegation_actions, delegated_to_other, }); } diff --git a/magicblock-chainlink/src/cloner/mod.rs b/magicblock-chainlink/src/cloner/mod.rs index f63d27578..9d1de024e 100644 --- a/magicblock-chainlink/src/cloner/mod.rs +++ b/magicblock-chainlink/src/cloner/mod.rs @@ -1,6 +1,7 @@ use async_trait::async_trait; use errors::ClonerResult; use solana_account::AccountSharedData; +use solana_instruction::Instruction; use solana_pubkey::Pubkey; use solana_signature::Signature; @@ -12,6 +13,7 @@ pub struct AccountCloneRequest { pub pubkey: Pubkey, pub account: AccountSharedData, pub commit_frequency_ms: Option, + pub delegation_actions: Vec, /// If the account is delegated to another validator, /// this contains that validator's pubkey. None if account is not /// delegated to another validator. diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index ae548b70f..d6777daea 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -74,7 +74,7 @@ dependencies = [ "solana-signature", "solana-transaction", "solana-transaction-status", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -83,7 +83,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aba2aec0682aa448f93db9b93df8fb331c119cb4d66fe9ba61d6b42dd3a91105" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-packet", "solana-pubkey", @@ -223,7 +223,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -466,7 +466,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -477,7 +477,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -639,7 +639,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -657,7 +657,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -780,7 +780,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -890,7 +890,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -981,7 +981,7 @@ checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1059,7 +1059,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1362,7 +1362,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1386,7 +1386,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1397,7 +1397,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1480,7 +1480,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.111", + "syn 2.0.117", "unicode-xid", ] @@ -1539,7 +1539,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1562,7 +1562,7 @@ checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1668,7 +1668,7 @@ checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1681,7 +1681,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1715,7 +1715,7 @@ dependencies = [ "solana-account-info", "solana-cpi", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-memory", "solana-pubkey", "solana-system-interface", @@ -1920,6 +1920,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +[[package]] +name = "five8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f76610e969fa1784327ded240f1e28a3fd9520c9cec93b636fcf62dd37f772" +dependencies = [ + "five8_core", +] + [[package]] name = "five8_const" version = "0.1.4" @@ -1929,6 +1938,15 @@ dependencies = [ "five8_core", ] +[[package]] +name = "five8_const" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a0f1728185f277989ca573a402716ae0beaaea3f76a8ff87ef9dd8fb19436c5" +dependencies = [ + "five8_core", +] + [[package]] name = "five8_core" version = "0.1.2" @@ -2098,7 +2116,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2220,7 +2238,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3288,7 +3306,7 @@ dependencies = [ "magicblock-rpc-client", "rand 0.9.2", "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v3-interface 3.0.0", "solana-loader-v4-interface", @@ -3314,7 +3332,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-core", "magicblock-program", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", "solana-transaction", "solana-transaction-error", @@ -3420,7 +3438,7 @@ dependencies = [ "solana-feature-set", "solana-fee-calculator", "solana-genesis-config", - "solana-hash", + "solana-hash 2.2.1", "solana-inline-spl", "solana-instruction", "solana-keypair", @@ -3430,7 +3448,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-rpc-client", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", "solana-system-program", @@ -3456,7 +3474,7 @@ dependencies = [ "magicblock-accounts-db", "magicblock-config", "magicblock-core", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "magicblock-magic-program-api 0.8.2", "magicblock-metrics", "parking_lot", @@ -3468,7 +3486,7 @@ dependencies = [ "solana-clock", "solana-commitment-config", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-loader-v3-interface 3.0.0", @@ -3521,7 +3539,7 @@ dependencies = [ "futures-util", "lru", "magicblock-committor-program", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3532,7 +3550,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-commitment-config", "solana-compute-budget-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -3579,7 +3597,7 @@ dependencies = [ "magicblock-magic-program-api 0.8.2", "solana-account", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-program", "solana-pubkey", "solana-signature", @@ -3595,6 +3613,35 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "magicblock-delegation-program" +version = "1.1.3" +dependencies = [ + "bincode", + "borsh 1.6.0", + "bytemuck", + "const-crypto", + "curve25519-dalek 4.1.3", + "num_enum", + "pinocchio 0.10.2", + "pinocchio-log", + "pinocchio-pubkey", + "pinocchio-system 0.5.0", + "rand 0.8.5", + "rkyv 0.7.45", + "serde", + "sha2 0.10.9", + "solana-address", + "solana-curve25519", + "solana-program", + "solana-sdk", + "solana-sha256-hasher 3.1.0", + "static_assertions", + "strum 0.27.2", + "thiserror 1.0.69", + "x25519-dalek", +] + [[package]] name = "magicblock-delegation-program" version = "1.1.3" @@ -3618,17 +3665,17 @@ dependencies = [ "bytemuck", "const-crypto", "num_enum", - "pinocchio", + "pinocchio 0.9.2", "pinocchio-log", "pinocchio-pubkey", - "pinocchio-system", + "pinocchio-system 0.3.0", "rkyv 0.7.45", "solana-curve25519", "solana-program", "solana-security-txt", "static_assertions", "strum 0.27.2", - "thiserror 2.0.17", + "thiserror 1.0.69", ] [[package]] @@ -3651,7 +3698,7 @@ dependencies = [ "serde", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-measure", @@ -3757,7 +3804,7 @@ dependencies = [ "solana-account-info", "solana-clock", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-log-collector", @@ -3782,7 +3829,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-clock", "solana-commitment-config", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rpc-client", @@ -3851,7 +3898,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.2" dependencies = [ - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -4052,7 +4099,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4214,7 +4261,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4297,7 +4344,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4380,7 +4427,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4455,6 +4502,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" + [[package]] name = "pbkdf2" version = "0.11.0" @@ -4484,7 +4537,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4538,7 +4591,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4559,6 +4612,19 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b971851087bc3699b001954ad02389d50c41405ece3548cbcafc88b3e20017a" +[[package]] +name = "pinocchio" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06810dac15a4ef83d3dabdb4f2f22fb39c9adff669cd2781da4f716510a647c" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-define-syscall 4.0.1", + "solana-instruction-view", + "solana-program-error 3.0.0", +] + [[package]] name = "pinocchio-log" version = "0.5.1" @@ -4585,8 +4651,8 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0225638cadcbebae8932cb7f49cb5da7c15c21beb19f048f05a5ca7d93f065" dependencies = [ - "five8_const", - "pinocchio", + "five8_const 0.1.4", + "pinocchio 0.9.2", "sha2-const-stable", ] @@ -4596,10 +4662,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "141ed5eafb4ab04568bb0e224e3dc9a9de13c933de4c004e0d1a553498be3a7c" dependencies = [ - "pinocchio", + "pinocchio 0.9.2", "pinocchio-pubkey", ] +[[package]] +name = "pinocchio-system" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24044a0815753862b558e179e78f03f7344cb755de48617a09d7d23b50883b6c" +dependencies = [ + "pinocchio 0.10.2", + "solana-address", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -4695,7 +4771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4739,9 +4815,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -4754,7 +4830,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "version_check", "yansi", ] @@ -4890,7 +4966,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.111", + "syn 2.0.117", "tempfile", ] @@ -4910,7 +4986,7 @@ dependencies = [ "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.111", + "syn 2.0.117", "tempfile", ] @@ -4937,7 +5013,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -4950,7 +5026,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5032,7 +5108,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5052,7 +5128,7 @@ checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5084,7 +5160,7 @@ dependencies = [ "rustc-hash 2.1.1", "rustls 0.23.35", "socket2 0.6.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -5107,7 +5183,7 @@ dependencies = [ "rustls-pki-types", "rustls-platform-verifier", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -5129,9 +5205,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -5341,7 +5417,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5531,7 +5607,7 @@ checksum = "bd83f5f173ff41e00337d97f6572e416d022ef8a19f371817259ae960324c482" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -5999,7 +6075,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6064,7 +6140,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6090,7 +6166,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -6293,7 +6369,7 @@ dependencies = [ "spl-token-2022 7.0.0", "spl-token-group-interface", "spl-token-metadata-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", "zstd", ] @@ -6321,11 +6397,21 @@ checksum = "e0c17d606a298a205fae325489fbed88ee6dc4463c111672172327e741c8905d" dependencies = [ "bincode", "serde", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-memory", "solana-pubkey", ] +[[package]] +name = "solana-account-view" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37ca34c37f92ee341b73d5ce7c8ef5bb38e9a87955b4bd343c63fa18b149215" +dependencies = [ + "solana-address", + "solana-program-error 3.0.0", +] + [[package]] name = "solana-accounts-db" version = "2.2.1" @@ -6359,7 +6445,7 @@ dependencies = [ "smallvec", "solana-bucket-map", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-inline-spl", "solana-lattice-hash", "solana-measure", @@ -6372,7 +6458,27 @@ dependencies = [ "static_assertions", "tar", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", +] + +[[package]] +name = "solana-address" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c5d02824391b072dc5cd0aaa85fb0af9784a21d23286a767994d1e8a322131" +dependencies = [ + "borsh 1.6.0", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "five8", + "five8_const 1.0.0", + "serde", + "sha2-const-stable", + "solana-define-syscall 5.0.0", + "solana-program-error 3.0.0", + "solana-sha256-hasher 3.1.0", + "wincode", ] [[package]] @@ -6414,7 +6520,7 @@ dependencies = [ "solana-pubkey", "solana-system-interface", "solana-transaction-context", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6438,7 +6544,7 @@ dependencies = [ "solana-program", "solana-sdk", "tarpc", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-serde", ] @@ -6485,7 +6591,7 @@ checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" dependencies = [ "num-bigint 0.4.6", "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -6506,8 +6612,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" dependencies = [ "blake3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -6522,8 +6628,8 @@ dependencies = [ "ark-ff", "ark-serialize", "bytemuck", - "solana-define-syscall", - "thiserror 2.0.17", + "solana-define-syscall 2.2.1", + "thiserror 2.0.18", ] [[package]] @@ -6557,7 +6663,7 @@ dependencies = [ "solana-cpi", "solana-curve25519", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-loader-v3-interface 3.0.0", @@ -6574,7 +6680,7 @@ dependencies = [ "solana-sbpf", "solana-sdk-ids", "solana-secp256k1-recover", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-stable-layout", "solana-system-interface", "solana-sysvar", @@ -6582,7 +6688,7 @@ dependencies = [ "solana-timings", "solana-transaction-context", "solana-type-overrides", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6671,7 +6777,7 @@ dependencies = [ "solana-commitment-config", "solana-connection-cache", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-measure", @@ -6692,7 +6798,7 @@ dependencies = [ "solana-transaction", "solana-transaction-error", "solana-udp-client", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -6705,7 +6811,7 @@ dependencies = [ "solana-account", "solana-commitment-config", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -6738,7 +6844,7 @@ checksum = "7ace9fea2daa28354d107ea879cff107181d85cd4e0f78a2bedb10e1a428c97e" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", ] [[package]] @@ -6779,7 +6885,7 @@ dependencies = [ "solana-sdk-ids", "solana-svm-transaction", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6849,7 +6955,7 @@ dependencies = [ "solana-net-utils", "solana-time-utils", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -6889,9 +6995,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11" dependencies = [ "solana-account-info", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-stable-layout", ] @@ -6905,9 +7011,9 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "subtle", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -6925,6 +7031,18 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf784bb2cb3e02cac9801813c30187344228d2ae952534902108f6150573a33d" +[[package]] +name = "solana-define-syscall" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e5b1c0bc1d4a4d10c88a4100499d954c09d3fecfae4912c1a074dff68b1738" + +[[package]] +name = "solana-define-syscall" +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" @@ -6969,7 +7087,7 @@ checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sdk-macro", "solana-sysvar-id", @@ -6982,7 +7100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c5fd2662ae7574810904585fd443545ed2b568dbd304b25a31e79ccc76e81b" dependencies = [ "siphasher 0.3.11", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", ] @@ -7009,7 +7127,7 @@ dependencies = [ "serde_derive", "solana-address-lookup-table-interface", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-message", @@ -7017,7 +7135,7 @@ dependencies = [ "solana-pubkey", "solana-sdk-ids", "solana-system-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7032,7 +7150,7 @@ dependencies = [ "solana-account", "solana-account-info", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-rent", "solana-sdk-ids", @@ -7048,9 +7166,9 @@ dependencies = [ "ahash 0.8.12", "lazy_static", "solana-epoch-schedule", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -7095,7 +7213,7 @@ checksum = "b83f88a126213cbcb57672c5e70ddb9791eff9b480e9f39fe9285fd2abca66fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -7114,7 +7232,7 @@ dependencies = [ "solana-cluster-type", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-inflation", "solana-keypair", "solana-logger", @@ -7123,7 +7241,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-sdk-ids", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-shred-version", "solana-signer", "solana-time-utils", @@ -7157,6 +7275,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "solana-hash" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8064ea1d591ec791be95245058ca40f4f5345d390c200069d0f79bbf55bfae55" + [[package]] name = "solana-inflation" version = "2.2.1" @@ -7190,11 +7314,23 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-pubkey", "wasm-bindgen", ] +[[package]] +name = "solana-instruction-view" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60147e4d0a4620013df40bf30a86dd299203ff12fcb8b593cd51014fce0875d8" +dependencies = [ + "solana-account-view", + "solana-address", + "solana-define-syscall 4.0.1", + "solana-program-error 3.0.0", +] + [[package]] name = "solana-instructions-sysvar" version = "2.2.1" @@ -7204,7 +7340,7 @@ dependencies = [ "bitflags 2.10.0", "solana-account-info", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-sanitize", "solana-sdk-ids", @@ -7219,8 +7355,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" dependencies = [ "sha3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -7390,7 +7526,7 @@ dependencies = [ "serde", "serde_derive", "solana-bincode", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-sanitize", @@ -7414,9 +7550,9 @@ dependencies = [ "reqwest", "solana-clock", "solana-cluster-type", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-time-utils", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7425,7 +7561,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092" dependencies = [ - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -7471,9 +7607,9 @@ dependencies = [ "serde", "serde_derive", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -7483,7 +7619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde971a20b8dbf60144d6a84439dda86b5466e00e2843091fe731083cda614da" dependencies = [ "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-nonce", "solana-sdk-ids", ] @@ -7495,11 +7631,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b526398ade5dea37f1f147ce55dae49aa017a5d7326606359b0445ca8d946581" dependencies = [ "num_enum", - "solana-hash", + "solana-hash 2.2.1", "solana-packet", "solana-pubkey", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", ] @@ -7538,7 +7674,7 @@ dependencies = [ "rand 0.8.5", "rayon", "serde", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-metrics", "solana-packet", @@ -7568,8 +7704,8 @@ checksum = "8ad1ea160d08dc423c35021fa3e437a5783eb256f5ab8bc3024e27db913acf42" dependencies = [ "ark-bn254", "light-poseidon", - "solana-define-syscall", - "thiserror 2.0.17", + "solana-define-syscall 2.2.1", + "thiserror 2.0.18", ] [[package]] @@ -7645,13 +7781,13 @@ dependencies = [ "solana-clock", "solana-cpi", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-example-mocks", "solana-feature-gate-interface", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-keccak-hasher", @@ -7664,7 +7800,7 @@ dependencies = [ "solana-native-token", "solana-nonce", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-memory", "solana-program-option", "solana-program-pack", @@ -7676,7 +7812,7 @@ dependencies = [ "solana-secp256k1-recover", "solana-serde-varint", "solana-serialize-utils", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-short-vec", "solana-slot-hashes", "solana-slot-history", @@ -7686,7 +7822,7 @@ dependencies = [ "solana-sysvar", "solana-sysvar-id", "solana-vote-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", ] @@ -7698,7 +7834,7 @@ checksum = "473ffe73c68d93e9f2aa726ad2985fe52760052709aaab188100a42c618060ec" dependencies = [ "solana-account-info", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", ] @@ -7718,6 +7854,12 @@ dependencies = [ "solana-pubkey", ] +[[package]] +name = "solana-program-error" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1af32c995a7b692a915bb7414d5f8e838450cf7c70414e763d8abcae7b51f28" + [[package]] name = "solana-program-memory" version = "2.2.1" @@ -7725,7 +7867,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b0268f6c89825fb634a34bd0c3b8fdaeaecfc3728be1d622a8ee6dd577b60d4" dependencies = [ "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -7740,7 +7882,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "319f0ef15e6e12dc37c597faccb7d62525a509fec5f6975ecb9419efddeb277b" dependencies = [ - "solana-program-error", + "solana-program-error 2.2.2", ] [[package]] @@ -7763,7 +7905,7 @@ dependencies = [ "solana-epoch-rewards", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-last-restart-slot", "solana-log-collector", @@ -7781,7 +7923,7 @@ dependencies = [ "solana-timings", "solana-transaction-context", "solana-type-overrides", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -7817,7 +7959,7 @@ dependencies = [ "solana-svm 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "solana-timings", "solana-vote-program", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -7833,7 +7975,7 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "five8_const", + "five8_const 0.1.4", "getrandom 0.2.16", "js-sys", "num-traits", @@ -7842,9 +7984,9 @@ dependencies = [ "serde_derive", "solana-atomic-u64", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "wasm-bindgen", ] @@ -7867,7 +8009,7 @@ dependencies = [ "solana-pubkey", "solana-rpc-client-api", "solana-signature", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-tungstenite", @@ -7902,7 +8044,7 @@ dependencies = [ "solana-streamer", "solana-tls-utils", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -8012,7 +8154,7 @@ dependencies = [ "solana-epoch-info", "solana-epoch-schedule", "solana-feature-gate-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -8053,7 +8195,7 @@ dependencies = [ "solana-transaction-error", "solana-transaction-status-client-types", "solana-version", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8064,13 +8206,13 @@ checksum = "0244e2bf439ec424179414173cdc8b43e34371608752799c5610bf17430eee18" dependencies = [ "solana-account", "solana-commitment-config", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-nonce", "solana-pubkey", "solana-rpc-client", "solana-sdk-ids", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8155,7 +8297,7 @@ dependencies = [ "symlink", "tar", "tempfile", - "thiserror 2.0.17", + "thiserror 2.0.18", "zstd", ] @@ -8169,7 +8311,7 @@ dependencies = [ "log", "solana-compute-budget", "solana-compute-budget-instruction", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-sdk-ids", @@ -8177,7 +8319,7 @@ dependencies = [ "solana-svm-transaction", "solana-transaction", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8270,7 +8412,7 @@ dependencies = [ "solana-transaction-context", "solana-transaction-error", "solana-validator-exit", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", ] @@ -8292,7 +8434,7 @@ dependencies = [ "bs58", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -8321,8 +8463,8 @@ checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" dependencies = [ "borsh 1.6.0", "libsecp256k1", - "solana-define-syscall", - "thiserror 2.0.17", + "solana-define-syscall 2.2.1", + "thiserror 2.0.18", ] [[package]] @@ -8423,8 +8565,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0037386961c0d633421f53560ad7c80675c0447cba4d1bb66d60974dd486c7ea" dependencies = [ "sha2 0.10.9", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", +] + +[[package]] +name = "solana-sha256-hasher" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" +dependencies = [ + "sha2 0.10.9", + "solana-define-syscall 4.0.1", + "solana-hash 4.2.0", ] [[package]] @@ -8443,8 +8596,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afd3db0461089d1ad1a78d9ba3f15b563899ca2386351d38428faa5350c60a98" dependencies = [ "solana-hard-forks", - "solana-hash", - "solana-sha256-hasher", + "solana-hash 2.2.1", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -8481,7 +8634,7 @@ checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sysvar-id", ] @@ -8524,7 +8677,7 @@ dependencies = [ "solana-cpi", "solana-decode-error", "solana-instruction", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "solana-system-interface", "solana-sysvar-id", @@ -8569,7 +8722,7 @@ dependencies = [ "protobuf-src", "serde", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -8622,7 +8775,7 @@ dependencies = [ "solana-tls-utils", "solana-transaction-error", "solana-transaction-metrics-tracker", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util 0.7.17", "x509-parser", @@ -8647,7 +8800,7 @@ dependencies = [ "solana-compute-budget-instruction", "solana-feature-set", "solana-fee-structure", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-loader-v4-program", @@ -8670,7 +8823,7 @@ dependencies = [ "solana-transaction-context", "solana-transaction-error", "solana-type-overrides", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8691,7 +8844,7 @@ dependencies = [ "solana-compute-budget-instruction", "solana-feature-set", "solana-fee-structure", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-loader-v4-program", @@ -8715,7 +8868,7 @@ dependencies = [ "solana-transaction-context", "solana-transaction-error", "solana-type-overrides", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -8733,7 +8886,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fc4392f0eed412141a376e99dfb052069b96f13697a9abb335504babe29387a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-sdk-ids", @@ -8789,7 +8942,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bd98a25e5bcba8b6be8bcbb7b84b24c2a6a8178d7fb0e3077a916855ceba91a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-keypair", "solana-message", "solana-pubkey", @@ -8813,16 +8966,16 @@ dependencies = [ "serde_derive", "solana-account-info", "solana-clock", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-last-restart-slot", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-memory", "solana-pubkey", "solana-rent", @@ -8860,7 +9013,7 @@ dependencies = [ "solana-commitment-config", "solana-connection-cache", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -8934,7 +9087,7 @@ dependencies = [ "solana-signer", "solana-transaction", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -8949,7 +9102,7 @@ dependencies = [ "serde_derive", "solana-bincode", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -9029,7 +9182,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v2-interface", "solana-message", @@ -9049,7 +9202,7 @@ dependencies = [ "spl-token-2022 7.0.0", "spl-token-group-interface", "spl-token-metadata-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9072,7 +9225,7 @@ dependencies = [ "solana-transaction", "solana-transaction-context", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9097,7 +9250,7 @@ dependencies = [ "solana-net-utils", "solana-streamer", "solana-transaction-error", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -9147,7 +9300,7 @@ dependencies = [ "solana-account", "solana-bincode", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-packet", "solana-pubkey", @@ -9156,7 +9309,7 @@ dependencies = [ "solana-svm-transaction", "solana-transaction", "solana-vote-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9172,7 +9325,7 @@ dependencies = [ "serde_derive", "solana-clock", "solana-decode-error", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rent", @@ -9200,7 +9353,7 @@ dependencies = [ "solana-clock", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-packet", @@ -9213,7 +9366,7 @@ dependencies = [ "solana-transaction", "solana-transaction-context", "solana-vote-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9264,7 +9417,7 @@ dependencies = [ "solana-signature", "solana-signer", "subtle", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", "zeroize", ] @@ -9318,7 +9471,7 @@ dependencies = [ "solana-signature", "solana-signer", "subtle", - "thiserror 2.0.17", + "thiserror 2.0.18", "zeroize", ] @@ -9349,7 +9502,7 @@ dependencies = [ "simdutf8", "sonic-number", "sonic-simd", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9412,8 +9565,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ "bytemuck", - "solana-program-error", - "solana-sha256-hasher", + "solana-program-error 2.2.2", + "solana-sha256-hasher 2.2.1", "spl-discriminator-derive", ] @@ -9425,7 +9578,7 @@ checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" dependencies = [ "quote", "spl-discriminator-syn", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9437,7 +9590,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.9", - "syn 2.0.111", + "syn 2.0.117", "thiserror 1.0.69", ] @@ -9464,7 +9617,7 @@ dependencies = [ "solana-instruction", "solana-msg", "solana-program-entrypoint", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", ] @@ -9491,11 +9644,11 @@ dependencies = [ "num-traits", "solana-decode-error", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-program-option", "solana-pubkey", "solana-zk-sdk", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9520,7 +9673,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.9", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9536,7 +9689,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -9613,7 +9766,7 @@ dependencies = [ "spl-token-metadata-interface", "spl-transfer-hook-interface", "spl-type-length-value", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9639,7 +9792,7 @@ dependencies = [ "solana-program", "solana-zk-sdk", "spl-pod", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9661,7 +9814,7 @@ checksum = "0e3597628b0d2fe94e7900fd17cdb4cfbb31ee35c66f82809d27d86e44b2848b" dependencies = [ "curve25519-dalek 4.1.3", "solana-zk-sdk", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -9676,7 +9829,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -9696,7 +9849,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -9719,7 +9872,7 @@ dependencies = [ "solana-decode-error", "solana-instruction", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "solana-pubkey", "spl-discriminator", "spl-pod", @@ -9741,7 +9894,7 @@ dependencies = [ "solana-account-info", "solana-decode-error", "solana-msg", - "solana-program-error", + "solana-program-error 2.2.2", "spl-discriminator", "spl-pod", "thiserror 1.0.69", @@ -9805,7 +9958,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -9833,9 +9986,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -9874,7 +10027,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10207,11 +10360,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -10222,18 +10375,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10326,7 +10479,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10571,7 +10724,7 @@ dependencies = [ "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10585,7 +10738,7 @@ dependencies = [ "prost-build 0.13.5", "prost-types 0.13.5", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10667,7 +10820,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -10996,7 +11149,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -11114,6 +11267,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a7a568eda854acc9945ed136a9d50b8c6d31911584624958808ae96eee3912" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "windows" version = "0.62.2" @@ -11167,7 +11345,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -11178,7 +11356,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -11561,6 +11739,18 @@ dependencies = [ "tap", ] +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek 4.1.3", + "rand_core 0.6.4", + "serde", + "zeroize", +] + [[package]] name = "x509-parser" version = "0.14.0" @@ -11623,7 +11813,7 @@ dependencies = [ "solana-account", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-signature", @@ -11654,7 +11844,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure 0.13.2", ] @@ -11675,7 +11865,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -11695,7 +11885,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure 0.13.2", ] @@ -11716,7 +11906,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -11749,7 +11939,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index 9509bc0dc..d0286aca6 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -101,6 +101,7 @@ impl IxtestContext { pubkey, account: program_stub.clone(), commit_frequency_ms: None, + delegation_actions: vec![], delegated_to_other: None, }) .await From d17162a84e852ce562b86925a18f5cc32a592469 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 25 Feb 2026 21:25:02 +0530 Subject: [PATCH 02/16] remove parse_delegation_actions and instead make parse_delegation_record return actions --- .../src/scheduled_commits_processor.rs | 2 +- .../chainlink/fetch_cloner/ata_projection.rs | 11 +- .../src/chainlink/fetch_cloner/delegation.rs | 50 +++--- .../src/chainlink/fetch_cloner/mod.rs | 97 +++++------- .../src/chainlink/fetch_cloner/pipeline.rs | 145 +++++++----------- magicblock-chainlink/src/cloner/mod.rs | 41 ++++- .../test-chainlink/src/ixtest_context.rs | 4 +- 7 files changed, 177 insertions(+), 173 deletions(-) diff --git a/magicblock-accounts/src/scheduled_commits_processor.rs b/magicblock-accounts/src/scheduled_commits_processor.rs index 88c4ed4ed..3c3440366 100644 --- a/magicblock-accounts/src/scheduled_commits_processor.rs +++ b/magicblock-accounts/src/scheduled_commits_processor.rs @@ -238,7 +238,7 @@ impl ScheduledCommitsProcessorImpl { .map(|finalize| vec![commit, finalize]) .unwrap_or(vec![commit]) }) - .unwrap_or(vec![]) + .unwrap_or_default() } }; let patched_errors = result diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs index b1483e2ab..b6b918613 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs @@ -12,7 +12,7 @@ use tracing::*; use super::{delegation, types::AccountWithCompanion, FetchCloner}; use crate::{ - cloner::{AccountCloneRequest, Cloner}, + cloner::{AccountCloneRequest, Cloner, DelegationActions}, remote_account_provider::{ChainPubsubClient, ChainRpcClient}, }; @@ -127,15 +127,16 @@ where ) .await { + let (deleg_record, _delegation_actions) = deleg; delegated_to_other = - delegation::get_delegated_to_other(this, &deleg); - commit_frequency_ms = Some(deleg.commit_frequency_ms); + delegation::get_delegated_to_other(this, &deleg_record); + commit_frequency_ms = Some(deleg_record.commit_frequency_ms); if let Some(projected_ata) = this .maybe_project_delegated_ata_from_eata( ata_account.account_shared_data(), &eata_shared, - &deleg, + &deleg_record, ) { account_to_clone = projected_ata; @@ -147,7 +148,7 @@ where pubkey: ata_pubkey, account: account_to_clone, commit_frequency_ms, - delegation_actions: vec![], + delegation_actions: DelegationActions::default(), delegated_to_other, }); } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index d7663e3f1..e01ed31fb 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -6,49 +6,59 @@ use magicblock_core::token_programs::EATA_PROGRAM_ID; use magicblock_metrics::metrics; use solana_account::ReadableAccount; use solana_instruction::Instruction; +use solana_program::program_error::ProgramError; use solana_pubkey::Pubkey; use tracing::*; use super::FetchCloner; use crate::{ chainlink::errors::{ChainlinkError, ChainlinkResult}, - cloner::Cloner, + cloner::{Cloner, DelegationActions}, remote_account_provider::{ ChainPubsubClient, ChainRpcClient, MatchSlotsConfig, ResolvedAccountSharedData, }, }; +/// Parses a delegation record from account data bytes. +/// Returns the parsed DelegationRecord, or InvalidDelegationRecord error +/// if parsing fails. pub(crate) fn parse_delegation_record( data: &[u8], delegation_record_pubkey: Pubkey, -) -> ChainlinkResult { - DelegationRecord::try_from_bytes_with_discriminator(data) +) -> ChainlinkResult<(DelegationRecord, Option)> { + let delegation_record_size = DelegationRecord::size_with_discriminator(); + if data.len() < delegation_record_size { + return Err(ChainlinkError::InvalidDelegationRecord( + delegation_record_pubkey, + ProgramError::InvalidAccountData, + )); + } + let record = + DelegationRecord::try_from_bytes_with_discriminator( + &data[..delegation_record_size], + ) .copied() .map_err(|err| { ChainlinkError::InvalidDelegationRecord( delegation_record_pubkey, err, ) - }) -} + })?; -pub(crate) fn parse_delegation_actions( - data: &[u8], - delegation_record_pubkey: Pubkey, -) -> ChainlinkResult> { - let delegation_record_size = DelegationRecord::size_with_discriminator(); if data.len() <= delegation_record_size { - return Ok(vec![]); + Ok((record, None)) + } else { + let actions_data = &data[delegation_record_size..]; + let actions = bincode::deserialize::>(actions_data) + .map_err(|err| { + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + err.to_string(), + ) + })?; + Ok((record, Some(actions.into()))) } - - let actions_data = &data[delegation_record_size..]; - bincode::deserialize::>(actions_data).map_err(|err| { - ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - err.to_string(), - ) - }) } pub(crate) fn apply_delegation_record_to_account( @@ -106,7 +116,7 @@ pub(crate) async fn fetch_and_parse_delegation_record( account_pubkey: Pubkey, min_context_slot: u64, fetch_origin: metrics::AccountFetchOrigin, -) -> Option +) -> Option<(DelegationRecord, Option)> where T: ChainRpcClient, U: ChainPubsubClient, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 081a31b06..947cdbe50 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -50,7 +50,10 @@ use crate::{ account_still_undelegating_on_chain::account_still_undelegating_on_chain, blacklisted_accounts::blacklisted_accounts, }, - cloner::{errors::ClonerResult, AccountCloneRequest, Cloner}, + cloner::{ + errors::ClonerResult, AccountCloneRequest, Cloner, + DelegationActions, + }, remote_account_provider::{ program_account::get_loaderv3_get_program_data_address, ChainPubsubClient, ChainRpcClient, ForwardedSubscriptionUpdate, @@ -336,7 +339,7 @@ where ) -> ( Option, Option, - Vec, + DelegationActions, ) { let ForwardedSubscriptionUpdate { pubkey, account } = update; let owned_by_delegation_program = @@ -381,34 +384,8 @@ where let account = if let Some(delegation_record) = delegation_record { - let delegation_record_size = - DelegationRecord::size_with_discriminator(); - if delegation_record.data().len() - == delegation_record_size - { - // Regular delegation record layout. - } else { - // DelegateWithActions layout (DelegationRecord + trailing bytes). - } - - let delegation_actions = - match Self::parse_delegation_actions( - delegation_record.data(), - delegation_record_pubkey, - ) { - Ok(actions) => actions, - Err(err) => { - error!( - pubkey = %pubkey, - error = %err, - "Failed to parse delegation actions" - ); - vec![] - } - }; - - let delegation_record = - match Self::parse_delegation_record( + let delegation_record_with_actions = + match delegation::parse_delegation_record( delegation_record.data(), delegation_record_pubkey, ) { @@ -425,7 +402,11 @@ where // If the delegation record is valid we set the owner and delegation // status on the account - if let Some(delegation_record) = delegation_record { + if let Some(( + delegation_record, + delegation_actions, + )) = delegation_record_with_actions + { if tracing::enabled!(tracing::Level::TRACE) { let delegation_record_display = format!("{:?}", delegation_record); @@ -469,25 +450,26 @@ where ( Some(account.into_account_shared_data()), Some(delegation_record), - delegation_actions, + delegation_actions.unwrap_or_default(), ) } 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, vec![]) + ( + None, + None, + DelegationActions::default(), + ) } } else { // If no delegation record exists we must assume the account itself is // a delegation record or metadata - let delegation_record_size = - DelegationRecord::size_with_discriminator(); - if account.data().len() == delegation_record_size { - // Regular delegation record layout. - } else { - // DelegateWithActions layout (DelegationRecord + trailing bytes). - } - (Some(account.into_account_shared_data()), None, vec![]) + ( + Some(account.into_account_shared_data()), + None, + DelegationActions::default(), + ) }; if !subs_to_remove.is_empty() { @@ -506,7 +488,7 @@ where error = ?err, "Failed to fetch delegation record" ); - (None, None, vec![]) + (None, None, DelegationActions::default()) } Err(err) => { warn!( @@ -514,20 +496,24 @@ where error = ?err, "Failed to fetch delegation record" ); - (None, None, vec![]) + (None, None, DelegationActions::default()) } } } else { let (account, deleg_record) = self .maybe_project_ata_from_subscription_update(pubkey, account) .await; - (Some(account), deleg_record, vec![]) + ( + Some(account), + deleg_record, + DelegationActions::default(), + ) } } 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, vec![]) + (None, None, DelegationActions::default()) } } @@ -586,7 +572,7 @@ where pubkey: ata_pubkey, account: projected_ata, commit_frequency_ms: None, - delegation_actions: vec![], + delegation_actions: DelegationActions::default(), delegated_to_other: None, }) } @@ -654,6 +640,7 @@ where let Some(deleg_record) = deleg_record else { return (ata_account, None); }; + let (deleg_record, _delegation_actions) = deleg_record; if let Some(projected_ata) = self.maybe_project_delegated_ata_from_eata( &ata_account, @@ -695,17 +682,10 @@ where fn parse_delegation_record( data: &[u8], delegation_record_pubkey: Pubkey, - ) -> ChainlinkResult { + ) -> ChainlinkResult<(DelegationRecord, Option)> { delegation::parse_delegation_record(data, delegation_record_pubkey) } - fn parse_delegation_actions( - data: &[u8], - delegation_record_pubkey: Pubkey, - ) -> ChainlinkResult> { - delegation::parse_delegation_actions(data, delegation_record_pubkey) - } - /// Applies delegation record settings to an account: sets the owner, /// delegation status, and confined status based on the delegation /// record's authority field. @@ -738,7 +718,7 @@ where account_pubkey: Pubkey, min_context_slot: u64, fetch_origin: metrics::AccountFetchOrigin, - ) -> Option { + ) -> Option<(DelegationRecord, Option)> { delegation::fetch_and_parse_delegation_record( self, account_pubkey, @@ -987,9 +967,10 @@ where } let delegated_on_chain = deleg_record.as_ref().is_some_and(|dr| { - dr.authority.eq(&self.validator_pubkey) - || dr.authority.eq(&Pubkey::default()) + dr.0.authority.eq(&self.validator_pubkey) + || dr.0.authority.eq(&Pubkey::default()) }); + let deleg_record = deleg_record.map(|el| el.0); if !account_still_undelegating_on_chain( pubkey, delegated_on_chain, @@ -1418,7 +1399,7 @@ where pubkey, account, commit_frequency_ms: None, - delegation_actions: vec![], + delegation_actions: DelegationActions::default(), delegated_to_other: None, }) .await?; diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 2ba7e10b5..9efc2664e 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -19,7 +19,10 @@ use super::{ }; use crate::{ chainlink::errors::{ChainlinkError, ChainlinkResult}, - cloner::{errors::ClonerResult, AccountCloneRequest, Cloner}, + cloner::{ + errors::ClonerResult, AccountCloneRequest, Cloner, + DelegationActions, + }, remote_account_provider::{ program_account::{ get_loaderv3_get_program_data_address, ProgramAccountResolver, @@ -143,7 +146,7 @@ fn classify_single_account( pubkey, account: account_shared_data, commit_frequency_ms: None, - delegation_actions: vec![], + delegation_actions: DelegationActions::default(), delegated_to_other: None, }); } @@ -293,92 +296,62 @@ where 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) = if let Some( - delegation_record_data, - ) = - delegation_record - { - let delegation_record_size = - dlp::state::DelegationRecord::size_with_discriminator(); - if delegation_record_data.data().len() == delegation_record_size - { - // Regular delegation record layout. - } else { - // DelegateWithActions layout (DelegationRecord + trailing bytes). - } - - // NOTE: failing here is fine when resolving all accounts for a transaction - // since if something is off we better not run it anyways - // However we may consider a different behavior when user is getting - // multiple accounts. - let delegation_actions = - match FetchCloner::::parse_delegation_actions( - delegation_record_data.data(), - delegation_record_pubkey, - ) { - Ok(x) => x, - Err(err) => { - // Cancel all new subs since we won't clone any accounts - cancel_subs( - &this.remote_account_provider, - CancelStrategy::New { - new_subs: pubkeys - .iter() - .cloned() - .chain(record_subs.iter().cloned()) - .collect(), - existing_subs: existing_subs.clone(), - }, - ) - .await; - return Err(err); - } - }; - - let delegation_record = - match FetchCloner::::parse_delegation_record( - delegation_record_data.data(), - delegation_record_pubkey, - ) { - Ok(x) => x, - Err(err) => { - // Cancel all new subs since we won't clone any accounts - cancel_subs( - &this.remote_account_provider, - CancelStrategy::New { - new_subs: pubkeys - .iter() - .cloned() - .chain(record_subs.iter().cloned()) - .collect(), - existing_subs: existing_subs.clone(), - }, - ) - .await; - return Err(err); - } - }; - - trace!(pubkey = %pubkey, "Delegation record found"); - - let delegated_to_other = - this.get_delegated_to_other(&delegation_record); - - let commit_freq = this.apply_delegation_record_to_account( - &mut account, - &delegation_record, - ); + let (commit_frequency_ms, delegated_to_other, delegation_actions) = + if let Some(delegation_record_data) = delegation_record { + // NOTE: failing here is fine when resolving all accounts for a transaction + // since if something is off we better not run it anyways + // However we may consider a different behavior when user is getting + // multiple accounts. + let (delegation_record, delegation_actions) = + match FetchCloner::::parse_delegation_record( + delegation_record_data.data(), + delegation_record_pubkey, + ) { + Ok(x) => x, + Err(err) => { + // Cancel all new subs since we won't clone any accounts + cancel_subs( + &this.remote_account_provider, + CancelStrategy::New { + new_subs: pubkeys + .iter() + .cloned() + .chain(record_subs.iter().cloned()) + .collect(), + existing_subs: existing_subs.clone(), + }, + ) + .await; + return Err(err); + } + }; + + trace!(pubkey = %pubkey, "Delegation record found"); + + let delegated_to_other = + this.get_delegated_to_other(&delegation_record); + + let commit_freq = this.apply_delegation_record_to_account( + &mut account, + &delegation_record, + ); - // Collect unique owner programs to subscribe concurrently after the loop - if account.delegated() { - owner_programs_to_subscribe.insert(delegation_record.owner); - } + // Collect unique owner programs to subscribe concurrently after the loop + if account.delegated() { + owner_programs_to_subscribe + .insert(delegation_record.owner); + } - (commit_freq, delegated_to_other, delegation_actions) - } else { - missing_delegation_record.push((pubkey, account.remote_slot())); - (None, None, vec![]) - }; + ( + commit_freq, + delegated_to_other, + delegation_actions.unwrap_or_default(), + ) + } else { + missing_delegation_record + .push((pubkey, account.remote_slot())); + (None, None, DelegationActions::default()) + }; accounts_to_clone.push(AccountCloneRequest { pubkey, account: account.into_account_shared_data(), diff --git a/magicblock-chainlink/src/cloner/mod.rs b/magicblock-chainlink/src/cloner/mod.rs index 9d1de024e..b90c4cbc5 100644 --- a/magicblock-chainlink/src/cloner/mod.rs +++ b/magicblock-chainlink/src/cloner/mod.rs @@ -1,5 +1,6 @@ use async_trait::async_trait; use errors::ClonerResult; +use std::ops::Deref; use solana_account::AccountSharedData; use solana_instruction::Instruction; use solana_pubkey::Pubkey; @@ -9,11 +10,49 @@ use crate::remote_account_provider::program_account::LoadedProgram; pub mod errors; +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct DelegationActions(Vec); + +impl DelegationActions { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +impl From> for DelegationActions { + fn from(value: Vec) -> Self { + Self(value) + } +} + +impl From for Vec { + fn from(value: DelegationActions) -> Self { + value.0 + } +} + +impl IntoIterator for DelegationActions { + type Item = Instruction; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl Deref for DelegationActions { + type Target = [Instruction]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + pub struct AccountCloneRequest { pub pubkey: Pubkey, pub account: AccountSharedData, pub commit_frequency_ms: Option, - pub delegation_actions: Vec, + pub delegation_actions: DelegationActions, /// If the account is delegated to another validator, /// this contains that validator's pubkey. None if account is not /// delegated to another validator. diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index d0286aca6..ad4ac1565 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use integration_test_tools::dlp_interface; use magicblock_chainlink::{ accounts_bank::mock::AccountsBankStub, - cloner::{AccountCloneRequest, Cloner}, + cloner::{AccountCloneRequest, Cloner, DelegationActions}, config::ChainlinkConfig, fetch_cloner::FetchCloner, native_program_accounts, @@ -101,7 +101,7 @@ impl IxtestContext { pubkey, account: program_stub.clone(), commit_frequency_ms: None, - delegation_actions: vec![], + delegation_actions: DelegationActions::default(), delegated_to_other: None, }) .await From d219a76eb5dd357ec9497966baf391213aad7e20 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Sun, 1 Mar 2026 02:59:32 +0530 Subject: [PATCH 03/16] use dlp-api --- Cargo.lock | 281 +++++++++++++++- Cargo.toml | 1 + magicblock-committor-service/Cargo.toml | 1 + .../src/tasks/args_task.rs | 22 +- .../src/tasks/buffer_task.rs | 8 +- .../src/transactions.rs | 10 +- magicblock-validator-admin/Cargo.toml | 1 + magicblock-validator-admin/src/claim_fees.rs | 2 +- test-integration/Cargo.lock | 301 ++++++++++++++---- test-integration/Cargo.toml | 3 +- .../programs/schedulecommit/Cargo.toml | 1 + .../programs/schedulecommit/src/api.rs | 4 +- test-integration/test-chainlink/Cargo.toml | 1 + .../test-chainlink/src/ixtest_context.rs | 6 +- .../test-committor-service/Cargo.toml | 1 + .../tests/test_intent_executor.rs | 6 +- .../tests/utils/instructions.rs | 2 +- .../test-magicblock-api/Cargo.toml | 1 + .../tests/test_claim_fees.rs | 2 +- .../test-schedule-intent/Cargo.toml | 1 + .../tests/test_schedule_intents.rs | 2 +- test-integration/test-tools/Cargo.toml | 1 + .../test-tools/src/dlp_interface.rs | 8 +- 23 files changed, 561 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6c69f7e2..5e525fb02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "aead" version = "0.5.2" @@ -839,9 +845,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.49" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -1146,6 +1152,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1231,6 +1246,28 @@ dependencies = [ "subtle", ] +[[package]] +name = "ct-codecs" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10589d1a5e400d61f9f38f12f884cfd080ff345de8f17efda36fe0e4a02aa8" + +[[package]] +name = "ctor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "424e0138278faeb2b401f174ad17e715c829512d74f3d1e81eb43365c2e0590e" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "ctr" version = "0.9.2" @@ -1351,6 +1388,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dary_heap" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d2e3287df1c007e74221c49ca10a95d557349e54b3a75dc2fb14712c751f04" + [[package]] name = "data-encoding" version = "2.9.0" @@ -1438,6 +1481,36 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dlp-api" +version = "0.1.0" +dependencies = [ + "bincode", + "borsh 1.6.0", + "libsodium-rs", + "magicblock-delegation-program", + "rand 0.8.5", + "serde", + "solana-program", + "solana-sdk", + "thiserror 2.0.18", +] + +[[package]] +name = "dtor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -1642,11 +1715,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "filetime" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +dependencies = [ + "cfg-if", + "libc", + "libredox", +] + [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "five8" @@ -1694,6 +1778,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] @@ -2736,6 +2821,30 @@ version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +[[package]] +name = "libflate" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3248b8d211bd23a104a42d81b4fa8bb8ac4a3b75e7a43d85d2c9ccb6179cd74" +dependencies = [ + "adler32", + "core2", + "crc32fast", + "dary_heap", + "libflate_lz77", +] + +[[package]] +name = "libflate_lz77" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a599cb10a9cd92b1300debcef28da8f70b935ec937f44fcd1b70a7c986a11c5c" +dependencies = [ + "core2", + "hashbrown 0.16.1", + "rle-decode-fast", +] + [[package]] name = "libloading" version = "0.8.9" @@ -2746,6 +2855,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags 2.10.0", + "libc", + "redox_syscall 0.7.0", +] + [[package]] name = "librocksdb-sys" version = "0.17.1+9.9.3" @@ -2809,6 +2929,38 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libsodium-rs" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a6a6c03c914ffa9e53f76300ab4e81a86230f8b884c7f224eb6617ab685878" +dependencies = [ + "ct-codecs", + "ctor", + "libc", + "libsodium-sys-stable", + "pkg-config", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "libsodium-sys-stable" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5d23f4a051a13cf1085b2c5a050d4d890d80c754534cc4247eff525fa5283d" +dependencies = [ + "cc", + "libc", + "libflate", + "minisign-verify", + "pkg-config", + "tar", + "ureq", + "vcpkg", + "zip", +] + [[package]] name = "libsqlite3-sys" version = "0.35.0" @@ -2820,6 +2972,15 @@ 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" @@ -3193,6 +3354,7 @@ dependencies = [ "base64 0.21.7", "bincode", "borsh 1.6.0", + "dlp-api", "dyn-clone", "futures-util", "lazy_static", @@ -3299,10 +3461,11 @@ dependencies = [ "solana-curve25519", "solana-program", "solana-sdk", + "solana-security-txt", "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -3565,6 +3728,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.2" dependencies = [ + "dlp-api", "magicblock-delegation-program", "magicblock-program", "magicblock-rpc-client", @@ -3680,6 +3844,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "minisign-verify" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e856fdd13623a2f5f2f54676a4ee49502a96a80ef4a62bcedd23d52427c44d43" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -4004,7 +4174,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", "windows-link", ] @@ -4749,6 +4919,15 @@ dependencies = [ "bitflags 2.10.0", ] +[[package]] +name = "redox_syscall" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "ref-cast" version = "1.0.25" @@ -4959,6 +5138,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "rle-decode-fast" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" + [[package]] name = "rocksdb" version = "0.22.0" @@ -8427,6 +8612,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "task-local-extensions" version = "0.1.4" @@ -9046,6 +9242,12 @@ dependencies = [ "webpki-roots 0.24.0", ] +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typenum" version = "1.19.0" @@ -9133,6 +9335,31 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" +dependencies = [ + "base64 0.22.1", + "log", + "percent-encoding", + "ureq-proto", + "utf-8", +] + +[[package]] +name = "ureq-proto" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +dependencies = [ + "base64 0.22.1", + "http 1.4.0", + "httparse", + "log", +] + [[package]] name = "uriparse" version = "0.6.4" @@ -9786,6 +10013,16 @@ dependencies = [ "tap", ] +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix 1.1.2", +] + [[package]] name = "yansi" version = "1.0.1" @@ -9949,6 +10186,38 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "zip" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" +dependencies = [ + "crc32fast", + "flate2", + "indexmap 2.12.1", + "memchr", + "typed-path", + "zopfli", +] + +[[package]] +name = "zlib-rs" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" + +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 8bc3893b0..3dfe8594f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,6 +105,7 @@ magicblock-core = { path = "./magicblock-core" } magicblock-delegation-program = { path = "../delegation-program", default-features = false, features = [ "sdk", ] } +dlp-api = { path = "../delegation-program/dlp-api" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-committor-service/Cargo.toml b/magicblock-committor-service/Cargo.toml index 4aa583f8d..9ce042af8 100644 --- a/magicblock-committor-service/Cargo.toml +++ b/magicblock-committor-service/Cargo.toml @@ -25,6 +25,7 @@ magicblock-committor-program = { workspace = true, features = [ magicblock-delegation-program = { workspace = true, features = [ "no-entrypoint", ] } +dlp-api = { workspace = true } magicblock-metrics = { workspace = true } magicblock-program = { workspace = true } magicblock-rpc-client = { workspace = true } diff --git a/magicblock-committor-service/src/tasks/args_task.rs b/magicblock-committor-service/src/tasks/args_task.rs index 3f883fbbf..3afc813bb 100644 --- a/magicblock-committor-service/src/tasks/args_task.rs +++ b/magicblock-committor-service/src/tasks/args_task.rs @@ -1,13 +1,13 @@ use dlp::{ args::{CommitDiffArgs, CommitStateArgs}, compute_diff, - instruction_builder::{ - call_handler_size_budget, call_handler_v2_size_budget, - commit_diff_size_budget, commit_size_budget, finalize_size_budget, - undelegate_size_budget, - }, AccountSizeClass, }; +use dlp_api::instruction_builder::{ + call_handler_size_budget, call_handler_v2_size_budget, + commit_diff_size_budget, commit_size_budget, finalize_size_budget, + undelegate_size_budget, +}; use magicblock_metrics::metrics::LabelValue; use solana_account::ReadableAccount; use solana_instruction::Instruction; @@ -69,7 +69,7 @@ impl BaseTask for ArgsTask { data: value.committed_account.account.data.clone(), allow_undelegation: value.allow_undelegation, }; - dlp::instruction_builder::commit_state( + dlp_api::instruction_builder::commit_state( *validator, value.committed_account.pubkey, value.committed_account.account.owner, @@ -88,7 +88,7 @@ impl BaseTask for ArgsTask { allow_undelegation: value.allow_undelegation, }; - dlp::instruction_builder::commit_diff( + dlp_api::instruction_builder::commit_diff( *validator, value.committed_account.pubkey, value.committed_account.account.owner, @@ -96,13 +96,13 @@ impl BaseTask for ArgsTask { ) } ArgsTaskType::Finalize(value) => { - dlp::instruction_builder::finalize( + dlp_api::instruction_builder::finalize( *validator, value.delegated_account, ) } ArgsTaskType::Undelegate(value) => { - dlp::instruction_builder::undelegate( + dlp_api::instruction_builder::undelegate( *validator, value.delegated_account, value.owner_program, @@ -111,7 +111,7 @@ impl BaseTask for ArgsTask { } ArgsTaskType::BaseAction(value) => { let action = &value.action; - dlp::instruction_builder::call_handler( + dlp_api::instruction_builder::call_handler( *validator, action.destination_program, action.escrow_authority, @@ -121,7 +121,7 @@ impl BaseTask for ArgsTask { } ArgsTaskType::BaseActionV2(value) => { let action = &value.action; - dlp::instruction_builder::call_handler_v2( + dlp_api::instruction_builder::call_handler_v2( *validator, action.destination_program, value.source_program, diff --git a/magicblock-committor-service/src/tasks/buffer_task.rs b/magicblock-committor-service/src/tasks/buffer_task.rs index fc8440a1a..26347521c 100644 --- a/magicblock-committor-service/src/tasks/buffer_task.rs +++ b/magicblock-committor-service/src/tasks/buffer_task.rs @@ -1,9 +1,11 @@ use dlp::{ args::CommitStateFromBufferArgs, compute_diff, - instruction_builder::{commit_diff_size_budget, commit_size_budget}, AccountSizeClass, }; +use dlp_api::instruction_builder::{ + commit_diff_size_budget, commit_size_budget, +}; use magicblock_committor_program::Chunks; use magicblock_metrics::metrics::LabelValue; use solana_instruction::Instruction; @@ -118,7 +120,7 @@ impl BaseTask for BufferTask { &commit_id_slice, ); - dlp::instruction_builder::commit_state_from_buffer( + dlp_api::instruction_builder::commit_state_from_buffer( *validator, task.committed_account.pubkey, task.committed_account.account.owner, @@ -139,7 +141,7 @@ impl BaseTask for BufferTask { &commit_id_slice, ); - dlp::instruction_builder::commit_diff_from_buffer( + dlp_api::instruction_builder::commit_diff_from_buffer( *validator, task.committed_account.pubkey, task.committed_account.account.owner, diff --git a/magicblock-committor-service/src/transactions.rs b/magicblock-committor-service/src/transactions.rs index 7e8ef1759..a9481428e 100644 --- a/magicblock-committor-service/src/transactions.rs +++ b/magicblock-committor-service/src/transactions.rs @@ -179,7 +179,7 @@ mod test { buffer_pda: &Pubkey, commit_args: CommitStateFromBufferArgs, ) -> Instruction { - dlp::instruction_builder::commit_state_from_buffer( + dlp_api::instruction_builder::commit_state_from_buffer( validator_auth, *pubkey, *delegated_account_owner, @@ -227,7 +227,7 @@ mod test { validator_auth: Pubkey, pubkey: &Pubkey, ) -> Instruction { - dlp::instruction_builder::finalize(validator_auth, *pubkey) + dlp_api::instruction_builder::finalize(validator_auth, *pubkey) } // These tests statically determine the optimal ix count to fit into a single @@ -332,7 +332,7 @@ mod test { data, ..CommitStateArgs::default() }; - dlp::instruction_builder::commit_state( + dlp_api::instruction_builder::commit_state( auth.pubkey(), Pubkey::new_unique(), Pubkey::new_unique(), @@ -519,7 +519,7 @@ mod test { max_chunks_per_transaction("Max undelegate per tx", |auth_pubkey| { let pubkey = Pubkey::new_unique(); let owner_program = Pubkey::new_unique(); - vec![dlp::instruction_builder::undelegate( + vec![dlp_api::instruction_builder::undelegate( auth_pubkey, pubkey, owner_program, @@ -531,7 +531,7 @@ mod test { max_chunks_per_transaction_using_lookup_table( "Max undelegate per tx using lookup", |auth_pubkey, committee, owner_program| { - vec![dlp::instruction_builder::undelegate( + vec![dlp_api::instruction_builder::undelegate( auth_pubkey, committee, owner_program, diff --git a/magicblock-validator-admin/Cargo.toml b/magicblock-validator-admin/Cargo.toml index 6b463701b..7c869314c 100644 --- a/magicblock-validator-admin/Cargo.toml +++ b/magicblock-validator-admin/Cargo.toml @@ -11,6 +11,7 @@ edition.workspace = true tracing = { workspace = true } magicblock-delegation-program = { workspace = true } +dlp-api = { workspace = true } magicblock-program = { workspace = true } magicblock-rpc-client = { workspace = true } diff --git a/magicblock-validator-admin/src/claim_fees.rs b/magicblock-validator-admin/src/claim_fees.rs index f4eca4ebc..f3a1932ab 100644 --- a/magicblock-validator-admin/src/claim_fees.rs +++ b/magicblock-validator-admin/src/claim_fees.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use dlp::instruction_builder::validator_claim_fees; +use dlp_api::instruction_builder::validator_claim_fees; use magicblock_program::validator::validator_authority; use magicblock_rpc_client::MagicBlockRpcClientError; use solana_commitment_config::CommitmentConfig; diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index d6777daea..56e43e968 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -27,6 +27,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "aead" version = "0.5.2" @@ -936,9 +942,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.49" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -1224,6 +1230,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1303,6 +1318,28 @@ dependencies = [ "subtle", ] +[[package]] +name = "ct-codecs" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10589d1a5e400d61f9f38f12f884cfd080ff345de8f17efda36fe0e4a02aa8" + +[[package]] +name = "ctor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "424e0138278faeb2b401f174ad17e715c829512d74f3d1e81eb43365c2e0590e" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "ctr" version = "0.9.2" @@ -1400,6 +1437,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dary_heap" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d2e3287df1c007e74221c49ca10a95d557349e54b3a75dc2fb14712c751f04" + [[package]] name = "dashmap" version = "5.5.3" @@ -1565,12 +1608,42 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dlp-api" +version = "0.1.0" +dependencies = [ + "bincode", + "borsh 1.6.0", + "libsodium-rs", + "magicblock-delegation-program 1.1.3", + "rand 0.8.5", + "serde", + "solana-program", + "solana-sdk", + "thiserror 2.0.18", +] + [[package]] name = "downcast" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "dtor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -1916,9 +1989,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "five8" @@ -1966,6 +2039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] @@ -2910,9 +2984,10 @@ dependencies = [ "anyhow", "borsh 1.6.0", "color-backtrace", + "dlp-api", "magicblock-config", "magicblock-core", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "random-port", "rayon", "serde", @@ -2924,7 +2999,7 @@ dependencies = [ "tempfile", "toml 0.8.23", "tracing", - "ureq", + "ureq 2.12.1", "url", ] @@ -3064,6 +3139,30 @@ version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +[[package]] +name = "libflate" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3248b8d211bd23a104a42d81b4fa8bb8ac4a3b75e7a43d85d2c9ccb6179cd74" +dependencies = [ + "adler32", + "core2", + "crc32fast", + "dary_heap", + "libflate_lz77", +] + +[[package]] +name = "libflate_lz77" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a599cb10a9cd92b1300debcef28da8f70b935ec937f44fcd1b70a7c986a11c5c" +dependencies = [ + "core2", + "hashbrown 0.16.1", + "rle-decode-fast", +] + [[package]] name = "libloading" version = "0.8.9" @@ -3154,6 +3253,38 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libsodium-rs" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a6a6c03c914ffa9e53f76300ab4e81a86230f8b884c7f224eb6617ab685878" +dependencies = [ + "ct-codecs", + "ctor", + "libc", + "libsodium-sys-stable", + "pkg-config", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "libsodium-sys-stable" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5d23f4a051a13cf1085b2c5a050d4d890d80c754534cc4247eff525fa5283d" +dependencies = [ + "cc", + "libc", + "libflate", + "minisign-verify", + "pkg-config", + "tar", + "ureq 3.2.0", + "vcpkg", + "zip", +] + [[package]] name = "libsqlite3-sys" version = "0.35.0" @@ -3165,6 +3296,15 @@ 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" @@ -3535,6 +3675,7 @@ dependencies = [ "base64 0.21.7", "bincode", "borsh 1.6.0", + "dlp-api", "dyn-clone", "futures-util", "lru", @@ -3621,25 +3762,23 @@ dependencies = [ "borsh 1.6.0", "bytemuck", "const-crypto", - "curve25519-dalek 4.1.3", "num_enum", "pinocchio 0.10.2", "pinocchio-log", "pinocchio-pubkey", - "pinocchio-system 0.5.0", + "pinocchio-system", "rand 0.8.5", "rkyv 0.7.45", "serde", - "sha2 0.10.9", "solana-address", "solana-curve25519", "solana-program", "solana-sdk", + "solana-security-txt", "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", - "thiserror 1.0.69", - "x25519-dalek", + "thiserror 2.0.18", ] [[package]] @@ -3655,29 +3794,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "magicblock-delegation-program" -version = "1.1.3" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372#2cb491032f372faa4cfdb55e3f05cefd7e07351d" -dependencies = [ - "bincode", - "borsh 1.6.0", - "bytemuck", - "const-crypto", - "num_enum", - "pinocchio 0.9.2", - "pinocchio-log", - "pinocchio-pubkey", - "pinocchio-system 0.3.0", - "rkyv 0.7.45", - "solana-curve25519", - "solana-program", - "solana-security-txt", - "static_assertions", - "strum 0.27.2", - "thiserror 1.0.69", -] - [[package]] name = "magicblock-ledger" version = "0.8.2" @@ -3898,6 +4014,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.2" dependencies = [ + "dlp-api", "magicblock-delegation-program 1.1.3", "magicblock-program", "magicblock-rpc-client", @@ -4007,6 +4124,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "minisign-verify" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e856fdd13623a2f5f2f54676a4ee49502a96a80ef4a62bcedd23d52427c44d43" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -4656,16 +4779,6 @@ dependencies = [ "sha2-const-stable", ] -[[package]] -name = "pinocchio-system" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141ed5eafb4ab04568bb0e224e3dc9a9de13c933de4c004e0d1a553498be3a7c" -dependencies = [ - "pinocchio 0.9.2", - "pinocchio-pubkey", -] - [[package]] name = "pinocchio-system" version = "0.5.0" @@ -4864,8 +4977,9 @@ name = "program-schedulecommit" version = "0.0.0" dependencies = [ "borsh 1.6.0", + "dlp-api", "ephemeral-rollups-sdk", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "magicblock-magic-program-api 0.8.2", "rkyv 0.7.45", "solana-program", @@ -5610,6 +5724,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "rle-decode-fast" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" + [[package]] name = "rocksdb" version = "0.22.0" @@ -5857,7 +5977,7 @@ dependencies = [ "borsh 1.6.0", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "program-schedulecommit", "solana-program", "solana-rpc-client", @@ -5872,10 +5992,11 @@ version = "0.0.0" dependencies = [ "async-trait", "borsh 1.6.0", + "dlp-api", "futures", "magicblock-committor-program", "magicblock-committor-service", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -10158,11 +10279,12 @@ name = "test-chainlink" version = "0.0.0" dependencies = [ "bincode", + "dlp-api", "futures", "integration-test-tools", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "program-flexi-counter", "program-mini", "solana-account", @@ -10246,7 +10368,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "program-flexi-counter", "solana-rpc-client", "solana-sdk", @@ -10261,13 +10383,14 @@ name = "test-magicblock-api" version = "0.0.0" dependencies = [ "cleanass", + "dlp-api", "integration-test-tools", "isocountry", "lazy_static", "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "magicblock-program", "magicblock-validator-admin", "solana-rpc-client", @@ -10306,8 +10429,9 @@ dependencies = [ name = "test-schedule-intent" version = "0.0.0" dependencies = [ + "dlp-api", "integration-test-tools", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3", "program-flexi-counter", "solana-rpc-client-api", "solana-sdk", @@ -10903,6 +11027,12 @@ dependencies = [ "webpki-roots 0.24.0", ] +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typenum" version = "1.19.0" @@ -10989,6 +11119,31 @@ dependencies = [ "webpki-roots 0.26.11", ] +[[package]] +name = "ureq" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" +dependencies = [ + "base64 0.22.1", + "log", + "percent-encoding", + "ureq-proto", + "utf-8", +] + +[[package]] +name = "ureq-proto" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +dependencies = [ + "base64 0.22.1", + "http 1.4.0", + "httparse", + "log", +] + [[package]] name = "uriparse" version = "0.6.4" @@ -11739,18 +11894,6 @@ dependencies = [ "tap", ] -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek 4.1.3", - "rand_core 0.6.4", - "serde", - "zeroize", -] - [[package]] name = "x509-parser" version = "0.14.0" @@ -11942,6 +12085,38 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "zip" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" +dependencies = [ + "crc32fast", + "flate2", + "indexmap 2.12.1", + "memchr", + "typed-path", + "zopfli", +] + +[[package]] +name = "zlib-rs" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" + +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + [[package]] name = "zstd" version = "0.13.3" diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 3aeaaf5ed..d35cd2bd7 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -60,9 +60,10 @@ magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain- "modular-sdk", ] } magicblock_magic_program_api = { package = "magicblock-magic-program-api", path = "../magicblock-magic-program-api" } -magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "2cb491032f372", features = [ +magicblock-delegation-program = { path = "../../delegation-program", features = [ "no-entrypoint", ] } +dlp-api = { path = "../../delegation-program/dlp-api" } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } magicblock-table-mania = { path = "../magicblock-table-mania" } diff --git a/test-integration/programs/schedulecommit/Cargo.toml b/test-integration/programs/schedulecommit/Cargo.toml index 272fab194..691fd2a44 100644 --- a/test-integration/programs/schedulecommit/Cargo.toml +++ b/test-integration/programs/schedulecommit/Cargo.toml @@ -8,6 +8,7 @@ borsh = { workspace = true } ephemeral-rollups-sdk = { workspace = true } solana-program = { workspace = true } magicblock-delegation-program = { workspace = true } +dlp-api = { workspace = true } magicblock_magic_program_api = { workspace = true } rkyv = { workspace = true } static_assertions = { workspace = true } diff --git a/test-integration/programs/schedulecommit/src/api.rs b/test-integration/programs/schedulecommit/src/api.rs index 8f359a56c..94459188d 100644 --- a/test-integration/programs/schedulecommit/src/api.rs +++ b/test-integration/programs/schedulecommit/src/api.rs @@ -90,13 +90,13 @@ pub fn grow_order_book_instruction( } pub fn init_payer_escrow(payer: Pubkey) -> [Instruction; 2] { - let top_up_ix = dlp::instruction_builder::top_up_ephemeral_balance( + let top_up_ix = dlp_api::instruction_builder::top_up_ephemeral_balance( payer, payer, Some(300_000_000), Some(0), ); - let delegate_ix = dlp::instruction_builder::delegate_ephemeral_balance( + let delegate_ix = dlp_api::instruction_builder::delegate_ephemeral_balance( payer, payer, DelegateEphemeralBalanceArgs { diff --git a/test-integration/test-chainlink/Cargo.toml b/test-integration/test-chainlink/Cargo.toml index 227c1efc8..a428129be 100644 --- a/test-integration/test-chainlink/Cargo.toml +++ b/test-integration/test-chainlink/Cargo.toml @@ -10,6 +10,7 @@ tracing = { workspace = true } magicblock-chainlink = { workspace = true } magicblock-config = { workspace = true } magicblock-delegation-program = { workspace = true } +dlp-api = { workspace = true } program-mini = { workspace = true, features = ["no-entrypoint"] } program-flexi-counter = { workspace = true, features = ["no-entrypoint"] } solana-account = { workspace = true } diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index ad4ac1565..1f6b5c896 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -305,7 +305,7 @@ impl IxtestContext { // In order to make the account undelegatable we first need to // commmit and finalize - let commit_ix = dlp::instruction_builder::commit_state( + let commit_ix = dlp_api::instruction_builder::commit_state( self.validator_kp.pubkey(), counter_pda, program_flexi_counter::id(), @@ -316,11 +316,11 @@ impl IxtestContext { data: vec![0, 1, 0], }, ); - let finalize_ix = dlp::instruction_builder::finalize( + let finalize_ix = dlp_api::instruction_builder::finalize( self.validator_kp.pubkey(), counter_pda, ); - let undelegate_ix = dlp::instruction_builder::undelegate( + let undelegate_ix = dlp_api::instruction_builder::undelegate( self.validator_kp.pubkey(), counter_pda, program_flexi_counter::id(), diff --git a/test-integration/test-committor-service/Cargo.toml b/test-integration/test-committor-service/Cargo.toml index 4d6af1f58..7cd9cd848 100644 --- a/test-integration/test-committor-service/Cargo.toml +++ b/test-integration/test-committor-service/Cargo.toml @@ -17,6 +17,7 @@ magicblock-committor-service = { workspace = true, features = [ magicblock-delegation-program = { workspace = true, features = [ "no-entrypoint", ] } +dlp-api = { workspace = true } magicblock-program = { workspace = true } magicblock-rpc-client = { workspace = true } magicblock-table-mania = { workspace = true, features = [ 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 fd53a00bf..0cf1e792f 100644 --- a/test-integration/test-committor-service/tests/test_intent_executor.rs +++ b/test-integration/test-committor-service/tests/test_intent_executor.rs @@ -955,7 +955,7 @@ async fn test_commit_unfinalized_account_recovery() { // This simulates finalization stage failure { let commit_allow_undelegation_ix = - dlp::instruction_builder::commit_state( + dlp_api::instruction_builder::commit_state( fixture.authority.pubkey(), pda, account.owner, @@ -1037,7 +1037,7 @@ async fn test_commit_unfinalized_account_recovery_two_stage() { // This simulates finalization stage failure { let commit_allow_undelegation_ix = - dlp::instruction_builder::commit_state( + dlp_api::instruction_builder::commit_state( fixture.authority.pubkey(), counters[0].1, counters[0].2.owner, @@ -1169,7 +1169,7 @@ async fn setup_payer_with_keypair( sleep(Duration::from_secs(1)); // Create actor escrow - let ix = dlp::instruction_builder::top_up_ephemeral_balance( + let ix = dlp_api::instruction_builder::top_up_ephemeral_balance( payer.pubkey(), payer.pubkey(), Some(LAMPORTS_PER_SOL / 2), diff --git a/test-integration/test-committor-service/tests/utils/instructions.rs b/test-integration/test-committor-service/tests/utils/instructions.rs index 0fcb37f97..7e4b6585f 100644 --- a/test-integration/test-committor-service/tests/utils/instructions.rs +++ b/test-integration/test-committor-service/tests/utils/instructions.rs @@ -3,7 +3,7 @@ use solana_sdk::{instruction::Instruction, rent::Rent, signature::Keypair}; use test_kit::Signer; pub fn init_validator_fees_vault_ix(validator_auth: Pubkey) -> Instruction { - dlp::instruction_builder::init_validator_fees_vault( + dlp_api::instruction_builder::init_validator_fees_vault( validator_auth, validator_auth, validator_auth, diff --git a/test-integration/test-magicblock-api/Cargo.toml b/test-integration/test-magicblock-api/Cargo.toml index 799034041..b25e99487 100644 --- a/test-integration/test-magicblock-api/Cargo.toml +++ b/test-integration/test-magicblock-api/Cargo.toml @@ -11,6 +11,7 @@ cleanass = { workspace = true } magicblock-api = { workspace = true } magicblock-config = { workspace = true } magicblock-delegation-program = { workspace = true } +dlp-api = { workspace = true } magicblock-program = { path = "../../programs/magicblock" } magicblock-validator-admin = { path = "../../magicblock-validator-admin" } magic-domain-program = { workspace = true } diff --git a/test-integration/test-magicblock-api/tests/test_claim_fees.rs b/test-integration/test-magicblock-api/tests/test_claim_fees.rs index 5b7ffc8a9..20532df60 100644 --- a/test-integration/test-magicblock-api/tests/test_claim_fees.rs +++ b/test-integration/test-magicblock-api/tests/test_claim_fees.rs @@ -1,6 +1,6 @@ use std::{thread::sleep, time::Duration}; -use dlp::instruction_builder::validator_claim_fees; +use dlp_api::instruction_builder::validator_claim_fees; use integration_test_tools::{ loaded_accounts::LoadedAccounts, IntegrationTestContext, }; diff --git a/test-integration/test-schedule-intent/Cargo.toml b/test-integration/test-schedule-intent/Cargo.toml index c2eeb1f20..57d6d1f08 100644 --- a/test-integration/test-schedule-intent/Cargo.toml +++ b/test-integration/test-schedule-intent/Cargo.toml @@ -11,6 +11,7 @@ integration-test-tools = { workspace = true } magicblock-delegation-program = { workspace = true, features = [ "no-entrypoint", ] } +dlp-api = { workspace = true } program-flexi-counter = { workspace = true, features = ["no-entrypoint"] } solana-sdk = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs index fb8406eac..980ee9fe1 100644 --- a/test-integration/test-schedule-intent/tests/test_schedule_intents.rs +++ b/test-integration/test-schedule-intent/tests/test_schedule_intents.rs @@ -514,7 +514,7 @@ fn setup_payer(ctx: &IntegrationTestContext) -> Keypair { .unwrap(); // Create actor escrow - let ix = dlp::instruction_builder::top_up_ephemeral_balance( + let ix = dlp_api::instruction_builder::top_up_ephemeral_balance( payer.pubkey(), payer.pubkey(), Some(LAMPORTS_PER_SOL / 2), diff --git a/test-integration/test-tools/Cargo.toml b/test-integration/test-tools/Cargo.toml index 3bccbbe57..00c8c7a9a 100644 --- a/test-integration/test-tools/Cargo.toml +++ b/test-integration/test-tools/Cargo.toml @@ -18,6 +18,7 @@ magicblock-config = { workspace = true } magicblock-delegation-program = { workspace = true, features = [ "no-entrypoint", ] } +dlp-api = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client = { workspace = true } solana-rpc-client-api = { workspace = true } diff --git a/test-integration/test-tools/src/dlp_interface.rs b/test-integration/test-tools/src/dlp_interface.rs index 139c37ce7..5140c17a7 100644 --- a/test-integration/test-tools/src/dlp_interface.rs +++ b/test-integration/test-tools/src/dlp_interface.rs @@ -19,7 +19,7 @@ pub fn create_topup_ixs( lamports: u64, validator: Option, ) -> Vec { - let topup_ix = dlp::instruction_builder::top_up_ephemeral_balance( + let topup_ix = dlp_api::instruction_builder::top_up_ephemeral_balance( payer, recvr, Some(lamports), @@ -27,7 +27,7 @@ pub fn create_topup_ixs( ); let mut ixs = vec![topup_ix]; if let Some(validator) = validator { - let delegate_ix = dlp::instruction_builder::delegate_ephemeral_balance( + let delegate_ix = dlp_api::instruction_builder::delegate_ephemeral_balance( payer, recvr, DelegateEphemeralBalanceArgs { @@ -49,7 +49,7 @@ pub fn create_delegate_ixs( validator: Option, ) -> Vec { let change_owner_ix = system_instruction::assign(&delegatee, &dlp::id()); - let delegate_ix = dlp::instruction_builder::delegate( + let delegate_ix = dlp_api::instruction_builder::delegate( payer, delegatee, None, @@ -68,7 +68,7 @@ pub fn create_delegate_to_any_ixs( validator: Option, ) -> Vec { let change_owner_ix = system_instruction::assign(&delegatee, &dlp::id()); - let delegate_ix = dlp::instruction_builder::delegate_with_any_validator( + let delegate_ix = dlp_api::instruction_builder::delegate_with_any_validator( payer, delegatee, None, From 7b3ec82c17f5e43cb753766d5d325dc0f52bdc4b Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Sun, 1 Mar 2026 11:56:45 +0530 Subject: [PATCH 04/16] deseriallize, then decrypt using dlp-api, and then deserialize again --- Cargo.lock | 1 + magicblock-api/src/magic_validator.rs | 1 + magicblock-chainlink/Cargo.toml | 1 + .../src/chainlink/fetch_cloner/delegation.rs | 382 +++++++++++++++++- .../src/chainlink/fetch_cloner/mod.rs | 26 +- .../src/chainlink/fetch_cloner/pipeline.rs | 2 +- .../src/chainlink/fetch_cloner/tests.rs | 4 + magicblock-chainlink/src/chainlink/mod.rs | 3 + .../tests/utils/test_context.rs | 1 + test-integration/Cargo.lock | 1 + .../test-chainlink/src/ixtest_context.rs | 1 + .../test-chainlink/src/test_context.rs | 1 + 12 files changed, 413 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e525fb02..bf888640b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3286,6 +3286,7 @@ dependencies = [ "assert_matches", "async-trait", "bincode", + "dlp-api", "futures-util", "helius-laserstream", "lru 0.16.2", diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 249513aa7..0d61aea21 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -462,6 +462,7 @@ impl MagicValidator { &accounts_bank, &cloner, config.validator.keypair.pubkey(), + Some(config.validator.keypair.insecure_clone()), faucet_pubkey, chainlink_config, &config.chainlink, diff --git a/magicblock-chainlink/Cargo.toml b/magicblock-chainlink/Cargo.toml index 24c08fc86..175e5725f 100644 --- a/magicblock-chainlink/Cargo.toml +++ b/magicblock-chainlink/Cargo.toml @@ -18,6 +18,7 @@ parking_lot = { workspace = true } magicblock-magic-program-api = { workspace = true } magicblock-metrics = { workspace = true } magicblock-delegation-program = { workspace = true } +dlp-api = { workspace = true } solana-account = { workspace = true } solana-account-decoder = { workspace = true } solana-account-decoder-client-types = { workspace = true } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index e01ed31fb..f3de78081 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,13 +1,18 @@ use dlp::{ - pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, + args::{MaybeEncryptedIxData, MaybeEncryptedPubkey, PostDelegationActions}, + pda::delegation_record_pda_from_delegated_account, + state::DelegationRecord, }; +use dlp_api::encryption; use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::EATA_PROGRAM_ID; use magicblock_metrics::metrics; use solana_account::ReadableAccount; -use solana_instruction::Instruction; +use solana_instruction::{AccountMeta, Instruction}; +use solana_keypair::Keypair; use solana_program::program_error::ProgramError; use solana_pubkey::Pubkey; +use solana_signer::Signer; use tracing::*; use super::FetchCloner; @@ -20,12 +25,53 @@ use crate::{ }, }; +#[derive(Clone)] +pub(crate) struct ValidatorDecryptionContext { + x25519_pubkey: [u8; encryption::KEY_LEN], + x25519_secret: [u8; encryption::KEY_LEN], +} + +impl ValidatorDecryptionContext { + pub(crate) fn from_validator_keypair( + keypair: &Keypair, + ) -> ChainlinkResult { + let x25519_pubkey = + encryption::ed25519_pubkey_to_x25519(keypair.pubkey().as_array()) + .map_err(|err| { + ChainlinkError::InvalidDelegationActions( + keypair.pubkey(), + format!("Failed to derive validator x25519 pubkey: {err}"), + ) + })?; + + let keypair_bytes = keypair.to_bytes(); + let x25519_secret = + encryption::ed25519_secret_to_x25519(&keypair_bytes).map_err( + |err| { + ChainlinkError::InvalidDelegationActions( + keypair.pubkey(), + format!( + "Failed to derive validator x25519 secret key: {err}" + ), + ) + }, + )?; + + Ok(Self { + x25519_pubkey, + x25519_secret, + }) + } +} + /// Parses a delegation record from account data bytes. /// Returns the parsed DelegationRecord, or InvalidDelegationRecord error /// if parsing fails. pub(crate) fn parse_delegation_record( data: &[u8], delegation_record_pubkey: Pubkey, + validator_pubkey: Pubkey, + decryption_ctx: Option<&ValidatorDecryptionContext>, ) -> ChainlinkResult<(DelegationRecord, Option)> { let delegation_record_size = DelegationRecord::size_with_discriminator(); if data.len() < delegation_record_size { @@ -49,16 +95,176 @@ pub(crate) fn parse_delegation_record( if data.len() <= delegation_record_size { Ok((record, None)) } else { + // Actions for accounts delegated to other validators are not relevant + // for this node and may be encrypted for a different recipient. + if record.authority != validator_pubkey + && record.authority != Pubkey::default() + { + return Ok((record, None)); + } + let actions_data = &data[delegation_record_size..]; - let actions = bincode::deserialize::>(actions_data) - .map_err(|err| { + let actions = parse_post_delegation_actions( + actions_data, + delegation_record_pubkey, + decryption_ctx, + )?; + Ok((record, Some(actions))) + } +} + +fn parse_post_delegation_actions( + actions_data: &[u8], + delegation_record_pubkey: Pubkey, + decryption_ctx: Option<&ValidatorDecryptionContext>, +) -> ChainlinkResult { + let actions: PostDelegationActions = + bincode::deserialize(actions_data).map_err(|err| { + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + format!("Failed to deserialize PostDelegationActions: {err}"), + ) + })?; + + let mut pubkeys = actions.signers; + for non_signer in actions.non_signers { + pubkeys.push(decrypt_pubkey( + non_signer, + delegation_record_pubkey, + decryption_ctx, + )?); + } + + let instructions = actions + .instructions + .into_iter() + .map(|ix| { + let program_id = pubkeys.get(ix.program_id as usize).copied().ok_or( + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + format!( + "Invalid program_id index {} for pubkey table len {}", + ix.program_id, + pubkeys.len() + ), + ), + )?; + + let accounts = ix + .accounts + .into_iter() + .map(|compact_meta| { + let account_pubkey = pubkeys + .get(compact_meta.key() as usize) + .copied() + .ok_or(ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + format!( + "Invalid account index {} for pubkey table len {}", + compact_meta.key(), + pubkeys.len() + ), + ))?; + + Ok(AccountMeta { + pubkey: account_pubkey, + is_signer: compact_meta.is_signer(), + is_writable: compact_meta.is_writable(), + }) + }) + .collect::>>()?; + + let data = decrypt_ix_data( + ix.data, + delegation_record_pubkey, + decryption_ctx, + )?; + + Ok(Instruction { + program_id, + accounts, + data, + }) + }) + .collect::>>()?; + + Ok(instructions.into()) +} + +fn decrypt_pubkey( + maybe_encrypted_pubkey: MaybeEncryptedPubkey, + delegation_record_pubkey: Pubkey, + decryption_ctx: Option<&ValidatorDecryptionContext>, +) -> ChainlinkResult { + match maybe_encrypted_pubkey { + MaybeEncryptedPubkey::ClearText(pubkey) => Ok(pubkey), + MaybeEncryptedPubkey::Encrypted(buffer) => { + let plaintext = decrypt_buffer( + buffer.as_bytes(), + delegation_record_pubkey, + decryption_ctx, + "pubkey", + )?; + Pubkey::try_from(plaintext.as_slice()).map_err(|_| { ChainlinkError::InvalidDelegationActions( delegation_record_pubkey, - err.to_string(), + format!( + "Decrypted pubkey has invalid length: {}", + plaintext.len() + ), ) - })?; - Ok((record, Some(actions.into()))) + }) + } + } +} + +fn decrypt_ix_data( + maybe_encrypted_ix_data: MaybeEncryptedIxData, + delegation_record_pubkey: Pubkey, + decryption_ctx: Option<&ValidatorDecryptionContext>, +) -> ChainlinkResult> { + let mut data = maybe_encrypted_ix_data.prefix; + let encrypted_suffix = maybe_encrypted_ix_data.suffix.into_inner(); + + if !encrypted_suffix.is_empty() { + let suffix = decrypt_buffer( + &encrypted_suffix, + delegation_record_pubkey, + decryption_ctx, + "ix data suffix", + )?; + data.extend_from_slice(&suffix); } + + Ok(data) +} + +fn decrypt_buffer( + encrypted: &[u8], + delegation_record_pubkey: Pubkey, + decryption_ctx: Option<&ValidatorDecryptionContext>, + field_label: &str, +) -> ChainlinkResult> { + let Some(decryption_ctx) = decryption_ctx else { + return Err(ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + format!( + "Encrypted {field_label} present but validator decryption context is unavailable" + ), + )); + }; + + encryption::decrypt( + encrypted, + &decryption_ctx.x25519_pubkey, + &decryption_ctx.x25519_secret, + ) + .map_err(|err| { + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + format!("Failed to decrypt {field_label}: {err}"), + ) + }) } pub(crate) fn apply_delegation_record_to_account( @@ -145,7 +351,7 @@ where if let Some(delegation_record_remote) = delegation_records.pop() { match delegation_record_remote.fresh_account() { Some(delegation_record_account) => { - FetchCloner::::parse_delegation_record( + this.parse_delegation_record( delegation_record_account.data(), delegation_record_pubkey, ) @@ -181,3 +387,163 @@ where res } + +#[cfg(test)] +mod tests { + use dlp::args::{ + EncryptedBuffer, MaybeEncryptedInstruction, MaybeEncryptedIxData, + MaybeEncryptedPubkey, PostDelegationActions, + }; + use solana_program::pubkey::Pubkey; + + use super::*; + + fn serialize_record_with_actions(actions: PostDelegationActions) -> Vec { + let record = DelegationRecord { + owner: Pubkey::new_unique(), + authority: Pubkey::new_unique(), + commit_frequency_ms: 1000, + delegation_slot: 1, + lamports: 1_000_000, + }; + + let mut data = vec![0; DelegationRecord::size_with_discriminator()]; + record.to_bytes_with_discriminator(&mut data).unwrap(); + data.extend_from_slice(&bincode::serialize(&actions).unwrap()); + data + } + + #[test] + fn parses_post_delegation_actions_cleartext() { + let signer = Pubkey::new_unique(); + let program_id = Pubkey::new_unique(); + let account = Pubkey::new_unique(); + + let payload = serialize_record_with_actions(PostDelegationActions { + signers: vec![signer], + non_signers: vec![ + MaybeEncryptedPubkey::ClearText(program_id), + MaybeEncryptedPubkey::ClearText(account), + ], + instructions: vec![MaybeEncryptedInstruction { + program_id: 1, + accounts: vec![ + dlp::compact::AccountMeta::new_readonly(0, true), + dlp::compact::AccountMeta::new(2, false), + ], + data: MaybeEncryptedIxData { + prefix: vec![7, 8, 9], + suffix: EncryptedBuffer::default(), + }, + }], + }); + + let (_, actions) = parse_delegation_record( + &payload, + Pubkey::new_unique(), + Pubkey::new_unique(), + None, + ) + .unwrap(); + + let actions: Vec = actions.unwrap().into(); + assert_eq!(actions.len(), 1); + assert_eq!(actions[0].program_id, program_id); + assert_eq!(actions[0].accounts.len(), 2); + assert_eq!(actions[0].accounts[0].pubkey, signer); + assert!(actions[0].accounts[0].is_signer); + assert!(!actions[0].accounts[0].is_writable); + assert_eq!(actions[0].accounts[1].pubkey, account); + assert!(!actions[0].accounts[1].is_signer); + assert!(actions[0].accounts[1].is_writable); + assert_eq!(actions[0].data, vec![7, 8, 9]); + } + + #[test] + fn decrypts_encrypted_post_delegation_actions() { + let validator = Keypair::new(); + let decryption_ctx = + ValidatorDecryptionContext::from_validator_keypair(&validator) + .unwrap(); + + let signer = Pubkey::new_unique(); + let program_id = Pubkey::new_unique(); + let account = Pubkey::new_unique(); + + let encrypted_program_id = dlp_api::encryption::encrypt_ed25519_recipient( + program_id.as_array(), + validator.pubkey().as_array(), + ) + .unwrap(); + let encrypted_suffix = dlp_api::encryption::encrypt_ed25519_recipient( + &[3, 4, 5], + validator.pubkey().as_array(), + ) + .unwrap(); + + let payload = serialize_record_with_actions(PostDelegationActions { + signers: vec![signer], + non_signers: vec![ + MaybeEncryptedPubkey::Encrypted(EncryptedBuffer::new( + encrypted_program_id, + )), + MaybeEncryptedPubkey::ClearText(account), + ], + instructions: vec![MaybeEncryptedInstruction { + program_id: 1, + accounts: vec![ + dlp::compact::AccountMeta::new_readonly(0, true), + dlp::compact::AccountMeta::new(2, false), + ], + data: MaybeEncryptedIxData { + prefix: vec![1, 2], + suffix: EncryptedBuffer::new(encrypted_suffix), + }, + }], + }); + + let (_, actions) = parse_delegation_record( + &payload, + Pubkey::new_unique(), + validator.pubkey(), + Some(&decryption_ctx), + ) + .unwrap(); + + let actions: Vec = actions.unwrap().into(); + assert_eq!(actions[0].program_id, program_id); + assert_eq!(actions[0].accounts[0].pubkey, signer); + assert_eq!(actions[0].accounts[1].pubkey, account); + assert_eq!(actions[0].data, vec![1, 2, 3, 4, 5]); + } + + #[test] + fn fails_when_encrypted_actions_have_no_decryption_context() { + let validator = Keypair::new(); + let encrypted_program_id = dlp_api::encryption::encrypt_ed25519_recipient( + Pubkey::new_unique().as_array(), + validator.pubkey().as_array(), + ) + .unwrap(); + + let payload = serialize_record_with_actions(PostDelegationActions { + signers: vec![], + non_signers: vec![MaybeEncryptedPubkey::Encrypted( + EncryptedBuffer::new(encrypted_program_id), + )], + instructions: vec![], + }); + + let err = parse_delegation_record( + &payload, + Pubkey::new_unique(), + validator.pubkey(), + None, + ) + .unwrap_err(); + assert!(matches!( + err, + ChainlinkError::InvalidDelegationActions(_, _) + )); + } +} diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 947cdbe50..00262fdd4 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -19,6 +19,7 @@ use magicblock_core::token_programs::{ use magicblock_metrics::metrics::{self, AccountFetchOrigin}; use scc::{hash_map::Entry, HashMap}; use solana_account::{AccountSharedData, ReadableAccount}; +use solana_keypair::Keypair; use solana_pubkey::Pubkey; use solana_sdk_ids::system_program; use tokio::{ @@ -37,6 +38,7 @@ mod types; pub use self::types::FetchAndCloneResult; use self::{ + delegation::ValidatorDecryptionContext, subscription::{cancel_subs, CancelStrategy}, types::{ AccountWithCompanion, ClassifiedAccounts, ExistingSubs, @@ -83,6 +85,7 @@ where accounts_bank: Arc, cloner: Arc, validator_pubkey: Pubkey, + validator_decryption_ctx: Option, /// These are accounts that we should never clone into our validator. /// native programs, sysvars, native tokens, validator identity and faucet @@ -106,6 +109,7 @@ where accounts_bank: &Arc, cloner: &Arc, validator_pubkey: Pubkey, + validator_keypair: Option, faucet_pubkey: Pubkey, subscription_updates_rx: mpsc::Receiver, allowed_programs: Option>, @@ -115,11 +119,23 @@ where let allowed_programs = allowed_programs.map(|programs| { programs.iter().map(|p| p.id).collect::>() }); + let validator_decryption_ctx = validator_keypair.as_ref().and_then( + |keypair| match ValidatorDecryptionContext::from_validator_keypair( + keypair, + ) { + Ok(ctx) => Some(ctx), + Err(err) => { + error!(error = %err, "Failed to initialize action decryption context"); + None + } + }, + ); let me = Arc::new(Self { remote_account_provider: remote_account_provider.clone(), accounts_bank: accounts_bank.clone(), cloner: cloner.clone(), validator_pubkey, + validator_decryption_ctx, pending_requests: Arc::new(HashMap::new()), fetch_count: Arc::new(AtomicU64::new(0)), blacklisted_accounts, @@ -385,7 +401,7 @@ where delegation_record { let delegation_record_with_actions = - match delegation::parse_delegation_record( + match self.parse_delegation_record( delegation_record.data(), delegation_record_pubkey, ) { @@ -680,10 +696,16 @@ where /// Returns the parsed DelegationRecord, or InvalidDelegationRecord error /// if parsing fails. fn parse_delegation_record( + &self, data: &[u8], delegation_record_pubkey: Pubkey, ) -> ChainlinkResult<(DelegationRecord, Option)> { - delegation::parse_delegation_record(data, delegation_record_pubkey) + delegation::parse_delegation_record( + data, + delegation_record_pubkey, + self.validator_pubkey, + self.validator_decryption_ctx.as_ref(), + ) } /// Applies delegation record settings to an account: sets the owner, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 9efc2664e..460998d47 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -303,7 +303,7 @@ where // However we may consider a different behavior when user is getting // multiple accounts. let (delegation_record, delegation_actions) = - match FetchCloner::::parse_delegation_record( + match this.parse_delegation_record( delegation_record_data.data(), delegation_record_pubkey, ) { diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index 8dcb206fb..173712793 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -185,6 +185,7 @@ fn init_fetch_cloner( bank, &cloner, validator_pubkey, + None, faucet_pubkey, subscription_rx, None, @@ -1681,6 +1682,7 @@ async fn test_allowed_programs_filters_programs() { &accounts_bank, &cloner, validator_pubkey, + None, random_pubkey(), subscription_rx, allowed_programs, @@ -1749,6 +1751,7 @@ async fn test_allowed_programs_none_allows_all() { &accounts_bank, &cloner, validator_pubkey, + None, random_pubkey(), subscription_rx, None, // No restriction @@ -1816,6 +1819,7 @@ async fn test_allowed_programs_empty_allows_all() { &accounts_bank, &cloner, validator_pubkey, + None, random_pubkey(), subscription_rx, allowed_programs, diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index e537aab02..c62b4fd4b 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -15,6 +15,7 @@ use magicblock_metrics::metrics::AccountFetchOrigin; use solana_account::{AccountSharedData, ReadableAccount}; use solana_commitment_config::CommitmentConfig; use solana_feature_set; +use solana_keypair::Keypair; use solana_pubkey::Pubkey; use solana_transaction::sanitized::SanitizedTransaction; use tokio::{sync::mpsc, task}; @@ -113,6 +114,7 @@ impl accounts_bank: &Arc, cloner: &Arc, validator_pubkey: Pubkey, + validator_keypair: Option, faucet_pubkey: Pubkey, config: ChainlinkConfig, chainlink_config: &ChainLinkConfig, @@ -136,6 +138,7 @@ impl accounts_bank, cloner, validator_pubkey, + validator_keypair, faucet_pubkey, rx, chainlink_config.allowed_programs.clone(), diff --git a/magicblock-chainlink/tests/utils/test_context.rs b/magicblock-chainlink/tests/utils/test_context.rs index 206d9efe9..bf1075e97 100644 --- a/magicblock-chainlink/tests/utils/test_context.rs +++ b/magicblock-chainlink/tests/utils/test_context.rs @@ -96,6 +96,7 @@ impl TestContext { &bank, &cloner, validator_pubkey, + None, faucet_pubkey, rx, None, diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 56e43e968..13e583b1e 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -3608,6 +3608,7 @@ dependencies = [ "arc-swap", "async-trait", "bincode", + "dlp-api", "futures-util", "helius-laserstream", "lru", diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index 1f6b5c896..e35bb7cdc 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -126,6 +126,7 @@ impl IxtestContext { &bank, &cloner, validator_kp.pubkey(), + None, faucet_kp.pubkey(), rx, None, diff --git a/test-integration/test-chainlink/src/test_context.rs b/test-integration/test-chainlink/src/test_context.rs index af839f405..79c8ed79f 100644 --- a/test-integration/test-chainlink/src/test_context.rs +++ b/test-integration/test-chainlink/src/test_context.rs @@ -99,6 +99,7 @@ impl TestContext { &bank, &cloner, validator_pubkey, + None, faucet_pubkey, rx, None, From 30d45fc68fe42236208789459a8dce0baae9c502 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Sun, 1 Mar 2026 13:49:54 +0530 Subject: [PATCH 05/16] ensure accounts exist --- magicblock-chainlink/src/chainlink/errors.rs | 3 + .../src/chainlink/fetch_cloner/delegation.rs | 105 ++++++++------ .../src/chainlink/fetch_cloner/mod.rs | 135 ++++++++++++++++-- .../src/chainlink/fetch_cloner/pipeline.rs | 15 ++ 4 files changed, 204 insertions(+), 54 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/errors.rs b/magicblock-chainlink/src/chainlink/errors.rs index ef2832dda..7e96e5f20 100644 --- a/magicblock-chainlink/src/chainlink/errors.rs +++ b/magicblock-chainlink/src/chainlink/errors.rs @@ -43,4 +43,7 @@ pub enum ChainlinkError { #[error("Unexpected number of accounts returned when fetching account with companion: {0}")] UnexpectedAccountCount(String), + + #[error("Missing accounts required by delegation actions: {0:?}")] + MissingDelegationActionAccounts(Vec), } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index f3de78081..59a27e38b 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -398,10 +398,13 @@ mod tests { use super::*; - fn serialize_record_with_actions(actions: PostDelegationActions) -> Vec { + fn serialize_record_with_actions( + authority: Pubkey, + actions: PostDelegationActions, + ) -> Vec { let record = DelegationRecord { owner: Pubkey::new_unique(), - authority: Pubkey::new_unique(), + authority, commit_frequency_ms: 1000, delegation_slot: 1, lamports: 1_000_000, @@ -419,29 +422,33 @@ mod tests { let program_id = Pubkey::new_unique(); let account = Pubkey::new_unique(); - let payload = serialize_record_with_actions(PostDelegationActions { - signers: vec![signer], - non_signers: vec![ - MaybeEncryptedPubkey::ClearText(program_id), - MaybeEncryptedPubkey::ClearText(account), - ], - instructions: vec![MaybeEncryptedInstruction { - program_id: 1, - accounts: vec![ - dlp::compact::AccountMeta::new_readonly(0, true), - dlp::compact::AccountMeta::new(2, false), + let validator_pubkey = Pubkey::new_unique(); + let payload = serialize_record_with_actions( + validator_pubkey, + PostDelegationActions { + signers: vec![signer], + non_signers: vec![ + MaybeEncryptedPubkey::ClearText(program_id), + MaybeEncryptedPubkey::ClearText(account), ], - data: MaybeEncryptedIxData { - prefix: vec![7, 8, 9], - suffix: EncryptedBuffer::default(), - }, - }], - }); + instructions: vec![MaybeEncryptedInstruction { + program_id: 1, + accounts: vec![ + dlp::compact::AccountMeta::new_readonly(0, true), + dlp::compact::AccountMeta::new(2, false), + ], + data: MaybeEncryptedIxData { + prefix: vec![7, 8, 9], + suffix: EncryptedBuffer::default(), + }, + }], + }, + ); let (_, actions) = parse_delegation_record( &payload, Pubkey::new_unique(), - Pubkey::new_unique(), + validator_pubkey, None, ) .unwrap(); @@ -481,26 +488,29 @@ mod tests { ) .unwrap(); - let payload = serialize_record_with_actions(PostDelegationActions { - signers: vec![signer], - non_signers: vec![ - MaybeEncryptedPubkey::Encrypted(EncryptedBuffer::new( - encrypted_program_id, - )), - MaybeEncryptedPubkey::ClearText(account), - ], - instructions: vec![MaybeEncryptedInstruction { - program_id: 1, - accounts: vec![ - dlp::compact::AccountMeta::new_readonly(0, true), - dlp::compact::AccountMeta::new(2, false), + let payload = serialize_record_with_actions( + validator.pubkey(), + PostDelegationActions { + signers: vec![signer], + non_signers: vec![ + MaybeEncryptedPubkey::Encrypted(EncryptedBuffer::new( + encrypted_program_id, + )), + MaybeEncryptedPubkey::ClearText(account), ], - data: MaybeEncryptedIxData { - prefix: vec![1, 2], - suffix: EncryptedBuffer::new(encrypted_suffix), - }, - }], - }); + instructions: vec![MaybeEncryptedInstruction { + program_id: 1, + accounts: vec![ + dlp::compact::AccountMeta::new_readonly(0, true), + dlp::compact::AccountMeta::new(2, false), + ], + data: MaybeEncryptedIxData { + prefix: vec![1, 2], + suffix: EncryptedBuffer::new(encrypted_suffix), + }, + }], + }, + ); let (_, actions) = parse_delegation_record( &payload, @@ -526,13 +536,16 @@ mod tests { ) .unwrap(); - let payload = serialize_record_with_actions(PostDelegationActions { - signers: vec![], - non_signers: vec![MaybeEncryptedPubkey::Encrypted( - EncryptedBuffer::new(encrypted_program_id), - )], - instructions: vec![], - }); + let payload = serialize_record_with_actions( + validator.pubkey(), + PostDelegationActions { + signers: vec![], + non_signers: vec![MaybeEncryptedPubkey::Encrypted( + EncryptedBuffer::new(encrypted_program_id), + )], + instructions: vec![], + }, + ); let err = parse_delegation_record( &payload, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 00262fdd4..258c44cb8 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -41,9 +41,8 @@ use self::{ delegation::ValidatorDecryptionContext, subscription::{cancel_subs, CancelStrategy}, types::{ - AccountWithCompanion, ClassifiedAccounts, ExistingSubs, - PartitionedNotFound, RefreshDecision, ResolvedDelegatedAccounts, - ResolvedPrograms, + AccountWithCompanion, ClassifiedAccounts, PartitionedNotFound, + RefreshDecision, ResolvedDelegatedAccounts, ResolvedPrograms, }, }; use super::errors::{ChainlinkError, ChainlinkResult}; @@ -779,8 +778,8 @@ where // We keep all existing subscriptions including delegation records and program data // accounts that were directly requested - let ExistingSubs { existing_subs } = - pipeline::build_existing_subs(self, pubkeys); + let mut existing_subs = + pipeline::build_existing_subs(self, pubkeys).existing_subs; // Track all new subscriptions created during this call let mut new_subs: HashSet = HashSet::new(); @@ -880,7 +879,7 @@ where // For potentially delegated accounts we update the owner and delegation state first let ResolvedDelegatedAccounts { mut accounts_to_clone, - record_subs, + mut record_subs, missing_delegation_record, } = pipeline::resolve_delegated_accounts( self, @@ -898,7 +897,7 @@ where let ResolvedPrograms { loaded_programs, - program_data_subs, + mut program_data_subs, } = pipeline::resolve_programs_with_program_data( self, programs, @@ -912,6 +911,9 @@ where // Track program data account subscriptions new_subs.extend(program_data_subs.iter().copied()); + let mut loaded_programs = loaded_programs; + let mut all_requested_pubkeys = pubkeys.to_vec(); + // We will compute subscription cancellations after ATA handling, once accounts_to_clone is finalized // Handle ATAs: for each detected ATA, we derive the eATA PDA, subscribe to both, @@ -928,9 +930,126 @@ where .await; accounts_to_clone.extend(ata_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 = + pipeline::collect_delegation_action_dependencies(&accounts_to_clone); + let action_dependencies_to_fetch = action_dependencies + .into_iter() + .filter(|dependency| { + self.accounts_bank.get_account(dependency).is_none() + && !accounts_to_clone + .iter() + .any(|request| request.pubkey.eq(dependency)) + && !loaded_programs + .iter() + .any(|program| program.program_id.eq(dependency)) + }) + .collect::>(); + + if !action_dependencies_to_fetch.is_empty() { + if tracing::enabled!(tracing::Level::TRACE) { + trace!( + dependencies = ?action_dependencies_to_fetch, + "Ensuring delegation action dependencies" + ); + } + + existing_subs.extend( + action_dependencies_to_fetch + .iter() + .filter(|dependency| self.is_watching(dependency)) + .copied(), + ); + + self.fetch_count.fetch_add( + action_dependencies_to_fetch.len() as u64, + Ordering::Relaxed, + ); + let action_dep_accs = self + .remote_account_provider + .try_get_multi( + &action_dependencies_to_fetch, + None, + fetch_origin, + None, + ) + .await?; + new_subs.extend(action_dependencies_to_fetch.iter().copied()); + + let ClassifiedAccounts { + not_found, + plain, + owned_by_deleg, + programs, + atas, + } = pipeline::classify_remote_accounts( + action_dep_accs, + &action_dependencies_to_fetch, + ); + + if !not_found.is_empty() { + return Err(ChainlinkError::MissingDelegationActionAccounts( + not_found.iter().map(|(pubkey, _)| *pubkey).collect(), + )); + } + if !atas.is_empty() { + return Err(ChainlinkError::MissingDelegationActionAccounts( + atas.iter().map(|(pubkey, _, _, _)| *pubkey).collect(), + )); + } + + let ResolvedDelegatedAccounts { + accounts_to_clone: action_dep_accounts_to_clone, + record_subs: action_dep_record_subs, + missing_delegation_record: action_dep_missing_delegation_record, + } = pipeline::resolve_delegated_accounts( + self, + owned_by_deleg, + plain, + min_context_slot, + fetch_origin, + &action_dependencies_to_fetch, + existing_subs.clone(), + ) + .await?; + + if !action_dep_missing_delegation_record.is_empty() { + return Err(ChainlinkError::MissingDelegationActionAccounts( + action_dep_missing_delegation_record + .iter() + .map(|(pubkey, _)| *pubkey) + .collect(), + )); + } + + new_subs.extend(action_dep_record_subs.iter().copied()); + record_subs.extend(action_dep_record_subs); + + let ResolvedPrograms { + loaded_programs: action_dep_loaded_programs, + program_data_subs: action_dep_program_data_subs, + } = pipeline::resolve_programs_with_program_data( + self, + programs, + min_context_slot, + fetch_origin, + &action_dependencies_to_fetch, + existing_subs.clone(), + ) + .await?; + + new_subs.extend(action_dep_program_data_subs.iter().copied()); + program_data_subs.extend(action_dep_program_data_subs); + + accounts_to_clone.extend(action_dep_accounts_to_clone); + loaded_programs.extend(action_dep_loaded_programs); + all_requested_pubkeys.extend(action_dependencies_to_fetch); + } + // Compute sub cancellations now since we may potentially fail during a cloning step let cancel_strategy = pipeline::compute_cancel_strategy( - pubkeys, + &all_requested_pubkeys, &accounts_to_clone, &loaded_programs, record_subs, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs index 460998d47..09759021d 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/pipeline.rs @@ -62,6 +62,21 @@ where ExistingSubs { existing_subs } } +pub(crate) fn collect_delegation_action_dependencies( + accounts_to_clone: &[AccountCloneRequest], +) -> HashSet { + let mut dependencies = HashSet::new(); + for request in accounts_to_clone { + for instruction in request.delegation_actions.iter() { + dependencies.insert(instruction.program_id); + for account_meta in &instruction.accounts { + dependencies.insert(account_meta.pubkey); + } + } + } + dependencies +} + /// Classifies fetched remote accounts into categories pub(crate) fn classify_remote_accounts( accs: Vec, From b0163a804b7a3ba821aa43eeb02d3a70e1af4db1 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Mon, 2 Mar 2026 17:33:28 +0530 Subject: [PATCH 06/16] add send_sanitized_transaction and related changes --- magicblock-account-cloner/src/lib.rs | 28 ++++++++- .../src/chainlink/fetch_cloner/delegation.rs | 59 +++++++++++++------ 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/magicblock-account-cloner/src/lib.rs b/magicblock-account-cloner/src/lib.rs index 590130e4d..668475564 100644 --- a/magicblock-account-cloner/src/lib.rs +++ b/magicblock-account-cloner/src/lib.rs @@ -19,7 +19,9 @@ use magicblock_committor_service::{ BaseIntentCommittor, CommittorService, }; use magicblock_config::config::ChainLinkConfig; -use magicblock_core::link::transactions::TransactionSchedulerHandle; +use magicblock_core::link::transactions::{ + SanitizeableTransaction, TransactionSchedulerHandle, +}; use magicblock_ledger::LatestBlock; use magicblock_magic_program_api::instruction::AccountModification; use magicblock_program::{ @@ -38,7 +40,7 @@ use solana_sdk_ids::loader_v4; use solana_signature::Signature; use solana_signer::{Signer, SignerError}; use solana_sysvar::rent::Rent; -use solana_transaction::Transaction; +use solana_transaction::{sanitized::SanitizedTransaction, Transaction}; use tokio::sync::oneshot; use tracing::*; @@ -84,6 +86,15 @@ impl ChainlinkCloner { Ok(sig) } + async fn send_sanitized_transaction( + &self, + tx: SanitizedTransaction, + sig: Signature, + ) -> ClonerResult { + self.tx_scheduler.execute(tx).await?; + Ok(sig) + } + fn build_clone_message(request: &AccountCloneRequest) -> Option { if request.account.delegated() { // Account is delegated to us @@ -410,13 +421,24 @@ impl Cloner for ChainlinkCloner { let recent_blockhash = self.block.load().blockhash; let tx = self .transaction_to_clone_regular_account(&request, recent_blockhash)?; + let bypass_sigverify_for_replay_actions = + !request.delegation_actions.is_empty(); + let sig = tx.signatures[0]; + + let send_res = if bypass_sigverify_for_replay_actions { + let sanitized_tx = tx.sanitize(false)?; + self.send_sanitized_transaction(sanitized_tx, sig).await + } else { + self.send_transaction(tx).await + }; + if request.account.delegated() { self.maybe_prepare_lookup_tables( request.pubkey, *request.account.owner(), ); } - self.send_transaction(tx).await.map_err(|err| { + send_res.map_err(|err| { ClonerError::FailedToCloneRegularAccount( request.pubkey, Box::new(err), diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 59a27e38b..52cf08727 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,5 +1,8 @@ use dlp::{ - args::{MaybeEncryptedIxData, MaybeEncryptedPubkey, PostDelegationActions}, + args::{ + MaybeEncryptedAccountMeta, MaybeEncryptedIxData, MaybeEncryptedPubkey, + PostDelegationActions, + }, pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; @@ -128,7 +131,7 @@ fn parse_post_delegation_actions( let mut pubkeys = actions.signers; for non_signer in actions.non_signers { - pubkeys.push(decrypt_pubkey( + pubkeys.push(decrypt_non_signer_pubkey( non_signer, delegation_record_pubkey, decryption_ctx, @@ -218,6 +221,30 @@ fn decrypt_pubkey( } } +fn decrypt_non_signer_pubkey( + non_signer: MaybeEncryptedAccountMeta, + delegation_record_pubkey: Pubkey, + decryption_ctx: Option<&ValidatorDecryptionContext>, +) -> ChainlinkResult { + match non_signer { + MaybeEncryptedAccountMeta::Encrypted(buffer) => { + decrypt_pubkey( + MaybeEncryptedPubkey::Encrypted(buffer), + delegation_record_pubkey, + decryption_ctx, + ) + } + // Clear-text non-signer payload only carries compact flags/index, not + // the pubkey bytes, so we cannot reconstruct a full instruction. + MaybeEncryptedAccountMeta::ClearText(_meta) => Err( + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + "Clear-text non-signer account metadata is unsupported for replay".to_string(), + ), + ), + } +} + fn decrypt_ix_data( maybe_encrypted_ix_data: MaybeEncryptedIxData, delegation_record_pubkey: Pubkey, @@ -391,8 +418,8 @@ where #[cfg(test)] mod tests { use dlp::args::{ - EncryptedBuffer, MaybeEncryptedInstruction, MaybeEncryptedIxData, - MaybeEncryptedPubkey, PostDelegationActions, + EncryptedBuffer, MaybeEncryptedAccountMeta, MaybeEncryptedInstruction, + MaybeEncryptedIxData, PostDelegationActions, }; use solana_program::pubkey::Pubkey; @@ -426,11 +453,8 @@ mod tests { let payload = serialize_record_with_actions( validator_pubkey, PostDelegationActions { - signers: vec![signer], - non_signers: vec![ - MaybeEncryptedPubkey::ClearText(program_id), - MaybeEncryptedPubkey::ClearText(account), - ], + signers: vec![signer, program_id, account], + non_signers: vec![], instructions: vec![MaybeEncryptedInstruction { program_id: 1, accounts: vec![ @@ -491,18 +515,15 @@ mod tests { let payload = serialize_record_with_actions( validator.pubkey(), PostDelegationActions { - signers: vec![signer], - non_signers: vec![ - MaybeEncryptedPubkey::Encrypted(EncryptedBuffer::new( - encrypted_program_id, - )), - MaybeEncryptedPubkey::ClearText(account), - ], + signers: vec![signer, account], + non_signers: vec![MaybeEncryptedAccountMeta::Encrypted( + EncryptedBuffer::new(encrypted_program_id), + )], instructions: vec![MaybeEncryptedInstruction { - program_id: 1, + program_id: 2, accounts: vec![ dlp::compact::AccountMeta::new_readonly(0, true), - dlp::compact::AccountMeta::new(2, false), + dlp::compact::AccountMeta::new(1, false), ], data: MaybeEncryptedIxData { prefix: vec![1, 2], @@ -540,7 +561,7 @@ mod tests { validator.pubkey(), PostDelegationActions { signers: vec![], - non_signers: vec![MaybeEncryptedPubkey::Encrypted( + non_signers: vec![MaybeEncryptedAccountMeta::Encrypted( EncryptedBuffer::new(encrypted_program_id), )], instructions: vec![], From 102b6a88d1ece164386131de0093935b5bf71f6f Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 3 Mar 2026 00:02:08 +0530 Subject: [PATCH 07/16] use decrypt from dlp-api --- .../src/chainlink/fetch_cloner/delegation.rs | 276 +++--------------- .../src/chainlink/fetch_cloner/mod.rs | 19 +- 2 files changed, 43 insertions(+), 252 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 52cf08727..39f718004 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,12 +1,11 @@ use dlp::{ args::{ - MaybeEncryptedAccountMeta, MaybeEncryptedIxData, MaybeEncryptedPubkey, - PostDelegationActions, + MaybeEncryptedAccountMeta, MaybeEncryptedPubkey, PostDelegationActions, }, pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; -use dlp_api::encryption; +use dlp_api::decrypt::Decrypt; use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::EATA_PROGRAM_ID; use magicblock_metrics::metrics; @@ -15,7 +14,6 @@ use solana_instruction::{AccountMeta, Instruction}; use solana_keypair::Keypair; use solana_program::program_error::ProgramError; use solana_pubkey::Pubkey; -use solana_signer::Signer; use tracing::*; use super::FetchCloner; @@ -28,45 +26,6 @@ use crate::{ }, }; -#[derive(Clone)] -pub(crate) struct ValidatorDecryptionContext { - x25519_pubkey: [u8; encryption::KEY_LEN], - x25519_secret: [u8; encryption::KEY_LEN], -} - -impl ValidatorDecryptionContext { - pub(crate) fn from_validator_keypair( - keypair: &Keypair, - ) -> ChainlinkResult { - let x25519_pubkey = - encryption::ed25519_pubkey_to_x25519(keypair.pubkey().as_array()) - .map_err(|err| { - ChainlinkError::InvalidDelegationActions( - keypair.pubkey(), - format!("Failed to derive validator x25519 pubkey: {err}"), - ) - })?; - - let keypair_bytes = keypair.to_bytes(); - let x25519_secret = - encryption::ed25519_secret_to_x25519(&keypair_bytes).map_err( - |err| { - ChainlinkError::InvalidDelegationActions( - keypair.pubkey(), - format!( - "Failed to derive validator x25519 secret key: {err}" - ), - ) - }, - )?; - - Ok(Self { - x25519_pubkey, - x25519_secret, - }) - } -} - /// Parses a delegation record from account data bytes. /// Returns the parsed DelegationRecord, or InvalidDelegationRecord error /// if parsing fails. @@ -74,7 +33,7 @@ pub(crate) fn parse_delegation_record( data: &[u8], delegation_record_pubkey: Pubkey, validator_pubkey: Pubkey, - decryption_ctx: Option<&ValidatorDecryptionContext>, + validator_keypair: Option<&Keypair>, ) -> ChainlinkResult<(DelegationRecord, Option)> { let delegation_record_size = DelegationRecord::size_with_discriminator(); if data.len() < delegation_record_size { @@ -83,17 +42,13 @@ pub(crate) fn parse_delegation_record( ProgramError::InvalidAccountData, )); } - let record = - DelegationRecord::try_from_bytes_with_discriminator( - &data[..delegation_record_size], - ) - .copied() - .map_err(|err| { - ChainlinkError::InvalidDelegationRecord( - delegation_record_pubkey, - err, - ) - })?; + let record = DelegationRecord::try_from_bytes_with_discriminator( + &data[..delegation_record_size], + ) + .copied() + .map_err(|err| { + ChainlinkError::InvalidDelegationRecord(delegation_record_pubkey, err) + })?; if data.len() <= delegation_record_size { Ok((record, None)) @@ -110,7 +65,7 @@ pub(crate) fn parse_delegation_record( let actions = parse_post_delegation_actions( actions_data, delegation_record_pubkey, - decryption_ctx, + validator_keypair, )?; Ok((record, Some(actions))) } @@ -119,179 +74,27 @@ pub(crate) fn parse_delegation_record( fn parse_post_delegation_actions( actions_data: &[u8], delegation_record_pubkey: Pubkey, - decryption_ctx: Option<&ValidatorDecryptionContext>, + validator_keypair: Option<&Keypair>, ) -> ChainlinkResult { - let actions: PostDelegationActions = - bincode::deserialize(actions_data).map_err(|err| { + let actions: PostDelegationActions = bincode::deserialize(actions_data) + .map_err(|err| { ChainlinkError::InvalidDelegationActions( delegation_record_pubkey, format!("Failed to deserialize PostDelegationActions: {err}"), ) })?; - let mut pubkeys = actions.signers; - for non_signer in actions.non_signers { - pubkeys.push(decrypt_non_signer_pubkey( - non_signer, - delegation_record_pubkey, - decryption_ctx, - )?); - } - let instructions = actions - .instructions - .into_iter() - .map(|ix| { - let program_id = pubkeys.get(ix.program_id as usize).copied().ok_or( - ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - format!( - "Invalid program_id index {} for pubkey table len {}", - ix.program_id, - pubkeys.len() - ), - ), - )?; - - let accounts = ix - .accounts - .into_iter() - .map(|compact_meta| { - let account_pubkey = pubkeys - .get(compact_meta.key() as usize) - .copied() - .ok_or(ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - format!( - "Invalid account index {} for pubkey table len {}", - compact_meta.key(), - pubkeys.len() - ), - ))?; - - Ok(AccountMeta { - pubkey: account_pubkey, - is_signer: compact_meta.is_signer(), - is_writable: compact_meta.is_writable(), - }) - }) - .collect::>>()?; - - let data = decrypt_ix_data( - ix.data, - delegation_record_pubkey, - decryption_ctx, - )?; - - Ok(Instruction { - program_id, - accounts, - data, - }) - }) - .collect::>>()?; - - Ok(instructions.into()) -} - -fn decrypt_pubkey( - maybe_encrypted_pubkey: MaybeEncryptedPubkey, - delegation_record_pubkey: Pubkey, - decryption_ctx: Option<&ValidatorDecryptionContext>, -) -> ChainlinkResult { - match maybe_encrypted_pubkey { - MaybeEncryptedPubkey::ClearText(pubkey) => Ok(pubkey), - MaybeEncryptedPubkey::Encrypted(buffer) => { - let plaintext = decrypt_buffer( - buffer.as_bytes(), - delegation_record_pubkey, - decryption_ctx, - "pubkey", - )?; - Pubkey::try_from(plaintext.as_slice()).map_err(|_| { - ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - format!( - "Decrypted pubkey has invalid length: {}", - plaintext.len() - ), - ) - }) - } - } -} - -fn decrypt_non_signer_pubkey( - non_signer: MaybeEncryptedAccountMeta, - delegation_record_pubkey: Pubkey, - decryption_ctx: Option<&ValidatorDecryptionContext>, -) -> ChainlinkResult { - match non_signer { - MaybeEncryptedAccountMeta::Encrypted(buffer) => { - decrypt_pubkey( - MaybeEncryptedPubkey::Encrypted(buffer), - delegation_record_pubkey, - decryption_ctx, - ) - } - // Clear-text non-signer payload only carries compact flags/index, not - // the pubkey bytes, so we cannot reconstruct a full instruction. - MaybeEncryptedAccountMeta::ClearText(_meta) => Err( + .decrypt_with_keypair(validator_keypair.unwrap()) + .map_err(|err| { ChainlinkError::InvalidDelegationActions( delegation_record_pubkey, - "Clear-text non-signer account metadata is unsupported for replay".to_string(), - ), - ), - } -} - -fn decrypt_ix_data( - maybe_encrypted_ix_data: MaybeEncryptedIxData, - delegation_record_pubkey: Pubkey, - decryption_ctx: Option<&ValidatorDecryptionContext>, -) -> ChainlinkResult> { - let mut data = maybe_encrypted_ix_data.prefix; - let encrypted_suffix = maybe_encrypted_ix_data.suffix.into_inner(); - - if !encrypted_suffix.is_empty() { - let suffix = decrypt_buffer( - &encrypted_suffix, - delegation_record_pubkey, - decryption_ctx, - "ix data suffix", - )?; - data.extend_from_slice(&suffix); - } - - Ok(data) -} - -fn decrypt_buffer( - encrypted: &[u8], - delegation_record_pubkey: Pubkey, - decryption_ctx: Option<&ValidatorDecryptionContext>, - field_label: &str, -) -> ChainlinkResult> { - let Some(decryption_ctx) = decryption_ctx else { - return Err(ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - format!( - "Encrypted {field_label} present but validator decryption context is unavailable" - ), - )); - }; + "Encrypted pubkey present but validator keypair is unavailable" + .to_string(), + ) + })?; - encryption::decrypt( - encrypted, - &decryption_ctx.x25519_pubkey, - &decryption_ctx.x25519_secret, - ) - .map_err(|err| { - ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - format!("Failed to decrypt {field_label}: {err}"), - ) - }) + Ok(instructions.into()) } pub(crate) fn apply_delegation_record_to_account( @@ -377,13 +180,12 @@ where Ok(mut delegation_records) => { if let Some(delegation_record_remote) = delegation_records.pop() { match delegation_record_remote.fresh_account() { - Some(delegation_record_account) => { - this.parse_delegation_record( + Some(delegation_record_account) => this + .parse_delegation_record( delegation_record_account.data(), delegation_record_pubkey, ) - .ok() - } + .ok(), None => None, } } else { @@ -422,6 +224,7 @@ mod tests { MaybeEncryptedIxData, PostDelegationActions, }; use solana_program::pubkey::Pubkey; + use solana_signer::Signer; use super::*; @@ -493,19 +296,17 @@ mod tests { #[test] fn decrypts_encrypted_post_delegation_actions() { let validator = Keypair::new(); - let decryption_ctx = - ValidatorDecryptionContext::from_validator_keypair(&validator) - .unwrap(); let signer = Pubkey::new_unique(); let program_id = Pubkey::new_unique(); let account = Pubkey::new_unique(); - let encrypted_program_id = dlp_api::encryption::encrypt_ed25519_recipient( - program_id.as_array(), - validator.pubkey().as_array(), - ) - .unwrap(); + let encrypted_program_id = + dlp_api::encryption::encrypt_ed25519_recipient( + program_id.as_array(), + validator.pubkey().as_array(), + ) + .unwrap(); let encrypted_suffix = dlp_api::encryption::encrypt_ed25519_recipient( &[3, 4, 5], validator.pubkey().as_array(), @@ -537,7 +338,7 @@ mod tests { &payload, Pubkey::new_unique(), validator.pubkey(), - Some(&decryption_ctx), + Some(&validator), ) .unwrap(); @@ -549,13 +350,14 @@ mod tests { } #[test] - fn fails_when_encrypted_actions_have_no_decryption_context() { + fn fails_when_encrypted_actions_have_no_validator_keypair() { let validator = Keypair::new(); - let encrypted_program_id = dlp_api::encryption::encrypt_ed25519_recipient( - Pubkey::new_unique().as_array(), - validator.pubkey().as_array(), - ) - .unwrap(); + let encrypted_program_id = + dlp_api::encryption::encrypt_ed25519_recipient( + Pubkey::new_unique().as_array(), + validator.pubkey().as_array(), + ) + .unwrap(); let payload = serialize_record_with_actions( validator.pubkey(), diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 258c44cb8..af0a23588 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -38,7 +38,6 @@ mod types; pub use self::types::FetchAndCloneResult; use self::{ - delegation::ValidatorDecryptionContext, subscription::{cancel_subs, CancelStrategy}, types::{ AccountWithCompanion, ClassifiedAccounts, PartitionedNotFound, @@ -84,7 +83,7 @@ where accounts_bank: Arc, cloner: Arc, validator_pubkey: Pubkey, - validator_decryption_ctx: Option, + validator_keypair: Option>, /// These are accounts that we should never clone into our validator. /// native programs, sysvars, native tokens, validator identity and faucet @@ -118,23 +117,12 @@ where let allowed_programs = allowed_programs.map(|programs| { programs.iter().map(|p| p.id).collect::>() }); - let validator_decryption_ctx = validator_keypair.as_ref().and_then( - |keypair| match ValidatorDecryptionContext::from_validator_keypair( - keypair, - ) { - Ok(ctx) => Some(ctx), - Err(err) => { - error!(error = %err, "Failed to initialize action decryption context"); - None - } - }, - ); let me = Arc::new(Self { remote_account_provider: remote_account_provider.clone(), accounts_bank: accounts_bank.clone(), cloner: cloner.clone(), validator_pubkey, - validator_decryption_ctx, + validator_keypair: validator_keypair.map(Arc::new), pending_requests: Arc::new(HashMap::new()), fetch_count: Arc::new(AtomicU64::new(0)), blacklisted_accounts, @@ -703,7 +691,7 @@ where data, delegation_record_pubkey, self.validator_pubkey, - self.validator_decryption_ctx.as_ref(), + self.validator_keypair.as_deref(), ) } @@ -973,6 +961,7 @@ where None, fetch_origin, None, + min_context_slot, ) .await?; new_subs.extend(action_dependencies_to_fetch.iter().copied()); From 41a5eb13671c437e806ce83fe15fa6c884f3fd79 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 4 Mar 2026 00:34:26 +0530 Subject: [PATCH 08/16] change dep path for dlp-api --- Cargo.lock | 36 +++++++++---------- Cargo.toml | 2 +- .../src/chainlink/fetch_cloner/delegation.rs | 25 +++++++------ test-integration/Cargo.toml | 2 +- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf888640b..f9a1566a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1481,21 +1481,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "dlp-api" -version = "0.1.0" -dependencies = [ - "bincode", - "borsh 1.6.0", - "libsodium-rs", - "magicblock-delegation-program", - "rand 0.8.5", - "serde", - "solana-program", - "solana-sdk", - "thiserror 2.0.18", -] - [[package]] name = "dtor" version = "0.1.1" @@ -3286,7 +3271,6 @@ dependencies = [ "assert_matches", "async-trait", "bincode", - "dlp-api", "futures-util", "helius-laserstream", "lru 0.16.2", @@ -3295,6 +3279,7 @@ dependencies = [ "magicblock-config", "magicblock-core", "magicblock-delegation-program", + "magicblock-delegation-program-api", "magicblock-magic-program-api", "magicblock-metrics", "parking_lot", @@ -3355,13 +3340,13 @@ dependencies = [ "base64 0.21.7", "bincode", "borsh 1.6.0", - "dlp-api", "dyn-clone", "futures-util", "lazy_static", "lru 0.16.2", "magicblock-committor-program", "magicblock-delegation-program", + "magicblock-delegation-program-api", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3469,6 +3454,21 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "magicblock-delegation-program-api" +version = "0.1.0" +dependencies = [ + "bincode", + "borsh 1.6.0", + "libsodium-rs", + "magicblock-delegation-program", + "rand 0.8.5", + "serde", + "solana-program", + "solana-sdk", + "thiserror 1.0.69", +] + [[package]] name = "magicblock-ledger" version = "0.8.2" @@ -3729,8 +3729,8 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.2" dependencies = [ - "dlp-api", "magicblock-delegation-program", + "magicblock-delegation-program-api", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", diff --git a/Cargo.toml b/Cargo.toml index 3dfe8594f..ba7aa0f45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,7 +105,7 @@ magicblock-core = { path = "./magicblock-core" } magicblock-delegation-program = { path = "../delegation-program", default-features = false, features = [ "sdk", ] } -dlp-api = { path = "../delegation-program/dlp-api" } +dlp-api = { package = "magicblock-delegation-program-api", path = "../delegation-program/dlp-api" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 39f718004..5e0be86da 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,16 +1,14 @@ use dlp::{ - args::{ - MaybeEncryptedAccountMeta, MaybeEncryptedPubkey, PostDelegationActions, - }, + args::PostDelegationActions, pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; use dlp_api::decrypt::Decrypt; +use dlp_api::encryption::KEY_LEN; use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::EATA_PROGRAM_ID; use magicblock_metrics::metrics; use solana_account::ReadableAccount; -use solana_instruction::{AccountMeta, Instruction}; use solana_keypair::Keypair; use solana_program::program_error::ProgramError; use solana_pubkey::Pubkey; @@ -84,15 +82,16 @@ fn parse_post_delegation_actions( ) })?; - let instructions = actions - .decrypt_with_keypair(validator_keypair.unwrap()) - .map_err(|err| { - ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - "Encrypted pubkey present but validator keypair is unavailable" - .to_string(), - ) - })?; + let instructions = match validator_keypair { + Some(keypair) => actions.decrypt_with_keypair(keypair), + None => actions.decrypt(&[0; KEY_LEN], &[0; KEY_LEN]), + } + .map_err(|err| { + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + format!("Failed to parse/decrypt PostDelegationActions: {err}"), + ) + })?; Ok(instructions.into()) } diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index d35cd2bd7..713f0000b 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -63,7 +63,7 @@ magicblock_magic_program_api = { package = "magicblock-magic-program-api", path magicblock-delegation-program = { path = "../../delegation-program", features = [ "no-entrypoint", ] } -dlp-api = { path = "../../delegation-program/dlp-api" } +dlp-api = { package = "magicblock-delegation-program-api", path = "../../delegation-program/dlp-api" } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } magicblock-table-mania = { path = "../magicblock-table-mania" } From a45f7a6ffaa6e0ac6643238c261bc6c557f33215 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 4 Mar 2026 01:43:59 +0530 Subject: [PATCH 09/16] add 10_post_delegation_token_transfer.rs --- .../src/chainlink/fetch_cloner/delegation.rs | 4 +- test-integration/Cargo.lock | 51 ++--- test-integration/test-cloning/Cargo.toml | 3 + .../10_post_delegation_token_transfer.rs | 190 ++++++++++++++++++ 4 files changed, 222 insertions(+), 26 deletions(-) create mode 100644 test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 5e0be86da..c6706aacb 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -1,7 +1,6 @@ use dlp::{ args::PostDelegationActions, - pda::delegation_record_pda_from_delegated_account, - state::DelegationRecord, + pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; use dlp_api::decrypt::Decrypt; use dlp_api::encryption::KEY_LEN; @@ -222,6 +221,7 @@ mod tests { EncryptedBuffer, MaybeEncryptedAccountMeta, MaybeEncryptedInstruction, MaybeEncryptedIxData, PostDelegationActions, }; + use solana_instruction::Instruction; use solana_program::pubkey::Pubkey; use solana_signer::Signer; diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 13e583b1e..582373de9 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -1608,21 +1608,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "dlp-api" -version = "0.1.0" -dependencies = [ - "bincode", - "borsh 1.6.0", - "libsodium-rs", - "magicblock-delegation-program 1.1.3", - "rand 0.8.5", - "serde", - "solana-program", - "solana-sdk", - "thiserror 2.0.18", -] - [[package]] name = "downcast" version = "0.11.0" @@ -2984,10 +2969,10 @@ dependencies = [ "anyhow", "borsh 1.6.0", "color-backtrace", - "dlp-api", "magicblock-config", "magicblock-core", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "random-port", "rayon", "serde", @@ -3608,7 +3593,6 @@ dependencies = [ "arc-swap", "async-trait", "bincode", - "dlp-api", "futures-util", "helius-laserstream", "lru", @@ -3616,6 +3600,7 @@ dependencies = [ "magicblock-config", "magicblock-core", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "magicblock-magic-program-api 0.8.2", "magicblock-metrics", "parking_lot", @@ -3676,12 +3661,12 @@ dependencies = [ "base64 0.21.7", "bincode", "borsh 1.6.0", - "dlp-api", "dyn-clone", "futures-util", "lru", "magicblock-committor-program", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3795,6 +3780,21 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "magicblock-delegation-program-api" +version = "0.1.0" +dependencies = [ + "bincode", + "borsh 1.6.0", + "libsodium-rs", + "magicblock-delegation-program 1.1.3", + "rand 0.8.5", + "serde", + "solana-program", + "solana-sdk", + "thiserror 1.0.69", +] + [[package]] name = "magicblock-ledger" version = "0.8.2" @@ -4015,8 +4015,8 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.2" dependencies = [ - "dlp-api", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -4978,9 +4978,9 @@ name = "program-schedulecommit" version = "0.0.0" dependencies = [ "borsh 1.6.0", - "dlp-api", "ephemeral-rollups-sdk", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "magicblock-magic-program-api 0.8.2", "rkyv 0.7.45", "solana-program", @@ -5993,11 +5993,11 @@ version = "0.0.0" dependencies = [ "async-trait", "borsh 1.6.0", - "dlp-api", "futures", "magicblock-committor-program", "magicblock-committor-service", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -10280,12 +10280,12 @@ name = "test-chainlink" version = "0.0.0" dependencies = [ "bincode", - "dlp-api", "futures", "integration-test-tools", "magicblock-chainlink", "magicblock-config", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "program-flexi-counter", "program-mini", "solana-account", @@ -10308,11 +10308,14 @@ name = "test-cloning" version = "0.0.0" dependencies = [ "integration-test-tools", + "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "program-flexi-counter", "program-mini", "solana-loader-v4-interface", "solana-sdk", "spl-memo-interface", + "spl-token", "test-chainlink", "test-kit", "tokio", @@ -10384,7 +10387,6 @@ name = "test-magicblock-api" version = "0.0.0" dependencies = [ "cleanass", - "dlp-api", "integration-test-tools", "isocountry", "lazy_static", @@ -10392,6 +10394,7 @@ dependencies = [ "magicblock-api", "magicblock-config", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "magicblock-program", "magicblock-validator-admin", "solana-rpc-client", @@ -10430,9 +10433,9 @@ dependencies = [ name = "test-schedule-intent" version = "0.0.0" dependencies = [ - "dlp-api", "integration-test-tools", "magicblock-delegation-program 1.1.3", + "magicblock-delegation-program-api", "program-flexi-counter", "solana-rpc-client-api", "solana-sdk", diff --git a/test-integration/test-cloning/Cargo.toml b/test-integration/test-cloning/Cargo.toml index 75baf79d8..0ace1acae 100644 --- a/test-integration/test-cloning/Cargo.toml +++ b/test-integration/test-cloning/Cargo.toml @@ -9,8 +9,11 @@ program-mini = { workspace = true, features = ["no-entrypoint"] } integration-test-tools = { workspace = true } tracing = { workspace = true } test-chainlink = { workspace = true } +magicblock-delegation-program = { workspace = true } +dlp-api = { workspace = true } solana-loader-v4-interface = { workspace = true, features = ["serde"] } solana-sdk = { workspace = true } +spl-token = { workspace = true } spl-memo-interface = { workspace = true } test-kit = { workspace = true } tokio = { workspace = true, features = ["full"] } diff --git a/test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs b/test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs new file mode 100644 index 000000000..a71edeada --- /dev/null +++ b/test-integration/test-cloning/tests/10_post_delegation_token_transfer.rs @@ -0,0 +1,190 @@ +use std::{thread::sleep, time::Duration}; + +use dlp::args::DelegateArgs; +use dlp_api::instruction_builder::{ + delegate_with_actions, Encryptable, PostDelegationInstruction, +}; +use integration_test_tools::IntegrationTestContext; +use solana_sdk::{ + signature::Keypair, signer::Signer, system_instruction, + transaction::Transaction, +}; +use spl_token::{ + instruction as spl_token_ix, + solana_program::program_pack::Pack, + state::{Account as TokenAccount, Mint}, +}; +use test_kit::init_logger; + +fn token_balance_chain(ctx: &IntegrationTestContext, account: &Keypair) -> u64 { + let balance = ctx + .try_chain_client() + .unwrap() + .get_token_account_balance(&account.pubkey()) + .unwrap(); + balance.amount.parse::().unwrap() +} + +fn token_balance_ephem( + ctx: &IntegrationTestContext, + account: &Keypair, +) -> Option { + ctx.try_ephem_client() + .unwrap() + .get_token_account_balance(&account.pubkey()) + .ok() + .and_then(|balance| balance.amount.parse::().ok()) +} + +#[test] +fn test_post_delegation_action_executes_spl_token_transfer_100() { + init_logger!(); + let ctx = IntegrationTestContext::try_new().unwrap(); + + let authority = Keypair::new(); + let mint = Keypair::new(); + let token_x = Keypair::new(); + let token_y = Keypair::new(); + + ctx.airdrop_chain(&authority.pubkey(), 2_000_000_000).unwrap(); + + let chain_client = ctx.try_chain_client().unwrap(); + let mint_rent = chain_client + .get_minimum_balance_for_rent_exemption(Mint::LEN) + .unwrap(); + let token_rent = chain_client + .get_minimum_balance_for_rent_exemption(TokenAccount::LEN) + .unwrap(); + + let setup_ixs = vec![ + system_instruction::create_account( + &authority.pubkey(), + &mint.pubkey(), + mint_rent, + Mint::LEN as u64, + &spl_token::id(), + ), + spl_token_ix::initialize_mint( + &spl_token::id(), + &mint.pubkey(), + &authority.pubkey(), + None, + 0, + ) + .unwrap(), + system_instruction::create_account( + &authority.pubkey(), + &token_x.pubkey(), + token_rent, + TokenAccount::LEN as u64, + &spl_token::id(), + ), + spl_token_ix::initialize_account( + &spl_token::id(), + &token_x.pubkey(), + &mint.pubkey(), + &authority.pubkey(), + ) + .unwrap(), + system_instruction::create_account( + &authority.pubkey(), + &token_y.pubkey(), + token_rent, + TokenAccount::LEN as u64, + &spl_token::id(), + ), + spl_token_ix::initialize_account( + &spl_token::id(), + &token_y.pubkey(), + &mint.pubkey(), + &authority.pubkey(), + ) + .unwrap(), + spl_token_ix::mint_to( + &spl_token::id(), + &mint.pubkey(), + &token_x.pubkey(), + &authority.pubkey(), + &[], + 100, + ) + .unwrap(), + ]; + let mut setup_tx = + Transaction::new_with_payer(&setup_ixs, Some(&authority.pubkey())); + let (_sig, confirmed) = ctx.send_and_confirm_transaction_chain( + &mut setup_tx, + &[&authority, &mint, &token_x, &token_y], + ) + .unwrap(); + assert!(confirmed); + + // Clone token accounts once so we can assert pre/post balances in ephem. + ctx.fetch_ephem_account(token_x.pubkey()).unwrap(); + ctx.fetch_ephem_account(token_y.pubkey()).unwrap(); + + assert_eq!(token_balance_chain(&ctx, &token_x), 100); + assert_eq!(token_balance_chain(&ctx, &token_y), 0); + assert_eq!(token_balance_ephem(&ctx, &token_x), Some(100)); + assert_eq!(token_balance_ephem(&ctx, &token_y), Some(0)); + + let transfer_100_ix = spl_token_ix::transfer( + &spl_token::id(), + &token_x.pubkey(), + &token_y.pubkey(), + &authority.pubkey(), + &[], + 100, + ) + .unwrap(); + let post_actions: Vec = + vec![transfer_100_ix.cleartext()]; + + let validator = ctx.ephem_validator_identity; + let delegate_with_actions_ix = delegate_with_actions( + authority.pubkey(), + authority.pubkey(), + None, + DelegateArgs { + commit_frequency_ms: u32::MAX, + seeds: vec![], + validator, + }, + post_actions, + ); + + let assign_ix = system_instruction::assign(&authority.pubkey(), &dlp::id()); + let mut delegate_tx = Transaction::new_with_payer( + &[assign_ix, delegate_with_actions_ix], + Some(&authority.pubkey()), + ); + let (_sig, confirmed) = + ctx.send_and_confirm_transaction_chain(&mut delegate_tx, &[&authority]) + .unwrap(); + assert!(confirmed); + + // Trigger delegated account clone; this is where post-delegation actions + // are executed on ephem. + ctx.fetch_ephem_account(authority.pubkey()).unwrap(); + + // Poll briefly because clone + action execution is async relative to fetch. + let mut found = None; + for _ in 0..30 { + let bx = token_balance_ephem(&ctx, &token_x); + let by = token_balance_ephem(&ctx, &token_y); + if bx == Some(0) && by == Some(100) { + found = Some((bx, by)); + break; + } + sleep(Duration::from_millis(200)); + } + let (x_after, y_after) = found.unwrap_or_else(|| { + ( + token_balance_ephem(&ctx, &token_x), + token_balance_ephem(&ctx, &token_y), + ) + }); + + assert_eq!(x_after, Some(0)); + assert_eq!(y_after, Some(100)); +} From ccfda83b6580ec0f55cc6cad10ef838d7af1d8d0 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 4 Mar 2026 15:25:11 +0530 Subject: [PATCH 10/16] review --- .../src/chainlink/fetch_cloner/mod.rs | 52 ++++++++----------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index af0a23588..031128830 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -51,8 +51,7 @@ use crate::{ blacklisted_accounts::blacklisted_accounts, }, cloner::{ - errors::ClonerResult, AccountCloneRequest, Cloner, - DelegationActions, + errors::ClonerResult, AccountCloneRequest, Cloner, DelegationActions, }, remote_account_provider::{ program_account::get_loaderv3_get_program_data_address, @@ -387,21 +386,21 @@ where let account = if let Some(delegation_record) = delegation_record { - let delegation_record_with_actions = - match self.parse_delegation_record( + let delegation_record_with_actions = match self + .parse_delegation_record( delegation_record.data(), delegation_record_pubkey, ) { - Ok(x) => Some(x), - Err(err) => { - warn!( - pubkey = %pubkey, - error = %err, - "Failed to parse delegation record" - ); - None - } - }; + Ok(x) => Some(x), + Err(err) => { + error!( + pubkey = %pubkey, + error = %err, + "Failed to parse delegation record" + ); + None + } + }; // If the delegation record is valid we set the owner and delegation // status on the account @@ -459,11 +458,7 @@ where // 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()) } } else { // If no delegation record exists we must assume the account itself is @@ -506,11 +501,7 @@ where let (account, deleg_record) = self .maybe_project_ata_from_subscription_update(pubkey, account) .await; - ( - Some(account), - deleg_record, - DelegationActions::default(), - ) + (Some(account), deleg_record, DelegationActions::default()) } } else { // This should not happen since we call this method with sub updates which always hold @@ -921,7 +912,9 @@ where // Ensure all accounts referenced by delegation actions exist and are // cloned before we execute those actions as part of account cloning. let action_dependencies = - pipeline::collect_delegation_action_dependencies(&accounts_to_clone); + pipeline::collect_delegation_action_dependencies( + &accounts_to_clone, + ); let action_dependencies_to_fetch = action_dependencies .into_iter() .filter(|dependency| { @@ -1096,10 +1089,11 @@ where return RefreshDecision::YesAndMarkEmptyIfNotFound; } - let delegated_on_chain = deleg_record.as_ref().is_some_and(|dr| { - dr.0.authority.eq(&self.validator_pubkey) - || dr.0.authority.eq(&Pubkey::default()) - }); + let delegated_on_chain = + deleg_record.as_ref().is_some_and(|(dr, _)| { + dr.authority.eq(&self.validator_pubkey) + || dr.authority.eq(&Pubkey::default()) + }); let deleg_record = deleg_record.map(|el| el.0); if !account_still_undelegating_on_chain( pubkey, From 7f916ced7c00f595ddbb95cebc325e361a02c168 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 4 Mar 2026 19:06:13 +0530 Subject: [PATCH 11/16] replace bincode with borsh --- Cargo.lock | 1 + magicblock-chainlink/Cargo.toml | 1 + .../src/chainlink/fetch_cloner/delegation.rs | 10 +++++----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9a1566a4..1428cc09a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3271,6 +3271,7 @@ dependencies = [ "assert_matches", "async-trait", "bincode", + "borsh 1.6.0", "futures-util", "helius-laserstream", "lru 0.16.2", diff --git a/magicblock-chainlink/Cargo.toml b/magicblock-chainlink/Cargo.toml index 175e5725f..29eca43fc 100644 --- a/magicblock-chainlink/Cargo.toml +++ b/magicblock-chainlink/Cargo.toml @@ -7,6 +7,7 @@ edition.workspace = true arc-swap = "1.7" async-trait = { workspace = true } bincode = { workspace = true } +borsh = { workspace = true } futures-util = { workspace = true } helius-laserstream = { workspace = true } tracing = { workspace = true } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index c6706aacb..b6b61c61b 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -73,7 +73,7 @@ fn parse_post_delegation_actions( delegation_record_pubkey: Pubkey, validator_keypair: Option<&Keypair>, ) -> ChainlinkResult { - let actions: PostDelegationActions = bincode::deserialize(actions_data) + let actions: PostDelegationActions = borsh::from_slice(actions_data) .map_err(|err| { ChainlinkError::InvalidDelegationActions( delegation_record_pubkey, @@ -219,7 +219,7 @@ where mod tests { use dlp::args::{ EncryptedBuffer, MaybeEncryptedAccountMeta, MaybeEncryptedInstruction, - MaybeEncryptedIxData, PostDelegationActions, + MaybeEncryptedIxData, MaybeEncryptedPubkey, PostDelegationActions, }; use solana_instruction::Instruction; use solana_program::pubkey::Pubkey; @@ -241,7 +241,7 @@ mod tests { let mut data = vec![0; DelegationRecord::size_with_discriminator()]; record.to_bytes_with_discriminator(&mut data).unwrap(); - data.extend_from_slice(&bincode::serialize(&actions).unwrap()); + data.extend_from_slice(&borsh::to_vec(&actions).unwrap()); data } @@ -316,7 +316,7 @@ mod tests { validator.pubkey(), PostDelegationActions { signers: vec![signer, account], - non_signers: vec![MaybeEncryptedAccountMeta::Encrypted( + non_signers: vec![MaybeEncryptedPubkey::Encrypted( EncryptedBuffer::new(encrypted_program_id), )], instructions: vec![MaybeEncryptedInstruction { @@ -362,7 +362,7 @@ mod tests { validator.pubkey(), PostDelegationActions { signers: vec![], - non_signers: vec![MaybeEncryptedAccountMeta::Encrypted( + non_signers: vec![MaybeEncryptedPubkey::Encrypted( EncryptedBuffer::new(encrypted_program_id), )], instructions: vec![], From 60d8e531f845b61fcf009c5aed50faf103c74f72 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 4 Mar 2026 19:30:44 +0530 Subject: [PATCH 12/16] Make validator_keypair non-option and avoid passing pubkey --- magicblock-api/src/magic_validator.rs | 3 +- .../src/chainlink/fetch_cloner/delegation.rs | 49 +++--- .../src/chainlink/fetch_cloner/mod.rs | 12 +- .../src/chainlink/fetch_cloner/tests.rs | 160 ++++++++++-------- magicblock-chainlink/src/chainlink/mod.rs | 6 +- .../tests/utils/test_context.rs | 8 +- .../test-chainlink/src/ixtest_context.rs | 3 +- .../test-chainlink/src/test_context.rs | 8 +- 8 files changed, 140 insertions(+), 109 deletions(-) diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 0d61aea21..9f9bd6e55 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -461,8 +461,7 @@ impl MagicValidator { commitment_config, &accounts_bank, &cloner, - config.validator.keypair.pubkey(), - Some(config.validator.keypair.insecure_clone()), + config.validator.keypair.insecure_clone(), faucet_pubkey, chainlink_config, &config.chainlink, diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index b6b61c61b..090d2d592 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -3,7 +3,6 @@ use dlp::{ pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, }; use dlp_api::decrypt::Decrypt; -use dlp_api::encryption::KEY_LEN; use magicblock_accounts_db::traits::AccountsBank; use magicblock_core::token_programs::EATA_PROGRAM_ID; use magicblock_metrics::metrics; @@ -11,6 +10,7 @@ use solana_account::ReadableAccount; use solana_keypair::Keypair; use solana_program::program_error::ProgramError; use solana_pubkey::Pubkey; +use solana_signer::Signer; use tracing::*; use super::FetchCloner; @@ -29,8 +29,7 @@ use crate::{ pub(crate) fn parse_delegation_record( data: &[u8], delegation_record_pubkey: Pubkey, - validator_pubkey: Pubkey, - validator_keypair: Option<&Keypair>, + validator_keypair: &Keypair, ) -> ChainlinkResult<(DelegationRecord, Option)> { let delegation_record_size = DelegationRecord::size_with_discriminator(); if data.len() < delegation_record_size { @@ -52,7 +51,7 @@ pub(crate) fn parse_delegation_record( } else { // Actions for accounts delegated to other validators are not relevant // for this node and may be encrypted for a different recipient. - if record.authority != validator_pubkey + if record.authority != validator_keypair.pubkey() && record.authority != Pubkey::default() { return Ok((record, None)); @@ -71,7 +70,7 @@ pub(crate) fn parse_delegation_record( fn parse_post_delegation_actions( actions_data: &[u8], delegation_record_pubkey: Pubkey, - validator_keypair: Option<&Keypair>, + validator_keypair: &Keypair, ) -> ChainlinkResult { let actions: PostDelegationActions = borsh::from_slice(actions_data) .map_err(|err| { @@ -81,11 +80,9 @@ fn parse_post_delegation_actions( ) })?; - let instructions = match validator_keypair { - Some(keypair) => actions.decrypt_with_keypair(keypair), - None => actions.decrypt(&[0; KEY_LEN], &[0; KEY_LEN]), - } - .map_err(|err| { + let instructions = actions + .decrypt_with_keypair(validator_keypair) + .map_err(|err| { ChainlinkError::InvalidDelegationActions( delegation_record_pubkey, format!("Failed to parse/decrypt PostDelegationActions: {err}"), @@ -251,17 +248,21 @@ mod tests { let program_id = Pubkey::new_unique(); let account = Pubkey::new_unique(); - let validator_pubkey = Pubkey::new_unique(); + let validator = Keypair::new(); let payload = serialize_record_with_actions( - validator_pubkey, + validator.pubkey(), PostDelegationActions { signers: vec![signer, program_id, account], non_signers: vec![], instructions: vec![MaybeEncryptedInstruction { program_id: 1, accounts: vec![ - dlp::compact::AccountMeta::new_readonly(0, true), - dlp::compact::AccountMeta::new(2, false), + MaybeEncryptedAccountMeta::ClearText( + dlp::compact::AccountMeta::new_readonly(0, true), + ), + MaybeEncryptedAccountMeta::ClearText( + dlp::compact::AccountMeta::new(2, false), + ), ], data: MaybeEncryptedIxData { prefix: vec![7, 8, 9], @@ -274,8 +275,7 @@ mod tests { let (_, actions) = parse_delegation_record( &payload, Pubkey::new_unique(), - validator_pubkey, - None, + &validator, ) .unwrap(); @@ -322,8 +322,12 @@ mod tests { instructions: vec![MaybeEncryptedInstruction { program_id: 2, accounts: vec![ - dlp::compact::AccountMeta::new_readonly(0, true), - dlp::compact::AccountMeta::new(1, false), + MaybeEncryptedAccountMeta::ClearText( + dlp::compact::AccountMeta::new_readonly(0, true), + ), + MaybeEncryptedAccountMeta::ClearText( + dlp::compact::AccountMeta::new(1, false), + ), ], data: MaybeEncryptedIxData { prefix: vec![1, 2], @@ -336,8 +340,7 @@ mod tests { let (_, actions) = parse_delegation_record( &payload, Pubkey::new_unique(), - validator.pubkey(), - Some(&validator), + &validator, ) .unwrap(); @@ -349,8 +352,9 @@ mod tests { } #[test] - fn fails_when_encrypted_actions_have_no_validator_keypair() { + fn fails_when_encrypted_actions_have_wrong_validator_keypair() { let validator = Keypair::new(); + let wrong_validator = Keypair::new(); let encrypted_program_id = dlp_api::encryption::encrypt_ed25519_recipient( Pubkey::new_unique().as_array(), @@ -372,8 +376,7 @@ mod tests { let err = parse_delegation_record( &payload, Pubkey::new_unique(), - validator.pubkey(), - None, + &wrong_validator, ) .unwrap_err(); assert!(matches!( diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 031128830..b166936ac 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -21,6 +21,7 @@ use scc::{hash_map::Entry, HashMap}; use solana_account::{AccountSharedData, ReadableAccount}; use solana_keypair::Keypair; use solana_pubkey::Pubkey; +use solana_signer::Signer; use solana_sdk_ids::system_program; use tokio::{ sync::{mpsc, oneshot}, @@ -82,7 +83,7 @@ where accounts_bank: Arc, cloner: Arc, validator_pubkey: Pubkey, - validator_keypair: Option>, + validator_keypair: Arc, /// These are accounts that we should never clone into our validator. /// native programs, sysvars, native tokens, validator identity and faucet @@ -105,12 +106,12 @@ where remote_account_provider: &Arc>, accounts_bank: &Arc, cloner: &Arc, - validator_pubkey: Pubkey, - validator_keypair: Option, + validator_keypair: Keypair, faucet_pubkey: Pubkey, subscription_updates_rx: mpsc::Receiver, allowed_programs: Option>, ) -> Arc { + let validator_pubkey = validator_keypair.pubkey(); let blacklisted_accounts = blacklisted_accounts(&validator_pubkey, &faucet_pubkey); let allowed_programs = allowed_programs.map(|programs| { @@ -121,7 +122,7 @@ where accounts_bank: accounts_bank.clone(), cloner: cloner.clone(), validator_pubkey, - validator_keypair: validator_keypair.map(Arc::new), + validator_keypair: Arc::new(validator_keypair), pending_requests: Arc::new(HashMap::new()), fetch_count: Arc::new(AtomicU64::new(0)), blacklisted_accounts, @@ -681,8 +682,7 @@ where delegation::parse_delegation_record( data, delegation_record_pubkey, - self.validator_pubkey, - self.validator_keypair.as_deref(), + self.validator_keypair.as_ref(), ) } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs index 173712793..01fe52c42 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/tests.rs @@ -1,6 +1,8 @@ use std::{collections::HashMap, sync::Arc}; use solana_account::{Account, AccountSharedData, WritableAccount}; +use solana_keypair::Keypair; +use solana_signer::Signer; use solana_sdk_ids::system_program; use tokio::sync::mpsc; @@ -111,7 +113,7 @@ struct FetcherTestCtx { async fn setup( accounts: I, current_slot: u64, - validator_pubkey: Pubkey, + validator_keypair: Keypair, ) -> FetcherTestCtx where I: IntoIterator, @@ -154,7 +156,7 @@ where let (fetch_cloner, subscription_tx) = init_fetch_cloner( remote_account_provider.clone(), &accounts_bank, - validator_pubkey, + validator_keypair, faucet_pubkey, ); @@ -175,7 +177,7 @@ fn init_fetch_cloner( RemoteAccountProvider, >, bank: &Arc, - validator_pubkey: Pubkey, + validator_keypair: Keypair, faucet_pubkey: Pubkey, ) -> TestFetchClonerResult { let (subscription_tx, subscription_rx) = mpsc::channel(100); @@ -184,8 +186,7 @@ fn init_fetch_cloner( &remote_account_provider, bank, &cloner, - validator_pubkey, - None, + validator_keypair, faucet_pubkey, subscription_rx, None, @@ -198,7 +199,8 @@ fn init_fetch_cloner( // ----------------- #[tokio::test] async fn test_fetch_and_clone_single_non_delegated_account() { - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_pubkey = random_pubkey(); let account_owner = random_pubkey(); @@ -215,7 +217,7 @@ async fn test_fetch_and_clone_single_non_delegated_account() { accounts_bank, fetch_cloner, .. - } = setup([(account_pubkey, account.clone())], 100, validator_pubkey).await; + } = setup([(account_pubkey, account.clone())], 100, validator_keypair.insecure_clone()).await; let result = fetch_cloner .fetch_and_clone_accounts( @@ -241,7 +243,8 @@ async fn test_fetch_and_clone_single_non_delegated_account() { #[tokio::test] async fn test_fetch_and_clone_single_non_existing_account() { - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let non_existing_pubkey = random_pubkey(); // Setup with no accounts (empty collection) @@ -252,7 +255,7 @@ async fn test_fetch_and_clone_single_non_existing_account() { } = setup( std::iter::empty::<(Pubkey, Account)>(), 100, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -279,7 +282,8 @@ async fn test_fetch_and_clone_single_non_existing_account() { #[tokio::test] async fn test_fetch_and_clone_single_delegated_account_with_valid_delegation_record( ) { - let validator_pubkey = random_pubkey(); + 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; @@ -303,7 +307,7 @@ async fn test_fetch_and_clone_single_delegated_account_with_valid_delegation_rec } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -357,7 +361,8 @@ async fn test_fetch_and_clone_single_delegated_account_with_valid_delegation_rec #[tokio::test] async fn test_fetch_and_clone_single_delegated_account_with_different_authority( ) { - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let different_authority = random_pubkey(); // Different authority let account_pubkey = random_pubkey(); let account_owner = random_pubkey(); @@ -382,7 +387,7 @@ async fn test_fetch_and_clone_single_delegated_account_with_different_authority( } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -438,7 +443,8 @@ async fn test_fetch_and_clone_single_delegated_account_without_delegation_record ) { // In case the delegation record itself was subscribed to already and then we subscribe to // the account itself, then the subscription to the delegation record should not be removed - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_pubkey = random_pubkey(); let account_owner = random_pubkey(); @@ -463,7 +469,7 @@ async fn test_fetch_and_clone_single_delegated_account_without_delegation_record } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -528,7 +534,8 @@ async fn test_fetch_and_clone_single_delegated_account_without_delegation_record #[tokio::test] async fn test_fetch_and_clone_multiple_accounts_mixed_types() { - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -574,7 +581,7 @@ async fn test_fetch_and_clone_multiple_accounts_mixed_types() { rpc_client, fetch_cloner, .. - } = setup(accounts, CURRENT_SLOT, validator_pubkey).await; + } = setup(accounts, CURRENT_SLOT, validator_keypair.insecure_clone()).await; // Add delegation record for the delegated account add_delegation_record_for( @@ -641,7 +648,8 @@ async fn test_fetch_and_clone_multiple_accounts_mixed_types() { #[tokio::test] async fn test_fetch_and_clone_valid_delegated_account_and_account_with_invalid_delegation_record( ) { - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -676,7 +684,7 @@ async fn test_fetch_and_clone_valid_delegated_account_and_account_with_invalid_d rpc_client, fetch_cloner, .. - } = setup(accounts, CURRENT_SLOT, validator_pubkey).await; + } = setup(accounts, CURRENT_SLOT, validator_keypair.insecure_clone()).await; // Add valid delegation record for first account add_delegation_record_for( @@ -723,7 +731,8 @@ async fn test_fetch_and_clone_valid_delegated_account_and_account_with_invalid_d #[tokio::test] async fn test_deleg_record_stale() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; const INITIAL_DELEG_RECORD_SLOT: u64 = CURRENT_SLOT - 10; @@ -744,7 +753,7 @@ async fn test_deleg_record_stale() { } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -799,7 +808,8 @@ async fn test_deleg_record_stale() { #[tokio::test] async fn test_account_stale() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; const INITIAL_ACC_SLOT: u64 = CURRENT_SLOT - 10; @@ -820,7 +830,7 @@ async fn test_account_stale() { } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -875,7 +885,8 @@ async fn test_account_stale() { #[tokio::test] async fn test_delegation_record_unsub_race_condition_prevention() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -897,7 +908,7 @@ async fn test_delegation_record_unsub_race_condition_prevention() { } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -960,7 +971,8 @@ async fn test_delegation_record_unsub_race_condition_prevention() { #[tokio::test] async fn test_fetch_and_clone_with_dedup_concurrent_requests() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -980,7 +992,7 @@ async fn test_fetch_and_clone_with_dedup_concurrent_requests() { } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1032,7 +1044,8 @@ async fn test_fetch_and_clone_with_dedup_concurrent_requests() { #[tokio::test] async fn test_undelegation_requested_subscription_behavior() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1054,7 +1067,7 @@ async fn test_undelegation_requested_subscription_behavior() { } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1102,7 +1115,8 @@ async fn test_undelegation_requested_subscription_behavior() { #[tokio::test] async fn test_delegated_authoritative_skip_unsubscribes_subscription() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1125,7 +1139,7 @@ async fn test_delegated_authoritative_skip_unsubscribes_subscription() { } = setup( [(account_pubkey, delegated_account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1213,7 +1227,8 @@ async fn test_delegated_authoritative_skip_unsubscribes_subscription() { #[tokio::test] async fn test_parallel_fetch_prevention_multiple_accounts() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1256,7 +1271,7 @@ async fn test_parallel_fetch_prevention_multiple_accounts() { accounts_bank, fetch_cloner, .. - } = setup(accounts, CURRENT_SLOT, validator_pubkey).await; + } = setup(accounts, CURRENT_SLOT, validator_keypair.insecure_clone()).await; // Use shared FetchCloner to test deduplication across multiple accounts // Spawn multiple concurrent requests for overlapping sets of accounts @@ -1327,7 +1342,8 @@ async fn test_parallel_fetch_prevention_multiple_accounts() { #[tokio::test] async fn test_fetch_with_some_acounts_marked_as_empty_if_not_found() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1350,7 +1366,7 @@ async fn test_fetch_with_some_acounts_marked_as_empty_if_not_found() { fetch_cloner, remote_account_provider, .. - } = setup(accounts, CURRENT_SLOT, validator_pubkey).await; + } = setup(accounts, CURRENT_SLOT, validator_keypair.insecure_clone()).await; // Configure fetch_cloner to mark some accounts as empty if not found fetch_cloner @@ -1403,7 +1419,8 @@ async fn test_fetch_with_some_acounts_marked_as_empty_if_not_found() { #[tokio::test] async fn test_confined_delegation_behavior() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1438,7 +1455,7 @@ async fn test_confined_delegation_behavior() { (account2_pubkey, account2.clone()), ], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1499,7 +1516,8 @@ async fn test_confined_delegation_behavior() { #[tokio::test] async fn test_fetch_and_clone_undelegating_account_that_is_closed_on_chain() { init_logger(); - let validator_pubkey = random_pubkey(); + 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; @@ -1522,7 +1540,7 @@ async fn test_fetch_and_clone_undelegating_account_that_is_closed_on_chain() { } = setup( std::iter::empty::<(Pubkey, Account)>(), CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1564,7 +1582,8 @@ async fn test_fetch_and_clone_undelegating_account_that_is_closed_on_chain() { #[tokio::test] async fn test_auto_airdrop_uses_non_stale_remote_slot_from_bank_account() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let payer_pubkey = random_pubkey(); const CURRENT_SLOT: u64 = 100; const LOCAL_SLOT: u64 = 250; @@ -1577,7 +1596,7 @@ async fn test_auto_airdrop_uses_non_stale_remote_slot_from_bank_account() { } = setup( std::iter::empty::<(Pubkey, Account)>(), CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1602,7 +1621,8 @@ async fn test_auto_airdrop_uses_non_stale_remote_slot_from_bank_account() { #[tokio::test] async fn test_auto_airdrop_uses_chain_slot_when_account_not_in_bank() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let payer_pubkey = random_pubkey(); const CURRENT_SLOT: u64 = 100; const AIRDROP_LAMPORTS: u64 = 1_000_000_000; @@ -1614,7 +1634,7 @@ async fn test_auto_airdrop_uses_chain_slot_when_account_not_in_bank() { } = setup( std::iter::empty::<(Pubkey, Account)>(), CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1638,7 +1658,8 @@ async fn test_auto_airdrop_uses_chain_slot_when_account_not_in_bank() { #[tokio::test] async fn test_allowed_programs_filters_programs() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let program_id_allowed = random_pubkey(); let program_id_blocked = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1669,7 +1690,7 @@ async fn test_allowed_programs_filters_programs() { fetch_cloner: _fetch_cloner, remote_account_provider, .. - } = setup(setup_accounts.into_iter(), CURRENT_SLOT, validator_pubkey).await; + } = setup(setup_accounts.into_iter(), CURRENT_SLOT, validator_keypair.insecure_clone()).await; // Create FetchCloner with only one program allowed let (_subscription_tx, subscription_rx) = mpsc::channel(100); @@ -1681,8 +1702,7 @@ async fn test_allowed_programs_filters_programs() { &remote_account_provider, &accounts_bank, &cloner, - validator_pubkey, - None, + validator_keypair.insecure_clone(), random_pubkey(), subscription_rx, allowed_programs, @@ -1718,7 +1738,8 @@ async fn test_allowed_programs_filters_programs() { #[tokio::test] async fn test_allowed_programs_none_allows_all() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let program_id1 = random_pubkey(); let program_id2 = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1741,7 +1762,7 @@ async fn test_allowed_programs_none_allows_all() { fetch_cloner: _fetch_cloner, remote_account_provider, .. - } = setup(setup_accounts.into_iter(), CURRENT_SLOT, validator_pubkey).await; + } = setup(setup_accounts.into_iter(), CURRENT_SLOT, validator_keypair.insecure_clone()).await; // Create FetchCloner with NO allowed_programs restriction (None) let (_subscription_tx, subscription_rx) = mpsc::channel(100); @@ -1750,8 +1771,7 @@ async fn test_allowed_programs_none_allows_all() { &remote_account_provider, &accounts_bank, &cloner, - validator_pubkey, - None, + validator_keypair.insecure_clone(), random_pubkey(), subscription_rx, None, // No restriction @@ -1785,7 +1805,8 @@ async fn test_allowed_programs_none_allows_all() { #[tokio::test] async fn test_allowed_programs_empty_allows_all() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let program_id1 = random_pubkey(); let program_id2 = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1808,7 +1829,7 @@ async fn test_allowed_programs_empty_allows_all() { fetch_cloner: _fetch_cloner, remote_account_provider, .. - } = setup(setup_accounts.into_iter(), CURRENT_SLOT, validator_pubkey).await; + } = setup(setup_accounts.into_iter(), CURRENT_SLOT, validator_keypair.insecure_clone()).await; // Create FetchCloner with an EMPTY allowed_programs list let (_subscription_tx, subscription_rx) = mpsc::channel(100); @@ -1818,8 +1839,7 @@ async fn test_allowed_programs_empty_allows_all() { &remote_account_provider, &accounts_bank, &cloner, - validator_pubkey, - None, + validator_keypair.insecure_clone(), random_pubkey(), subscription_rx, allowed_programs, @@ -1857,7 +1877,8 @@ async fn test_allowed_programs_empty_allows_all() { #[tokio::test] async fn test_subscribe_to_original_owner_program_on_delegated_account_fetch() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1879,7 +1900,7 @@ async fn test_subscribe_to_original_owner_program_on_delegated_account_fetch() { } = setup( [(account_pubkey, account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -1927,7 +1948,8 @@ async fn test_subscribe_to_original_owner_program_on_delegated_account_fetch() { #[tokio::test] async fn test_no_program_subscription_for_undelegated_account() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -1948,7 +1970,7 @@ async fn test_no_program_subscription_for_undelegated_account() { } = setup( [(account_pubkey, undelegated_account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -2063,7 +2085,8 @@ async fn send_subscription_update_and_get_subscribed_programs( async fn test_subscribe_to_original_owner_program_on_delegated_account_subscription_update( ) { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -2085,7 +2108,7 @@ async fn test_subscribe_to_original_owner_program_on_delegated_account_subscript } = setup( [(account_pubkey, delegated_account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -2129,7 +2152,8 @@ async fn test_subscribe_to_original_owner_program_on_delegated_account_subscript async fn test_no_program_subscription_for_undelegated_account_subscription_update( ) { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let account_owner = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -2150,7 +2174,7 @@ async fn test_no_program_subscription_for_undelegated_account_subscription_updat } = setup( [(account_pubkey, undelegated_account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -2178,7 +2202,8 @@ async fn test_no_program_subscription_for_undelegated_account_subscription_updat async fn test_delegated_eata_subscription_update_clones_raw_eata_and_projects_ata( ) { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let wallet_owner = random_pubkey(); let mint = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -2196,7 +2221,7 @@ async fn test_delegated_eata_subscription_update_clones_raw_eata_and_projects_at } = setup( [(eata_pubkey, eata_account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; @@ -2270,7 +2295,8 @@ async fn test_delegated_eata_subscription_update_clones_raw_eata_and_projects_at #[tokio::test] async fn test_delegated_eata_update_does_not_override_delegated_ata_in_bank() { init_logger(); - let validator_pubkey = random_pubkey(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let wallet_owner = random_pubkey(); let mint = random_pubkey(); const CURRENT_SLOT: u64 = 100; @@ -2290,7 +2316,7 @@ async fn test_delegated_eata_update_does_not_override_delegated_ata_in_bank() { } = setup( [(eata_pubkey, eata_account.clone())], CURRENT_SLOT, - validator_pubkey, + validator_keypair.insecure_clone(), ) .await; diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index c62b4fd4b..96b3cf1a1 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -17,6 +17,7 @@ use solana_commitment_config::CommitmentConfig; use solana_feature_set; use solana_keypair::Keypair; use solana_pubkey::Pubkey; +use solana_signer::Signer; use solana_transaction::sanitized::SanitizedTransaction; use tokio::{sync::mpsc, task}; use tracing::*; @@ -113,14 +114,14 @@ impl commitment: CommitmentConfig, accounts_bank: &Arc, cloner: &Arc, - validator_pubkey: Pubkey, - validator_keypair: Option, + validator_keypair: Keypair, faucet_pubkey: Pubkey, config: ChainlinkConfig, chainlink_config: &ChainLinkConfig, ) -> ChainlinkResult< Chainlink, V, C>, > { + let validator_pubkey = validator_keypair.pubkey(); // Extract accounts provider and create fetch cloner while connecting // the subscription channel let (tx, rx) = tokio::sync::mpsc::channel(100); @@ -137,7 +138,6 @@ impl &provider, accounts_bank, cloner, - validator_pubkey, validator_keypair, faucet_pubkey, rx, diff --git a/magicblock-chainlink/tests/utils/test_context.rs b/magicblock-chainlink/tests/utils/test_context.rs index bf1075e97..c5cc9753e 100644 --- a/magicblock-chainlink/tests/utils/test_context.rs +++ b/magicblock-chainlink/tests/utils/test_context.rs @@ -24,8 +24,10 @@ use magicblock_chainlink::{ }; use magicblock_config::config::{ChainLinkConfig, LifecycleMode}; use solana_account::{Account, AccountSharedData}; +use solana_keypair::Keypair; use solana_program::{clock::Slot, sysvar::clock}; use solana_pubkey::Pubkey; +use solana_signer::Signer; use tokio::sync::mpsc; use tracing::*; @@ -64,7 +66,8 @@ impl TestContext { let lifecycle_mode = LifecycleMode::Ephemeral; let bank = Arc::::default(); let cloner = Arc::new(ClonerStub::new(bank.clone())); - let validator_pubkey = Pubkey::new_unique(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let faucet_pubkey = Pubkey::new_unique(); let (fetch_cloner, remote_account_provider) = { let (tx, rx) = tokio::sync::mpsc::channel(100); @@ -95,8 +98,7 @@ impl TestContext { &provider, &bank, &cloner, - validator_pubkey, - None, + validator_keypair.insecure_clone(), faucet_pubkey, rx, None, diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index e35bb7cdc..61e5978d5 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -125,8 +125,7 @@ impl IxtestContext { &provider, &bank, &cloner, - validator_kp.pubkey(), - None, + validator_kp.insecure_clone(), faucet_kp.pubkey(), rx, None, diff --git a/test-integration/test-chainlink/src/test_context.rs b/test-integration/test-chainlink/src/test_context.rs index 79c8ed79f..1070fd758 100644 --- a/test-integration/test-chainlink/src/test_context.rs +++ b/test-integration/test-chainlink/src/test_context.rs @@ -24,7 +24,9 @@ use magicblock_chainlink::{ }; use magicblock_config::config::{ChainLinkConfig, LifecycleMode}; use solana_account::{Account, AccountSharedData}; +use solana_keypair::Keypair; use solana_pubkey::Pubkey; +use solana_signer::Signer; use solana_sdk::{clock::Slot, sysvar::clock}; use tokio::sync::mpsc; use tracing::*; @@ -64,7 +66,8 @@ impl TestContext { let lifecycle_mode = LifecycleMode::Ephemeral; let bank = Arc::::default(); let cloner = Arc::new(ClonerStub::new(bank.clone())); - let validator_pubkey = Pubkey::new_unique(); + let validator_keypair = Keypair::new(); + let validator_pubkey = validator_keypair.pubkey(); let faucet_pubkey = Pubkey::new_unique(); let chain_slot = Arc::new(AtomicU64::new(slot)); let (fetch_cloner, remote_account_provider) = { @@ -98,8 +101,7 @@ impl TestContext { &provider, &bank, &cloner, - validator_pubkey, - None, + validator_keypair.insecure_clone(), faucet_pubkey, rx, None, From d96f590138f7dc1a01b9ac565d09ee4e9618e293 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 4 Mar 2026 22:13:26 +0530 Subject: [PATCH 13/16] handle ATA/EATA actions properly --- .../src/chainlink/fetch_cloner/mod.rs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index b166936ac..759fe10a4 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -21,8 +21,8 @@ use scc::{hash_map::Entry, HashMap}; use solana_account::{AccountSharedData, ReadableAccount}; use solana_keypair::Keypair; use solana_pubkey::Pubkey; -use solana_signer::Signer; use solana_sdk_ids::system_program; +use solana_signer::Signer; use tokio::{ sync::{mpsc, oneshot}, task, @@ -502,7 +502,15 @@ where let (account, deleg_record) = self .maybe_project_ata_from_subscription_update(pubkey, account) .await; - (Some(account), deleg_record, DelegationActions::default()) + if let Some((deleg_record, actions)) = deleg_record { + ( + Some(account), + Some(deleg_record), + actions.unwrap_or_default(), + ) + } else { + (Some(account), None, DelegationActions::default()) + } } } else { // This should not happen since we call this method with sub updates which always hold @@ -576,7 +584,10 @@ where &self, ata_pubkey: Pubkey, ata_account: AccountSharedData, - ) -> (AccountSharedData, Option) { + ) -> ( + AccountSharedData, + Option<(DelegationRecord, Option)>, + ) { let Some(ata_info) = is_ata(&ata_pubkey, &ata_account) else { return (ata_account, None); }; @@ -635,16 +646,16 @@ where let Some(deleg_record) = deleg_record else { return (ata_account, None); }; - let (deleg_record, _delegation_actions) = deleg_record; + let (deleg_record, delegation_actions) = deleg_record; if let Some(projected_ata) = self.maybe_project_delegated_ata_from_eata( &ata_account, &eata_account, &deleg_record, ) { - return (projected_ata, Some(deleg_record)); + return (projected_ata, Some((deleg_record, delegation_actions))); } - (ata_account, Some(deleg_record)) + (ata_account, Some((deleg_record, delegation_actions))) } fn maybe_project_delegated_ata_from_eata( From c4fa3cff444dcbb965d3479874c9e9290562bdfb Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Sun, 8 Mar 2026 11:55:18 +0100 Subject: [PATCH 14/16] feat: separate action tx --- magicblock-account-cloner/src/lib.rs | 44 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/magicblock-account-cloner/src/lib.rs b/magicblock-account-cloner/src/lib.rs index 668475564..43482c072 100644 --- a/magicblock-account-cloner/src/lib.rs +++ b/magicblock-account-cloner/src/lib.rs @@ -114,7 +114,7 @@ impl ChainlinkCloner { &self, request: &AccountCloneRequest, recent_blockhash: Hash, - ) -> Result { + ) -> Result<(Transaction, Option), SignerError> { let account_modification = AccountModification { pubkey: request.pubkey, lamports: Some(request.account.lamports()), @@ -133,7 +133,7 @@ impl ChainlinkCloner { message, ); // Defined positive commit frequency means commits should be scheduled - let mut ixs = match request.commit_frequency_ms { + let ixs = match request.commit_frequency_ms { // TODO(GabrielePicco): Hotfix. Do not schedule frequency commits until we impose limits. // 1. Allow configuring a higher minimum. // 2. Stop committing accounts if they have been committed more than X times, @@ -173,14 +173,25 @@ impl ChainlinkCloner { } _ => vec![modify_ix], }; - if !request.delegation_actions.is_empty() { - ixs.extend(request.delegation_actions.clone()); - } + let actions_tx = if !request.delegation_actions.is_empty() { + let mut tx = Transaction::new_with_payer( + &request + .delegation_actions + .clone() + .into_iter() + .collect::>(), + Some(&validator_authority_id()), + ); + tx.partial_sign(&[&validator_authority()], recent_blockhash); + Some(tx) + } else { + None + }; let mut tx = Transaction::new_with_payer(&ixs, Some(&validator_authority_id())); tx.try_sign(&[&validator_authority()], recent_blockhash)?; - Ok(tx) + Ok((tx, actions_tx)) } /// Creates a transaction to clone the given program into the validator. @@ -419,18 +430,19 @@ impl Cloner for ChainlinkCloner { request: AccountCloneRequest, ) -> ClonerResult { let recent_blockhash = self.block.load().blockhash; - let tx = self + let (tx, actions_tx) = self .transaction_to_clone_regular_account(&request, recent_blockhash)?; - let bypass_sigverify_for_replay_actions = - !request.delegation_actions.is_empty(); let sig = tx.signatures[0]; - - let send_res = if bypass_sigverify_for_replay_actions { - let sanitized_tx = tx.sanitize(false)?; - self.send_sanitized_transaction(sanitized_tx, sig).await - } else { - self.send_transaction(tx).await - }; + let send_res = self.send_transaction(tx).await; + + if let Some(actions_tx) = actions_tx { + let sanitized_tx = actions_tx.sanitize(false)?; + let actions_res = + self.send_sanitized_transaction(sanitized_tx, sig).await; + if let Err(err) = actions_res { + warn!(error = ?err, "Failed to send delegation actions"); + } + } if request.account.delegated() { self.maybe_prepare_lookup_tables( From 0eee454146065d247daa6f46f066513d7b1ba91d Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Sun, 8 Mar 2026 11:56:09 +0100 Subject: [PATCH 15/16] fix: actions for eata --- .../src/chainlink/fetch_cloner/ata_projection.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs index b6b918613..ddf75bca2 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/ata_projection.rs @@ -12,7 +12,7 @@ use tracing::*; use super::{delegation, types::AccountWithCompanion, FetchCloner}; use crate::{ - cloner::{AccountCloneRequest, Cloner, DelegationActions}, + cloner::{AccountCloneRequest, Cloner}, remote_account_provider::{ChainPubsubClient, ChainRpcClient}, }; @@ -114,6 +114,7 @@ where let mut account_to_clone = ata_account.account_shared_data_cloned(); let mut commit_frequency_ms = None; let mut delegated_to_other = None; + let mut actions = None; // If there's an eATA, try to use it + delegation record to project the ATA if let Some(eata_acc) = maybe_eata_account { @@ -127,10 +128,11 @@ where ) .await { - let (deleg_record, _delegation_actions) = deleg; + let (deleg_record, delegation_actions) = deleg; delegated_to_other = delegation::get_delegated_to_other(this, &deleg_record); commit_frequency_ms = Some(deleg_record.commit_frequency_ms); + actions = delegation_actions; if let Some(projected_ata) = this .maybe_project_delegated_ata_from_eata( @@ -148,7 +150,7 @@ where pubkey: ata_pubkey, account: account_to_clone, commit_frequency_ms, - delegation_actions: DelegationActions::default(), + delegation_actions: actions.unwrap_or_default(), delegated_to_other, }); } From 0d0023058f2cb523d167497e87b8c3635b6510d7 Mon Sep 17 00:00:00 2001 From: Dodecahedr0x Date: Sun, 8 Mar 2026 11:56:38 +0100 Subject: [PATCH 16/16] fix: test types --- .../src/chainlink/fetch_cloner/delegation.rs | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs index 090d2d592..7bfb514f6 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/delegation.rs @@ -83,11 +83,11 @@ fn parse_post_delegation_actions( let instructions = actions .decrypt_with_keypair(validator_keypair) .map_err(|err| { - ChainlinkError::InvalidDelegationActions( - delegation_record_pubkey, - format!("Failed to parse/decrypt PostDelegationActions: {err}"), - ) - })?; + ChainlinkError::InvalidDelegationActions( + delegation_record_pubkey, + format!("Failed to parse/decrypt PostDelegationActions: {err}"), + ) + })?; Ok(instructions.into()) } @@ -252,7 +252,11 @@ mod tests { let payload = serialize_record_with_actions( validator.pubkey(), PostDelegationActions { - signers: vec![signer, program_id, account], + signers: vec![ + *signer.as_array(), + *program_id.as_array(), + *account.as_array(), + ], non_signers: vec![], instructions: vec![MaybeEncryptedInstruction { program_id: 1, @@ -272,12 +276,9 @@ mod tests { }, ); - let (_, actions) = parse_delegation_record( - &payload, - Pubkey::new_unique(), - &validator, - ) - .unwrap(); + let (_, actions) = + parse_delegation_record(&payload, Pubkey::new_unique(), &validator) + .unwrap(); let actions: Vec = actions.unwrap().into(); assert_eq!(actions.len(), 1); @@ -315,7 +316,7 @@ mod tests { let payload = serialize_record_with_actions( validator.pubkey(), PostDelegationActions { - signers: vec![signer, account], + signers: vec![*signer.as_array(), *account.as_array()], non_signers: vec![MaybeEncryptedPubkey::Encrypted( EncryptedBuffer::new(encrypted_program_id), )], @@ -337,12 +338,9 @@ mod tests { }, ); - let (_, actions) = parse_delegation_record( - &payload, - Pubkey::new_unique(), - &validator, - ) - .unwrap(); + let (_, actions) = + parse_delegation_record(&payload, Pubkey::new_unique(), &validator) + .unwrap(); let actions: Vec = actions.unwrap().into(); assert_eq!(actions[0].program_id, program_id);