diff --git a/Cargo.lock b/Cargo.lock index 97f926893a7d00..e5ec850a793510 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6451,8 +6451,6 @@ dependencies = [ [[package]] name = "solana-account" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f949fe4edaeaea78c844023bfc1c898e0b1f5a100f8a8d2d0f85d0a7b090258" dependencies = [ "bincode", "qualifier_attr", @@ -6532,8 +6530,6 @@ dependencies = [ [[package]] name = "solana-account-info" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c17d606a298a205fae325489fbed88ee6dc4463c111672172327e741c8905d" dependencies = [ "bincode", "serde", @@ -6678,8 +6674,6 @@ dependencies = [ [[package]] name = "solana-address-lookup-table-interface" version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1673f67efe870b64a65cb39e6194be5b26527691ce5922909939961a6e6b395" dependencies = [ "bincode", "bytemuck", @@ -6695,8 +6689,6 @@ dependencies = [ [[package]] name = "solana-atomic-u64" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52e52720efe60465b052b9e7445a01c17550666beec855cce66f44766697bc2" dependencies = [ "parking_lot 0.12.3", ] @@ -6855,8 +6847,6 @@ dependencies = [ [[package]] name = "solana-big-mod-exp" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" dependencies = [ "num-bigint 0.4.6", "num-traits", @@ -6866,8 +6856,6 @@ dependencies = [ [[package]] name = "solana-bincode" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a3787b8cf9c9fe3dd360800e8b70982b9e5a8af9e11c354b6665dd4a003adc" dependencies = [ "bincode", "serde", @@ -6877,8 +6865,6 @@ dependencies = [ [[package]] name = "solana-blake3-hasher" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" dependencies = [ "blake3", "solana-define-syscall", @@ -6908,8 +6894,6 @@ dependencies = [ [[package]] name = "solana-bn254" version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4420f125118732833f36facf96a27e7b78314b2d642ba07fa9ffdacd8d79e243" dependencies = [ "ark-bn254", "ark-ec", @@ -6923,8 +6907,6 @@ dependencies = [ [[package]] name = "solana-borsh" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718333bcd0a1a7aed6655aa66bef8d7fb047944922b2d3a18f49cbc13e73d004" dependencies = [ "borsh 0.10.3", "borsh 1.5.7", @@ -7387,8 +7369,6 @@ dependencies = [ [[package]] name = "solana-client-traits" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83f0071874e629f29e0eb3dab8a863e98502ac7aba55b7e0df1803fc5cac72a7" dependencies = [ "solana-account", "solana-commitment-config", @@ -7408,8 +7388,6 @@ dependencies = [ [[package]] name = "solana-clock" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c2177a1b9fe8326004f1151a5acd124420b737811080b1035df31349e4d892" dependencies = [ "serde", "serde_derive", @@ -7421,8 +7399,6 @@ dependencies = [ [[package]] name = "solana-cluster-type" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ace9fea2daa28354d107ea879cff107181d85cd4e0f78a2bedb10e1a428c97e" dependencies = [ "serde", "serde_derive", @@ -7434,8 +7410,6 @@ dependencies = [ [[package]] name = "solana-commitment-config" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac49c4dde3edfa832de1697e9bcdb7c3b3f7cb7a1981b7c62526c8bb6700fb73" dependencies = [ "serde", "serde_derive", @@ -7456,6 +7430,7 @@ name = "solana-compute-budget-instruction" version = "2.3.0" dependencies = [ "agave-feature-set", + "assert_matches", "bincode", "criterion", "log", @@ -7483,8 +7458,6 @@ dependencies = [ [[package]] name = "solana-compute-budget-interface" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5df17b195d312b66dccdde9beec6709766d8230cb4718c4c08854f780d0309" dependencies = [ "borsh 1.5.7", "serde", @@ -7719,8 +7692,6 @@ dependencies = [ [[package]] name = "solana-cpi" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11" dependencies = [ "solana-account-info", "solana-define-syscall", @@ -7745,8 +7716,6 @@ dependencies = [ [[package]] name = "solana-decode-error" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a6a6383af236708048f8bd8d03db8ca4ff7baf4a48e5d580f4cce545925470" dependencies = [ "num-traits", ] @@ -7754,14 +7723,10 @@ dependencies = [ [[package]] name = "solana-define-syscall" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf784bb2cb3e02cac9801813c30187344228d2ae952534902108f6150573a33d" [[package]] name = "solana-derivation-path" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939756d798b25c5ec3cca10e06212bdca3b1443cb9bb740a38124f58b258737b" dependencies = [ "derivation-path", "qstring", @@ -7815,8 +7780,6 @@ dependencies = [ [[package]] name = "solana-ed25519-program" version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0fc717048fdbe5d2ee7d673d73e6a30a094002f4a29ca7630ac01b6bddec04" dependencies = [ "bytemuck", "bytemuck_derive", @@ -7875,8 +7838,6 @@ dependencies = [ [[package]] name = "solana-epoch-info" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ef6f0b449290b0b9f32973eefd95af35b01c5c0c34c569f936c34c5b20d77b" dependencies = [ "serde", "serde_derive", @@ -7885,8 +7846,6 @@ dependencies = [ [[package]] name = "solana-epoch-rewards" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" dependencies = [ "serde", "serde_derive", @@ -7901,8 +7860,6 @@ dependencies = [ [[package]] name = "solana-epoch-rewards-hasher" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c5fd2662ae7574810904585fd443545ed2b568dbd304b25a31e79ccc76e81b" dependencies = [ "siphasher", "solana-hash", @@ -7912,8 +7869,6 @@ dependencies = [ [[package]] name = "solana-epoch-schedule" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fce071fbddecc55d727b1d7ed16a629afe4f6e4c217bc8d00af3b785f6f67ed" dependencies = [ "serde", "serde_derive", @@ -7927,8 +7882,6 @@ dependencies = [ [[package]] name = "solana-example-mocks" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84461d56cbb8bb8d539347151e0525b53910102e4bced875d49d5139708e39d3" dependencies = [ "serde", "serde_derive", @@ -7992,8 +7945,6 @@ dependencies = [ [[package]] name = "solana-feature-gate-interface" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9c7fbf3e58b64a667c5f35e90af580538a95daea7001ff7806c0662d301bdf" dependencies = [ "bincode", "serde", @@ -8011,8 +7962,6 @@ dependencies = [ [[package]] name = "solana-feature-set" version = "2.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92f6c09cc41059c0e03ccbee7f5d4cc0a315d68ef0d59b67eb90246adfd8cc35" dependencies = [ "ahash 0.8.11", "lazy_static", @@ -8036,8 +7985,6 @@ dependencies = [ [[package]] name = "solana-fee-calculator" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89bc408da0fb3812bc3008189d148b4d3e08252c79ad810b245482a3f70cd8d" dependencies = [ "log", "serde", @@ -8049,8 +7996,6 @@ dependencies = [ [[package]] name = "solana-fee-structure" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f45f94a88efdb512805563181dfa1c85c60a21b6e6d602bf24a2ea88f9399d6e" dependencies = [ "serde", "serde_derive", @@ -8062,8 +8007,6 @@ dependencies = [ [[package]] name = "solana-file-download" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96156c84b006ce3f00b37fa852a7d93de13ede4c40a58269663c3e01907453e3" dependencies = [ "console", "indicatif", @@ -8074,8 +8017,6 @@ dependencies = [ [[package]] name = "solana-frozen-abi" version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bdd72d99751bcd646dc6a32772bf181c7b49f5379e4a4c8946920f3082b0ec6" dependencies = [ "bs58", "bv", @@ -8094,8 +8035,6 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83f88a126213cbcb57672c5e70ddb9791eff9b480e9f39fe9285fd2abca66fa" dependencies = [ "proc-macro2", "quote", @@ -8151,8 +8090,6 @@ dependencies = [ [[package]] name = "solana-genesis-config" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968dabd2b92d57131473eddbd475339da530e14f54397386abf303de3a2595a2" dependencies = [ "bincode", "chrono", @@ -8301,8 +8238,6 @@ dependencies = [ [[package]] name = "solana-hard-forks" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c28371f878e2ead55611d8ba1b5fb879847156d04edea13693700ad1a28baf" dependencies = [ "serde", "serde_derive", @@ -8313,8 +8248,6 @@ dependencies = [ [[package]] name = "solana-hash" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf7bcb14392900fe02e4e34e90234fbf0c673d4e327888410ba99fa2ba0f4e99" dependencies = [ "borsh 1.5.7", "bs58", @@ -8333,8 +8266,6 @@ dependencies = [ [[package]] name = "solana-inflation" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23eef6a09eb8e568ce6839573e4966850e85e9ce71e6ae1a6c930c1c43947de3" dependencies = [ "serde", "serde_derive", @@ -8345,8 +8276,6 @@ dependencies = [ [[package]] name = "solana-instruction" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce496a475e5062ba5de97215ab39d9c358f9c9df4bb7f3a45a1f1a8bd9065ed" dependencies = [ "bincode", "borsh 1.5.7", @@ -8365,8 +8294,6 @@ dependencies = [ [[package]] name = "solana-instructions-sysvar" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427f2d0d6dc0bb49f16cef5e7f975180d2e80aab9bdd3b2af68e2d029ec63f43" dependencies = [ "bitflags 2.9.0", "solana-account-info", @@ -8382,8 +8309,6 @@ dependencies = [ [[package]] name = "solana-keccak-hasher" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" dependencies = [ "sha3", "solana-define-syscall", @@ -8418,8 +8343,6 @@ dependencies = [ [[package]] name = "solana-keypair" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dbb7042c2e0c561afa07242b2099d55c57bd1b1da3b6476932197d84e15e3e4" dependencies = [ "bs58", "ed25519-dalek", @@ -8437,8 +8360,6 @@ dependencies = [ [[package]] name = "solana-last-restart-slot" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6360ac2fdc72e7463565cd256eedcf10d7ef0c28a1249d261ec168c1b55cdd" dependencies = [ "serde", "serde_derive", @@ -8551,8 +8472,6 @@ dependencies = [ [[package]] name = "solana-loader-v2-interface" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8ab08006dad78ae7cd30df8eea0539e207d08d91eaefb3e1d49a446e1c49654" dependencies = [ "serde", "serde_bytes", @@ -8565,8 +8484,6 @@ dependencies = [ [[package]] name = "solana-loader-v3-interface" version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4be76cfa9afd84ca2f35ebc09f0da0f0092935ccdac0595d98447f259538c2" dependencies = [ "serde", "serde_bytes", @@ -8580,8 +8497,6 @@ dependencies = [ [[package]] name = "solana-loader-v4-interface" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "706a777242f1f39a83e2a96a2a6cb034cb41169c6ecbee2cf09cb873d9659e7e" dependencies = [ "serde", "serde_bytes", @@ -8683,8 +8598,6 @@ dependencies = [ [[package]] name = "solana-logger" version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8e777ec1afd733939b532a42492d888ec7c88d8b4127a5d867eb45c6eb5cd5" dependencies = [ "env_logger", "lazy_static", @@ -8714,8 +8627,6 @@ dependencies = [ [[package]] name = "solana-message" version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6bf99c4570173710107a1f233f3bee226feea5fc817308707d4f7cb100a72d" dependencies = [ "bincode", "blake3", @@ -8758,8 +8669,6 @@ dependencies = [ [[package]] name = "solana-msg" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092" dependencies = [ "solana-define-syscall", ] @@ -8767,8 +8676,6 @@ dependencies = [ [[package]] name = "solana-native-token" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e9de00960197412e4be3902a6cd35e60817c511137aca6c34c66cd5d4017ec" [[package]] name = "solana-net-shaper" @@ -8815,8 +8722,6 @@ checksum = "8b8a731ed60e89177c8a7ab05fe0f1511cedd3e70e773f288f9de33a9cfdc21e" [[package]] name = "solana-nonce" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703e22eb185537e06204a5bd9d509b948f0066f2d1d814a6f475dafb3ddf1325" dependencies = [ "serde", "serde_derive", @@ -8829,8 +8734,6 @@ dependencies = [ [[package]] name = "solana-nonce-account" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde971a20b8dbf60144d6a84439dda86b5466e00e2843091fe731083cda614da" dependencies = [ "solana-account", "solana-hash", @@ -8851,8 +8754,6 @@ dependencies = [ [[package]] name = "solana-offchain-message" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b526398ade5dea37f1f147ce55dae49aa017a5d7326606359b0445ca8d946581" dependencies = [ "num_enum", "solana-hash", @@ -8867,8 +8768,6 @@ dependencies = [ [[package]] name = "solana-packet" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004f2d2daf407b3ec1a1ca5ec34b3ccdfd6866dd2d3c7d0715004a96e4b6d127" dependencies = [ "bincode", "bitflags 2.9.0", @@ -8976,8 +8875,6 @@ dependencies = [ [[package]] name = "solana-poh-config" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d650c3b4b9060082ac6b0efbbb66865089c58405bfb45de449f3f2b91eccee75" dependencies = [ "serde", "serde_derive", @@ -8998,8 +8895,6 @@ dependencies = [ [[package]] name = "solana-precompile-error" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff64daa2933c22982b323d88d0cdf693201ef56ac381ae16737fd5f579e07d6" dependencies = [ "num-traits", "solana-decode-error", @@ -9008,8 +8903,6 @@ dependencies = [ [[package]] name = "solana-precompiles" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a460ab805ec063802105b463ecb5eb02c3ffe469e67a967eea8a6e778e0bc06" dependencies = [ "lazy_static", "solana-ed25519-program", @@ -9025,8 +8918,6 @@ dependencies = [ [[package]] name = "solana-presigner" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a57a24e6a4125fc69510b6774cd93402b943191b6cddad05de7281491c90fe" dependencies = [ "solana-pubkey", "solana-signature", @@ -9036,8 +8927,6 @@ dependencies = [ [[package]] name = "solana-program" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "586469467e93ceb79048f8d8e3a619bf61d05396ee7de95cb40280301a589d05" dependencies = [ "bincode", "blake3", @@ -9118,8 +9007,6 @@ dependencies = [ [[package]] name = "solana-program-entrypoint" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473ffe73c68d93e9f2aa726ad2985fe52760052709aaab188100a42c618060ec" dependencies = [ "solana-account-info", "solana-msg", @@ -9130,8 +9017,6 @@ dependencies = [ [[package]] name = "solana-program-error" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8ae2c1a8d0d4ae865882d5770a7ebca92bab9c685e43f0461682c6c05a35bfa" dependencies = [ "borsh 1.5.7", "num-traits", @@ -9146,24 +9031,17 @@ dependencies = [ [[package]] name = "solana-program-memory" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b0268f6c89825fb634a34bd0c3b8fdaeaecfc3728be1d622a8ee6dd577b60d4" dependencies = [ - "num-traits", "solana-define-syscall", ] [[package]] name = "solana-program-option" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc677a2e9bc616eda6dbdab834d463372b92848b2bfe4a1ed4e4b4adba3397d0" [[package]] name = "solana-program-pack" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "319f0ef15e6e12dc37c597faccb7d62525a509fec5f6975ecb9419efddeb277b" dependencies = [ "solana-program-error", ] @@ -9255,8 +9133,6 @@ dependencies = [ [[package]] name = "solana-pubkey" version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad77cf9f30b971a1eec48dde6a863dcac60ba005a34dfde23736afa5c7ac667" dependencies = [ "arbitrary", "borsh 0.10.3", @@ -9345,8 +9221,6 @@ dependencies = [ [[package]] name = "solana-quic-definitions" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e606feac5110eb5d8afaa43ccaeea3ec49ccec36773387930b5ba545e745aea2" dependencies = [ "solana-keypair", ] @@ -9385,8 +9259,6 @@ dependencies = [ [[package]] name = "solana-rent" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1aea8fdea9de98ca6e8c2da5827707fb3842833521b528a713810ca685d2480" dependencies = [ "serde", "serde_derive", @@ -9400,8 +9272,6 @@ dependencies = [ [[package]] name = "solana-rent-collector" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c1e19f5d5108b0d824244425e43bc78bbb9476e2199e979b0230c9f632d3bf4" dependencies = [ "serde", "serde_derive", @@ -9419,8 +9289,6 @@ dependencies = [ [[package]] name = "solana-rent-debits" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f6f9113c6003492e74438d1288e30cffa8ccfdc2ef7b49b9e816d8034da18cd" dependencies = [ "solana-pubkey", "solana-reward-info", @@ -9429,8 +9297,6 @@ dependencies = [ [[package]] name = "solana-reserved-account-keys" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b293f4246626c0e0a991531f08848a713ada965612e99dc510963f04d12cae7" dependencies = [ "lazy_static", "solana-feature-set", @@ -9441,8 +9307,6 @@ dependencies = [ [[package]] name = "solana-reward-info" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18205b69139b1ae0ab8f6e11cdcb627328c0814422ad2482000fa2ca54ae4a2f" dependencies = [ "serde", "serde_derive", @@ -9456,6 +9320,7 @@ version = "2.3.0" dependencies = [ "agave-feature-set", "agave-reserved-account-keys", + "assert_matches", "base64 0.22.1", "bincode", "bs58", @@ -9559,6 +9424,7 @@ dependencies = [ "solana-program", "solana-pubkey", "solana-rpc-client-api", + "solana-sdk-ids", "solana-signature", "solana-signer", "solana-system-transaction", @@ -9821,8 +9687,6 @@ dependencies = [ [[package]] name = "solana-sanitize" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f1bc1357b8188d9c4a3af3fc55276e56987265eb7ad073ae6f8180ee54cecf" [[package]] name = "solana-sbpf" @@ -9846,8 +9710,6 @@ dependencies = [ [[package]] name = "solana-sdk" version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8af90d2ce445440e0548fa4a5f96fe8b265c22041a68c942012ffadd029667d" dependencies = [ "bincode", "bs58", @@ -9917,8 +9779,6 @@ dependencies = [ [[package]] name = "solana-sdk-ids" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5d8b9cc68d5c88b062a33e23a6466722467dde0035152d8fb1afbcdf350a5f" dependencies = [ "solana-pubkey", ] @@ -9926,8 +9786,6 @@ dependencies = [ [[package]] name = "solana-sdk-macro" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86280da8b99d03560f6ab5aca9de2e38805681df34e0bb8f238e69b29433b9df" dependencies = [ "bs58", "proc-macro2", @@ -9938,8 +9796,6 @@ dependencies = [ [[package]] name = "solana-secp256k1-program" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a1caa972414cc78122c32bdae65ac5fe89df7db598585a5cde19d16a20280a" dependencies = [ "bincode", "digest 0.10.7", @@ -9951,13 +9807,12 @@ dependencies = [ "solana-instruction", "solana-precompile-error", "solana-sdk-ids", + "solana-signature", ] [[package]] name = "solana-secp256k1-recover" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" dependencies = [ "borsh 1.5.7", "libsecp256k1", @@ -9968,8 +9823,6 @@ dependencies = [ [[package]] name = "solana-secp256r1-program" version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cda2aa1bbaceda14763c4f142a00b486f2f262cfd901bd0410649ad0404d5f7" dependencies = [ "bytemuck", "openssl", @@ -9988,8 +9841,6 @@ checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183" [[package]] name = "solana-seed-derivable" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beb82b5adb266c6ea90e5cf3967235644848eac476c5a1f2f9283a143b7c97f" dependencies = [ "solana-derivation-path", ] @@ -9997,8 +9848,6 @@ dependencies = [ [[package]] name = "solana-seed-phrase" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36187af2324f079f65a675ec22b31c24919cb4ac22c79472e85d819db9bbbc15" dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", @@ -10030,8 +9879,6 @@ dependencies = [ [[package]] name = "solana-serde" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1931484a408af466e14171556a47adaa215953c7f48b24e5f6b0282763818b04" dependencies = [ "serde", ] @@ -10039,8 +9886,6 @@ dependencies = [ [[package]] name = "solana-serde-varint" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc07d00200d82e6def2f7f7a45738e3406b17fe54a18adcf0defa16a97ccadb" dependencies = [ "serde", ] @@ -10048,8 +9893,6 @@ dependencies = [ [[package]] name = "solana-serialize-utils" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "817a284b63197d2b27afdba829c5ab34231da4a9b4e763466a003c40ca4f535e" dependencies = [ "solana-instruction", "solana-pubkey", @@ -10059,8 +9902,6 @@ dependencies = [ [[package]] name = "solana-sha256-hasher" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0037386961c0d633421f53560ad7c80675c0447cba4d1bb66d60974dd486c7ea" dependencies = [ "sha2 0.10.8", "solana-define-syscall", @@ -10070,8 +9911,6 @@ dependencies = [ [[package]] name = "solana-short-vec" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c54c66f19b9766a56fa0057d060de8378676cb64987533fa088861858fc5a69" dependencies = [ "serde", "solana-frozen-abi", @@ -10081,8 +9920,6 @@ dependencies = [ [[package]] name = "solana-shred-version" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afd3db0461089d1ad1a78d9ba3f15b563899ca2386351d38428faa5350c60a98" dependencies = [ "solana-hard-forks", "solana-hash", @@ -10092,8 +9929,6 @@ dependencies = [ [[package]] name = "solana-signature" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d251c8f3dc015f320b4161daac7f108156c837428e5a8cc61136d25beb11d6" dependencies = [ "bs58", "ed25519-dalek", @@ -10109,8 +9944,6 @@ dependencies = [ [[package]] name = "solana-signer" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c41991508a4b02f021c1342ba00bcfa098630b213726ceadc7cb032e051975b" dependencies = [ "solana-pubkey", "solana-signature", @@ -10120,8 +9953,6 @@ dependencies = [ [[package]] name = "solana-slot-hashes" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce" dependencies = [ "serde", "serde_derive", @@ -10133,8 +9964,6 @@ dependencies = [ [[package]] name = "solana-slot-history" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ccc1b2067ca22754d5283afb2b0126d61eae734fc616d23871b0943b0d935e" dependencies = [ "bv", "serde", @@ -10146,8 +9975,6 @@ dependencies = [ [[package]] name = "solana-stable-layout" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f14f7d02af8f2bc1b5efeeae71bc1c2b7f0f65cd75bcc7d8180f2c762a57f54" dependencies = [ "solana-instruction", "solana-pubkey", @@ -10545,8 +10372,6 @@ dependencies = [ [[package]] name = "solana-system-transaction" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd98a25e5bcba8b6be8bcbb7b84b24c2a6a8178d7fb0e3077a916855ceba91a" dependencies = [ "solana-hash", "solana-keypair", @@ -10560,8 +10385,6 @@ dependencies = [ [[package]] name = "solana-sysvar" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf6b44740d7f0c9f375d045c165bc0aab4a90658f92d6835aeb0649afaeaff9a" dependencies = [ "base64 0.22.1", "bincode", @@ -10599,8 +10422,6 @@ dependencies = [ [[package]] name = "solana-sysvar-id" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5762b273d3325b047cfda250787f8d796d781746860d5d0a746ee29f3e8812c1" dependencies = [ "solana-pubkey", "solana-sdk-ids", @@ -10669,8 +10490,6 @@ dependencies = [ [[package]] name = "solana-time-utils" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af261afb0e8c39252a04d026e3ea9c405342b08c871a2ad8aa5448e068c784c" [[package]] name = "solana-timings" @@ -10823,8 +10642,6 @@ dependencies = [ [[package]] name = "solana-transaction" version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abec848d081beb15a324c633cd0e0ab33033318063230389895cae503ec9b544" dependencies = [ "bincode", "serde", @@ -10915,8 +10732,6 @@ dependencies = [ [[package]] name = "solana-transaction-error" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a9dc8fdb61c6088baab34fc3a8b8473a03a7a5fd404ed8dd502fa79b67cb1" dependencies = [ "serde", "serde_derive", @@ -11146,8 +10961,6 @@ dependencies = [ [[package]] name = "solana-validator-exit" version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bbf6d7a3c0b28dd5335c52c0e9eae49d0ae489a8f324917faf0ded65a812c1d" [[package]] name = "solana-version" @@ -11258,8 +11071,6 @@ dependencies = [ [[package]] name = "solana-vote-interface" version = "2.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f039b0788337bedc6c5450d2f237718f938defb5ce0e0ad8ef507e78dcd370" dependencies = [ "arbitrary", "bincode", @@ -11378,6 +11189,7 @@ dependencies = [ name = "solana-zk-elgamal-proof-program-tests" version = "2.3.0" dependencies = [ + "assert_matches", "bytemuck", "solana-account", "solana-compute-budget", @@ -14028,3 +13840,11 @@ dependencies = [ "cc", "pkg-config", ] + +[[patch.unused]] +name = "solana-package-metadata" +version = "2.2.1" + +[[patch.unused]] +name = "solana-package-metadata-macro" +version = "2.2.1" diff --git a/Cargo.toml b/Cargo.toml index 8f18cd7083e820..6dc61af10a9b37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -645,6 +645,106 @@ zstd = "0.13.3" opt-level = 3 [patch.crates-io] +# The following entries are auto-generated by /bin/bash +solana-account = { path = "/home/sol/src/solana-sdk/account" } +solana-account-info = { path = "/home/sol/src/solana-sdk/account-info" } +solana-address-lookup-table-interface = { path = "/home/sol/src/solana-sdk/address-lookup-table-interface" } +solana-atomic-u64 = { path = "/home/sol/src/solana-sdk/atomic-u64" } +solana-big-mod-exp = { path = "/home/sol/src/solana-sdk/big-mod-exp" } +solana-bincode = { path = "/home/sol/src/solana-sdk/bincode" } +solana-blake3-hasher = { path = "/home/sol/src/solana-sdk/blake3-hasher" } +solana-bn254 = { path = "/home/sol/src/solana-sdk/bn254" } +solana-borsh = { path = "/home/sol/src/solana-sdk/borsh" } +solana-client-traits = { path = "/home/sol/src/solana-sdk/client-traits" } +solana-clock = { path = "/home/sol/src/solana-sdk/clock" } +solana-cluster-type = { path = "/home/sol/src/solana-sdk/cluster-type" } +solana-commitment-config = { path = "/home/sol/src/solana-sdk/commitment-config" } +solana-compute-budget-interface = { path = "/home/sol/src/solana-sdk/compute-budget-interface" } +solana-cpi = { path = "/home/sol/src/solana-sdk/cpi" } +solana-decode-error = { path = "/home/sol/src/solana-sdk/decode-error" } +solana-define-syscall = { path = "/home/sol/src/solana-sdk/define-syscall" } +solana-derivation-path = { path = "/home/sol/src/solana-sdk/derivation-path" } +solana-ed25519-program = { path = "/home/sol/src/solana-sdk/ed25519-program" } +solana-epoch-info = { path = "/home/sol/src/solana-sdk/epoch-info" } +solana-epoch-rewards = { path = "/home/sol/src/solana-sdk/epoch-rewards" } +solana-epoch-rewards-hasher = { path = "/home/sol/src/solana-sdk/epoch-rewards-hasher" } +solana-epoch-schedule = { path = "/home/sol/src/solana-sdk/epoch-schedule" } +solana-example-mocks = { path = "/home/sol/src/solana-sdk/example-mocks" } +solana-feature-gate-interface = { path = "/home/sol/src/solana-sdk/feature-gate-interface" } +solana-feature-set = { path = "/home/sol/src/solana-sdk/feature-set" } +solana-fee-calculator = { path = "/home/sol/src/solana-sdk/fee-calculator" } +solana-fee-structure = { path = "/home/sol/src/solana-sdk/fee-structure" } +solana-file-download = { path = "/home/sol/src/solana-sdk/file-download" } +solana-frozen-abi = { path = "/home/sol/src/solana-sdk/frozen-abi" } +solana-frozen-abi-macro = { path = "/home/sol/src/solana-sdk/frozen-abi-macro" } +solana-genesis-config = { path = "/home/sol/src/solana-sdk/genesis-config" } +solana-hard-forks = { path = "/home/sol/src/solana-sdk/hard-forks" } +solana-hash = { path = "/home/sol/src/solana-sdk/hash" } +solana-inflation = { path = "/home/sol/src/solana-sdk/inflation" } +solana-instruction = { path = "/home/sol/src/solana-sdk/instruction" } +solana-instructions-sysvar = { path = "/home/sol/src/solana-sdk/instructions-sysvar" } +solana-keccak-hasher = { path = "/home/sol/src/solana-sdk/keccak-hasher" } +solana-keypair = { path = "/home/sol/src/solana-sdk/keypair" } +solana-last-restart-slot = { path = "/home/sol/src/solana-sdk/last-restart-slot" } +solana-loader-v2-interface = { path = "/home/sol/src/solana-sdk/loader-v2-interface" } +solana-loader-v3-interface = { path = "/home/sol/src/solana-sdk/loader-v3-interface" } +solana-loader-v4-interface = { path = "/home/sol/src/solana-sdk/loader-v4-interface" } +solana-logger = { path = "/home/sol/src/solana-sdk/logger" } +solana-message = { path = "/home/sol/src/solana-sdk/message" } +solana-msg = { path = "/home/sol/src/solana-sdk/msg" } +solana-native-token = { path = "/home/sol/src/solana-sdk/native-token" } +solana-nonce = { path = "/home/sol/src/solana-sdk/nonce" } +solana-nonce-account = { path = "/home/sol/src/solana-sdk/nonce-account" } +solana-offchain-message = { path = "/home/sol/src/solana-sdk/offchain-message" } +solana-package-metadata = { path = "/home/sol/src/solana-sdk/package-metadata" } +solana-package-metadata-macro = { path = "/home/sol/src/solana-sdk/package-metadata-macro" } +solana-packet = { path = "/home/sol/src/solana-sdk/packet" } +solana-poh-config = { path = "/home/sol/src/solana-sdk/poh-config" } +solana-precompile-error = { path = "/home/sol/src/solana-sdk/precompile-error" } +solana-precompiles = { path = "/home/sol/src/solana-sdk/precompiles" } +solana-presigner = { path = "/home/sol/src/solana-sdk/presigner" } +solana-program = { path = "/home/sol/src/solana-sdk/program" } +solana-program-entrypoint = { path = "/home/sol/src/solana-sdk/program-entrypoint" } +solana-program-error = { path = "/home/sol/src/solana-sdk/program-error" } +solana-program-memory = { path = "/home/sol/src/solana-sdk/program-memory" } +solana-program-option = { path = "/home/sol/src/solana-sdk/program-option" } +solana-program-pack = { path = "/home/sol/src/solana-sdk/program-pack" } +solana-pubkey = { path = "/home/sol/src/solana-sdk/pubkey" } +solana-quic-definitions = { path = "/home/sol/src/solana-sdk/quic-definitions" } +solana-rent = { path = "/home/sol/src/solana-sdk/rent" } +solana-rent-collector = { path = "/home/sol/src/solana-sdk/rent-collector" } +solana-rent-debits = { path = "/home/sol/src/solana-sdk/rent-debits" } +solana-reserved-account-keys = { path = "/home/sol/src/solana-sdk/reserved-account-keys" } +solana-reward-info = { path = "/home/sol/src/solana-sdk/reward-info" } +solana-sanitize = { path = "/home/sol/src/solana-sdk/sanitize" } +solana-sdk = { path = "/home/sol/src/solana-sdk/sdk" } +solana-sdk-ids = { path = "/home/sol/src/solana-sdk/sdk-ids" } +solana-sdk-macro = { path = "/home/sol/src/solana-sdk/sdk-macro" } +solana-secp256k1-program = { path = "/home/sol/src/solana-sdk/secp256k1-program" } +solana-secp256k1-recover = { path = "/home/sol/src/solana-sdk/secp256k1-recover" } +solana-secp256r1-program = { path = "/home/sol/src/solana-sdk/secp256r1-program" } +solana-seed-derivable = { path = "/home/sol/src/solana-sdk/seed-derivable" } +solana-seed-phrase = { path = "/home/sol/src/solana-sdk/seed-phrase" } +solana-serde = { path = "/home/sol/src/solana-sdk/serde" } +solana-serde-varint = { path = "/home/sol/src/solana-sdk/serde-varint" } +solana-serialize-utils = { path = "/home/sol/src/solana-sdk/serialize-utils" } +solana-sha256-hasher = { path = "/home/sol/src/solana-sdk/sha256-hasher" } +solana-short-vec = { path = "/home/sol/src/solana-sdk/short-vec" } +solana-shred-version = { path = "/home/sol/src/solana-sdk/shred-version" } +solana-signature = { path = "/home/sol/src/solana-sdk/signature" } +solana-signer = { path = "/home/sol/src/solana-sdk/signer" } +solana-slot-hashes = { path = "/home/sol/src/solana-sdk/slot-hashes" } +solana-slot-history = { path = "/home/sol/src/solana-sdk/slot-history" } +solana-stable-layout = { path = "/home/sol/src/solana-sdk/stable-layout" } +solana-system-transaction = { path = "/home/sol/src/solana-sdk/system-transaction" } +solana-sysvar = { path = "/home/sol/src/solana-sdk/sysvar" } +solana-sysvar-id = { path = "/home/sol/src/solana-sdk/sysvar-id" } +solana-time-utils = { path = "/home/sol/src/solana-sdk/time-utils" } +solana-transaction = { path = "/home/sol/src/solana-sdk/transaction" } +solana-transaction-error = { path = "/home/sol/src/solana-sdk/transaction-error" } +solana-validator-exit = { path = "/home/sol/src/solana-sdk/validator-exit" } +solana-vote-interface = { path = "/home/sol/src/solana-sdk/vote-interface" } + # for details, see https://github.com/anza-xyz/crossbeam/commit/fd279d707025f0e60951e429bf778b4813d1b6bf crossbeam-epoch = { git = "https://github.com/anza-xyz/crossbeam", rev = "fd279d707025f0e60951e429bf778b4813d1b6bf" } diff --git a/cli/src/cli.rs b/cli/src/cli.rs index a7d5d5cbf8074f..017f2c2344bc73 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -1768,7 +1768,7 @@ where match result { Err(err) => { let maybe_tx_err = err.get_transaction_error(); - if let Some(TransactionError::InstructionError(_, ix_error)) = maybe_tx_err { + if let Some(TransactionError::InstructionError(_, ix_error, _, _)) = maybe_tx_err { if let Some(specific_error) = error_adapter(&ix_error) { return Err(specific_error.into()); } diff --git a/cli/src/program.rs b/cli/src/program.rs index 1c7f727f232010..a8136272449399 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -2214,12 +2214,16 @@ fn close( if let ClientErrorKind::TransactionError(TransactionError::InstructionError( _, InstructionError::InvalidInstructionData, + _, + _, )) = err.kind() { return Err("Closing a buffer account is not supported by the cluster".into()); } else if let ClientErrorKind::TransactionError(TransactionError::InstructionError( _, InstructionError::InvalidArgument, + _, + _, )) = err.kind() { return Err("Closing a program account is not supported by the cluster".into()); @@ -2437,6 +2441,8 @@ fn process_extend_program( if let ClientErrorKind::TransactionError(TransactionError::InstructionError( _, InstructionError::InvalidInstructionData, + _, + _, )) = err.kind() { return Err("Extending a program is not supported by the cluster".into()); @@ -2532,6 +2538,8 @@ fn process_migrate_program( if let ClientErrorKind::TransactionError(TransactionError::InstructionError( _, InstructionError::InvalidInstructionData, + _, + _, )) = err.kind() { return Err("Migrating a program is not supported by the cluster".into()); diff --git a/compute-budget-instruction/Cargo.toml b/compute-budget-instruction/Cargo.toml index 779418adb2ec0e..d4163af7203549 100644 --- a/compute-budget-instruction/Cargo.toml +++ b/compute-budget-instruction/Cargo.toml @@ -29,6 +29,7 @@ crate-type = ["lib"] name = "solana_compute_budget_instruction" [dev-dependencies] +assert_matches = { workspace = true } bincode = { workspace = true } criterion = { workspace = true } rand = { workspace = true } diff --git a/compute-budget-instruction/src/compute_budget_instruction_details.rs b/compute-budget-instruction/src/compute_budget_instruction_details.rs index 23a0b4bd234759..c669f2f0f3a348 100644 --- a/compute-budget-instruction/src/compute_budget_instruction_details.rs +++ b/compute-budget-instruction/src/compute_budget_instruction_details.rs @@ -111,6 +111,8 @@ impl ComputeBudgetInstructionDetails { return Err(TransactionError::InstructionError( index, InstructionError::InvalidInstructionData, + None, + None, )); } } else { @@ -153,8 +155,12 @@ impl ComputeBudgetInstructionDetails { } fn process_instruction(&mut self, index: u8, instruction: &SVMInstruction) -> Result<()> { - let invalid_instruction_data_error = - TransactionError::InstructionError(index, InstructionError::InvalidInstructionData); + let invalid_instruction_data_error = TransactionError::InstructionError( + index, + InstructionError::InvalidInstructionData, + None, + Some(instruction.program_id_index), + ); let duplicate_instruction_error = TransactionError::DuplicateInstruction(index); match try_from_slice_unchecked(instruction.data) { @@ -407,6 +413,8 @@ mod test { let expected_heap_size_err = Err(TransactionError::InstructionError( 3, InstructionError::InvalidInstructionData, + None, + None, )); // invalid: requested_heap_size can't be zero let instruction_details = ComputeBudgetInstructionDetails { diff --git a/compute-budget-instruction/src/instructions_processor.rs b/compute-budget-instruction/src/instructions_processor.rs index b3c00aed1bcc9a..43fa2b55bfd084 100644 --- a/compute-budget-instruction/src/instructions_processor.rs +++ b/compute-budget-instruction/src/instructions_processor.rs @@ -164,6 +164,8 @@ mod tests { Err(TransactionError::InstructionError( 0, InstructionError::InvalidInstructionData, + None, + None, )) ); test!( @@ -174,6 +176,8 @@ mod tests { Err(TransactionError::InstructionError( 0, InstructionError::InvalidInstructionData, + None, + None, )) ); test!( @@ -184,6 +188,8 @@ mod tests { Err(TransactionError::InstructionError( 0, InstructionError::InvalidInstructionData, + None, + None, )) ); test!( @@ -222,6 +228,8 @@ mod tests { Err(TransactionError::InstructionError( 3, InstructionError::InvalidInstructionData, + None, + None, )) ); test!( diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index 359b39905cb63d..c66453af330912 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -1573,17 +1573,20 @@ mod tests { (transaction.signatures[0], meta.status) }) .collect(); - let expected_tx_results = vec![ - (success_signature, Ok(())), + assert_eq!(actual_tx_results.len(), 2); + assert_eq!(actual_tx_results[0], (success_signature, Ok(()))); + assert_matches!( + actual_tx_results[1], ( - ix_error_signature, + actual_ix_signature, Err(TransactionError::InstructionError( 0, InstructionError::Custom(1), + None, + Some(ii), )), - ), - ]; - assert_eq!(actual_tx_results, expected_tx_results); + ) if ii > 0 && actual_ix_signature == ix_error_signature + ); poh_recorder .read() diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index 19d512e2595eb7..e5bf72dbcd95c6 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -5347,17 +5347,22 @@ pub(crate) mod tests { (transaction.signatures[0], meta.status) }) .collect(); - let expected_tx_results = vec![ - (test_signatures_iter.next().unwrap(), Ok(())), + assert_eq!(actual_tx_results.len(), 2); + let first_expected_result = test_signatures_iter.next().unwrap(); + assert_eq!(actual_tx_results[0], (first_expected_result, Ok(()))); + let second_expected_result = test_signatures_iter.next().unwrap(); + assert_matches!( + actual_tx_results[1], ( - test_signatures_iter.next().unwrap(), + actual_result, Err(TransactionError::InstructionError( 0, InstructionError::Custom(1), + None, + Some(ii), )), - ), - ]; - assert_eq!(actual_tx_results, expected_tx_results); + ) if ii > 0 && actual_result == second_expected_result + ); assert!(test_signatures_iter.next().is_none()); } Blockstore::destroy(&ledger_path).unwrap(); diff --git a/core/tests/scheduler_cost_adjustment.rs b/core/tests/scheduler_cost_adjustment.rs index 368757d2ea9468..3e2e93b09e4cc3 100644 --- a/core/tests/scheduler_cost_adjustment.rs +++ b/core/tests/scheduler_cost_adjustment.rs @@ -1,5 +1,6 @@ #![cfg(test)] use { + assert_matches::assert_matches, solana_compute_budget::compute_budget_limits::MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT, solana_cost_model::cost_model::CostModel, solana_runtime::{bank::Bank, bank_forks::BankForks}, @@ -230,19 +231,20 @@ fn test_builtin_ix_cost_adjustment_with_cu_limit_too_low() { // Cost model & Compute budget: reserve/allocate requested CU Limit `1` // VM Execution: consume `1` CU, then fail // Result: 0 adjustment - let expected = TestResult { - cost_adjustment: 0, - execution_status: Err(TransactionError::InstructionError( - 0, - InstructionError::ComputationalBudgetExceeded, - )), - }; - assert_eq!( - expected, + assert_matches!( test_setup.execute_test_transaction(&[ test_setup.transfer_ix(), test_setup.set_cu_limit_ix(cu_limit), - ]) + ]), + TestResult { + cost_adjustment: 0, + execution_status: Err(TransactionError::InstructionError( + 0, + InstructionError::ComputationalBudgetExceeded, + None, + Some(ii), + )), + } if ii > 0 ); } @@ -282,16 +284,17 @@ fn test_builtin_ix_cost_adjustment_with_memo_no_cu_limit() { // (3_000 + 200_000) = 203_000 CUs (note: less than memo_ix needs) // VM Execution: consume all allocated CUs, then fail // Result: no adjustment - let expected = TestResult { - cost_adjustment: 0, - execution_status: Err(TransactionError::InstructionError( - 1, - InstructionError::ProgramFailedToComplete, - )), - }; - assert_eq!( - expected, - test_setup.execute_test_transaction(&[test_setup.transfer_ix(), memo_ix.clone()],) + assert_matches!( + test_setup.execute_test_transaction(&[test_setup.transfer_ix(), memo_ix.clone()],), + TestResult { + cost_adjustment: 0, + execution_status: Err(TransactionError::InstructionError( + 1, + InstructionError::ProgramFailedToComplete, + None, + Some(ii), + )), + } if ii > 0 ); } diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index e28efcfc9189f7..a936b477540e48 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -3995,12 +3995,14 @@ pub mod tests { bank.transfer(1_000, &mint_keypair, &pubkey).unwrap(); assert_eq!(bank.transaction_count(), 1); assert_eq!(bank.get_balance(&pubkey), 1_000); - assert_eq!( + assert_matches!( bank.transfer(10_001, &mint_keypair, &pubkey), Err(TransactionError::InstructionError( 0, - SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); assert_eq!( bank.transfer(10_001, &mint_keypair, &pubkey), diff --git a/program-test/tests/panic.rs b/program-test/tests/panic.rs index de8e74b3d40902..0e56050f4a0140 100644 --- a/program-test/tests/panic.rs +++ b/program-test/tests/panic.rs @@ -1,4 +1,5 @@ use { + assert_matches::assert_matches, solana_program_test::{processor, ProgramTest}, solana_sdk::{ account_info::AccountInfo, @@ -30,13 +31,18 @@ async fn panic_test() { &[&context.payer], context.last_blockhash, ); - assert_eq!( + assert_matches!( context .banks_client .process_transaction(transaction) .await .unwrap_err() .unwrap(), - TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete) + TransactionError::InstructionError( + 0, + InstructionError::ProgramFailedToComplete, + None, + Some(ii), + ) if ii > 0 ); } diff --git a/program-test/tests/warp.rs b/program-test/tests/warp.rs index 2728fcfd98a66a..51a66947cdf884 100644 --- a/program-test/tests/warp.rs +++ b/program-test/tests/warp.rs @@ -3,6 +3,7 @@ mod setup; use { + assert_matches::assert_matches, bincode::deserialize, log::debug, setup::{setup_stake, setup_vote}, @@ -78,14 +79,19 @@ async fn clock_sysvar_updated_from_warp() { &[&context.payer], context.last_blockhash, ); - assert_eq!( + assert_matches!( context .banks_client .process_transaction(transaction) .await .unwrap_err() .unwrap(), - TransactionError::InstructionError(0, InstructionError::Custom(WRONG_SLOT_ERROR)) + TransactionError::InstructionError( + 0, + InstructionError::Custom(WRONG_SLOT_ERROR), + None, + Some(ii), + ) if ii > 0 ); // Warp to success! diff --git a/programs/bpf-loader-tests/tests/common.rs b/programs/bpf-loader-tests/tests/common.rs index 99cae212c7f481..95724bc43a5e0c 100644 --- a/programs/bpf-loader-tests/tests/common.rs +++ b/programs/bpf-loader-tests/tests/common.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use { + assert_matches::assert_matches, solana_program_test::*, solana_sdk::{ account::AccountSharedData, @@ -41,14 +42,19 @@ pub async fn assert_ix_error( recent_blockhash, ); - assert_eq!( + assert_matches!( client .process_transaction(transaction) .await .unwrap_err() .unwrap(), - TransactionError::InstructionError(0, expected_err), - "{assertion_failed_msg}", + TransactionError::InstructionError( + 0, + actual_err, + Some(_) | None, + Some(ii), + ) if ii > 0 && actual_err == expected_err, + "{assertion_failed_msg}" ); } diff --git a/programs/bpf-loader-tests/tests/extend_program_ix.rs b/programs/bpf-loader-tests/tests/extend_program_ix.rs index 8f50b2f4289170..53ee59c48ab419 100644 --- a/programs/bpf-loader-tests/tests/extend_program_ix.rs +++ b/programs/bpf-loader-tests/tests/extend_program_ix.rs @@ -155,7 +155,12 @@ async fn test_failed_extend_twice_in_same_slot() { .await .unwrap_err() .unwrap(), - TransactionError::InstructionError(0, InstructionError::InvalidArgument) + TransactionError::InstructionError( + 0, + InstructionError::InvalidArgument, + None, + Some(ii), + ) if ii > 0 ); } diff --git a/programs/ed25519-tests/tests/process_transaction.rs b/programs/ed25519-tests/tests/process_transaction.rs index e8b1c3b85a1c8b..a6932d67aa8966 100644 --- a/programs/ed25519-tests/tests/process_transaction.rs +++ b/programs/ed25519-tests/tests/process_transaction.rs @@ -70,8 +70,13 @@ async fn test_failure() { assert_matches!( client.process_transaction(transaction).await, Err(BanksClientError::TransactionError( - TransactionError::InstructionError(0, InstructionError::Custom(3)) - )) + TransactionError::InstructionError( + 0, + InstructionError::Custom(3), + None, + Some(ii), + ), + )) if ii > 0 ); // this assert is for documenting the matched error code above assert_eq!(3, PrecompileError::InvalidDataOffsets as u32); diff --git a/programs/stake-tests/tests/test_move_stake_and_lamports.rs b/programs/stake-tests/tests/test_move_stake_and_lamports.rs index b78924addcf5c6..011b42e26be132 100644 --- a/programs/stake-tests/tests/test_move_stake_and_lamports.rs +++ b/programs/stake-tests/tests/test_move_stake_and_lamports.rs @@ -269,7 +269,7 @@ async fn process_instruction( Err(e) => { // banks client error -> transaction error -> instruction error -> program error match e.unwrap() { - TransactionError::InstructionError(_, e) => Err(e.try_into().unwrap()), + TransactionError::InstructionError(_, e, _, _) => Err(e.try_into().unwrap()), TransactionError::InsufficientFundsForRent { .. } => { Err(ProgramError::InsufficientFunds) } diff --git a/programs/zk-elgamal-proof-tests/Cargo.toml b/programs/zk-elgamal-proof-tests/Cargo.toml index 2b0f682c3689d0..9915a2595be33f 100644 --- a/programs/zk-elgamal-proof-tests/Cargo.toml +++ b/programs/zk-elgamal-proof-tests/Cargo.toml @@ -8,6 +8,7 @@ license = { workspace = true } edition = { workspace = true } [dev-dependencies] +assert_matches = { workspace = true } bytemuck = { workspace = true } solana-account = { workspace = true } solana-compute-budget = { workspace = true } diff --git a/programs/zk-elgamal-proof-tests/tests/process_transaction.rs b/programs/zk-elgamal-proof-tests/tests/process_transaction.rs index adfa96c68c410d..e2ec7a138fd459 100644 --- a/programs/zk-elgamal-proof-tests/tests/process_transaction.rs +++ b/programs/zk-elgamal-proof-tests/tests/process_transaction.rs @@ -1,4 +1,5 @@ use { + assert_matches::assert_matches, bytemuck::{bytes_of, Pod}, solana_account::Account, solana_instruction::error::InstructionError, @@ -761,9 +762,14 @@ async fn test_verify_proof_without_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) + TransactionError::InstructionError( + 0, + InstructionError::InvalidInstructionData, + None, + Some(ii), + ) if ii > 0 ); // try to verify a valid proof, but with a wrong proof type @@ -785,9 +791,14 @@ async fn test_verify_proof_without_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) + TransactionError::InstructionError( + 0, + InstructionError::InvalidInstructionData, + None, + Some(ii), + ) if ii > 0 ); } @@ -816,9 +827,14 @@ async fn test_verify_proof_without_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(0, InstructionError::InvalidInstructionData) + TransactionError::InstructionError( + 0, + InstructionError::InvalidInstructionData, + None, + Some(ii), + ) if ii > 0 ) } @@ -870,9 +886,14 @@ async fn test_verify_proof_with_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(1, InstructionError::InvalidInstructionData) + TransactionError::InstructionError( + 1, + InstructionError::InvalidInstructionData, + None, + Some(ii), + ) if ii > 0 ); // try to create proof context state with incorrect account data length @@ -897,9 +918,14 @@ async fn test_verify_proof_with_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(1, InstructionError::InvalidAccountData) + TransactionError::InstructionError( + 1, + InstructionError::InvalidAccountData, + None, + Some(ii), + ) if ii > 0 ); // try to create proof context state with insufficient rent @@ -957,9 +983,14 @@ async fn test_verify_proof_with_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(1, InstructionError::InvalidInstructionData) + TransactionError::InstructionError( + 1, + InstructionError::InvalidInstructionData, + None, + Some(ii), + ) if ii > 0 ); } @@ -996,9 +1027,14 @@ async fn test_verify_proof_with_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(0, InstructionError::AccountAlreadyInitialized) + TransactionError::InstructionError( + 0, + InstructionError::AccountAlreadyInitialized, + None, + Some(ii), + ) if ii > 0 ); // self-owned context state account @@ -1099,9 +1135,14 @@ async fn test_verify_proof_from_account_with_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(1, InstructionError::InvalidInstructionData) + TransactionError::InstructionError( + 1, + InstructionError::InvalidInstructionData, + None, + Some(ii), + ) if ii > 0 ); // successfully create a proof context state @@ -1144,9 +1185,14 @@ async fn test_verify_proof_from_account_with_context( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(0, InstructionError::AccountAlreadyInitialized) + TransactionError::InstructionError( + 0, + InstructionError::AccountAlreadyInitialized, + None, + Some(ii), + ) if ii > 0 ); // self-owned context state account @@ -1245,9 +1291,14 @@ async fn test_close_context_state( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(0, InstructionError::InvalidAccountOwner) + TransactionError::InstructionError( + 0, + InstructionError::InvalidAccountOwner, + None, + Some(ii), + ) if ii > 0 ); // successfully close proof context state @@ -1347,9 +1398,14 @@ async fn test_close_context_state( .await .unwrap_err() .unwrap(); - assert_eq!( + assert_matches!( err, - TransactionError::InstructionError(2, InstructionError::InvalidInstructionData) + TransactionError::InstructionError( + 2, + InstructionError::InvalidInstructionData, + None, + Some(ii), + ) if ii > 0 ); // close self-owned proof context accounts diff --git a/rpc-client/Cargo.toml b/rpc-client/Cargo.toml index f781a0fa670a9f..1e8c95358ebbe9 100644 --- a/rpc-client/Cargo.toml +++ b/rpc-client/Cargo.toml @@ -35,6 +35,7 @@ solana-instruction = { workspace = true } solana-message = { workspace = true } solana-pubkey = { workspace = true } solana-rpc-client-api = { workspace = true } +solana-sdk-ids = { workspace = true } solana-signature = { workspace = true } solana-transaction = { workspace = true, features = ["bincode"] } solana-transaction-error = { workspace = true } diff --git a/rpc-client/src/mock_sender.rs b/rpc-client/src/mock_sender.rs index e2b7e5562b551d..d100ef7824da4f 100644 --- a/rpc-client/src/mock_sender.rs +++ b/rpc-client/src/mock_sender.rs @@ -129,6 +129,8 @@ impl RpcSender for MockSender { Err(TransactionError::InstructionError( 0, InstructionError::UninitializedAccount, + None, + Some(42), // Mock responsible program account index. )) } else { Ok(()) diff --git a/rpc-client/src/rpc_client.rs b/rpc-client/src/rpc_client.rs index fad544ed4c44d3..773e87552d1bbb 100644 --- a/rpc-client/src/rpc_client.rs +++ b/rpc-client/src/rpc_client.rs @@ -3862,7 +3862,9 @@ mod tests { result.unwrap_err().kind(), ErrorKind::TransactionError(TransactionError::InstructionError( 0, - InstructionError::UninitializedAccount + InstructionError::UninitializedAccount, + None, + Some(42), // From mock response for "instruction_error" )) ); diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 6f900e87f33712..1304684867766f 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -70,6 +70,7 @@ tokio-util = { workspace = true, features = ["codec", "compat"] } [dev-dependencies] agave-reserved-account-keys = { workspace = true } +assert_matches = { workspace = true } serial_test = { workspace = true } solana-log-collector = { workspace = true } solana-net-utils = { workspace = true } diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index f79b45c16fdd28..66f5f4a8987556 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -4497,6 +4497,7 @@ pub mod tests { rpc_subscriptions::RpcSubscriptions, }, agave_reserved_account_keys::ReservedAccountKeys, + assert_matches::assert_matches, bincode::deserialize, jsonrpc_core::{futures, ErrorCode, MetaIoHandler, Output, Response, Value}, jsonrpc_core_client::transports::local, @@ -6652,15 +6653,19 @@ pub mod tests { confirmed_block_signatures[1] ); let res = io.handle_request_sync(&req, meta.clone()); - let expected_res: transaction::Result<()> = Err(TransactionError::InstructionError( - 0, - InstructionError::Custom(1), - )); let json: Value = serde_json::from_str(&res.unwrap()).unwrap(); let result: Option = serde_json::from_value(json["result"]["value"][0].clone()) .expect("actual response deserialization"); - assert_eq!(expected_res, result.as_ref().unwrap().status); + assert_matches!( + result.as_ref().unwrap().status, + Err(TransactionError::InstructionError( + 0, + InstructionError::Custom(1), + None, + Some(ii), + )) if ii > 0 + ); // disable rpc-tx-history, but attempt historical query meta.config.enable_rpc_transaction_history = false; @@ -7233,19 +7238,23 @@ pub mod tests { assert_eq!(meta.err, None); } else if transaction.signatures[0] == confirmed_block_signatures[1].to_string() { let meta = meta.unwrap(); - assert_eq!( + assert_matches!( meta.err, Some(TransactionError::InstructionError( 0, - InstructionError::Custom(1) - )) + InstructionError::Custom(1), + None, + Some(ii), + )) if ii > 0 ); - assert_eq!( + assert_matches!( meta.status, Err(TransactionError::InstructionError( 0, - InstructionError::Custom(1) - )) + InstructionError::Custom(1), + None, + Some(ii), + )) if ii > 0 ); } else { assert_eq!(meta, None); @@ -7279,19 +7288,23 @@ pub mod tests { assert_eq!(meta.err, None); } else if decoded_transaction.signatures[0] == confirmed_block_signatures[1] { let meta = meta.unwrap(); - assert_eq!( + assert_matches!( meta.err, Some(TransactionError::InstructionError( 0, - InstructionError::Custom(1) - )) + InstructionError::Custom(1), + None, + Some(ii), + )) if ii > 0 ); - assert_eq!( + assert_matches!( meta.status, Err(TransactionError::InstructionError( 0, - InstructionError::Custom(1) - )) + InstructionError::Custom(1), + None, + Some(ii), + )) if ii > 0 ); } else { assert_eq!(meta, None); diff --git a/runtime/src/account_saver.rs b/runtime/src/account_saver.rs index 001c116bd3f3ca..2653fc5a168eed 100644 --- a/runtime/src/account_saver.rs +++ b/runtime/src/account_saver.rs @@ -362,6 +362,8 @@ mod tests { Err(TransactionError::InstructionError( 1, InstructionError::InvalidArgument, + None, + Some(42), )), loaded, )]; @@ -457,6 +459,8 @@ mod tests { Err(TransactionError::InstructionError( 1, InstructionError::InvalidArgument, + None, + Some(42), )), loaded, )]; @@ -565,6 +569,8 @@ mod tests { Err(TransactionError::InstructionError( 1, InstructionError::InvalidArgument, + None, + Some(42), )), loaded, )]; diff --git a/runtime/src/bank/partitioned_epoch_rewards/mod.rs b/runtime/src/bank/partitioned_epoch_rewards/mod.rs index 21c3ee6cc063f7..7f26a1d4fa1489 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/mod.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/mod.rs @@ -861,9 +861,14 @@ mod tests { // When the bank is at the beginning of the new epoch, i.e. slot // 32, StakeError::EpochRewardsActive should be thrown for // actions like StakeInstruction::Withdraw - assert_eq!( + assert_matches!( stake_result, - Err(InstructionError(0, StakeError::EpochRewardsActive.into())) + Err(InstructionError( + 0, + actual_err, + None, + Some(ii) + )) if ii > 0 && actual_err == StakeError::EpochRewardsActive.into() ); } else { // When the bank is outside of reward interval, the withdraw diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index fd9a328839caaa..48a893b5aaf132 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -1078,7 +1078,12 @@ fn test_rent_exempt_executable_account() { ); assert_matches!( bank.process_transaction(&tx), - Err(TransactionError::InstructionError(0, _)) + Err(TransactionError::InstructionError( + 0, + _, + None, + Some(ii), + )) if ii > 0 ); assert_eq!(bank.get_balance(&account_pubkey), account_balance); } @@ -2458,9 +2463,14 @@ fn test_one_tx_two_out_atomic_fail() { ); let message = Message::new(&instructions, Some(&mint_keypair.pubkey())); let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash()); - assert_eq!( + assert_matches!( bank.process_transaction(&tx).unwrap_err(), - TransactionError::InstructionError(1, SystemError::ResultWithNegativeLamports.into()) + TransactionError::InstructionError( + 1, + actual_err, + None, + Some(ii), + ) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); assert_eq!(bank.get_balance(&mint_keypair.pubkey()), amount); assert_eq!(bank.get_balance(&key1), 0); @@ -2504,12 +2514,14 @@ fn test_detect_failed_duplicate_transactions() { let signature = tx.signatures[0]; assert!(!bank.has_signature(&signature)); - assert_eq!( + assert_matches!( bank.process_transaction(&tx), Err(TransactionError::InstructionError( 0, - SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); // The lamports didn't move, but the from address paid the transaction fee. @@ -2548,12 +2560,14 @@ fn test_insufficient_funds() { assert_eq!(bank.transaction_count(), 1); assert_eq!(bank.non_vote_transaction_count_since_restart(), 1); assert_eq!(bank.get_balance(&pubkey), amount); - assert_eq!( + assert_matches!( bank.transfer((mint_amount - amount) + 1, &mint_keypair, &pubkey), Err(TransactionError::InstructionError( 0, - SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); // transaction_count returns the count of all committed transactions since // bank_transaction_count_fix was activated, regardless of success @@ -2573,12 +2587,14 @@ fn test_executed_transaction_count_post_bank_transaction_count_fix() { let pubkey = solana_pubkey::new_rand(); let amount = genesis_config.rent.minimum_balance(0); bank.transfer(amount, &mint_keypair, &pubkey).unwrap(); - assert_eq!( + assert_matches!( bank.transfer((mint_amount - amount) + 1, &mint_keypair, &pubkey), Err(TransactionError::InstructionError( 0, - SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); // With bank_transaction_count_fix, transaction_count should include both the successful and @@ -2594,12 +2610,14 @@ fn test_executed_transaction_count_post_bank_transaction_count_fix() { genesis_config.epoch_schedule.first_normal_slot, ); - assert_eq!( + assert_matches!( bank2.transfer((mint_amount - amount) + 2, &mint_keypair, &pubkey), Err(TransactionError::InstructionError( 0, - SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); // The transaction_count inherited from parent bank is 3: 2 from the parent bank and 1 at this bank2 @@ -4554,12 +4572,14 @@ fn test_is_delta_with_no_committables() { // Should fail with InstructionError, but InstructionErrors are committable, // so is_delta should be true - assert_eq!( + assert_matches!( bank.transfer(10_001, &mint_keypair, &solana_pubkey::new_rand()), Err(TransactionError::InstructionError( 0, - SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); assert!(bank.is_delta.load(Relaxed)); @@ -4821,12 +4841,14 @@ fn test_add_builtin() { ); let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests(); - assert_eq!( + assert_matches!( bank.process_transaction(&transaction), Err(TransactionError::InstructionError( 1, - InstructionError::Custom(42) - )) + InstructionError::Custom(42), + None, + Some(ii), + )) if ii > 0 ); } @@ -4879,12 +4901,14 @@ fn test_add_duplicate_static_program() { let new_vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap(); // Vote loader account should not be updated since it was included in the genesis config. assert_eq!(vote_loader_account.data(), new_vote_loader_account.data()); - assert_eq!( + assert_matches!( bank.process_transaction(&transaction), Err(TransactionError::InstructionError( 1, - InstructionError::Custom(42) - )) + InstructionError::Custom(42), + None, + Some(ii), + )) if ii > 0 ); } @@ -5225,11 +5249,15 @@ fn test_assign_from_nonce_account_fail() { let message = Message::new(&[ix], Some(&nonce.pubkey())); let tx = Transaction::new(&[&nonce], message, blockhash); - let expect = Err(TransactionError::InstructionError( - 0, - InstructionError::ModifiedProgramId, - )); - assert_eq!(bank.process_transaction(&tx), expect); + assert_matches!( + bank.process_transaction(&tx), + Err(TransactionError::InstructionError( + 0, + InstructionError::ModifiedProgramId, + None, + Some(ii), + )) if ii > 0 + ); } #[test] @@ -5368,12 +5396,14 @@ fn test_nonce_transaction() { &[&custodian_keypair, &nonce_keypair], nonce_hash, ); - assert_eq!( + assert_matches!( bank.process_transaction(&nonce_tx), Err(TransactionError::InstructionError( 1, - system_instruction::SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); /* Check fee charged and nonce has advanced */ let mut recent_message = nonce_tx.message.clone(); @@ -5495,12 +5525,14 @@ fn test_nonce_transaction_with_tx_wide_caps() { &[&custodian_keypair, &nonce_keypair], nonce_hash, ); - assert_eq!( + assert_matches!( bank.process_transaction(&nonce_tx), Err(TransactionError::InstructionError( 1, - system_instruction::SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); /* Check fee charged and nonce has advanced */ let mut recent_message = nonce_tx.message.clone(); @@ -5624,12 +5656,14 @@ fn test_nonce_payer() { nonce_hash, ); debug!("{:?}", nonce_tx); - assert_eq!( + assert_matches!( bank.process_transaction(&nonce_tx), Err(TransactionError::InstructionError( 1, - system_instruction::SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); /* Check fee charged and nonce has advanced */ let mut recent_message = nonce_tx.message; @@ -5691,12 +5725,14 @@ fn test_nonce_payer_tx_wide_cap() { ); debug!("{:?}", nonce_tx); - assert_eq!( + assert_matches!( bank.process_transaction(&nonce_tx), Err(TransactionError::InstructionError( 1, - system_instruction::SystemError::ResultWithNegativeLamports.into(), - )) + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == SystemError::ResultWithNegativeLamports.into() ); /* Check fee charged and nonce has advanced */ let mut recent_message = nonce_tx.message; @@ -6009,12 +6045,14 @@ fn test_pre_post_transaction_balances() { // Failed transactions still produce balance sets // This is an InstructionError - fees charged - assert_eq!( + assert_matches!( commit_results[2].as_ref().unwrap().status, Err(TransactionError::InstructionError( 0, InstructionError::Custom(1), - )), + None, + Some(ii), + )) if ii > 0 ); assert_eq!( transaction_balances_set.pre_balances[2], @@ -7269,12 +7307,14 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { invocation_message.clone(), bank.last_blockhash(), ); - assert_eq!( + assert_matches!( bank.process_transaction(&transaction), Err(TransactionError::InstructionError( 0, - InstructionError::UnsupportedProgramId - )), + InstructionError::UnsupportedProgramId, + None, + Some(ii), + )) if ii > 0 ); { let program_cache = bank.transaction_processor.program_cache.read().unwrap(); @@ -7293,12 +7333,14 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { let instruction = Instruction::new_with_bytes(buffer_address, &[], Vec::new()); let message = Message::new(&[instruction], Some(&mint_keypair.pubkey())); let transaction = Transaction::new(&[&binding], message, bank.last_blockhash()); - assert_eq!( + assert_matches!( bank.process_transaction(&transaction), Err(TransactionError::InstructionError( 0, InstructionError::UnsupportedProgramId, - )), + None, + Some(ii), + )) if ii > 0 ); { let program_cache = bank.transaction_processor.program_cache.read().unwrap(); @@ -7445,12 +7487,17 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { )], Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(0, InstructionError::AccountAlreadyInitialized), + assert_matches!( bank_client .send_and_confirm_message(&[&mint_keypair, &upgrade_authority_keypair], message) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 0, + InstructionError::AccountAlreadyInitialized, + None, + Some(ii), + ) if ii > 0 ); // Test initialized ProgramData account @@ -7469,15 +7516,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::Custom(0)), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::Custom(0), + None, + Some(ii), + ) if ii > 0 ); // Test deploy no authority @@ -7503,12 +7555,17 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { )], Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(0, InstructionError::NotEnoughAccountKeys), + assert_matches!( bank_client .send_and_confirm_message(&[&mint_keypair], message) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 0, + InstructionError::NotEnoughAccountKeys, + None, + Some(ii), + ) if ii > 0 ); // Test deploy authority not a signer @@ -7535,12 +7592,17 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { )], Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature), + assert_matches!( bank_client .send_and_confirm_message(&[&mint_keypair], message) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 0, + InstructionError::MissingRequiredSignature, + None, + Some(ii), + ) if ii > 0 ); // Test invalid Buffer account state @@ -7560,15 +7622,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::InvalidAccountData), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::InvalidAccountData, + None, + Some(ii), + ) if ii > 0 ); // Test program account not rent exempt @@ -7588,15 +7655,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::ExecutableAccountNotRentExempt), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::ExecutableAccountNotRentExempt, + None, + Some(ii), + ) if ii > 0 ); // Test program account not rent exempt because data is larger than needed @@ -7621,15 +7693,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { &bpf_loader_upgradeable::id(), ); let message = Message::new(&instructions, Some(&mint_keypair.pubkey())); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::ExecutableAccountNotRentExempt), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::ExecutableAccountNotRentExempt, + None, + Some(ii), + ) if ii > 0 ); // Test program account too small @@ -7654,15 +7731,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { &bpf_loader_upgradeable::id(), ); let message = Message::new(&instructions, Some(&mint_keypair.pubkey())); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::AccountDataTooSmall), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::AccountDataTooSmall, + None, + Some(ii), + ) if ii > 0 ); // Test Insufficient payer funds (need more funds to cover the @@ -7691,15 +7773,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::Custom(1)), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::Custom(1), + None, + Some(ii), + ) if ii > 0 ); bank.store_account( &mint_keypair.pubkey(), @@ -7723,15 +7810,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::AccountDataTooSmall), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::AccountDataTooSmall, + None, + Some(ii), + ) if ii > 0 ); // Test max_data_len too large @@ -7757,15 +7849,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::InvalidArgument), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::InvalidArgument, + None, + Some(ii), + ) if ii > 0 ); // Test not the system account @@ -7824,15 +7921,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::InvalidAccountData), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::InvalidAccountData, + None, + Some(ii), + ) if ii > 0 ); // Test small buffer account @@ -7868,15 +7970,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::InvalidAccountData), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::InvalidAccountData, + None, + Some(ii), + ) if ii > 0 ); // Mismatched buffer and program authority @@ -7911,15 +8018,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::IncorrectAuthority), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::IncorrectAuthority, + None, + Some(ii), + ) if ii > 0 ); // Deploy buffer with mismatched None authority @@ -7954,15 +8066,20 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() { .unwrap(), Some(&mint_keypair.pubkey()), ); - assert_eq!( - TransactionError::InstructionError(1, InstructionError::IncorrectAuthority), + assert_matches!( bank_client .send_and_confirm_message( &[&mint_keypair, &program_keypair, &upgrade_authority_keypair], message ) .unwrap_err() - .unwrap() + .unwrap(), + TransactionError::InstructionError( + 1, + InstructionError::IncorrectAuthority, + None, + Some(ii), + ) if ii > 0 ); } @@ -8574,8 +8691,10 @@ fn test_program_is_native_loader() { bank.process_transaction(&tx), Err(TransactionError::InstructionError( 0, - InstructionError::UnsupportedProgramId - )) + InstructionError::UnsupportedProgramId, + None, + None, + )), ); } @@ -8610,12 +8729,14 @@ fn test_invoke_non_program_account_owned_by_a_builtin() { &[&mint_keypair, &created_account_keypair], bank.last_blockhash(), ); - assert_eq!( + assert_matches!( bank.process_transaction(&tx), Err(TransactionError::InstructionError( 0, - InstructionError::UnsupportedProgramId - )) + InstructionError::UnsupportedProgramId, + None, + Some(ii), + )) if ii > 0 ); } @@ -9987,12 +10108,14 @@ fn test_transfer_sysvar() { #[allow(deprecated)] let orig_lamports = bank.get_account(&sysvar::clock::id()).unwrap().lamports(); let tx = system_transaction::transfer(&mint_keypair, &blockhash_sysvar, 10, blockhash); - assert_eq!( + assert_matches!( bank.process_transaction(&tx), Err(TransactionError::InstructionError( 0, - InstructionError::ReadonlyLamportChange - )) + InstructionError::ReadonlyLamportChange, + None, + Some(ii), + )) if ii > 0 ); assert_eq!( bank.get_account(&sysvar::clock::id()).unwrap().lamports(), @@ -10006,12 +10129,14 @@ fn test_transfer_sysvar() { let ix = Instruction::new_with_bincode(program_id, &0, accounts); let message = Message::new(&[ix], Some(&mint_keypair.pubkey())); let tx = Transaction::new(&[&mint_keypair], message, blockhash); - assert_eq!( + assert_matches!( bank.process_transaction(&tx), Err(TransactionError::InstructionError( 0, - InstructionError::ReadonlyDataModified - )) + InstructionError::ReadonlyDataModified, + None, + Some(ii), + )) if ii > 0 ); } @@ -10331,8 +10456,10 @@ fn test_failed_compute_request_instruction() { results[0], Err(TransactionError::InstructionError( 0, - InstructionError::InvalidInstructionData - )) + InstructionError::InvalidInstructionData, + None, + None, + )), ); assert_eq!(results[1], Ok(())); // two transfers and the mock program @@ -10757,7 +10884,7 @@ fn test_an_empty_instruction_without_program() { let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); assert_eq!( bank.process_transaction(&tx).unwrap_err(), - TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId), + TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId, None, None), ); } @@ -11310,9 +11437,14 @@ fn test_invalid_rent_state_changes_fee_payer() { recent_blockhash, ); let result = bank.process_transaction(&tx); - assert_eq!( + assert_matches!( result.unwrap_err(), - TransactionError::InstructionError(0, InstructionError::Custom(1)) + TransactionError::InstructionError( + 0, + InstructionError::Custom(1), + None, + Some(ii), + ) if ii > 0 ); assert_ne!( fee_payer_balance, @@ -12184,6 +12316,8 @@ fn test_cap_accounts_data_allocations_per_transaction() { const NUM_MAX_SIZE_ALLOCATIONS_PER_TRANSACTION: usize = MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION as usize / MAX_PERMITTED_DATA_LENGTH as usize; + const NUM_MAX_SIZE_ALLOCATIONS_PER_TRANSACTION_AS_U8: u8 = + NUM_MAX_SIZE_ALLOCATIONS_PER_TRANSACTION as u8; let (genesis_config, mint_keypair) = create_genesis_config(1_000_000 * LAMPORTS_PER_SOL); let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config); @@ -12213,12 +12347,14 @@ fn test_cap_accounts_data_allocations_per_transaction() { let accounts_data_size_after = bank.load_accounts_data_size(); assert_eq!(accounts_data_size_before, accounts_data_size_after); - assert_eq!( + assert_matches!( result, Err(TransactionError::InstructionError( - NUM_MAX_SIZE_ALLOCATIONS_PER_TRANSACTION as u8, + NUM_MAX_SIZE_ALLOCATIONS_PER_TRANSACTION_AS_U8, solana_sdk::instruction::InstructionError::MaxAccountsDataAllocationsExceeded, - )), + None, + Some(ii), + )) if ii > 0 ); } @@ -12505,12 +12641,14 @@ fn test_feature_activation_loaded_programs_cache_preparation_phase() { // Load the program with the new environment. let transaction = Transaction::new(&signers, message, bank.last_blockhash()); let result_with_feature_enabled = bank.process_transaction(&transaction); - assert_eq!( + assert_matches!( result_with_feature_enabled, Err(TransactionError::InstructionError( 0, - InstructionError::UnsupportedProgramId - )) + InstructionError::UnsupportedProgramId, + None, + Some(ii), + )) if ii > 0 ); } @@ -12925,12 +13063,17 @@ fn test_system_instruction_unsigned_transaction() { &system_instruction::SystemInstruction::Transfer { lamports: amount }, account_metas, ); - assert_eq!( + assert_matches!( bank_client .send_and_confirm_instruction(&mallory_keypair, malicious_instruction) .unwrap_err() .unwrap(), - TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature) + TransactionError::InstructionError( + 0, + InstructionError::MissingRequiredSignature, + None, + Some(ii), + ) if ii > 0 ); assert_eq!( bank_client.get_balance(&alice_pubkey).unwrap(), @@ -13443,6 +13586,8 @@ fn test_filter_program_errors_and_collect_fee_details() { Err(TransactionError::InstructionError( 0, SystemError::ResultWithNegativeLamports.into(), + None, + None, )), fee_details, ), @@ -13708,9 +13853,14 @@ fn test_loader_v3_to_v4_migration() { let signers = &[&payer_keypair]; let transaction = Transaction::new(signers, message.clone(), bank.last_blockhash()); let error = bank.process_transaction(&transaction).unwrap_err(); - assert_eq!( + assert_matches!( error, - TransactionError::InstructionError(0, InstructionError::InvalidArgument) + TransactionError::InstructionError( + 0, + InstructionError::InvalidArgument, + None, + Some(ii), + ) if ii > 0 ); let bank = new_bank_from_parent_with_bank_forks( @@ -13811,35 +13961,37 @@ fn test_loader_v3_to_v4_migration() { bank.last_blockhash(), ); let error = bank.process_transaction(&transaction).unwrap_err(); - assert_eq!(error, TransactionError::InstructionError(0, expected_error)); + assert_matches!( + error, + TransactionError::InstructionError( + 0, + err, + None, + Some(ii), + ) if ii > 0 && err == expected_error + ); } - for (mut programdata_account, transaction, expected_execution_result) in [ + for (mut programdata_account, transaction, expected_error) in [ ( closed_programdata_account, finalized_migration_transaction.clone(), - Err(TransactionError::InstructionError( - 0, - InstructionError::UnsupportedProgramId, - )), + Some(InstructionError::UnsupportedProgramId), ), ( uninitialized_programdata_account, finalized_migration_transaction.clone(), - Err(TransactionError::InstructionError( - 0, - InstructionError::UnsupportedProgramId, - )), + Some(InstructionError::UnsupportedProgramId), ), ( finalized_programdata_account, finalized_migration_transaction, - Ok(()), + None, ), ( upgradeable_programdata_account, upgradeable_migration_transaction, - Ok(()), + None, ), ] { let bank = new_bank_from_parent_with_bank_forks( @@ -13873,7 +14025,19 @@ fn test_loader_v3_to_v4_migration() { let binding = mint_keypair.insecure_clone(); let transaction = Transaction::new(&[&binding], message, bank.last_blockhash()); let execution_result = bank.process_transaction(&transaction); - assert_eq!(execution_result, expected_execution_result); + if let Some(expected_err) = expected_error { + assert_matches!( + execution_result, + Err(TransactionError::InstructionError( + 0, + actual_err, + None, + Some(ii), + )) if ii > 0 && actual_err == expected_err + ); + } else { + assert_matches!(execution_result, Ok(())); + } } } diff --git a/storage-proto/proto/transaction_by_addr.proto b/storage-proto/proto/transaction_by_addr.proto index 5748b05655edba..2f98b40fa42034 100644 --- a/storage-proto/proto/transaction_by_addr.proto +++ b/storage-proto/proto/transaction_by_addr.proto @@ -70,6 +70,8 @@ message InstructionError { uint32 index = 1; InstructionErrorType error = 2; CustomError custom = 3; + optional uint32 inner_instruction_index = 4; + optional uint32 responsible_program_account_index = 5; } message TransactionDetails { diff --git a/storage-proto/src/convert.rs b/storage-proto/src/convert.rs index cd9372c8dc58ca..30b84e5dffa86f 100644 --- a/storage-proto/src/convert.rs +++ b/storage-proto/src/convert.rs @@ -728,10 +728,18 @@ impl TryFrom for TransactionError { fn try_from(transaction_error: tx_by_addr::TransactionError) -> Result { if transaction_error.transaction_error == 8 { if let Some(instruction_error) = transaction_error.instruction_error { + let inner_instruction_index = + instruction_error.inner_instruction_index.map(|i| i as u8); + let responsible_program_account_index = instruction_error + .responsible_program_account_index + .map(|i| i as u8); + if let Some(custom) = instruction_error.custom { return Ok(TransactionError::InstructionError( instruction_error.index as u8, InstructionError::Custom(custom.custom), + inner_instruction_index, + responsible_program_account_index, )); } @@ -795,6 +803,8 @@ impl TryFrom for TransactionError { return Ok(TransactionError::InstructionError( instruction_error.index as u8, ie, + inner_instruction_index, + responsible_program_account_index, )); } } @@ -909,7 +919,7 @@ impl From for tx_by_addr::TransactionError { TransactionError::ClusterMaintenance => { tx_by_addr::TransactionErrorType::ClusterMaintenance } - TransactionError::InstructionError(_, _) => { + TransactionError::InstructionError(_, _, _, _) => { tx_by_addr::TransactionErrorType::InstructionError } TransactionError::AccountBorrowOutstanding => { @@ -983,179 +993,181 @@ impl From for tx_by_addr::TransactionError { } } as i32, instruction_error: match transaction_error { - TransactionError::InstructionError(index, ref instruction_error) => { - Some(tx_by_addr::InstructionError { - index: index as u32, - error: match instruction_error { - InstructionError::GenericError => { - tx_by_addr::InstructionErrorType::GenericError - } - InstructionError::InvalidArgument => { - tx_by_addr::InstructionErrorType::InvalidArgument - } - InstructionError::InvalidInstructionData => { - tx_by_addr::InstructionErrorType::InvalidInstructionData - } - InstructionError::InvalidAccountData => { - tx_by_addr::InstructionErrorType::InvalidAccountData - } - InstructionError::AccountDataTooSmall => { - tx_by_addr::InstructionErrorType::AccountDataTooSmall - } - InstructionError::InsufficientFunds => { - tx_by_addr::InstructionErrorType::InsufficientFunds - } - InstructionError::IncorrectProgramId => { - tx_by_addr::InstructionErrorType::IncorrectProgramId - } - InstructionError::MissingRequiredSignature => { - tx_by_addr::InstructionErrorType::MissingRequiredSignature - } - InstructionError::AccountAlreadyInitialized => { - tx_by_addr::InstructionErrorType::AccountAlreadyInitialized - } - InstructionError::UninitializedAccount => { - tx_by_addr::InstructionErrorType::UninitializedAccount - } - InstructionError::UnbalancedInstruction => { - tx_by_addr::InstructionErrorType::UnbalancedInstruction - } - InstructionError::ModifiedProgramId => { - tx_by_addr::InstructionErrorType::ModifiedProgramId - } - InstructionError::ExternalAccountLamportSpend => { - tx_by_addr::InstructionErrorType::ExternalAccountLamportSpend - } - InstructionError::ExternalAccountDataModified => { - tx_by_addr::InstructionErrorType::ExternalAccountDataModified - } - InstructionError::ReadonlyLamportChange => { - tx_by_addr::InstructionErrorType::ReadonlyLamportChange - } - InstructionError::ReadonlyDataModified => { - tx_by_addr::InstructionErrorType::ReadonlyDataModified - } - InstructionError::DuplicateAccountIndex => { - tx_by_addr::InstructionErrorType::DuplicateAccountIndex - } - InstructionError::ExecutableModified => { - tx_by_addr::InstructionErrorType::ExecutableModified - } - InstructionError::RentEpochModified => { - tx_by_addr::InstructionErrorType::RentEpochModified - } - InstructionError::NotEnoughAccountKeys => { - tx_by_addr::InstructionErrorType::NotEnoughAccountKeys - } - InstructionError::AccountDataSizeChanged => { - tx_by_addr::InstructionErrorType::AccountDataSizeChanged - } - InstructionError::AccountNotExecutable => { - tx_by_addr::InstructionErrorType::AccountNotExecutable - } - InstructionError::AccountBorrowFailed => { - tx_by_addr::InstructionErrorType::AccountBorrowFailed - } - InstructionError::AccountBorrowOutstanding => { - tx_by_addr::InstructionErrorType::AccountBorrowOutstanding - } - InstructionError::DuplicateAccountOutOfSync => { - tx_by_addr::InstructionErrorType::DuplicateAccountOutOfSync - } - InstructionError::Custom(_) => tx_by_addr::InstructionErrorType::Custom, - InstructionError::InvalidError => { - tx_by_addr::InstructionErrorType::InvalidError - } - InstructionError::ExecutableDataModified => { - tx_by_addr::InstructionErrorType::ExecutableDataModified - } - InstructionError::ExecutableLamportChange => { - tx_by_addr::InstructionErrorType::ExecutableLamportChange - } - InstructionError::ExecutableAccountNotRentExempt => { - tx_by_addr::InstructionErrorType::ExecutableAccountNotRentExempt - } - InstructionError::UnsupportedProgramId => { - tx_by_addr::InstructionErrorType::UnsupportedProgramId - } - InstructionError::CallDepth => { - tx_by_addr::InstructionErrorType::CallDepth - } - InstructionError::MissingAccount => { - tx_by_addr::InstructionErrorType::MissingAccount - } - InstructionError::ReentrancyNotAllowed => { - tx_by_addr::InstructionErrorType::ReentrancyNotAllowed - } - InstructionError::MaxSeedLengthExceeded => { - tx_by_addr::InstructionErrorType::MaxSeedLengthExceeded - } - InstructionError::InvalidSeeds => { - tx_by_addr::InstructionErrorType::InvalidSeeds - } - InstructionError::InvalidRealloc => { - tx_by_addr::InstructionErrorType::InvalidRealloc - } - InstructionError::ComputationalBudgetExceeded => { - tx_by_addr::InstructionErrorType::ComputationalBudgetExceeded - } - InstructionError::PrivilegeEscalation => { - tx_by_addr::InstructionErrorType::PrivilegeEscalation - } - InstructionError::ProgramEnvironmentSetupFailure => { - tx_by_addr::InstructionErrorType::ProgramEnvironmentSetupFailure - } - InstructionError::ProgramFailedToComplete => { - tx_by_addr::InstructionErrorType::ProgramFailedToComplete - } - InstructionError::ProgramFailedToCompile => { - tx_by_addr::InstructionErrorType::ProgramFailedToCompile - } - InstructionError::Immutable => { - tx_by_addr::InstructionErrorType::Immutable - } - InstructionError::IncorrectAuthority => { - tx_by_addr::InstructionErrorType::IncorrectAuthority - } - InstructionError::BorshIoError(_) => { - tx_by_addr::InstructionErrorType::BorshIoError - } - InstructionError::AccountNotRentExempt => { - tx_by_addr::InstructionErrorType::AccountNotRentExempt - } - InstructionError::InvalidAccountOwner => { - tx_by_addr::InstructionErrorType::InvalidAccountOwner - } - InstructionError::ArithmeticOverflow => { - tx_by_addr::InstructionErrorType::ArithmeticOverflow - } - InstructionError::UnsupportedSysvar => { - tx_by_addr::InstructionErrorType::UnsupportedSysvar - } - InstructionError::IllegalOwner => { - tx_by_addr::InstructionErrorType::IllegalOwner - } - InstructionError::MaxAccountsDataAllocationsExceeded => { - tx_by_addr::InstructionErrorType::MaxAccountsDataAllocationsExceeded - } - InstructionError::MaxAccountsExceeded => { - tx_by_addr::InstructionErrorType::MaxAccountsExceeded - } - InstructionError::MaxInstructionTraceLengthExceeded => { - tx_by_addr::InstructionErrorType::MaxInstructionTraceLengthExceeded - } - InstructionError::BuiltinProgramsMustConsumeComputeUnits => { - tx_by_addr::InstructionErrorType::BuiltinProgramsMustConsumeComputeUnits - } - } as i32, - custom: match instruction_error { - InstructionError::Custom(custom) => { - Some(tx_by_addr::CustomError { custom: *custom }) - } - _ => None, - }, - }) - } + TransactionError::InstructionError( + index, + ref instruction_error, + inner_instruction_index, + responsible_program_account_index, + ) => Some(tx_by_addr::InstructionError { + index: index as u32, + error: match instruction_error { + InstructionError::GenericError => { + tx_by_addr::InstructionErrorType::GenericError + } + InstructionError::InvalidArgument => { + tx_by_addr::InstructionErrorType::InvalidArgument + } + InstructionError::InvalidInstructionData => { + tx_by_addr::InstructionErrorType::InvalidInstructionData + } + InstructionError::InvalidAccountData => { + tx_by_addr::InstructionErrorType::InvalidAccountData + } + InstructionError::AccountDataTooSmall => { + tx_by_addr::InstructionErrorType::AccountDataTooSmall + } + InstructionError::InsufficientFunds => { + tx_by_addr::InstructionErrorType::InsufficientFunds + } + InstructionError::IncorrectProgramId => { + tx_by_addr::InstructionErrorType::IncorrectProgramId + } + InstructionError::MissingRequiredSignature => { + tx_by_addr::InstructionErrorType::MissingRequiredSignature + } + InstructionError::AccountAlreadyInitialized => { + tx_by_addr::InstructionErrorType::AccountAlreadyInitialized + } + InstructionError::UninitializedAccount => { + tx_by_addr::InstructionErrorType::UninitializedAccount + } + InstructionError::UnbalancedInstruction => { + tx_by_addr::InstructionErrorType::UnbalancedInstruction + } + InstructionError::ModifiedProgramId => { + tx_by_addr::InstructionErrorType::ModifiedProgramId + } + InstructionError::ExternalAccountLamportSpend => { + tx_by_addr::InstructionErrorType::ExternalAccountLamportSpend + } + InstructionError::ExternalAccountDataModified => { + tx_by_addr::InstructionErrorType::ExternalAccountDataModified + } + InstructionError::ReadonlyLamportChange => { + tx_by_addr::InstructionErrorType::ReadonlyLamportChange + } + InstructionError::ReadonlyDataModified => { + tx_by_addr::InstructionErrorType::ReadonlyDataModified + } + InstructionError::DuplicateAccountIndex => { + tx_by_addr::InstructionErrorType::DuplicateAccountIndex + } + InstructionError::ExecutableModified => { + tx_by_addr::InstructionErrorType::ExecutableModified + } + InstructionError::RentEpochModified => { + tx_by_addr::InstructionErrorType::RentEpochModified + } + InstructionError::NotEnoughAccountKeys => { + tx_by_addr::InstructionErrorType::NotEnoughAccountKeys + } + InstructionError::AccountDataSizeChanged => { + tx_by_addr::InstructionErrorType::AccountDataSizeChanged + } + InstructionError::AccountNotExecutable => { + tx_by_addr::InstructionErrorType::AccountNotExecutable + } + InstructionError::AccountBorrowFailed => { + tx_by_addr::InstructionErrorType::AccountBorrowFailed + } + InstructionError::AccountBorrowOutstanding => { + tx_by_addr::InstructionErrorType::AccountBorrowOutstanding + } + InstructionError::DuplicateAccountOutOfSync => { + tx_by_addr::InstructionErrorType::DuplicateAccountOutOfSync + } + InstructionError::Custom(_) => tx_by_addr::InstructionErrorType::Custom, + InstructionError::InvalidError => { + tx_by_addr::InstructionErrorType::InvalidError + } + InstructionError::ExecutableDataModified => { + tx_by_addr::InstructionErrorType::ExecutableDataModified + } + InstructionError::ExecutableLamportChange => { + tx_by_addr::InstructionErrorType::ExecutableLamportChange + } + InstructionError::ExecutableAccountNotRentExempt => { + tx_by_addr::InstructionErrorType::ExecutableAccountNotRentExempt + } + InstructionError::UnsupportedProgramId => { + tx_by_addr::InstructionErrorType::UnsupportedProgramId + } + InstructionError::CallDepth => tx_by_addr::InstructionErrorType::CallDepth, + InstructionError::MissingAccount => { + tx_by_addr::InstructionErrorType::MissingAccount + } + InstructionError::ReentrancyNotAllowed => { + tx_by_addr::InstructionErrorType::ReentrancyNotAllowed + } + InstructionError::MaxSeedLengthExceeded => { + tx_by_addr::InstructionErrorType::MaxSeedLengthExceeded + } + InstructionError::InvalidSeeds => { + tx_by_addr::InstructionErrorType::InvalidSeeds + } + InstructionError::InvalidRealloc => { + tx_by_addr::InstructionErrorType::InvalidRealloc + } + InstructionError::ComputationalBudgetExceeded => { + tx_by_addr::InstructionErrorType::ComputationalBudgetExceeded + } + InstructionError::PrivilegeEscalation => { + tx_by_addr::InstructionErrorType::PrivilegeEscalation + } + InstructionError::ProgramEnvironmentSetupFailure => { + tx_by_addr::InstructionErrorType::ProgramEnvironmentSetupFailure + } + InstructionError::ProgramFailedToComplete => { + tx_by_addr::InstructionErrorType::ProgramFailedToComplete + } + InstructionError::ProgramFailedToCompile => { + tx_by_addr::InstructionErrorType::ProgramFailedToCompile + } + InstructionError::Immutable => tx_by_addr::InstructionErrorType::Immutable, + InstructionError::IncorrectAuthority => { + tx_by_addr::InstructionErrorType::IncorrectAuthority + } + InstructionError::BorshIoError(_) => { + tx_by_addr::InstructionErrorType::BorshIoError + } + InstructionError::AccountNotRentExempt => { + tx_by_addr::InstructionErrorType::AccountNotRentExempt + } + InstructionError::InvalidAccountOwner => { + tx_by_addr::InstructionErrorType::InvalidAccountOwner + } + InstructionError::ArithmeticOverflow => { + tx_by_addr::InstructionErrorType::ArithmeticOverflow + } + InstructionError::UnsupportedSysvar => { + tx_by_addr::InstructionErrorType::UnsupportedSysvar + } + InstructionError::IllegalOwner => { + tx_by_addr::InstructionErrorType::IllegalOwner + } + InstructionError::MaxAccountsDataAllocationsExceeded => { + tx_by_addr::InstructionErrorType::MaxAccountsDataAllocationsExceeded + } + InstructionError::MaxAccountsExceeded => { + tx_by_addr::InstructionErrorType::MaxAccountsExceeded + } + InstructionError::MaxInstructionTraceLengthExceeded => { + tx_by_addr::InstructionErrorType::MaxInstructionTraceLengthExceeded + } + InstructionError::BuiltinProgramsMustConsumeComputeUnits => { + tx_by_addr::InstructionErrorType::BuiltinProgramsMustConsumeComputeUnits + } + } as i32, + custom: match instruction_error { + InstructionError::Custom(custom) => { + Some(tx_by_addr::CustomError { custom: *custom }) + } + _ => None, + }, + inner_instruction_index: inner_instruction_index.map(|i| i as u32), + responsible_program_account_index: responsible_program_account_index + .map(|i| i as u32), + }), _ => None, }, transaction_details: match transaction_error { @@ -1477,8 +1489,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::AccountAlreadyInitialized); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::AccountAlreadyInitialized, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1486,8 +1502,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::AccountBorrowFailed); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::AccountBorrowFailed, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1495,8 +1515,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::AccountBorrowOutstanding); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::AccountBorrowOutstanding, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1504,8 +1528,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::AccountDataSizeChanged); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::AccountDataSizeChanged, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1513,8 +1541,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::AccountDataTooSmall); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::AccountDataTooSmall, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1522,8 +1554,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::AccountNotExecutable); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::AccountNotExecutable, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1531,7 +1567,8 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = TransactionError::InstructionError(10, InstructionError::CallDepth); + let transaction_error = + TransactionError::InstructionError(10, InstructionError::CallDepth, None, Some(42)); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1539,8 +1576,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ComputationalBudgetExceeded); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ComputationalBudgetExceeded, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1548,8 +1589,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::DuplicateAccountIndex); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::DuplicateAccountIndex, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1557,8 +1602,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::DuplicateAccountOutOfSync); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::DuplicateAccountOutOfSync, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1569,6 +1618,8 @@ mod test { let transaction_error = TransactionError::InstructionError( 10, InstructionError::ExecutableAccountNotRentExempt, + None, + Some(42), ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); @@ -1577,8 +1628,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ExecutableDataModified); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ExecutableDataModified, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1586,8 +1641,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ExecutableLamportChange); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ExecutableLamportChange, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1595,8 +1654,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ExecutableModified); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ExecutableModified, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1604,8 +1667,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ExternalAccountDataModified); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ExternalAccountDataModified, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1613,8 +1680,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ExternalAccountLamportSpend); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ExternalAccountLamportSpend, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1623,7 +1694,7 @@ mod test { ); let transaction_error = - TransactionError::InstructionError(10, InstructionError::GenericError); + TransactionError::InstructionError(10, InstructionError::GenericError, None, Some(42)); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1631,7 +1702,8 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = TransactionError::InstructionError(10, InstructionError::Immutable); + let transaction_error = + TransactionError::InstructionError(10, InstructionError::Immutable, None, Some(42)); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1639,8 +1711,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::IncorrectAuthority); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::IncorrectAuthority, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1648,8 +1724,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::IncorrectProgramId); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::IncorrectProgramId, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1657,8 +1737,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::InsufficientFunds); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::InsufficientFunds, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1666,8 +1750,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::InvalidAccountData); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::InvalidAccountData, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1675,8 +1763,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::InvalidArgument); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::InvalidArgument, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1685,7 +1777,7 @@ mod test { ); let transaction_error = - TransactionError::InstructionError(10, InstructionError::InvalidError); + TransactionError::InstructionError(10, InstructionError::InvalidError, None, Some(42)); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1693,8 +1785,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::InvalidInstructionData); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::InvalidInstructionData, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1702,8 +1798,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::InvalidRealloc); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::InvalidRealloc, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1712,7 +1812,7 @@ mod test { ); let transaction_error = - TransactionError::InstructionError(10, InstructionError::InvalidSeeds); + TransactionError::InstructionError(10, InstructionError::InvalidSeeds, None, Some(42)); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1720,8 +1820,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::MaxSeedLengthExceeded); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::MaxSeedLengthExceeded, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1729,8 +1833,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::MissingAccount); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::MissingAccount, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1738,8 +1846,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::MissingRequiredSignature); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::MissingRequiredSignature, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1747,8 +1859,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ModifiedProgramId); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ModifiedProgramId, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1756,8 +1872,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::NotEnoughAccountKeys); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::NotEnoughAccountKeys, + None, + None, + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1765,8 +1885,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::PrivilegeEscalation); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::PrivilegeEscalation, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1777,6 +1901,8 @@ mod test { let transaction_error = TransactionError::InstructionError( 10, InstructionError::ProgramEnvironmentSetupFailure, + None, + Some(42), ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); @@ -1785,8 +1911,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ProgramFailedToCompile); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ProgramFailedToCompile, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1794,8 +1924,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ProgramFailedToComplete); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ProgramFailedToComplete, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1803,8 +1937,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ReadonlyDataModified); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ReadonlyDataModified, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1812,8 +1950,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ReadonlyLamportChange); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ReadonlyLamportChange, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1821,8 +1963,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::ReentrancyNotAllowed); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::ReentrancyNotAllowed, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1830,8 +1976,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::RentEpochModified); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::RentEpochModified, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1839,8 +1989,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::UnbalancedInstruction); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::UnbalancedInstruction, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1848,8 +2002,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::UninitializedAccount); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::UninitializedAccount, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1857,8 +2015,12 @@ mod test { tx_by_addr_transaction_error.try_into().unwrap() ); - let transaction_error = - TransactionError::InstructionError(10, InstructionError::UnsupportedProgramId); + let transaction_error = TransactionError::InstructionError( + 10, + InstructionError::UnsupportedProgramId, + None, + Some(42), + ); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1867,7 +2029,7 @@ mod test { ); let transaction_error = - TransactionError::InstructionError(10, InstructionError::Custom(10)); + TransactionError::InstructionError(10, InstructionError::Custom(10), None, Some(42)); let tx_by_addr_transaction_error: tx_by_addr::TransactionError = transaction_error.clone().into(); assert_eq!( @@ -1931,6 +2093,8 @@ mod test { index: ix_index, error: ix_error as i32, custom: None, + inner_instruction_index: Some(41), + responsible_program_account_index: Some(11), }), transaction_details: None, }; @@ -1948,6 +2112,8 @@ mod test { custom: Some(tx_by_addr::CustomError { custom: custom_error, }), + inner_instruction_index: Some(41), + responsible_program_account_index: Some(11), }), transaction_details: None, }; diff --git a/svm/Cargo.toml b/svm/Cargo.toml index ffe206b20cbd8e..f3624e9bc7d2a4 100644 --- a/svm/Cargo.toml +++ b/svm/Cargo.toml @@ -12,6 +12,7 @@ edition = { workspace = true } [dependencies] ahash = { workspace = true } itertools = { workspace = true } +lazy_static = { workspace = true } log = { workspace = true } percentage = { workspace = true } qualifier_attr = { workspace = true, optional = true } diff --git a/svm/src/message_processor.rs b/svm/src/message_processor.rs index f8fd966840a56e..128f1e1f01848a 100644 --- a/svm/src/message_processor.rs +++ b/svm/src/message_processor.rs @@ -1,9 +1,10 @@ use { + solana_instruction::TRANSACTION_LEVEL_STACK_HEIGHT, solana_measure::measure_us, solana_program_runtime::invoke_context::InvokeContext, solana_svm_transaction::svm_message::SVMMessage, solana_timings::{ExecuteDetailsTimings, ExecuteTimings}, - solana_transaction_context::{IndexOfAccount, InstructionAccount}, + solana_transaction_context::{IndexOfAccount, InstructionAccount, TransactionContext}, solana_transaction_error::TransactionError, }; @@ -86,7 +87,87 @@ pub(crate) fn process_message( .total_us += process_instruction_us; result.map_err(|err| { - TransactionError::InstructionError(top_level_instruction_index as u8, err) + let transaction_context: &TransactionContext = invoke_context.transaction_context; + let responsible_program_account_index = &transaction_context + // By definition the last instruction (outer or inner) in the trace before the trace + // stopped being appended to is the one that encountered an error. + .get_instruction_trace_length() + .checked_sub(1) + .and_then(|index_in_trace| { + transaction_context + .get_instruction_context_at_index_in_trace(index_in_trace) + .ok() + }) + // The last program address in the instruction is that of the program being called. + .and_then(|ctx| ctx.get_last_program_key(transaction_context).ok()) + // The order of program accounts in the `TransactionContext` has no relation to the + // order of the program accounts in the original message. It's the index in the + // message that we need. + .and_then(|errored_program_pubkey| { + message + .account_keys() + .iter() + .position(|message_pubkey| message_pubkey.eq(errored_program_pubkey)) + }); + enum InnerInstructionIndexSearchState { + SearchingForTopLevelInstruction( + usize, // Index of top-level instruction being sought next + ), + InTopLevelInstruction( + Option, // Inner instruction index + ), + } + let mut state = InnerInstructionIndexSearchState::SearchingForTopLevelInstruction(0); + for index_in_trace in 0..transaction_context.get_instruction_trace_length() { + if let Ok(instruction_context) = + transaction_context.get_instruction_context_at_index_in_trace(index_in_trace) + { + let stack_height = instruction_context.get_stack_height(); + match state { + InnerInstructionIndexSearchState::SearchingForTopLevelInstruction( + candidate_top_level_instruction_index, + ) => { + if + // This is a top-level instruction + stack_height == TRANSACTION_LEVEL_STACK_HEIGHT + // and it's the top level instruction we're looking for. + && candidate_top_level_instruction_index == top_level_instruction_index + { + state = + InnerInstructionIndexSearchState::InTopLevelInstruction(None); + } + } + InnerInstructionIndexSearchState::InTopLevelInstruction( + inner_instruction_index, + ) => { + if stack_height == TRANSACTION_LEVEL_STACK_HEIGHT { + // We hit the next top-level instruction; + // We are done collecting inner instruction indexes. + break; + } else { + state = InnerInstructionIndexSearchState::InTopLevelInstruction( + inner_instruction_index.map(|i| i + 1).or(Some(1)), + ); + } + } + } + } else { + break; + } + } + TransactionError::InstructionError( + top_level_instruction_index as u8, + err, + if let InnerInstructionIndexSearchState::InTopLevelInstruction( + inner_instruction_index, + ) = state + { + inner_instruction_index + } else { + None + }, + responsible_program_account_index.map(|i| i as u8), + ) })?; } Ok(()) @@ -97,6 +178,7 @@ mod tests { use { super::*, agave_reserved_account_keys::ReservedAccountKeys, + assert_matches::assert_matches, openssl::{ ec::{EcGroup, EcKey}, nid::Nid, @@ -314,12 +396,14 @@ mod tests { &mut ExecuteTimings::default(), &mut 0, ); - assert_eq!( + assert_matches!( result, Err(TransactionError::InstructionError( 0, - InstructionError::ReadonlyLamportChange - )) + InstructionError::ReadonlyLamportChange, + None, + Some(ii), + )) if ii > 0 ); let message = new_sanitized_message(Message::new_with_compiled_instructions( @@ -358,12 +442,14 @@ mod tests { &mut ExecuteTimings::default(), &mut 0, ); - assert_eq!( + assert_matches!( result, Err(TransactionError::InstructionError( 0, - InstructionError::ReadonlyDataModified - )) + InstructionError::ReadonlyDataModified, + None, + Some(ii), + )) if ii > 0 ); } @@ -494,12 +580,14 @@ mod tests { &mut ExecuteTimings::default(), &mut 0, ); - assert_eq!( + assert_matches!( result, Err(TransactionError::InstructionError( 0, - InstructionError::AccountBorrowFailed - )) + InstructionError::AccountBorrowFailed, + None, + Some(ii), + )) if ii > 0 ); // Try to borrow mut the same account in a safe way @@ -696,12 +784,14 @@ mod tests { &mut 0, ); - assert_eq!( + assert_matches!( result, Err(TransactionError::InstructionError( 3, - InstructionError::Custom(0xbabb1e) - )) + InstructionError::Custom(0xbabb1e), + None, + Some(ii), + )) if ii > 0 ); assert_eq!(transaction_context.get_instruction_trace_length(), 4); } diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index c8cd65fbb5414e..e4f3d96596b6e0 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -1069,6 +1069,9 @@ mod tests { rollback_accounts::RollbackAccounts, }, agave_reserved_account_keys::ReservedAccountKeys, + assert_matches::assert_matches, + itertools::Itertools, + lazy_static::lazy_static, solana_account::{create_account_shared_data_for_test, WritableAccount}, solana_clock::Clock, solana_compute_budget_interface::ComputeBudgetInstruction, @@ -1076,10 +1079,12 @@ mod tests { solana_fee_calculator::FeeCalculator, solana_fee_structure::FeeDetails, solana_hash::Hash, + solana_instruction::{AccountMeta, Instruction}, solana_keypair::Keypair, solana_message::{LegacyMessage, Message, MessageHeader, SanitizedMessage}, solana_nonce as nonce, solana_program_runtime::{ + declare_process_instruction, execution_budget::{ SVMTransactionExecutionAndFeeBudgetLimits, SVMTransactionExecutionBudget, }, @@ -1088,12 +1093,14 @@ mod tests { solana_rent::Rent, solana_rent_collector::{RentCollector, RENT_EXEMPT_RENT_EPOCH}, solana_rent_debits::RentDebits, + solana_sdk::instruction::InstructionError, solana_sdk_ids::{bpf_loader, system_program, sysvar}, solana_signature::Signature, solana_svm_callback::{AccountState, InvokeContextCallback}, solana_transaction::{sanitized::SanitizedTransaction, Transaction}, solana_transaction_context::TransactionContext, solana_transaction_error::{TransactionError, TransactionError::DuplicateInstruction}, + std::convert::TryInto, test_case::test_case, }; @@ -1292,6 +1299,169 @@ mod tests { ); } + #[test_case(0, None; "Throw in program 0")] + #[test_case(1, Some(1); "Throw in program 1")] + #[test_case(2, Some(2); "Throw in program 2")] + #[test_case(3, Some(3); "Throw in program 3")] + #[test_case(4, Some(4); "Throw in program 4")] + #[test_case(5, Some(5); "Throw in program 5")] + #[test_case(6, Some(6); "Throw in program 6")] + fn test_instruction_error_carries_responsible_program_account_index( + index_of_program_that_should_throw_exception: u8, + expected_inner_instruction_index: Option, + ) { + lazy_static! { + static ref PROGRAM_ADDRESSES: [Pubkey; 7] = + std::array::from_fn(|_| Pubkey::new_unique()); + } + // This mock program takes in a list of programs and two bytes of data: + // (1) the index of the program that should throw an error + // (2) the index of the program being called + // + // The programs get executed - two at each CPI call depth - like this: + // + // Program 0 + // -- Program 1 + // -- Program 2 + // ---- Program 3 + // ---- Program 4 + // ------ Program 5 + // ------ Program 6 + declare_process_instruction!(MockBuiltin, 1 /* cu_to_consume */, |invoke_context| { + let transaction_context = invoke_context.transaction_context.clone(); + let instruction_context = transaction_context.get_current_instruction_context()?; + + let stack_height: u8 = invoke_context.get_stack_height().try_into().unwrap(); + let index_of_program_that_must_throw_exception = + instruction_context.get_instruction_data()[0] as usize; + let current_program_index = instruction_context.get_instruction_data()[1] as usize; + + // Ensure that the program the instruction data claims to be running is the program that + // is actually running. + let actual_program_address = *instruction_context + .get_last_program_key(&transaction_context) + .unwrap(); + assert_eq!( + actual_program_address, + PROGRAM_ADDRESSES[current_program_index], + "The address of the program at index {} that the instruction data claims to be running ({}) is not the program that is actually running ({})", + current_program_index, + PROGRAM_ADDRESSES[current_program_index], + actual_program_address, + ); + + if current_program_index == index_of_program_that_must_throw_exception { + return Err(InstructionError::Custom(0xdeadbeef)); + } + + if stack_height < 4 && current_program_index % 2 == 0 { + // Every odd program does CPIs unless it has reached the maximum CPI stack depth. + let mut last_result = Ok(()); + for ii in 1..3 { + let next_program_index = current_program_index.checked_add(ii).unwrap(); + let next_program_address = PROGRAM_ADDRESSES[next_program_index]; + let accounts = (next_program_index..PROGRAM_ADDRESSES.len()) + .map(|index| AccountMeta::new_readonly(PROGRAM_ADDRESSES[index], false)) + .collect_vec(); + last_result = invoke_context.native_invoke( + Instruction::new_with_bytes( + next_program_address, + &[ + index_of_program_that_must_throw_exception as u8, + next_program_index as u8, + ], + accounts, + ) + .into(), + &[], + ); + if last_result.is_err() { + return last_result; + } + } + return last_result; + } + + Ok(()) + }); + + // ======================================================= + // BEGIN: Create a transaction that calls the mock program + // ======================================================= + let base_program_index = 0; + let accounts = (0..PROGRAM_ADDRESSES.len()) + .map(|index| AccountMeta::new_readonly(PROGRAM_ADDRESSES[index], false)) + .collect_vec(); + let message: Message = Message::new( + &[Instruction::new_with_bytes( + PROGRAM_ADDRESSES[base_program_index], + &[ + index_of_program_that_should_throw_exception, + base_program_index as u8, /* index of program being called */ + ], + accounts, + )], + None, + ); + let sanitized_message = new_unchecked_sanitized_message(message); + let mut program_cache_for_tx_batch = ProgramCacheForTxBatch::default(); + for index in 0..PROGRAM_ADDRESSES.len() { + program_cache_for_tx_batch.replenish( + PROGRAM_ADDRESSES[index], + Arc::new(ProgramCacheEntry::new_builtin(0, 0, MockBuiltin::vm)), + ); + } + let batch_processor = TransactionBatchProcessor::::default(); + let sanitized_transaction = SanitizedTransaction::new_for_tests( + sanitized_message, + vec![Signature::new_unique()], + false, + ); + let mut mock_program_account = AccountSharedData::new(1, 0, &native_loader::id()); + mock_program_account.set_executable(true); + let loaded_transaction = LoadedTransaction { + accounts: (0..PROGRAM_ADDRESSES.len()) + .map(|index| (PROGRAM_ADDRESSES[index], mock_program_account.clone())) + .collect_vec(), + program_indices: vec![vec![0]], + fee_details: FeeDetails::default(), + rollback_accounts: RollbackAccounts::default(), + compute_budget: SVMTransactionExecutionBudget::default(), + rent: 0, + rent_debits: RentDebits::default(), + loaded_accounts_data_size: 32, + }; + // ======================================================= + // END: Create a transaction that calls the mock program + // ======================================================= + + let result = batch_processor.execute_loaded_transaction( + &MockBankCallback::default(), + &sanitized_transaction, + loaded_transaction, + &mut ExecuteTimings::default(), + &mut TransactionErrorMetrics::default(), + &mut program_cache_for_tx_batch, + &TransactionProcessingEnvironment::default(), + &TransactionProcessingConfig::default(), + ); + + let status = result.execution_details.status; + assert_matches!( + status.err(), + Some(TransactionError::InstructionError( + 0, + InstructionError::Custom(0xdeadbeef), + ii, + Some(jj), + )) if ii == expected_inner_instruction_index && jj == index_of_program_that_should_throw_exception, + "Expected the error to be attributable to the program with account index: \ + {index_of_program_that_should_throw_exception} at inner instruction index \ + {:?}.", + expected_inner_instruction_index, + ); + } + #[test] fn test_execute_loaded_transaction_recordings() { // Setting all the arguments correctly is too burdensome for testing