diff --git a/Cargo.lock b/Cargo.lock index f1bcc0e7..ae4ad997 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -281,9 +281,9 @@ dependencies = [ [[package]] name = "agave-feature-set" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e0d37e3232be339a6a19a376c7696458b6a8183e95bf806709fad71595010b" +checksum = "4a36f13a213d45f45f8ff87ea9fc6b0a792a7997c76b7c5d6d4a2ebe741d19d0" dependencies = [ "ahash", "solana-epoch-schedule 3.0.0", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "agave-fs" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89295def9adbab884000e4bdd88839caff7240a51fece0135147b526c84cea2d" +checksum = "08f4412d89cbeaa7cc39b6c1e37f052cb7f815433f3d2d6ed4f927da04c88f9a" dependencies = [ "agave-io-uring", "io-uring", @@ -309,9 +309,9 @@ dependencies = [ [[package]] name = "agave-geyser-plugin-interface" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9f17248234375e36023de5dddf0a5670a0d66451672f831a52fcb4b49400c6d" +checksum = "f46995dfc784b35e4156efabdda06669135c26f1814d2544cc4c9ff8df153ca7" dependencies = [ "log 0.4.29", "solana-clock 3.0.0", @@ -324,9 +324,9 @@ dependencies = [ [[package]] name = "agave-io-uring" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1294034c7136721e8443819052918e0d25da9f242ec8b6774c7552e49243939b" +checksum = "6b10398e813092a6f7f3d8a4ad4017870087bdb3a10ade3281b186086e6e775e" dependencies = [ "io-uring", "libc", @@ -337,9 +337,9 @@ dependencies = [ [[package]] name = "agave-logger" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04377a8569430250d1eb4e8a40c353d2921e3b1ae26a9262596b1c28cef0d91f" +checksum = "92bb03118dee8e9feb1e5f9a999c415a1aec647f2fbe330251bbb58a76caf3a1" dependencies = [ "env_logger", "libc", @@ -349,9 +349,9 @@ dependencies = [ [[package]] name = "agave-precompiles" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11b1fe7c3517dcc37f74ba06845ebf10f769a6072a222fb1d0b528b3a48bb980" +checksum = "c4321be6c2553f19159af1efaccc8b7951ad4b143840c91439da190f8205e92e" dependencies = [ "agave-feature-set", "bincode", @@ -371,9 +371,9 @@ dependencies = [ [[package]] name = "agave-reserved-account-keys" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c651f94dc123e67cacfcf320b686aaaf8daf7910a263982ab806fe50ae197eb0" +checksum = "6e4dbcc14290a572b94f8793561f74f87e8dd1efb6c28c883d79a84242ee9633" dependencies = [ "agave-feature-set", "solana-pubkey 3.0.0", @@ -382,9 +382,9 @@ dependencies = [ [[package]] name = "agave-snapshots" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ed2129e426ae5ba4e97be13a674378481521644e5cd86226ef9cc79ad4a186" +checksum = "8d885e8f6ddc79bf6b6d6b4347974e0d846feccab1c9ae666ad92e21cf43dfc4" dependencies = [ "agave-fs", "bincode", @@ -412,9 +412,9 @@ dependencies = [ [[package]] name = "agave-syscalls" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "580e09664e6b9fb15cc40bc073ab3271a4a67893d2e25a74594b9ee51a39d9a5" +checksum = "108ce050e29fa68a49928213a74f12fc314f8f6964cceeec908be700f1ae5a80" dependencies = [ "bincode", "libsecp256k1 0.6.0", @@ -455,9 +455,9 @@ dependencies = [ [[package]] name = "agave-transaction-view" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d87d10c46d625888ce61473881b7a9ebfb794e82db72dfaf434932b71aca46" +checksum = "5dc12186a81042cd93d5199adb469bdc7215968dda6c59f778a02eaa3aac7896" dependencies = [ "solana-hash 3.1.0", "solana-message 3.0.1", @@ -472,9 +472,9 @@ dependencies = [ [[package]] name = "agave-votor-messages" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae73c52174711f2775475c3251948dfb3cef750659124b688c6a486abbe73162" +checksum = "66191497da4f496b7866e41dc227f894ba58ee58127c7be29dd709574549baab" dependencies = [ "agave-logger", "serde", @@ -630,6 +630,49 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "anza-quinn" +version = "0.11.9-rustsec20260037" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91bfa08f6e7e4187354ff4f793b81cc08218a6a95cc48f5de7616d44452bf6e0" +dependencies = [ + "anza-quinn-proto", + "bytes 1.11.0", + "cfg_aliases", + "pin-project-lite", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls 0.23.36", + "socket2 0.6.1", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "anza-quinn-proto" +version = "0.11.13-rustsec20260037" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00a4d8cf8d72ee56e0ee20d3b4eef4785ce1b05299c4982c6de7f251c458efe" +dependencies = [ + "bytes 1.11.0", + "fastbloom", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash 2.1.1", + "rustls 0.23.36", + "rustls-pki-types", + "rustls-platform-verifier", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + [[package]] name = "aquamarine" version = "0.6.0" @@ -6087,7 +6130,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes 1.11.0", - "fastbloom", "getrandom 0.3.4", "lru-slab", "rand 0.9.2", @@ -6095,7 +6137,6 @@ dependencies = [ "rustc-hash 2.1.1", "rustls 0.23.36", "rustls-pki-types", - "rustls-platform-verifier", "slab", "thiserror 2.0.17", "tinyvec", @@ -7451,9 +7492,9 @@ dependencies = [ [[package]] name = "solana-account-decoder" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2743ab6d07e8261a2066d9f118a566a9c4c2143629a3c3d0a7dc58c3d37b659f" +checksum = "57fcc1c9e2a2d82c9aa09e0d34940b6c5a43c2fd5eea38c7caed0f6b177e27a8" dependencies = [ "Inflector", "base64 0.22.1", @@ -7493,9 +7534,9 @@ dependencies = [ [[package]] name = "solana-account-decoder-client-types" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903d72faba9acbb483b35e00d5c84e4245367336410553fc4d1f216219283724" +checksum = "43e62ffb8742a71d3e8b5263ba892cdc65b24b063fa5b5f414205350b031a730" dependencies = [ "base64 0.22.1", "bs58", @@ -7532,9 +7573,9 @@ dependencies = [ [[package]] name = "solana-accounts-db" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca8e528d3d72568fbf9aaf49775e5092708702f622ffb8b6f8cc6f249aa8af" +checksum = "9b4440c9ef4a236679a2ce959942aa2484820a87cfeebba9507f0e37fd53d922" dependencies = [ "agave-fs", "ahash", @@ -7800,9 +7841,9 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e9e9ecfbcdab74fa1cb71d96acaefdcf121f72216679b8e442d6706b04041c" +checksum = "36128e7525889b05f13a4dbfb86f1ff3aef2063ab63b899591d348226e20def8" dependencies = [ "agave-syscalls", "bincode", @@ -7829,9 +7870,9 @@ dependencies = [ [[package]] name = "solana-bucket-map" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f83cad0d9b2e5c1a743a49701c6851d76ff8c9e9b5070fadc6c9894419f40f" +checksum = "2a7cec41cfc4bf0db14ae82c0705e2d00034b5021268a07ef120f3870587c5bb" dependencies = [ "bv", "bytemuck", @@ -7848,9 +7889,9 @@ dependencies = [ [[package]] name = "solana-builtins" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39286125e1c326f980a9362af2efa4f0b97346d21454d80ebd49b4c8f7bdcf9d" +checksum = "784cd398c18e3d565d08382d1f83c94d4603647169239f37b32ba25439873b07" dependencies = [ "agave-feature-set", "solana-bpf-loader-program", @@ -7868,9 +7909,9 @@ dependencies = [ [[package]] name = "solana-builtins-default-costs" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35ec9ee016708e5127fbc7934471ba47ace8bc4915dd70ab8b9932a78162d5" +checksum = "98f0361a1c69c869ed9c03cd7fbbacbda5e51b80d41aab5e3b2b2a21f2bca5d9" dependencies = [ "agave-feature-set", "ahash", @@ -7886,10 +7927,11 @@ dependencies = [ [[package]] name = "solana-client" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee8a02f1f8646d456d75a0ca3aa3c8aee3e06b1f22a5b25dfcbdc8d87855aa5" +checksum = "56cdbbecbda755254a0c11010472a53036ff6fccdf5d7e908b92c95f04ff2497" dependencies = [ + "anza-quinn", "async-trait", "bincode", "dashmap", @@ -7898,7 +7940,6 @@ dependencies = [ "indexmap 2.13.0", "indicatif", "log 0.4.29", - "quinn", "rayon", "solana-account 3.3.0", "solana-client-traits", @@ -8002,9 +8043,9 @@ dependencies = [ [[package]] name = "solana-compute-budget" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ed761cecdab6839347c51f30dc3e27c8dbf42d6cf8e0ea14daa689527be31af" +checksum = "c346408840a596e128b1b5214fd72a2c1cf8484cc96965e10333f6a18fcb897b" dependencies = [ "solana-fee-structure", "solana-program-runtime", @@ -8012,9 +8053,9 @@ dependencies = [ [[package]] name = "solana-compute-budget-instruction" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6beec9d834485f151ba9d4e447a74eb2d5f283e281170f09d5c7b7289c25dba6" +checksum = "e5247f6c5a646681ed98f8f92b01d18ae75a22311ee00415ed2970d60dfcd610" dependencies = [ "agave-feature-set", "log 0.4.29", @@ -8044,9 +8085,9 @@ dependencies = [ [[package]] name = "solana-compute-budget-program" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c23bf81703f42d0e6b14c0e2bbc0af1145758ebebc02e58f7e2d87f9939ce5" +checksum = "bb474148341578c7aebd3a6d42e2f5b3be0c49ed28eb325460966d63073c9498" dependencies = [ "solana-program-runtime", ] @@ -8070,9 +8111,9 @@ dependencies = [ [[package]] name = "solana-connection-cache" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97904fc33d6ac88fe4012f631bd0a7674e5cdda22934930844e99618a140efdc" +checksum = "efbacf3640794251ba0efa0bc13fbbaeac90f0e02c15dd723da1b7fec058f3b2" dependencies = [ "async-trait", "bincode", @@ -8093,9 +8134,9 @@ dependencies = [ [[package]] name = "solana-cost-model" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acb993c81c44cc461bbe9476b384458a3841585b7ca0ff8c66930351ab83fd2" +checksum = "39e905e7a64c5b784e7b916d96ebc244f415cd535858b44d5e414b54a3fc198e" dependencies = [ "agave-feature-set", "ahash", @@ -8149,9 +8190,9 @@ dependencies = [ [[package]] name = "solana-curve25519" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7012a457fa158f4b0e7160add8d3882536177a2e4942be5c993f7bff65edbec" +checksum = "f3d7e1177e6006823b91e0a930d94992ed74f8a6327d54ee50a9457ff72e625a" dependencies = [ "bytemuck", "bytemuck_derive", @@ -8353,9 +8394,9 @@ dependencies = [ [[package]] name = "solana-fee" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e269a2656b7e21fbf05d1c716545bb70282c498db36e3d3ee25bd89b3bd6b6" +checksum = "56a1e5ee3af013f0851107fbf873c4949aeb7bfaeaea5444fa7ed0adb209696f" dependencies = [ "agave-feature-set", "solana-fee-structure", @@ -8657,9 +8698,9 @@ dependencies = [ [[package]] name = "solana-lattice-hash" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eea908b2fc2aa0757000d8ee1ef6643a5812b2a1709d1d98bfde5aae9d08fbb" +checksum = "4a723b440d3aaa896a5dd137b35b966cfd61ef64529636bb1125f3f2bc2d6b8a" dependencies = [ "base64 0.22.1", "blake3", @@ -8757,9 +8798,9 @@ dependencies = [ [[package]] name = "solana-loader-v4-program" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d33dffb6450fc700e9ddc4098eae8e0553e0d09d41bae170ad2cfc088ff11e" +checksum = "3f21fc8ee1d0f22ff002542f352eb5c38128dfc2dbc700be1db23251ecc3e78c" dependencies = [ "log 0.4.29", "solana-account 3.3.0", @@ -8781,9 +8822,9 @@ dependencies = [ [[package]] name = "solana-measure" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef687aac555fa8ab56f1fff63be6902c484784344ce195653bd840a3d19462be" +checksum = "1ee6df5d71fbc041b3badfd014753b76c643f5fcb9bba2498aae2a30d40616d0" [[package]] name = "solana-message" @@ -8830,9 +8871,9 @@ dependencies = [ [[package]] name = "solana-metrics" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3595ded6be33832d82c75d3bcae1018f48635b3ec47578d275c807ab1cb565" +checksum = "bb0f05dfe08e1b14429eb35feb15f89455d7c75d8a1704ee8da1f0ebf0993d42" dependencies = [ "crossbeam-channel", "gethostname", @@ -8876,9 +8917,9 @@ checksum = "ae8dd4c280dca9d046139eb5b7a5ac9ad10403fbd64964c7d7571214950d758f" [[package]] name = "solana-net-utils" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54820b244f1bc56514cf02232453046ea537c9e590478962e976a62162f17915" +checksum = "5ed12c06e326edff1a26380f18b01d1c9ec4723aeed2c0d6dec1035d9eacb1fa" dependencies = [ "anyhow", "bincode", @@ -8969,9 +9010,9 @@ dependencies = [ [[package]] name = "solana-perf" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ce50c6e8de8616805c3e7b327289288bdb3385b309ec197ddd5fa05ba16780" +checksum = "cae20efb5ec6c98b3932d6755d5df962ab51344f099d704317a79af2faa42403" dependencies = [ "ahash", "bincode", @@ -9012,9 +9053,9 @@ dependencies = [ [[package]] name = "solana-poseidon" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c9e5e07cb1bb04384dfe993f6cddcf88388181922a0706c8b4b7c012cf3e18" +checksum = "25a2c8f53a80947785b58e55bda1b619bac03f266c9055b7b0208775f0522057" dependencies = [ "ark-bn254 0.4.0", "ark-bn254 0.5.0", @@ -9212,9 +9253,9 @@ dependencies = [ [[package]] name = "solana-program-runtime" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1da9aa0062feef8162662725dbadc2f9aed390e64ab3536176085cced4b7050b" +checksum = "b9cefa43d3f60a2dd25e0fcc3a5a46f50de021c42981029b1e8f375e1d954853" dependencies = [ "base64 0.22.1", "bincode", @@ -9302,9 +9343,9 @@ dependencies = [ [[package]] name = "solana-pubsub-client" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3b7936218ede5b8a4c87182e5ddea5185725215b2a2866246e8152e52f7fcf" +checksum = "320923e8c430d05c515f2f413dee50afa0da421b4fe37dc4b76fd9f28b7409a7" dependencies = [ "crossbeam-channel", "futures-util", @@ -9328,17 +9369,17 @@ dependencies = [ [[package]] name = "solana-quic-client" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4adf1b06dce39d8c0bed00eba133128b3b96c8005313245bb6863d4eefd2022" +checksum = "4ede9c4da2447500b05c2fdc8b238c703b33943604a927dc197733bc91ac2a1f" dependencies = [ + "anza-quinn", + "anza-quinn-proto", "async-lock", "async-trait", "futures 0.3.31", "itertools 0.12.1", "log 0.4.29", - "quinn", - "quinn-proto", "rustls 0.23.36", "solana-connection-cache", "solana-keypair", @@ -9367,9 +9408,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c6a12644a32196de6e7dfdd5ad66183f952fe259ad4f166260838369f14a8e" +checksum = "09d48133891ea0e717d845059429b98d03bab34f3ec4e2b58bfe78248a898017" dependencies = [ "log 0.4.29", "num_cpus", @@ -9424,9 +9465,9 @@ dependencies = [ [[package]] name = "solana-rpc-client" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403ce2edf55df72d5334df102aee0e6798840e8911d96d9870a464337fcc86b6" +checksum = "29f7447f65aacd7ef752393bec2a9082d0313983b804f92d06fe72caf44e8cd6" dependencies = [ "async-trait", "base64 0.22.1", @@ -9464,9 +9505,9 @@ dependencies = [ [[package]] name = "solana-rpc-client-api" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c12b2f11d22f67d0be1704c8386e4b30ea5fab2ee9bc5b92b321b533d4b81c6" +checksum = "841d953ce18f99a07c8101e071dd54d2a99b80835ad2ea1566913c55d4bce2ef" dependencies = [ "anyhow", "jsonrpc-core", @@ -9485,9 +9526,9 @@ dependencies = [ [[package]] name = "solana-rpc-client-nonce-utils" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcf8cd1aad9c762370509d977072720df2aff499a2c4df9a31510d25561e626" +checksum = "b0e7777237c3791d40039ab1274d346949497f9be48cd688717ff001cb740cf9" dependencies = [ "solana-account 3.3.0", "solana-commitment-config", @@ -9502,9 +9543,9 @@ dependencies = [ [[package]] name = "solana-rpc-client-types" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e24a1a1bce172a4bcab315ae713fb61e364f8e8151358c7ac04d626a2794212" +checksum = "095c430a4ff4ddb10b7399f8d3d26eafeaccb84f8802568594f6f5941c60dff5" dependencies = [ "base64 0.22.1", "bs58", @@ -9529,9 +9570,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96cf0b658ccca2f5aaf81684829dbaba570f966faf59774f8a58d56ce2c116e4" +checksum = "bcade4e95d16de9ecdb7cc108eb65be6e9c468ba5c6dcf0b0f2cb42e68ccb9b5" dependencies = [ "agave-feature-set", "agave-fs", @@ -9666,9 +9707,9 @@ dependencies = [ [[package]] name = "solana-runtime-transaction" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58985074a7187b57ea6a20185b34a830986faf92abd725399bf2bbb89cccc9c7" +checksum = "85538e4376c5d8cab0fc9afa10a193edda72affa1727f56696600e3e2ffe0766" dependencies = [ "agave-transaction-view", "log 0.4.29", @@ -10065,10 +10106,12 @@ dependencies = [ [[package]] name = "solana-streamer" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "623840c97214530c492666f473170276e9df77bf9fc62332b67f8ff4ac027e21" +checksum = "e9c9d1d759bb2d08119e45dcb0ff6834038086cc7b2d1f4e279f2ac340d77bce" dependencies = [ + "anza-quinn", + "anza-quinn-proto", "arc-swap", "bytes 1.11.0", "crossbeam-channel", @@ -10085,8 +10128,6 @@ dependencies = [ "num_cpus", "pem 1.1.1", "percentage", - "quinn", - "quinn-proto", "rand 0.8.5", "rustls 0.23.36", "smallvec", @@ -10113,9 +10154,9 @@ dependencies = [ [[package]] name = "solana-svm" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3447fbe5c28bc4931ce928a91dc0b777153017a25817aa9675636407a957ea3b" +checksum = "586cd746aa1ef80bd5735813de1b3cb9b1b0c5b5b81ded3069aed213b45de046" dependencies = [ "ahash", "log 0.4.29", @@ -10156,9 +10197,9 @@ dependencies = [ [[package]] name = "solana-svm-callback" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50574c1cd55286e56d5382952ceea099ee4a4426c889a3b1e456806f83bdd92" +checksum = "b9114cc1391e57d0d6902c7c347964cb8e41e3c141ebb4be3ec5440be1c994fa" dependencies = [ "solana-account 3.3.0", "solana-clock 3.0.0", @@ -10168,30 +10209,30 @@ dependencies = [ [[package]] name = "solana-svm-feature-set" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4a59053cd2bbee5e85476739707f5030a089457c4140340960260e7aedc2a0" +checksum = "62a20c4fc8d409780c4592c17ac3e01b6f3dc949e6ffd3acbda6d2a21e67b53a" [[package]] name = "solana-svm-log-collector" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6097230b3506b5206088cb248012540f6adff10597a5da0d33c21523c79cdda" +checksum = "f92f14f80cf719d5bc2c14bbee50075920637d1f9afe2fce990e5394fa579293" dependencies = [ "log 0.4.29", ] [[package]] name = "solana-svm-measure" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55976a874cc3c07e0b1ec2a1177ec420c5608f61a8735c44aef1ca7c73b829d8" +checksum = "f4c68915dfa801dd03b3f7c3e0a510fe233754463e77f5afe6a30a51ac9fa326" [[package]] name = "solana-svm-timings" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3434a3ba8ca342c2c9b4c89ca0b506dbf460f77f6dd1dc7cf0ba804f8d749810" +checksum = "89a98d45197b57ae84bbf97647840adb153e444ad147638e742929d83343f48e" dependencies = [ "eager", "enum-iterator", @@ -10200,9 +10241,9 @@ dependencies = [ [[package]] name = "solana-svm-transaction" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db058c2c629ff5dc8fb2cf234d44c0d17d8464f94c62652219de88d83fa65a52" +checksum = "1a6074e3b4bdd7ade15db51a4f309eb9e22239d33b01f4ea5ecf6aff8f81d0ba" dependencies = [ "solana-hash 3.1.0", "solana-message 3.0.1", @@ -10214,9 +10255,9 @@ dependencies = [ [[package]] name = "solana-svm-type-overrides" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2511decc60b5c1c56d65670b42952b9a9139f0a7fa432a2a7a639c12f71f0e8" +checksum = "51b2ea7c2f849cd6d190e2607c2af779d3dad2792784cc13c0e9342e429c87a1" dependencies = [ "rand 0.8.5", ] @@ -10254,9 +10295,9 @@ dependencies = [ [[package]] name = "solana-system-program" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "821ea87b11b2a5232e238fe8dd48f10646405f8ca5c09dd036b5b57b1b2f8116" +checksum = "14d88343aac5ad97d240eca299c8dfcde833e861b6a40bff6fda3ac215efc211" dependencies = [ "bincode", "log 0.4.29", @@ -10390,9 +10431,9 @@ checksum = "0ced92c60aa76ec4780a9d93f3bd64dfa916e1b998eacc6f1c110f3f444f02c9" [[package]] name = "solana-tls-utils" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3173e89d55a1b85e1b86cf1384fb505a2211052e15a6f3aa4a28caf6d6b3c85" +checksum = "05b5c952335b378c92ad47286a7dee28acfd0b0ce1ac89562f51b4dcb33210ea" dependencies = [ "rustls 0.23.36", "solana-keypair", @@ -10403,9 +10444,9 @@ dependencies = [ [[package]] name = "solana-tpu-client" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2256899a1a9e31c70c1ea707e0b59613eec736503c7adede57accb40c50efef1" +checksum = "d331918bac33058ac2acd923c4cf646a8b7bc77fd7463d886da9f24b9e2787c1" dependencies = [ "async-trait", "bincode", @@ -10459,9 +10500,9 @@ dependencies = [ [[package]] name = "solana-transaction-context" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017886b71c6c22d15b08967c8d6f9e94f1745a2f01c280d08d22f82d5454bcd1" +checksum = "be7c191d89fb883fef0b4bb4225121f7ad14eb5664d5dc9707b4af661e21924c" dependencies = [ "bincode", "serde", @@ -10498,9 +10539,9 @@ dependencies = [ [[package]] name = "solana-transaction-metrics-tracker" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43917f2ad4d7faf3028a1fad990a0c5ee30e6e75913c73537eb81049ba171831" +checksum = "257ae75d68fe879753baef265a0d1bfcf9274b212dfc44ffea177ce0f1271508" dependencies = [ "base64 0.22.1", "bincode", @@ -10514,9 +10555,9 @@ dependencies = [ [[package]] name = "solana-transaction-status" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15be3ad6c8f39beffcb5e5a5c62c87696c3749e9ef20b8ec62544dec101d22a2" +checksum = "81283f595988fccb91f1697addde2efd074aea4e7b2853e4415e06a8754ff8ee" dependencies = [ "Inflector", "agave-reserved-account-keys", @@ -10557,9 +10598,9 @@ dependencies = [ [[package]] name = "solana-transaction-status-client-types" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b3cb8c718af0245ab3b84324f856661d87e29f193c0c0125ed0a4c212814d61" +checksum = "3a02265337e99bf3e446de1d8133b2d28556f06780e9ab516870317688f332e0" dependencies = [ "base64 0.22.1", "bincode", @@ -10581,9 +10622,9 @@ dependencies = [ [[package]] name = "solana-udp-client" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf297ba743dee44f1a011b06bbdcbd7cb4a6444ae8b42148de7818b007f6078" +checksum = "3f55aab86699ab277347e7086157a1a7c599ce3817c0a8bb07b62bbe3a113f44" dependencies = [ "async-trait", "solana-connection-cache", @@ -10597,9 +10638,9 @@ dependencies = [ [[package]] name = "solana-unified-scheduler-logic" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4bb4fd669df4c8601637667e81380b52d924c5c4bad6d14c550033483e2ad50" +checksum = "d653d85171c16e6b5e35c3525dd012b50b2c089f8ffe13692f599e7fe14b18fc" dependencies = [ "assert_matches", "solana-pubkey 3.0.0", @@ -10611,9 +10652,9 @@ dependencies = [ [[package]] name = "solana-version" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d1c28ae4e600f7b2b76cce76696c7ee4ab2078f5428125d04ed31c421dfb122" +checksum = "17a9c5d23a31d8f34aac59812099c9d8d76203a447d04b65824f5c913ced9072" dependencies = [ "agave-feature-set", "rand 0.8.5", @@ -10625,9 +10666,9 @@ dependencies = [ [[package]] name = "solana-vote" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791e2cdc4966a8dddce04b420adc53e8a95fe566a77e50062ac86252f6976e1d" +checksum = "c0809748b89d2aaf6ba4020554ad10487166deff1ff3304ac0a973d67c5f17b7" dependencies = [ "itertools 0.12.1", "log 0.4.29", @@ -10702,9 +10743,9 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2d2e3bfbb9c8e365f38338fa30875d2692b51057d24e776744af3d4455d06d" +checksum = "be3d7ddb2f7585dcc2225dec9991b15a76c2b80c3edad8f4d5b563fd6b7a2f25" dependencies = [ "agave-feature-set", "bincode", @@ -10734,9 +10775,9 @@ dependencies = [ [[package]] name = "solana-zk-elgamal-proof-program" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d51a84e64cbe2919fa976608ca4b71ea7de357b12391b97f67291114bf3f3ee" +checksum = "f83f4e40a373aee876998df8f2ffb2a7a6a49667b732a0e6de6d8e5655edc392" dependencies = [ "agave-feature-set", "bytemuck", @@ -10788,9 +10829,9 @@ dependencies = [ [[package]] name = "solana-zk-token-proof-program" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad8a36cc3f7e6b8f8ee0de12c0a40cc9d4600969b4f5dd9cda1d7bac042df71" +checksum = "6a51feb27c5d776ca053a9b4dd6d7635015fae86fd07b0e74f0cf38e78941d3c" dependencies = [ "agave-feature-set", "bytemuck", @@ -10805,9 +10846,9 @@ dependencies = [ [[package]] name = "solana-zk-token-sdk" -version = "3.1.6" +version = "3.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6e474c0678fc5aa288157bded120ac92f55cd8d7530344ad6f541e5c7dba1e" +checksum = "f2cd24e74dc810c1270c4c8237e4c1fb9f5b80ba3eba96da125070e17187b838" dependencies = [ "aes-gcm-siv", "base64 0.22.1", @@ -11212,6 +11253,7 @@ version = "1.1.1" dependencies = [ "actix-cors", "actix-web", + "agave-feature-set", "ansi_term", "anyhow", "atty", @@ -11455,6 +11497,7 @@ dependencies = [ name = "surfpool-types" version = "1.1.1" dependencies = [ + "agave-feature-set", "anchor-lang-idl", "blake3", "chrono", @@ -11475,7 +11518,6 @@ dependencies = [ "solana-transaction", "solana-transaction-context", "solana-transaction-error 3.0.0", - "strum 0.26.3", "test-case", "txtx-addon-kit", "txtx-addon-network-svm-types", diff --git a/Cargo.toml b/Cargo.toml index ccdd1ecf..1137ae74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ resolver = "2" [workspace.dependencies] actix-cors = "0.7.0" actix-web = { version = "4", default-features = false } -agave-feature-set = { version = "3.1", default-features = false } +agave-feature-set = { version = "3.1.9", default-features = false } agave-geyser-plugin-interface = { version = "3.1", default-features = false } agave-reserved-account-keys = { version = "3.1", default-features = false } anchor-lang-idl = "0.1.2" diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 1bf3e866..67da8f01 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -42,6 +42,7 @@ ratatui = { workspace = true } rust-embed = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +agave-feature-set = { workspace = true } solana-clock = { workspace = true } solana-commitment-config = { workspace = true } solana-epoch-info = { workspace = true } diff --git a/crates/cli/src/cli/mod.rs b/crates/cli/src/cli/mod.rs index 4060d318..0e660bc6 100644 --- a/crates/cli/src/cli/mod.rs +++ b/crates/cli/src/cli/mod.rs @@ -25,7 +25,7 @@ use surfpool_types::{ DEFAULT_DEVNET_RPC_URL, DEFAULT_GOSSIP_PORT, DEFAULT_MAINNET_RPC_URL, DEFAULT_NETWORK_HOST, DEFAULT_RPC_PORT, DEFAULT_SLOT_TIME_MS, DEFAULT_TESTNET_RPC_URL, DEFAULT_TPU_PORT, DEFAULT_TPU_QUIC_PORT, DEFAULT_WS_PORT, RpcConfig, SimnetConfig, SimnetEvent, StudioConfig, - SubgraphConfig, SurfpoolConfig, SvmFeature, SvmFeatureConfig, + SubgraphConfig, SurfpoolConfig, SvmFeatureConfig, parse_feature_pubkey, }; use txtx_cloud::LoginCommand; use txtx_core::manifest::WorkspaceManifest; @@ -235,13 +235,17 @@ pub struct StartSimnet { /// Path to the Test.toml test suite files to load (eg. surfpool start --anchor-test-config-path ./path/to/Test.toml) #[arg(long = "anchor-test-config-path")] pub anchor_test_config_paths: Vec, - /// Enable specific SVM features. Can be specified multiple times. (eg. surfpool start --feature enable-loader-v4 --feature enable-sbpf-v2-deployment-and-execution) - #[arg(long = "feature", short = 'f', value_parser = parse_svm_feature)] - pub features: Vec, - /// Disable specific SVM features. Can be specified multiple times. (eg. surfpool start --disable-feature disable-fees-sysvar) - #[arg(long = "disable-feature", value_parser = parse_svm_feature)] - pub disable_features: Vec, - /// Enable all SVM features (override mainnet defaults which are used by default) + /// Enable specific SVM features by pubkey. Can be specified multiple times. (eg. surfpool start --feature --feature ) + /// Note: providing feature names has been deprecated. Previously supported feature names will still work, but this will be dropped in the future. + /// Instead, you should migrate to providing the pubkey for the feature. + #[arg(long = "feature", short = 'f', value_parser = parse_feature_pubkey)] + pub features: Vec, + /// Disable specific SVM features by pubkey. Can be specified multiple times. (eg. surfpool start --disable-feature --disable-feature ) + /// Note: providing feature names has been deprecated. Previously supported feature names will still work, but this will be dropped in the future. + /// Instead, you should migrate to providing the pubkey for the feature. + #[arg(long = "disable-feature", value_parser = parse_feature_pubkey)] + pub disable_features: Vec, + /// Enable all SVM features from agave-feature-set (override mainnet defaults) #[clap(long = "features-all", action=ArgAction::SetTrue, default_value = "false")] pub all_features: bool, /// A set of inputs to use for the runbook (eg. surfpool start --runbook-input myInputs.json) @@ -265,15 +269,6 @@ pub struct StartSimnet { pub skip_signature_verification: bool, } -fn parse_svm_feature(s: &str) -> Result { - SvmFeature::from_str(s).map_err(|_| { - format!( - "Unknown SVM feature: '{}'. Use --help to see available features.", - s - ) - }) -} - #[derive(clap::ValueEnum, PartialEq, Clone, Debug)] pub enum NetworkType { /// Solana Mainnet-Beta (https://api.mainnet-beta.solana.com) @@ -369,10 +364,10 @@ impl StartSimnet { pub fn feature_config(&self) -> SvmFeatureConfig { let mut config = if self.all_features { - // Enable all SVM features (override mainnet defaults) + // Enable all SVM features from agave-feature-set (override mainnet defaults) let mut cfg = SvmFeatureConfig::default(); - for feature in SvmFeature::all() { - cfg = cfg.enable(feature); + for pubkey in agave_feature_set::FEATURE_NAMES.keys() { + cfg = cfg.enable(*pubkey); } cfg } else { @@ -381,13 +376,13 @@ impl StartSimnet { }; // Apply explicit enables (these override defaults) - for feature in &self.features { - config = config.enable(*feature); + for pubkey in &self.features { + config = config.enable(*pubkey); } // Apply explicit disables (these override defaults) - for feature in &self.disable_features { - config = config.disable(*feature); + for pubkey in &self.disable_features { + config = config.disable(*pubkey); } config diff --git a/crates/core/src/surfnet/locker.rs b/crates/core/src/surfnet/locker.rs index fb4f6d70..a223b24a 100644 --- a/crates/core/src/surfnet/locker.rs +++ b/crates/core/src/surfnet/locker.rs @@ -251,11 +251,15 @@ impl SurfnetSvmLocker { if result.is_none() { return match svm_reader.get_account_from_feature_set(pubkey) { - Some(account) => GetAccountResult::FoundAccount( - *pubkey, account, - // mark as not an account that should be updated in the SVM, since this is a local read and it already exists - false, - ), + Some(account) => { + GetAccountResult::FoundAccount( + *pubkey, account, + // mark this as an account to insert into the SVM, since the feature is activated and LiteSVM doesn't + // automatically insert activated feature accounts + // TODO: mark as false once https://github.com/LiteSVM/litesvm/pull/308 is released + true, + ) + } None => GetAccountResult::None(*pubkey), }; } else { @@ -326,8 +330,10 @@ impl SurfnetSvmLocker { result = match svm_reader.get_account_from_feature_set(pubkey) { Some(account) => GetAccountResult::FoundAccount( *pubkey, account, - // mark as not an account that should be updated in the SVM, since this is a local read and it already exists - false, + // mark this as an account to insert into the SVM, since the feature is activated and LiteSVM doesn't + // automatically insert activated feature accounts + // TODO: mark as false once https://github.com/LiteSVM/litesvm/pull/308 is released + true, ), None => GetAccountResult::None(*pubkey), } diff --git a/crates/core/src/surfnet/surfnet_lite_svm.rs b/crates/core/src/surfnet/surfnet_lite_svm.rs index 0a3e292d..cf5882f2 100644 --- a/crates/core/src/surfnet/surfnet_lite_svm.rs +++ b/crates/core/src/surfnet/surfnet_lite_svm.rs @@ -128,7 +128,10 @@ impl SurfnetLiteSvm { self.svm = LiteSVM::new() .with_blockhash_check(false) .with_sigverify(false) - .with_feature_set(feature_set); + .with_feature_set(feature_set) + .with_builtins() + .with_sysvars() + .with_default_programs(); create_native_mint(self); self diff --git a/crates/core/src/surfnet/svm.rs b/crates/core/src/surfnet/svm.rs index bbcb9638..25aaf54e 100644 --- a/crates/core/src/surfnet/svm.rs +++ b/crates/core/src/surfnet/svm.rs @@ -5,24 +5,7 @@ use std::{ time::SystemTime, }; -use agave_feature_set::{ - FeatureSet, abort_on_invalid_curve, blake3_syscall_enabled, curve25519_syscall_enabled, - deplete_cu_meter_on_vm_failure, deprecate_legacy_vote_ixs, - disable_deploy_of_alloc_free_syscall, disable_fees_sysvar, disable_sbpf_v0_execution, - disable_zk_elgamal_proof_program, enable_alt_bn128_compression_syscall, - enable_alt_bn128_syscall, enable_big_mod_exp_syscall, - enable_bpf_loader_set_authority_checked_ix, enable_extend_program_checked, - enable_get_epoch_stake_syscall, enable_loader_v4, enable_poseidon_syscall, - enable_sbpf_v1_deployment_and_execution, enable_sbpf_v2_deployment_and_execution, - enable_sbpf_v3_deployment_and_execution, fix_alt_bn128_multiplication_input_length, - formalize_loaded_transaction_data_size, get_sysvar_syscall_enabled, - increase_tx_account_lock_limit, last_restart_slot_sysvar, loosen_cpi_size_restriction, - mask_out_rent_epoch_in_vm_serialization, move_precompile_verification_to_svm, - move_stake_and_move_lamports_ixs, raise_cpi_nesting_limit_to_8, reenable_sbpf_v0_execution, - reenable_zk_elgamal_proof_program, remaining_compute_units_syscall_enabled, - remove_bpf_loader_incorrect_program_id, simplify_alt_bn128_syscall_error_codes, - stake_raise_minimum_delegation_to_1_sol, stricter_abi_and_runtime_constraints, -}; +use agave_feature_set::{FeatureSet, enable_extend_program_checked}; use base64::{Engine, prelude::BASE64_STANDARD}; use chrono::Utc; use convert_case::Casing; @@ -69,9 +52,8 @@ use surfpool_types::{ AccountChange, AccountProfileState, AccountSnapshot, DEFAULT_PROFILING_MAP_CAPACITY, DEFAULT_SLOT_TIME_MS, ExportSnapshotConfig, ExportSnapshotScope, FifoMap, Idl, OverrideInstance, ProfileResult, RpcProfileDepth, RpcProfileResultConfig, - RunbookExecutionStatusReport, SimnetEvent, SvmFeature, SvmFeatureConfig, - TransactionConfirmationStatus, TransactionStatusEvent, UiAccountChange, UiAccountProfileState, - UiProfileResult, VersionedIdl, + RunbookExecutionStatusReport, SimnetEvent, SvmFeatureConfig, TransactionConfirmationStatus, + TransactionStatusEvent, UiAccountChange, UiAccountProfileState, UiProfileResult, VersionedIdl, types::{ ComputeUnitsEstimationResult, KeyedProfileResult, UiKeyedProfileResult, UuidOrSignature, }, @@ -641,110 +623,19 @@ impl SurfnetSvm { /// * `config` - The feature configuration specifying which features to enable/disable. pub fn apply_feature_config(&mut self, config: &SvmFeatureConfig) { // Apply explicit enables - for feature in &config.enable { - if let Some(id) = Self::feature_to_id(feature) { - self.feature_set.activate(&id, 0); - } + for pubkey in &config.enable { + self.feature_set.activate(pubkey, 0); } // Apply explicit disables - for feature in &config.disable { - if let Some(id) = Self::feature_to_id(feature) { - self.feature_set.deactivate(&id); - } + for pubkey in &config.disable { + self.feature_set.deactivate(pubkey); } // Rebuild inner VM with updated feature set self.inner.apply_feature_config(self.feature_set.clone()); } - /// Maps an SvmFeature enum variant to its corresponding feature ID (Pubkey). - fn feature_to_id(feature: &SvmFeature) -> Option { - match feature { - SvmFeature::MovePrecompileVerificationToSvm => { - Some(move_precompile_verification_to_svm::id()) - } - SvmFeature::StricterAbiAndRuntimeConstraints => { - Some(stricter_abi_and_runtime_constraints::id()) - } - SvmFeature::EnableBpfLoaderSetAuthorityCheckedIx => { - Some(enable_bpf_loader_set_authority_checked_ix::id()) - } - SvmFeature::EnableLoaderV4 => Some(enable_loader_v4::id()), - SvmFeature::DepleteCuMeterOnVmFailure => Some(deplete_cu_meter_on_vm_failure::id()), - SvmFeature::AbortOnInvalidCurve => Some(abort_on_invalid_curve::id()), - SvmFeature::Blake3SyscallEnabled => Some(blake3_syscall_enabled::id()), - SvmFeature::Curve25519SyscallEnabled => Some(curve25519_syscall_enabled::id()), - SvmFeature::DisableDeployOfAllocFreeSyscall => { - Some(disable_deploy_of_alloc_free_syscall::id()) - } - SvmFeature::DisableFeesSysvar => Some(disable_fees_sysvar::id()), - SvmFeature::DisableSbpfV0Execution => Some(disable_sbpf_v0_execution::id()), - SvmFeature::EnableAltBn128CompressionSyscall => { - Some(enable_alt_bn128_compression_syscall::id()) - } - SvmFeature::EnableAltBn128Syscall => Some(enable_alt_bn128_syscall::id()), - SvmFeature::EnableBigModExpSyscall => Some(enable_big_mod_exp_syscall::id()), - SvmFeature::EnableGetEpochStakeSyscall => Some(enable_get_epoch_stake_syscall::id()), - SvmFeature::EnablePoseidonSyscall => Some(enable_poseidon_syscall::id()), - SvmFeature::EnableSbpfV1DeploymentAndExecution => { - Some(enable_sbpf_v1_deployment_and_execution::id()) - } - SvmFeature::EnableSbpfV2DeploymentAndExecution => { - Some(enable_sbpf_v2_deployment_and_execution::id()) - } - SvmFeature::EnableSbpfV3DeploymentAndExecution => { - Some(enable_sbpf_v3_deployment_and_execution::id()) - } - SvmFeature::GetSysvarSyscallEnabled => Some(get_sysvar_syscall_enabled::id()), - SvmFeature::LastRestartSlotSysvar => Some(last_restart_slot_sysvar::id()), - SvmFeature::ReenableSbpfV0Execution => Some(reenable_sbpf_v0_execution::id()), - SvmFeature::RemainingComputeUnitsSyscallEnabled => { - Some(remaining_compute_units_syscall_enabled::id()) - } - SvmFeature::RemoveBpfLoaderIncorrectProgramId => { - Some(remove_bpf_loader_incorrect_program_id::id()) - } - SvmFeature::MoveStakeAndMoveLamportsIxs => Some(move_stake_and_move_lamports_ixs::id()), - SvmFeature::StakeRaiseMinimumDelegationTo1Sol => { - Some(stake_raise_minimum_delegation_to_1_sol::id()) - } - SvmFeature::DeprecateLegacyVoteIxs => Some(deprecate_legacy_vote_ixs::id()), - SvmFeature::MaskOutRentEpochInVmSerialization => { - Some(mask_out_rent_epoch_in_vm_serialization::id()) - } - SvmFeature::SimplifyAltBn128SyscallErrorCodes => { - Some(simplify_alt_bn128_syscall_error_codes::id()) - } - SvmFeature::FixAltBn128MultiplicationInputLength => { - Some(fix_alt_bn128_multiplication_input_length::id()) - } - SvmFeature::IncreaseTxAccountLockLimit => Some(increase_tx_account_lock_limit::id()), - SvmFeature::EnableExtendProgramChecked => Some(enable_extend_program_checked::id()), - SvmFeature::FormalizeLoadedTransactionDataSize => { - Some(formalize_loaded_transaction_data_size::id()) - } - SvmFeature::DisableZkElgamalProofProgram => { - Some(disable_zk_elgamal_proof_program::id()) - } - SvmFeature::ReenableZkElgamalProofProgram => { - Some(reenable_zk_elgamal_proof_program::id()) - } - SvmFeature::RaiseCpiNestingLimitTo8 => Some(raise_cpi_nesting_limit_to_8::id()), - // Features not yet available in agave-feature-set 3.0.0 - will be added when upgrading - SvmFeature::AccountDataDirectMapping => None, // bpf_account_data_direct_mapping - SvmFeature::ProvideInstructionDataOffsetInVmR2 => None, // provide_instruction_data_offset_in_vm_r2 - SvmFeature::IncreaseCpiAccountInfoLimit => None, // increase_cpi_account_info_limit - SvmFeature::VoteStateV4 => None, // vote_state_v4 - SvmFeature::PoseidonEnforcePadding => None, // poseidon_enforce_padding - SvmFeature::FixAltBn128PairingLengthCheck => None, // fix_alt_bn128_pairing_length_check - SvmFeature::LiftCpiCallerRestriction => None, // lift_cpi_caller_restriction - SvmFeature::RemoveAccountsExecutableFlagChecks => None, // remove_accounts_executable_flag_checks - SvmFeature::LoosenCpiSizeRestriction => Some(loosen_cpi_size_restriction::id()), - SvmFeature::DisableRentFeesCollection => None, // disable_rent_fees_collection - } - } - pub fn increment_write_version(&mut self) -> u64 { self.write_version += 1; self.write_version @@ -1013,6 +904,9 @@ impl SurfnetSvm { } pub fn get_account_from_feature_set(&self, pubkey: &Pubkey) -> Option { + // Currently, liteSVM doesn't create feature gate accounts and store them in the vm, + // so when a user is fetching one, we make one on the fly. + // TODO: remove once https://github.com/LiteSVM/litesvm/pull/308 is released self.feature_set.active().get(pubkey).map(|_| { let feature_bytes = bincode::serialize(&FEATURE).unwrap(); let lamports = self @@ -3518,6 +3412,13 @@ impl SurfnetSvm { #[cfg(test)] mod tests { + use agave_feature_set::{ + blake3_syscall_enabled, curve25519_syscall_enabled, disable_fees_sysvar, + enable_extend_program_checked, enable_loader_v4, enable_sbpf_v1_deployment_and_execution, + enable_sbpf_v2_deployment_and_execution, enable_sbpf_v3_deployment_and_execution, + formalize_loaded_transaction_data_size, move_precompile_verification_to_svm, + raise_cpi_nesting_limit_to_8, + }; use base64::{Engine, engine::general_purpose}; use borsh::BorshSerialize; // use test_log::test; // uncomment to get logs from litesvm @@ -4296,50 +4197,6 @@ mod tests { // Feature configuration tests - #[test] - fn test_feature_to_id_all_features_have_mapping() { - // Track features with and without mappings - // Some features return None because they're not yet available in agave-feature-set 3.0.0 - let mut mapped_count = 0; - let mut unmapped_features = Vec::new(); - - for feature in SvmFeature::all() { - let id = SurfnetSvm::feature_to_id(&feature); - if id.is_some() { - mapped_count += 1; - } else { - unmapped_features.push(feature); - } - } - - // Currently 9 features return None (not available in agave-feature-set 3.0.0): - // AccountDataDirectMapping, ProvideInstructionDataOffsetInVmR2, IncreaseCpiAccountInfoLimit, - // VoteStateV4, PoseidonEnforcePadding, FixAltBn128PairingLengthCheck, LiftCpiCallerRestriction, - // RemoveAccountsExecutableFlagChecks, DisableRentFeesCollection - assert_eq!( - unmapped_features.len(), - 9, - "Expected 9 unmapped features (pending agave-feature-set upgrade), found: {:?}", - unmapped_features - ); - assert_eq!(mapped_count, 37, "Expected 37 mapped features"); - } - - #[test] - fn test_feature_to_id_returns_valid_pubkeys() { - // Spot check a few known features - let loader_v4_id = SurfnetSvm::feature_to_id(&SvmFeature::EnableLoaderV4); - assert!(loader_v4_id.is_some()); - assert_ne!(loader_v4_id.unwrap(), Pubkey::default()); - - let disable_fees_id = SurfnetSvm::feature_to_id(&SvmFeature::DisableFeesSysvar); - assert!(disable_fees_id.is_some()); - assert_ne!(disable_fees_id.unwrap(), Pubkey::default()); - - // Different features should have different IDs - assert_ne!(loader_v4_id, disable_fees_id); - } - #[test_case(TestType::sqlite(); "with on-disk sqlite db")] #[test_case(TestType::in_memory(); "with in-memory sqlite db")] #[test_case(TestType::no_db(); "with no db")] @@ -4365,7 +4222,7 @@ mod tests { assert!(!svm.feature_set.is_active(&feature_id)); // Now enable it via config - let config = SvmFeatureConfig::new().enable(SvmFeature::EnableLoaderV4); + let config = SvmFeatureConfig::new().enable(enable_loader_v4::id()); svm.apply_feature_config(&config); assert!(svm.feature_set.is_active(&feature_id)); @@ -4383,7 +4240,7 @@ mod tests { assert!(svm.feature_set.is_active(&feature_id)); // Now disable it via config - let config = SvmFeatureConfig::new().disable(SvmFeature::DisableFeesSysvar); + let config = SvmFeatureConfig::new().disable(disable_fees_sysvar::id()); svm.apply_feature_config(&config); assert!(!svm.feature_set.is_active(&feature_id)); @@ -4444,8 +4301,7 @@ mod tests { let (mut svm, _events_rx, _geyser_rx) = test_type.initialize_svm(); // Start with mainnet defaults, but enable loader v4 - let config = - SvmFeatureConfig::default_mainnet_features().enable(SvmFeature::EnableLoaderV4); + let config = SvmFeatureConfig::default_mainnet_features().enable(enable_loader_v4::id()); svm.apply_feature_config(&config); @@ -4468,10 +4324,10 @@ mod tests { let (mut svm, _events_rx, _geyser_rx) = test_type.initialize_svm(); let config = SvmFeatureConfig::new() - .enable(SvmFeature::EnableLoaderV4) - .enable(SvmFeature::EnableSbpfV2DeploymentAndExecution) - .disable(SvmFeature::DisableFeesSysvar) - .disable(SvmFeature::Blake3SyscallEnabled); + .enable(enable_loader_v4::id()) + .enable(enable_sbpf_v2_deployment_and_execution::id()) + .disable(disable_fees_sysvar::id()) + .disable(blake3_syscall_enabled::id()); svm.apply_feature_config(&config); @@ -4499,7 +4355,7 @@ mod tests { .is_some() ); - let config = SvmFeatureConfig::new().disable(SvmFeature::DisableFeesSysvar); + let config = SvmFeatureConfig::new().disable(disable_fees_sysvar::id()); svm.apply_feature_config(&config); // Native mint should still exist after (re-added in apply_feature_config) @@ -4519,8 +4375,8 @@ mod tests { let (mut svm, _events_rx, _geyser_rx) = test_type.initialize_svm(); let config = SvmFeatureConfig::new() - .enable(SvmFeature::EnableLoaderV4) - .disable(SvmFeature::DisableFeesSysvar); + .enable(enable_loader_v4::id()) + .disable(disable_fees_sysvar::id()); // Apply twice svm.apply_feature_config(&config); diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 2991c4e6..a6b74399 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -23,7 +23,7 @@ schemars_derive = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } serde_with = { workspace = true, features = ["alloc", "macros"] } -strum = { workspace = true } +agave-feature-set = { workspace = true } solana-account = { workspace = true } solana-account-decoder-client-types = { workspace = true } solana-clock = { workspace = true } diff --git a/crates/types/src/features.rs b/crates/types/src/features.rs index 5ba30e69..6e1fc02a 100644 --- a/crates/types/src/features.rs +++ b/crates/types/src/features.rs @@ -1,106 +1,119 @@ use std::str::FromStr; +use agave_feature_set::FEATURE_NAMES; use serde::{Deserialize, Serialize}; -use strum::{Display, EnumIter, EnumString, IntoEnumIterator, IntoStaticStr}; +use solana_pubkey::Pubkey; -/// SVM feature flags that can be enabled or disabled via CLI. +/// Returns the pubkey for a known feature name (kebab-case or snake_case). /// -/// These correspond to the fields in `solana_svm_feature_set::SVMFeatureSet`. -/// Use kebab-case on the CLI (e.g., `--feature disable-fees-sysvar`). -#[derive( - Debug, - Clone, - Copy, - PartialEq, - Eq, - Hash, - Serialize, - Deserialize, - EnumIter, - EnumString, - Display, - IntoStaticStr, -)] -#[strum(serialize_all = "kebab-case")] -#[serde(rename_all = "kebab-case")] -pub enum SvmFeature { - MovePrecompileVerificationToSvm, - StricterAbiAndRuntimeConstraints, - EnableBpfLoaderSetAuthorityCheckedIx, - EnableLoaderV4, - DepleteCuMeterOnVmFailure, - AbortOnInvalidCurve, - Blake3SyscallEnabled, - Curve25519SyscallEnabled, - DisableDeployOfAllocFreeSyscall, - DisableFeesSysvar, - DisableSbpfV0Execution, - EnableAltBn128CompressionSyscall, - EnableAltBn128Syscall, - EnableBigModExpSyscall, - EnableGetEpochStakeSyscall, - EnablePoseidonSyscall, - EnableSbpfV1DeploymentAndExecution, - EnableSbpfV2DeploymentAndExecution, - EnableSbpfV3DeploymentAndExecution, - GetSysvarSyscallEnabled, - LastRestartSlotSysvar, - ReenableSbpfV0Execution, - RemainingComputeUnitsSyscallEnabled, - RemoveBpfLoaderIncorrectProgramId, - MoveStakeAndMoveLamportsIxs, - StakeRaiseMinimumDelegationTo1Sol, - DeprecateLegacyVoteIxs, - MaskOutRentEpochInVmSerialization, - SimplifyAltBn128SyscallErrorCodes, - FixAltBn128MultiplicationInputLength, - IncreaseTxAccountLockLimit, - EnableExtendProgramChecked, - FormalizeLoadedTransactionDataSize, - DisableZkElgamalProofProgram, - ReenableZkElgamalProofProgram, - RaiseCpiNestingLimitTo8, - AccountDataDirectMapping, - ProvideInstructionDataOffsetInVmR2, - IncreaseCpiAccountInfoLimit, - VoteStateV4, - PoseidonEnforcePadding, - FixAltBn128PairingLengthCheck, - LiftCpiCallerRestriction, - RemoveAccountsExecutableFlagChecks, - LoosenCpiSizeRestriction, - DisableRentFeesCollection, +/// This covers the set of features previously exposed as CLI names. +fn lookup_feature_by_name(name: &str) -> Option { + use agave_feature_set::*; + + // Normalize: accept both kebab-case and snake_case by converting underscores to hyphens + let normalized = name.replace('_', "-"); + let s = normalized.as_str(); + + let pubkey = match s { + "move-precompile-verification-to-svm" => move_precompile_verification_to_svm::id(), + "stricter-abi-and-runtime-constraints" => stricter_abi_and_runtime_constraints::id(), + "enable-bpf-loader-set-authority-checked-ix" => { + enable_bpf_loader_set_authority_checked_ix::id() + } + "enable-loader-v4" => enable_loader_v4::id(), + "deplete-cu-meter-on-vm-failure" => deplete_cu_meter_on_vm_failure::id(), + "abort-on-invalid-curve" => abort_on_invalid_curve::id(), + "blake3-syscall-enabled" => blake3_syscall_enabled::id(), + "curve25519-syscall-enabled" => curve25519_syscall_enabled::id(), + "disable-deploy-of-alloc-free-syscall" => disable_deploy_of_alloc_free_syscall::id(), + "disable-fees-sysvar" => disable_fees_sysvar::id(), + "disable-sbpf-v0-execution" => disable_sbpf_v0_execution::id(), + "enable-alt-bn128-compression-syscall" => enable_alt_bn128_compression_syscall::id(), + "enable-alt-bn128-syscall" => enable_alt_bn128_syscall::id(), + "enable-big-mod-exp-syscall" => enable_big_mod_exp_syscall::id(), + "enable-get-epoch-stake-syscall" => enable_get_epoch_stake_syscall::id(), + "enable-poseidon-syscall" => enable_poseidon_syscall::id(), + "enable-sbpf-v1-deployment-and-execution" => enable_sbpf_v1_deployment_and_execution::id(), + "enable-sbpf-v2-deployment-and-execution" => enable_sbpf_v2_deployment_and_execution::id(), + "enable-sbpf-v3-deployment-and-execution" => enable_sbpf_v3_deployment_and_execution::id(), + "get-sysvar-syscall-enabled" => get_sysvar_syscall_enabled::id(), + "last-restart-slot-sysvar" => last_restart_slot_sysvar::id(), + "reenable-sbpf-v0-execution" => reenable_sbpf_v0_execution::id(), + "remaining-compute-units-syscall-enabled" => remaining_compute_units_syscall_enabled::id(), + "remove-bpf-loader-incorrect-program-id" => remove_bpf_loader_incorrect_program_id::id(), + "move-stake-and-move-lamports-ixs" => move_stake_and_move_lamports_ixs::id(), + "stake-raise-minimum-delegation-to-1-sol" => stake_raise_minimum_delegation_to_1_sol::id(), + "deprecate-legacy-vote-ixs" => deprecate_legacy_vote_ixs::id(), + "mask-out-rent-epoch-in-vm-serialization" => mask_out_rent_epoch_in_vm_serialization::id(), + "simplify-alt-bn128-syscall-error-codes" => simplify_alt_bn128_syscall_error_codes::id(), + "fix-alt-bn128-multiplication-input-length" => { + fix_alt_bn128_multiplication_input_length::id() + } + "increase-tx-account-lock-limit" => increase_tx_account_lock_limit::id(), + "enable-extend-program-checked" => enable_extend_program_checked::id(), + "formalize-loaded-transaction-data-size" => formalize_loaded_transaction_data_size::id(), + "disable-zk-elgamal-proof-program" => disable_zk_elgamal_proof_program::id(), + "reenable-zk-elgamal-proof-program" => reenable_zk_elgamal_proof_program::id(), + "raise-cpi-nesting-limit-to-8" => raise_cpi_nesting_limit_to_8::id(), + "account-data-direct-mapping" => account_data_direct_mapping::id(), + "provide-instruction-data-offset-in-vm-r2" => { + provide_instruction_data_offset_in_vm_r2::id() + } + "increase-cpi-account-info-limit" => increase_cpi_account_info_limit::id(), + "vote-state-v4" => vote_state_v4::id(), + "poseidon-enforce-padding" => poseidon_enforce_padding::id(), + "fix-alt-bn128-pairing-length-check" => fix_alt_bn128_pairing_length_check::id(), + // "lift-cpi-caller-restriction" not available in agave-feature-set 3.1.x + "remove-accounts-executable-flag-checks" => remove_accounts_executable_flag_checks::id(), + "loosen-cpi-size-restriction" => loosen_cpi_size_restriction::id(), + "disable-rent-fees-collection" => disable_rent_fees_collection::id(), + "deprecate-rent-exemption-threshold" => deprecate_rent_exemption_threshold::id(), + "replace-spl-token-with-p-token" => replace_spl_token_with_p_token::id(), + _ => return None, + }; + + Some(pubkey) } -impl SvmFeature { - /// Returns an iterator over all available SVM features. - pub fn all() -> impl Iterator { - SvmFeature::iter() - } - - /// Returns the kebab-case string representation used in CLI. - pub fn as_str(&self) -> &'static str { - self.into() +/// Parse a feature from either a name (kebab-case or snake_case) or a base58 pubkey string, +/// validating it against known agave feature gates. +pub fn parse_feature_pubkey(s: &str) -> Result { + // 1. Try name lookup (supports both kebab-case and snake_case) + if let Some(pubkey) = lookup_feature_by_name(s) { + return Ok(pubkey); } -} -/// Parse an SvmFeature from a string, with a custom error message. -pub fn parse_svm_feature(s: &str) -> Result { - SvmFeature::from_str(s).map_err(|_| { + // 2. Try base58 pubkey parse + let pubkey = Pubkey::from_str(s).map_err(|_| { format!( - "Unknown SVM feature: '{}'. Use --help to see available features.", + "Invalid feature pubkey: '{}'. Expected a base58-encoded pubkey of a known agave feature gate.", s ) - }) + })?; + + if !FEATURE_NAMES.contains_key(&pubkey) { + let mut available: Vec<_> = FEATURE_NAMES + .iter() + .map(|(k, name)| format!(" {} ({})", k, name)) + .collect(); + available.sort(); + return Err(format!( + "Available features:\n{}\n\nUnknown feature: '{}'. Not a known agave feature gate. Available features listed above.", + pubkey, + available.join("\n") + )); + } + + Ok(pubkey) } /// Configuration for SVM features, specifying which features to enable or disable. #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct SvmFeatureConfig { /// Features to explicitly enable (override defaults) - pub enable: Vec, + pub enable: Vec, /// Features to explicitly disable (override defaults) - pub disable: Vec, + pub disable: Vec, } impl SvmFeatureConfig { @@ -115,36 +128,39 @@ impl SvmFeatureConfig { /// Note: This may need periodic updates as mainnet features change. /// Last updated: 2025-01-25 (queried from mainnet RPC) pub fn default_mainnet_features() -> Self { + use agave_feature_set::*; + // Features that are NOT yet active on mainnet (should be disabled) let disable = vec![ // Blake3 syscall not yet on mainnet - SvmFeature::Blake3SyscallEnabled, + blake3_syscall_enabled::id(), // Legacy vote deprecation not yet on mainnet - SvmFeature::DeprecateLegacyVoteIxs, + deprecate_legacy_vote_ixs::id(), // SBPF v0 disable/reenable not yet on mainnet - SvmFeature::DisableSbpfV0Execution, - SvmFeature::ReenableSbpfV0Execution, + disable_sbpf_v0_execution::id(), + reenable_sbpf_v0_execution::id(), // ZK ElGamal disable not yet on mainnet (reenable IS active) - SvmFeature::DisableZkElgamalProofProgram, + disable_zk_elgamal_proof_program::id(), // Extended program checked not yet on mainnet - SvmFeature::EnableExtendProgramChecked, + enable_extend_program_checked::id(), // Loader v4 not yet on mainnet - SvmFeature::EnableLoaderV4, + enable_loader_v4::id(), // SBPF v1 not yet on mainnet (v2 and v3 ARE active) - SvmFeature::EnableSbpfV1DeploymentAndExecution, + enable_sbpf_v1_deployment_and_execution::id(), // Transaction data size formalization not yet on mainnet - SvmFeature::FormalizeLoadedTransactionDataSize, + formalize_loaded_transaction_data_size::id(), // Precompile verification move not yet on mainnet - SvmFeature::MovePrecompileVerificationToSvm, + move_precompile_verification_to_svm::id(), // Stake move instructions not yet on mainnet - SvmFeature::MoveStakeAndMoveLamportsIxs, + move_stake_and_move_lamports_ixs::id(), // Stake minimum delegation raise not yet on mainnet - SvmFeature::StakeRaiseMinimumDelegationTo1Sol, + stake_raise_minimum_delegation_to_1_sol::id(), // New features from LiteSVM 0.9.0 / Solana SVM v3.1 (not yet on mainnet) - SvmFeature::LiftCpiCallerRestriction, - SvmFeature::RemoveAccountsExecutableFlagChecks, - SvmFeature::LoosenCpiSizeRestriction, - SvmFeature::DisableRentFeesCollection, + remove_accounts_executable_flag_checks::id(), + loosen_cpi_size_restriction::id(), + disable_rent_fees_collection::id(), + deprecate_rent_exemption_threshold::id(), + replace_spl_token_with_p_token::id(), ]; Self { @@ -154,7 +170,7 @@ impl SvmFeatureConfig { } /// Adds a feature to enable. - pub fn enable(mut self, feature: SvmFeature) -> Self { + pub fn enable(mut self, feature: Pubkey) -> Self { if !self.enable.contains(&feature) { self.enable.push(feature); } @@ -164,7 +180,7 @@ impl SvmFeatureConfig { } /// Adds a feature to disable. - pub fn disable(mut self, feature: SvmFeature) -> Self { + pub fn disable(mut self, feature: Pubkey) -> Self { if !self.disable.contains(&feature) { self.disable.push(feature); } @@ -175,7 +191,7 @@ impl SvmFeatureConfig { /// Checks if a feature should be enabled based on this configuration. /// Returns None if not explicitly configured (use default). - pub fn is_enabled(&self, feature: &SvmFeature) -> Option { + pub fn is_enabled(&self, feature: &Pubkey) -> Option { if self.enable.contains(feature) { Some(true) } else if self.disable.contains(feature) { @@ -188,97 +204,49 @@ impl SvmFeatureConfig { #[cfg(test)] mod tests { - use super::*; + use agave_feature_set::*; - // ==================== SvmFeature parsing tests ==================== - - #[test] - fn test_feature_from_str_valid() { - assert_eq!( - SvmFeature::from_str("disable-fees-sysvar").unwrap(), - SvmFeature::DisableFeesSysvar - ); - assert_eq!( - SvmFeature::from_str("enable-loader-v4").unwrap(), - SvmFeature::EnableLoaderV4 - ); - assert_eq!( - SvmFeature::from_str("blake3-syscall-enabled").unwrap(), - SvmFeature::Blake3SyscallEnabled - ); - assert_eq!( - SvmFeature::from_str("enable-sbpf-v2-deployment-and-execution").unwrap(), - SvmFeature::EnableSbpfV2DeploymentAndExecution - ); - } + use super::*; - #[test] - fn test_feature_from_str_invalid() { - assert!(SvmFeature::from_str("invalid-feature").is_err()); - assert!(SvmFeature::from_str("").is_err()); - assert!(SvmFeature::from_str("disable_fees_sysvar").is_err()); // underscore instead of hyphen - assert!(SvmFeature::from_str("DISABLE-FEES-SYSVAR").is_err()); // uppercase - } + // ==================== parse_feature_pubkey tests ==================== #[test] - fn test_parse_svm_feature_error_message() { - let err = parse_svm_feature("not-a-feature").unwrap_err(); - assert!(err.contains("Unknown SVM feature")); - assert!(err.contains("not-a-feature")); + fn test_parse_feature_pubkey_valid() { + let pubkey = parse_feature_pubkey(&enable_loader_v4::id().to_string()).unwrap(); + assert_eq!(pubkey, enable_loader_v4::id()); } - // ==================== SvmFeature display tests ==================== - #[test] - fn test_feature_display() { - assert_eq!( - SvmFeature::DisableFeesSysvar.to_string(), - "disable-fees-sysvar" - ); - assert_eq!(SvmFeature::EnableLoaderV4.to_string(), "enable-loader-v4"); - assert_eq!( - SvmFeature::EnableSbpfV3DeploymentAndExecution.to_string(), - "enable-sbpf-v3-deployment-and-execution" - ); + fn test_parse_feature_name_snake_case() { + let pubkey = parse_feature_pubkey("enable_loader_v4").unwrap(); + assert_eq!(pubkey, enable_loader_v4::id()); } #[test] - fn test_feature_as_str() { - assert_eq!( - SvmFeature::DisableFeesSysvar.as_str(), - "disable-fees-sysvar" - ); - assert_eq!(SvmFeature::EnableLoaderV4.as_str(), "enable-loader-v4"); + fn test_parse_feature_name_kebab_case() { + let pubkey = parse_feature_pubkey("enable-loader-v4").unwrap(); + assert_eq!(pubkey, enable_loader_v4::id()); } #[test] - fn test_feature_roundtrip() { - for feature in SvmFeature::all() { - let s = feature.to_string(); - let parsed = SvmFeature::from_str(&s).unwrap(); - assert_eq!(feature, parsed, "Roundtrip failed for {:?}", feature); - } + fn test_parse_feature_name_prefers_name_over_pubkey() { + // Verify that a known feature name resolves correctly + let pubkey = parse_feature_pubkey("blake3_syscall_enabled").unwrap(); + assert_eq!(pubkey, blake3_syscall_enabled::id()); } - // ==================== SvmFeature::all() tests ==================== - #[test] - fn test_feature_all_count() { - // Ensure we have all 46 features - assert_eq!(SvmFeature::all().count(), 46); + fn test_parse_feature_unknown_name() { + let err = parse_feature_pubkey("nonexistent-feature-name").unwrap_err(); + assert!(err.contains("Invalid feature")); + assert!(err.contains("nonexistent-feature-name")); } #[test] - fn test_feature_all_unique() { - let all: Vec<_> = SvmFeature::all().collect(); - let mut seen = std::collections::HashSet::new(); - for feature in &all { - assert!( - seen.insert(feature), - "Duplicate feature in all(): {:?}", - feature - ); - } + fn test_parse_feature_pubkey_unknown_pubkey() { + // System program is not a feature gate + let err = parse_feature_pubkey("11111111111111111111111111111111").unwrap_err(); + assert!(err.contains("Not a known agave feature gate")); } // ==================== SvmFeatureConfig basic tests ==================== @@ -299,21 +267,16 @@ mod tests { #[test] fn test_feature_config_enable() { - let config = SvmFeatureConfig::new().enable(SvmFeature::EnableLoaderV4); - - assert_eq!(config.is_enabled(&SvmFeature::EnableLoaderV4), Some(true)); + let config = SvmFeatureConfig::new().enable(enable_loader_v4::id()); + assert_eq!(config.is_enabled(&enable_loader_v4::id()), Some(true)); assert_eq!(config.enable.len(), 1); assert!(config.disable.is_empty()); } #[test] fn test_feature_config_disable() { - let config = SvmFeatureConfig::new().disable(SvmFeature::DisableFeesSysvar); - - assert_eq!( - config.is_enabled(&SvmFeature::DisableFeesSysvar), - Some(false) - ); + let config = SvmFeatureConfig::new().disable(disable_fees_sysvar::id()); + assert_eq!(config.is_enabled(&disable_fees_sysvar::id()), Some(false)); assert!(config.enable.is_empty()); assert_eq!(config.disable.len(), 1); } @@ -321,51 +284,47 @@ mod tests { #[test] fn test_feature_config_is_enabled_not_configured() { let config = SvmFeatureConfig::new(); - assert_eq!(config.is_enabled(&SvmFeature::Blake3SyscallEnabled), None); + assert_eq!(config.is_enabled(&blake3_syscall_enabled::id()), None); } // ==================== SvmFeatureConfig complex scenarios ==================== #[test] fn test_feature_config_enable_then_disable() { - // Enabling then disabling should result in disabled let config = SvmFeatureConfig::new() - .enable(SvmFeature::EnableLoaderV4) - .disable(SvmFeature::EnableLoaderV4); + .enable(enable_loader_v4::id()) + .disable(enable_loader_v4::id()); - assert_eq!(config.is_enabled(&SvmFeature::EnableLoaderV4), Some(false)); + assert_eq!(config.is_enabled(&enable_loader_v4::id()), Some(false)); assert!(config.enable.is_empty()); assert_eq!(config.disable.len(), 1); } #[test] fn test_feature_config_disable_then_enable() { - // Disabling then enabling should result in enabled let config = SvmFeatureConfig::new() - .disable(SvmFeature::EnableLoaderV4) - .enable(SvmFeature::EnableLoaderV4); + .disable(enable_loader_v4::id()) + .enable(enable_loader_v4::id()); - assert_eq!(config.is_enabled(&SvmFeature::EnableLoaderV4), Some(true)); + assert_eq!(config.is_enabled(&enable_loader_v4::id()), Some(true)); assert_eq!(config.enable.len(), 1); assert!(config.disable.is_empty()); } #[test] fn test_feature_config_enable_idempotent() { - // Enabling the same feature twice should not duplicate let config = SvmFeatureConfig::new() - .enable(SvmFeature::EnableLoaderV4) - .enable(SvmFeature::EnableLoaderV4); + .enable(enable_loader_v4::id()) + .enable(enable_loader_v4::id()); assert_eq!(config.enable.len(), 1); } #[test] fn test_feature_config_disable_idempotent() { - // Disabling the same feature twice should not duplicate let config = SvmFeatureConfig::new() - .disable(SvmFeature::EnableLoaderV4) - .disable(SvmFeature::EnableLoaderV4); + .disable(enable_loader_v4::id()) + .disable(enable_loader_v4::id()); assert_eq!(config.disable.len(), 1); } @@ -373,22 +332,16 @@ mod tests { #[test] fn test_feature_config_multiple_features() { let config = SvmFeatureConfig::new() - .enable(SvmFeature::EnableLoaderV4) - .enable(SvmFeature::Blake3SyscallEnabled) - .disable(SvmFeature::DisableFeesSysvar) - .disable(SvmFeature::DisableSbpfV0Execution); - - assert_eq!(config.is_enabled(&SvmFeature::EnableLoaderV4), Some(true)); + .enable(enable_loader_v4::id()) + .enable(blake3_syscall_enabled::id()) + .disable(disable_fees_sysvar::id()) + .disable(disable_sbpf_v0_execution::id()); + + assert_eq!(config.is_enabled(&enable_loader_v4::id()), Some(true)); + assert_eq!(config.is_enabled(&blake3_syscall_enabled::id()), Some(true)); + assert_eq!(config.is_enabled(&disable_fees_sysvar::id()), Some(false)); assert_eq!( - config.is_enabled(&SvmFeature::Blake3SyscallEnabled), - Some(true) - ); - assert_eq!( - config.is_enabled(&SvmFeature::DisableFeesSysvar), - Some(false) - ); - assert_eq!( - config.is_enabled(&SvmFeature::DisableSbpfV0Execution), + config.is_enabled(&disable_sbpf_v0_execution::id()), Some(false) ); assert_eq!(config.enable.len(), 2); @@ -401,50 +354,49 @@ mod tests { fn test_mainnet_features_disabled_list() { let config = SvmFeatureConfig::default_mainnet_features(); - // All these should be disabled on mainnet (queried 2025-01-25) assert_eq!( - config.is_enabled(&SvmFeature::Blake3SyscallEnabled), + config.is_enabled(&blake3_syscall_enabled::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::DeprecateLegacyVoteIxs), + config.is_enabled(&deprecate_legacy_vote_ixs::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::DisableSbpfV0Execution), + config.is_enabled(&disable_sbpf_v0_execution::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::ReenableSbpfV0Execution), + config.is_enabled(&reenable_sbpf_v0_execution::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::DisableZkElgamalProofProgram), + config.is_enabled(&disable_zk_elgamal_proof_program::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::EnableExtendProgramChecked), + config.is_enabled(&enable_extend_program_checked::id()), Some(false) ); - assert_eq!(config.is_enabled(&SvmFeature::EnableLoaderV4), Some(false)); + assert_eq!(config.is_enabled(&enable_loader_v4::id()), Some(false)); assert_eq!( - config.is_enabled(&SvmFeature::EnableSbpfV1DeploymentAndExecution), + config.is_enabled(&enable_sbpf_v1_deployment_and_execution::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::FormalizeLoadedTransactionDataSize), + config.is_enabled(&formalize_loaded_transaction_data_size::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::MovePrecompileVerificationToSvm), + config.is_enabled(&move_precompile_verification_to_svm::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::MoveStakeAndMoveLamportsIxs), + config.is_enabled(&move_stake_and_move_lamports_ixs::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::StakeRaiseMinimumDelegationTo1Sol), + config.is_enabled(&stake_raise_minimum_delegation_to_1_sol::id()), Some(false) ); } @@ -457,19 +409,15 @@ mod tests { #[test] fn test_mainnet_features_override_with_enable() { - // Start with mainnet defaults, then enable a disabled feature - let config = - SvmFeatureConfig::default_mainnet_features().enable(SvmFeature::EnableLoaderV4); + let config = SvmFeatureConfig::default_mainnet_features().enable(enable_loader_v4::id()); - // Should now be enabled - assert_eq!(config.is_enabled(&SvmFeature::EnableLoaderV4), Some(true)); - // Other mainnet-disabled features should still be disabled + assert_eq!(config.is_enabled(&enable_loader_v4::id()), Some(true)); assert_eq!( - config.is_enabled(&SvmFeature::Blake3SyscallEnabled), + config.is_enabled(&blake3_syscall_enabled::id()), Some(false) ); assert_eq!( - config.is_enabled(&SvmFeature::EnableExtendProgramChecked), + config.is_enabled(&enable_extend_program_checked::id()), Some(false) ); } @@ -479,43 +427,28 @@ mod tests { let config = SvmFeatureConfig::default_mainnet_features(); // Features that ARE active on mainnet should not be in disable list - // These should return None (use default, which is enabled) - assert_eq!(config.is_enabled(&SvmFeature::DisableFeesSysvar), None); + assert_eq!(config.is_enabled(&disable_fees_sysvar::id()), None); + assert_eq!(config.is_enabled(&curve25519_syscall_enabled::id()), None); + assert_eq!(config.is_enabled(&enable_alt_bn128_syscall::id()), None); + assert_eq!(config.is_enabled(&enable_poseidon_syscall::id()), None); assert_eq!( - config.is_enabled(&SvmFeature::Curve25519SyscallEnabled), + config.is_enabled(&enable_sbpf_v2_deployment_and_execution::id()), None ); - assert_eq!(config.is_enabled(&SvmFeature::EnableAltBn128Syscall), None); - assert_eq!(config.is_enabled(&SvmFeature::EnablePoseidonSyscall), None); assert_eq!( - config.is_enabled(&SvmFeature::EnableSbpfV2DeploymentAndExecution), - None - ); - assert_eq!( - config.is_enabled(&SvmFeature::EnableSbpfV3DeploymentAndExecution), - None - ); - assert_eq!( - config.is_enabled(&SvmFeature::RaiseCpiNestingLimitTo8), + config.is_enabled(&enable_sbpf_v3_deployment_and_execution::id()), None ); + assert_eq!(config.is_enabled(&raise_cpi_nesting_limit_to_8::id()), None); } // ==================== Serialization tests ==================== - #[test] - fn test_feature_serde_roundtrip() { - let feature = SvmFeature::EnableLoaderV4; - let json = serde_json::to_string(&feature).unwrap(); - let parsed: SvmFeature = serde_json::from_str(&json).unwrap(); - assert_eq!(feature, parsed); - } - #[test] fn test_feature_config_serde_roundtrip() { let config = SvmFeatureConfig::new() - .enable(SvmFeature::EnableLoaderV4) - .disable(SvmFeature::DisableFeesSysvar); + .enable(enable_loader_v4::id()) + .disable(disable_fees_sysvar::id()); let json = serde_json::to_string(&config).unwrap(); let parsed: SvmFeatureConfig = serde_json::from_str(&json).unwrap(); @@ -523,66 +456,15 @@ mod tests { assert_eq!(config, parsed); } - #[test] - fn test_feature_json_format() { - let feature = SvmFeature::EnableLoaderV4; - let json = serde_json::to_string(&feature).unwrap(); - // Should use kebab-case due to serde rename_all - assert_eq!(json, "\"enable-loader-v4\""); - } - - #[test] - fn test_feature_config_json_format() { - let config = SvmFeatureConfig::new().enable(SvmFeature::EnableLoaderV4); - - let json = serde_json::to_string(&config).unwrap(); - assert!(json.contains("\"enable\"")); - assert!(json.contains("enable-loader-v4")); - } - // ==================== Edge cases ==================== - #[test] - fn test_feature_equality() { - assert_eq!(SvmFeature::EnableLoaderV4, SvmFeature::EnableLoaderV4); - assert_ne!(SvmFeature::EnableLoaderV4, SvmFeature::DisableFeesSysvar); - } - - #[test] - fn test_feature_clone() { - let feature = SvmFeature::EnableLoaderV4; - let cloned = feature.clone(); - assert_eq!(feature, cloned); - } - #[test] fn test_feature_config_clone() { let config = SvmFeatureConfig::new() - .enable(SvmFeature::EnableLoaderV4) - .disable(SvmFeature::DisableFeesSysvar); + .enable(enable_loader_v4::id()) + .disable(disable_fees_sysvar::id()); let cloned = config.clone(); assert_eq!(config, cloned); } - - #[test] - fn test_feature_hash() { - use std::collections::HashSet; - - let mut set = HashSet::new(); - set.insert(SvmFeature::EnableLoaderV4); - set.insert(SvmFeature::DisableFeesSysvar); - set.insert(SvmFeature::EnableLoaderV4); // duplicate - - assert_eq!(set.len(), 2); - assert!(set.contains(&SvmFeature::EnableLoaderV4)); - assert!(set.contains(&SvmFeature::DisableFeesSysvar)); - } - - #[test] - fn test_feature_debug() { - let feature = SvmFeature::EnableLoaderV4; - let debug_str = format!("{:?}", feature); - assert_eq!(debug_str, "EnableLoaderV4"); - } }