From 6ae4a2a944e63e1fe889bbc0dab54aea3b7dd7a9 Mon Sep 17 00:00:00 2001 From: Gabe Rodriguez Date: Wed, 1 Apr 2026 08:35:43 +0200 Subject: [PATCH] Swap spl-pod for solana-zero-copy + solana-nullable --- Cargo.lock | 255 ++++++++++-------- clients/cli/Cargo.toml | 1 + clients/cli/src/command.rs | 17 +- clients/cli/src/encryption_keypair.rs | 10 +- clients/cli/tests/command.rs | 4 +- clients/rust-legacy/Cargo.toml | 1 + clients/rust-legacy/src/token.rs | 5 +- .../tests/confidential_mint_burn.rs | 31 ++- .../tests/confidential_transfer.rs | 61 +++-- .../tests/confidential_transfer_fee.rs | 33 +-- clients/rust-legacy/tests/transfer_fee.rs | 25 +- clients/rust-legacy/tests/transfer_hook.rs | 9 +- confidential/proof-extraction/Cargo.toml | 1 - .../proof-extraction/src/instruction.rs | 5 +- interface/Cargo.toml | 11 +- .../confidential_mint_burn/instruction.rs | 42 ++- .../confidential_transfer/instruction.rs | 97 ++++--- .../extension/confidential_transfer/mod.rs | 31 ++- .../confidential_transfer_fee/instruction.rs | 39 ++- .../confidential_transfer_fee/mod.rs | 8 +- .../src/extension/cpi_guard/instruction.rs | 7 +- interface/src/extension/cpi_guard/mod.rs | 11 +- .../default_account_state/instruction.rs | 7 +- .../extension/default_account_state/mod.rs | 7 +- .../group_member_pointer/instruction.rs | 53 ++-- .../src/extension/group_member_pointer/mod.rs | 23 +- .../extension/group_pointer/instruction.rs | 53 ++-- interface/src/extension/group_pointer/mod.rs | 23 +- .../interest_bearing_mint/instruction.rs | 32 ++- .../extension/interest_bearing_mint/mod.rs | 76 +++--- .../extension/memo_transfer/instruction.rs | 7 +- interface/src/extension/memo_transfer/mod.rs | 11 +- .../extension/metadata_pointer/instruction.rs | 53 ++-- .../src/extension/metadata_pointer/mod.rs | 23 +- .../src/extension/mint_close_authority.rs | 20 +- interface/src/extension/mod.rs | 212 +++++++-------- .../src/extension/pausable/instruction.rs | 14 +- interface/src/extension/pausable/mod.rs | 30 ++- interface/src/extension/permanent_delegate.rs | 22 +- .../permissioned_burn/instruction.rs | 34 ++- .../src/extension/permissioned_burn/mod.rs | 20 +- .../extension/scaled_ui_amount/instruction.rs | 39 ++- .../src/extension/scaled_ui_amount/mod.rs | 23 +- interface/src/extension/transfer_fee/mod.rs | 137 +++++----- .../extension/transfer_hook/instruction.rs | 53 ++-- interface/src/extension/transfer_hook/mod.rs | 35 ++- interface/src/instruction.rs | 14 +- interface/src/lib.rs | 11 + interface/src/pod.rs | 53 ++-- interface/tests/serialization.rs | 28 +- program/Cargo.toml | 22 +- .../confidential_mint_burn/processor.rs | 30 ++- .../confidential_transfer/account_info.rs | 4 +- .../confidential_transfer/processor.rs | 66 +++-- .../confidential_transfer_fee/processor.rs | 19 +- .../group_member_pointer/processor.rs | 9 +- .../src/extension/group_pointer/processor.rs | 9 +- .../interest_bearing_mint/processor.rs | 5 +- .../extension/metadata_pointer/processor.rs | 9 +- program/src/extension/pausable/processor.rs | 6 +- .../extension/permissioned_burn/processor.rs | 6 +- .../extension/scaled_ui_amount/processor.rs | 5 +- .../src/extension/transfer_fee/processor.rs | 9 +- .../src/extension/transfer_hook/processor.rs | 9 +- program/src/offchain.rs | 4 +- program/src/onchain.rs | 5 +- program/src/processor.rs | 8 +- 67 files changed, 1243 insertions(+), 799 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8415aa01..b8d6b5473 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -543,7 +543,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -669,7 +669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -695,7 +695,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -770,7 +770,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -915,7 +915,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -926,7 +926,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1067,7 +1067,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1160,7 +1160,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1296,7 +1296,7 @@ dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1379,7 +1379,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1511,7 +1511,7 @@ checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1619,7 +1619,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1913,7 +1913,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1947,7 +1947,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1960,7 +1960,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1971,7 +1971,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1982,7 +1982,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2065,7 +2065,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2078,7 +2078,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2100,7 +2100,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.116", + "syn 2.0.117", "unicode-xid", ] @@ -2181,7 +2181,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2204,7 +2204,7 @@ checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2320,7 +2320,7 @@ dependencies = [ "enum-ordinalize 4.3.2", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2380,7 +2380,7 @@ checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2393,7 +2393,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2413,7 +2413,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2499,7 +2499,7 @@ checksum = "18c1ddb9231d8554c2d6bdf4cfaabf0c59251658c68b6c95cd52dd0c513a912a" dependencies = [ "getrandom 0.3.1", "libm", - "rand 0.9.1", + "rand 0.9.2", "siphasher 1.0.1", ] @@ -2718,7 +2718,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3425,7 +3425,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3662,7 +3662,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4223,7 +4223,7 @@ checksum = "8462d3cc74eaf4194f6c0bd7b18c6f3fa6293297f4bdb60fe4c4b022ea366e12" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4428,7 +4428,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4501,7 +4501,7 @@ dependencies = [ "proc-macro-crate 3.3.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4566,7 +4566,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4777,7 +4777,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4818,7 +4818,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5007,7 +5007,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "version_check", ] @@ -5021,7 +5021,7 @@ dependencies = [ "bit-vec", "bitflags 2.10.0", "num-traits", - "rand 0.9.1", + "rand 0.9.2", "rand_chacha 0.9.0", "rand_xorshift 0.4.0", "regex-syntax", @@ -5110,7 +5110,7 @@ checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5164,7 +5164,7 @@ dependencies = [ "fastbloom", "getrandom 0.3.1", "lru-slab", - "rand 0.9.1", + "rand 0.9.2", "ring", "rustc-hash 2.1.1", "rustls 0.23.35", @@ -5193,9 +5193,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -5232,9 +5232,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -5423,7 +5423,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6010,7 +6010,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6066,7 +6066,7 @@ dependencies = [ "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6105,7 +6105,7 @@ checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6156,6 +6156,12 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2-const-stable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" + [[package]] name = "sha3" version = "0.10.8" @@ -6400,13 +6406,13 @@ dependencies = [ [[package]] name = "solana-account-info" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc3397241392f5756925029acaa8515dc70fcbe3d8059d4885d7d6533baf64fd" +checksum = "a9cf16495d9eb53e3d04e72366a33bb1c20c24e78c171d8b8f5978357b63ae95" dependencies = [ "bincode", "serde_core", - "solana-address 2.0.0", + "solana-address 2.5.0", "solana-program-error", "solana-program-memory", ] @@ -6476,14 +6482,14 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2ecac8e1b7f74c2baa9e774c42817e3e75b20787134b76cc4d45e8a604488f5" dependencies = [ - "solana-address 2.0.0", + "solana-address 2.5.0", ] [[package]] name = "solana-address" -version = "2.0.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37320fd2945c5d654b2c6210624a52d66c3f1f73b653ed211ab91a703b35bdd" +checksum = "5f08236dacd0e6dc8234becef58e27c8567856644ef509d7e97957d55a91dc72" dependencies = [ "borsh", "bytemuck", @@ -6491,14 +6497,17 @@ dependencies = [ "curve25519-dalek 4.1.3", "five8 1.0.0", "five8_const", - "rand 0.8.5", + "rand 0.9.2", "serde", "serde_derive", + "sha2-const-stable", "solana-atomic-u64", - "solana-define-syscall 4.0.1", + "solana-define-syscall 5.0.0", + "solana-nullable", "solana-program-error", "solana-sanitize", "solana-sha256-hasher", + "wincode 0.4.9", ] [[package]] @@ -7735,7 +7744,7 @@ dependencies = [ "serde_derive", "solana-atomic-u64", "solana-sanitize", - "wincode 0.4.4", + "wincode 0.4.9", ] [[package]] @@ -8151,6 +8160,17 @@ dependencies = [ "solana-sdk-ids", ] +[[package]] +name = "solana-nullable" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da028344c595c7416769ff648d206de7962571291a4cea24c38a60b6f40d53bb" +dependencies = [ + "bytemuck", + "serde", + "serde_with", +] + [[package]] name = "solana-offchain-message" version = "3.0.0" @@ -8529,7 +8549,7 @@ version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6f7104d456b58e1418c21a8581e89810278d1190f70f27ece7fc0b2c9282a57" dependencies = [ - "solana-address 2.0.0", + "solana-address 2.5.0", ] [[package]] @@ -9071,7 +9091,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "def234c1956ff616d46c9dd953f251fa7096ddbaa6d52b165218de97882b7280" dependencies = [ - "solana-address 2.0.0", + "solana-address 2.5.0", ] [[package]] @@ -9083,7 +9103,7 @@ dependencies = [ "bs58", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -9580,7 +9600,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-address 2.0.0", + "solana-address 2.5.0", "solana-instruction", "solana-msg", "solana-program-error", @@ -9812,7 +9832,7 @@ dependencies = [ "bincode", "serde", "serde_derive", - "solana-address 2.0.0", + "solana-address 2.5.0", "solana-hash 4.2.0", "solana-instruction", "solana-instruction-error", @@ -10195,6 +10215,18 @@ dependencies = [ "solana-vote-program", ] +[[package]] +name = "solana-zero-copy" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f52dd8f733a13f6a18e55de83cf97c4c3f5fdf27ea3830bcff0b35313efcc2" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "serde", + "serde_derive", +] + [[package]] name = "solana-zk-elgamal-proof-program" version = "3.1.4" @@ -10249,6 +10281,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "solana-zk-sdk-pod" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01eefa7061114c88540964e605c7def3d358440cbd4a155655bca9acd6380e00" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "bytemuck_derive", + "serde", + "solana-nullable", + "thiserror 2.0.18", +] + [[package]] name = "solana-zk-token-proof-program" version = "3.1.4" @@ -10356,7 +10402,7 @@ checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" dependencies = [ "quote", "spl-discriminator-syn", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -10368,7 +10414,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.9", - "syn 2.0.116", + "syn 2.0.117", "thiserror 1.0.69", ] @@ -10484,7 +10530,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.9", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -10533,27 +10579,23 @@ dependencies = [ name = "spl-token-2022" version = "10.0.0" dependencies = [ - "arrayref", "base64 0.22.1", "bytemuck", "lazy_static", "mollusk-svm", - "num-derive", - "num-traits", "num_enum", "proptest", "serde", - "serde_json", "serde_with", "serial_test", "solana-account", "solana-account-info", + "solana-address 2.5.0", "solana-clock", "solana-cpi", - "solana-hash 4.2.0", "solana-instruction", - "solana-keypair", "solana-msg", + "solana-nullable", "solana-program-entrypoint", "solana-program-error", "solana-program-memory", @@ -10563,12 +10605,11 @@ dependencies = [ "solana-rent", "solana-sdk-ids", "solana-security-txt", - "solana-signer", "solana-system-interface 3.0.0", "solana-sysvar", - "solana-transaction", - "solana-transaction-error", + "solana-zero-copy", "solana-zk-sdk", + "solana-zk-sdk-pod", "spl-elgamal-registry-interface", "spl-memo-interface", "spl-pod", @@ -10581,7 +10622,6 @@ dependencies = [ "spl-token-metadata-interface", "spl-transfer-hook-interface", "test-case", - "thiserror 2.0.18", "tokio", ] @@ -10600,14 +10640,17 @@ dependencies = [ "serde_json", "serde_with", "solana-account-info", + "solana-address 2.5.0", "solana-instruction", + "solana-nullable", "solana-program-error", "solana-program-option", "solana-program-pack", "solana-pubkey 4.0.0", "solana-sdk-ids", + "solana-zero-copy", "solana-zk-sdk", - "spl-pod", + "solana-zk-sdk-pod", "spl-token-2022-interface 2.1.0", "spl-token-confidential-transfer-proof-extraction", "spl-token-confidential-transfer-proof-generation", @@ -10676,6 +10719,7 @@ dependencies = [ "solana-system-interface 3.0.0", "solana-test-validator", "solana-transaction-status", + "solana-zk-sdk-pod", "spl-associated-token-account-interface", "spl-memo-interface", "spl-pod", @@ -10724,6 +10768,7 @@ dependencies = [ "solana-signer", "solana-system-interface 3.0.0", "solana-transaction", + "solana-zk-sdk-pod", "spl-associated-token-account-interface", "spl-elgamal-registry", "spl-instruction-padding-interface", @@ -10771,7 +10816,6 @@ dependencies = [ "solana-pubkey 4.0.0", "solana-sdk-ids", "solana-zk-sdk", - "spl-pod", "thiserror 2.0.18", ] @@ -10880,19 +10924,18 @@ dependencies = [ [[package]] name = "spl-type-length-value" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca20a1a19f4507a98ca4b28ff5ed54cac9b9d34ed27863e2bde50a3238f9a6ac" +checksum = "2504631748c48d2a937414d64a12dcac4588d34bd07d355d648619c189d29435" dependencies = [ "bytemuck", "num-derive", "num-traits", "num_enum", "solana-account-info", - "solana-msg", "solana-program-error", + "solana-zero-copy", "spl-discriminator", - "spl-pod", "thiserror 2.0.18", ] @@ -10974,7 +11017,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -11002,9 +11045,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.116" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -11046,7 +11089,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -11191,7 +11234,7 @@ dependencies = [ "cfg-if 1.0.4", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -11202,7 +11245,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "test-case-core", ] @@ -11247,7 +11290,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -11258,7 +11301,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -11408,7 +11451,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -11669,7 +11712,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -11740,7 +11783,7 @@ dependencies = [ "http 1.3.1", "httparse", "log", - "rand 0.9.1", + "rand 0.9.2", "rustls 0.23.35", "rustls-pki-types", "sha1", @@ -12025,7 +12068,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -12060,7 +12103,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -12197,15 +12240,15 @@ dependencies = [ [[package]] name = "wincode" -version = "0.4.4" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "466e67917609b2d40a838a5b972d1a6237c9749600cb8de8f65559b90d48485b" +checksum = "657690780ce23e6f66576a782ffd88eb353512381817029cc1d7a99154bb6d1f" dependencies = [ "pastey", "proc-macro2", "quote", "thiserror 2.0.18", - "wincode-derive 0.4.2", + "wincode-derive 0.4.3", ] [[package]] @@ -12217,19 +12260,19 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] name = "wincode-derive" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a7a568eda854acc9945ed136a9d50b8c6d31911584624958808ae96eee3912" +checksum = "fca057fc9a13dd19cdb64ef558635d43c42667c0afa1ae7915ea1fa66993fd1a" dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -12641,7 +12684,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure 0.13.1", ] @@ -12663,7 +12706,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -12683,7 +12726,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure 0.13.1", ] @@ -12704,7 +12747,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -12726,7 +12769,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] diff --git a/clients/cli/Cargo.toml b/clients/cli/Cargo.toml index fb9e980cf..a813b3518 100644 --- a/clients/cli/Cargo.toml +++ b/clients/cli/Cargo.toml @@ -32,6 +32,7 @@ solana-remote-wallet = { version = "3.1.0", features = ["agave-unstable-api"] } solana-sdk = "3.0.0" solana-system-interface = "3.0.0" solana-transaction-status = "3.0.0" +solana-zk-sdk-pod = "0.1.0" spl-associated-token-account-interface = { version = "2.0.0" } spl-pod = { version = "0.7.2" } spl-token-interface = "2.0.0" diff --git a/clients/cli/src/command.rs b/clients/cli/src/command.rs index 5a6352003..3a51374ea 100644 --- a/clients/cli/src/command.rs +++ b/clients/cli/src/command.rs @@ -33,6 +33,7 @@ use { signature::{Keypair, Signer}, }, solana_system_interface::program as system_program, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, spl_associated_token_account_interface::address::get_associated_token_address_with_program_id, spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_2022::extension::confidential_transfer::account_info::{ @@ -60,8 +61,7 @@ use { }, solana_zk_sdk::encryption::{ auth_encryption::AeKey, - elgamal::{self, ElGamalKeypair}, - pod::elgamal::PodElGamalPubkey, + elgamal::{ElGamalKeypair, ElGamalPubkey}, }, state::{Account, AccountState, Mint}, }, @@ -1653,14 +1653,11 @@ async fn command_transfer( } (None, None, Some(args)) => { // deserialize `pod` ElGamal pubkeys - let recipient_elgamal_pubkey: elgamal::ElGamalPubkey = recipient_elgamal_pubkey - .unwrap() - .try_into() - .expect("Invalid recipient ElGamal pubkey"); - let auditor_elgamal_pubkey = auditor_elgamal_pubkey.map(|pubkey| { - let auditor_elgamal_pubkey: elgamal::ElGamalPubkey = - pubkey.try_into().expect("Invalid auditor ElGamal pubkey"); - auditor_elgamal_pubkey + let recipient_elgamal_pubkey = + ElGamalPubkey::try_from(recipient_elgamal_pubkey.unwrap().0.as_ref()) + .expect("Invalid recipient ElGamal pubkey"); + let auditor_elgamal_pubkey = auditor_elgamal_pubkey.map(|pubkey: PodElGamalPubkey| { + ElGamalPubkey::try_from(pubkey.0.as_ref()).expect("Invalid auditor ElGamal pubkey") }); let context_state_authority = config.fee_payer()?; diff --git a/clients/cli/src/encryption_keypair.rs b/clients/cli/src/encryption_keypair.rs index 534e71043..63710af61 100644 --- a/clients/cli/src/encryption_keypair.rs +++ b/clients/cli/src/encryption_keypair.rs @@ -5,10 +5,8 @@ use { base64::{prelude::BASE64_STANDARD, Engine}, clap::ArgMatches, - spl_token_2022_interface::solana_zk_sdk::encryption::{ - elgamal::{ElGamalKeypair, ElGamalPubkey}, - pod::elgamal::PodElGamalPubkey, - }, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, + spl_token_2022_interface::solana_zk_sdk::encryption::elgamal::{ElGamalKeypair, ElGamalPubkey}, }; const ELGAMAL_PUBKEY_MAX_BASE64_LEN: usize = 44; @@ -45,7 +43,7 @@ pub(crate) fn elgamal_pubkey_of( name: &str, ) -> Result { if let Ok(keypair) = elgamal_keypair_of(matches, name) { - let elgamal_pubkey = (*keypair.pubkey()).into(); + let elgamal_pubkey = PodElGamalPubkey(keypair.pubkey().into()); Ok(elgamal_pubkey) } else { let arg_str = matches.value_of(name).unwrap(); @@ -71,5 +69,5 @@ fn elgamal_pubkey_from_str(s: &str) -> Option { } let pubkey_vec = BASE64_STANDARD.decode(s).ok()?; let elgamal_pubkey = ElGamalPubkey::try_from(pubkey_vec.as_ref()).ok()?; - Some(elgamal_pubkey.into()) + Some(PodElGamalPubkey(elgamal_pubkey.into())) } diff --git a/clients/cli/tests/command.rs b/clients/cli/tests/command.rs index 10b3a90aa..323abb996 100644 --- a/clients/cli/tests/command.rs +++ b/clients/cli/tests/command.rs @@ -14,6 +14,7 @@ use { solana_sdk_ids::bpf_loader_upgradeable, solana_system_interface::{instruction as system_instruction, program as system_program}, solana_test_validator::{TestValidator, TestValidatorGenesis, UpgradeableProgramInfo}, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, spl_associated_token_account_interface::address::get_associated_token_address_with_program_id, spl_token_2022_interface::{ extension::{ @@ -35,7 +36,6 @@ use { BaseStateWithExtensions, ExtensionType, StateWithExtensionsOwned, }, instruction::create_native_mint, - solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey, state::{Account, AccountState, Mint, Multisig}, }, spl_token_cli::{ @@ -2957,7 +2957,7 @@ async fn confidential_transfer(test_validator: &TestValidator, payer: &Keypair) // update confidential transfer mint settings let auditor_keypair = ElGamalKeypair::new_rand(); - let auditor_pubkey: PodElGamalPubkey = (*auditor_keypair.pubkey()).into(); + let auditor_pubkey = PodElGamalPubkey(auditor_keypair.pubkey().into()); let new_auto_approve = true; process_test_command( diff --git a/clients/rust-legacy/Cargo.toml b/clients/rust-legacy/Cargo.toml index 227532f8e..806ae8cb8 100644 --- a/clients/rust-legacy/Cargo.toml +++ b/clients/rust-legacy/Cargo.toml @@ -44,6 +44,7 @@ solana-signature = "3.0.0" solana-signer = "3.0.0" solana-system-interface = "3.0.0" solana-transaction = "3.0.0" +solana-zk-sdk-pod = "0.1.0" spl-associated-token-account-interface = { version = "2.0.0" } spl-elgamal-registry = { version = "0.4.0", path = "../../confidential/elgamal-registry", features = ["no-entrypoint"] } spl-memo-interface = "2.0.0" diff --git a/clients/rust-legacy/src/token.rs b/clients/rust-legacy/src/token.rs index 3abafddf6..9becd5077 100644 --- a/clients/rust-legacy/src/token.rs +++ b/clients/rust-legacy/src/token.rs @@ -18,6 +18,7 @@ use { solana_signer::{signers::Signers, Signer, SignerError}, solana_system_interface::instruction as system_instruction, solana_transaction::Transaction, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey as ZkPodElGamalPubkey, spl_associated_token_account_interface::{ address::get_associated_token_address_with_program_id, instruction::{ @@ -152,7 +153,7 @@ pub enum ExtensionInitializationParams { ConfidentialTransferMint { authority: Option, auto_approve_new_accounts: bool, - auditor_elgamal_pubkey: Option, + auditor_elgamal_pubkey: Option, }, DefaultAccountState { state: AccountState, @@ -2036,7 +2037,7 @@ where &self, authority: &Pubkey, auto_approve_new_account: bool, - auditor_elgamal_pubkey: Option, + auditor_elgamal_pubkey: Option, signing_keypairs: &S, ) -> TokenResult { let signing_pubkeys = signing_keypairs.pubkeys(); diff --git a/clients/rust-legacy/tests/confidential_mint_burn.rs b/clients/rust-legacy/tests/confidential_mint_burn.rs index a4dc724b4..0f3b26bd2 100644 --- a/clients/rust-legacy/tests/confidential_mint_burn.rs +++ b/clients/rust-legacy/tests/confidential_mint_burn.rs @@ -10,6 +10,7 @@ use { transaction::TransactionError, transport::TransportError, }, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey as ZkPodElGamalPubkey, spl_token_2022::extension::confidential_mint_burn::account_info::{ BurnAccountInfo, SupplyAccountInfo, }, @@ -22,7 +23,9 @@ use { }, instruction::AuthorityType, solana_zk_sdk::encryption::{ - auth_encryption::*, elgamal::*, pod::elgamal::PodElGamalCiphertext, + auth_encryption::*, + elgamal::*, + pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey}, }, }, spl_token_client::{ @@ -93,10 +96,10 @@ async fn confidential_mint_burn_config() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = ZkPodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let supply_elgamal_keypair = ElGamalKeypair::new_rand(); - let supply_elgamal_pubkey = (*supply_elgamal_keypair.pubkey()).into(); + let supply_elgamal_pubkey = PodElGamalPubkey::from(*supply_elgamal_keypair.pubkey()); let supply_aes_key = AeKey::new_rand(); let decryptable_supply = supply_aes_key.encrypt(0).into(); @@ -247,10 +250,10 @@ async fn confidential_mint_burn_rotate_supply_elgamal_pubkey_with_option( let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = ZkPodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let supply_elgamal_keypair = ElGamalKeypair::new_rand(); - let supply_elgamal_pubkey = (*supply_elgamal_keypair.pubkey()).into(); + let supply_elgamal_pubkey = PodElGamalPubkey::from(*supply_elgamal_keypair.pubkey()); let supply_aes_key = AeKey::new_rand(); let decryptable_supply = supply_aes_key.encrypt(0).into(); @@ -386,10 +389,10 @@ async fn confidential_mint_burn_update_decryptable_supply() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = ZkPodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let supply_elgamal_keypair = ElGamalKeypair::new_rand(); - let supply_elgamal_pubkey = (*supply_elgamal_keypair.pubkey()).into(); + let supply_elgamal_pubkey = PodElGamalPubkey::from(*supply_elgamal_keypair.pubkey()); let supply_aes_key = AeKey::new_rand(); let decryptable_supply = supply_aes_key.encrypt(0).into(); @@ -792,10 +795,10 @@ async fn confidential_mint_burn_with_option(option: ConfidentialTransferOption) let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = ZkPodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let supply_elgamal_keypair = ElGamalKeypair::new_rand(); - let supply_elgamal_pubkey = (*supply_elgamal_keypair.pubkey()).into(); + let supply_elgamal_pubkey = PodElGamalPubkey::from(*supply_elgamal_keypair.pubkey()); let supply_aes_key = AeKey::new_rand(); let decryptable_supply = supply_aes_key.encrypt(0).into(); @@ -1074,10 +1077,10 @@ async fn pause_confidential_mint_burn() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = ZkPodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let supply_elgamal_keypair = ElGamalKeypair::new_rand(); - let supply_elgamal_pubkey = (*supply_elgamal_keypair.pubkey()).into(); + let supply_elgamal_pubkey = PodElGamalPubkey::from(*supply_elgamal_keypair.pubkey()); let supply_aes_key = AeKey::new_rand(); let decryptable_supply = supply_aes_key.encrypt(0).into(); @@ -1207,10 +1210,10 @@ async fn fail_close_mint_with_confidential_supply() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = ZkPodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let supply_elgamal_keypair = ElGamalKeypair::new_rand(); - let supply_elgamal_pubkey = (*supply_elgamal_keypair.pubkey()).into(); + let supply_elgamal_pubkey = PodElGamalPubkey::from(*supply_elgamal_keypair.pubkey()); let supply_aes_key = AeKey::new_rand(); let decryptable_supply = supply_aes_key.encrypt(0).into(); @@ -1305,7 +1308,7 @@ async fn confidential_burn_no_auditor() { let auto_approve_new_accounts = true; let supply_elgamal_keypair = ElGamalKeypair::new_rand(); - let supply_elgamal_pubkey = (*supply_elgamal_keypair.pubkey()).into(); + let supply_elgamal_pubkey = PodElGamalPubkey::from(*supply_elgamal_keypair.pubkey()); let supply_aes_key = AeKey::new_rand(); let decryptable_supply = supply_aes_key.encrypt(0).into(); diff --git a/clients/rust-legacy/tests/confidential_transfer.rs b/clients/rust-legacy/tests/confidential_transfer.rs index 11772105c..53dc8c842 100644 --- a/clients/rust-legacy/tests/confidential_transfer.rs +++ b/clients/rust-legacy/tests/confidential_transfer.rs @@ -15,6 +15,7 @@ use { transport::TransportError, }, solana_system_interface::instruction as system_instruction, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, spl_elgamal_registry::state::ELGAMAL_REGISTRY_ACCOUNT_LEN, spl_token_2022::extension::confidential_transfer::account_info::{ EmptyAccountAccountInfo, TransferAccountInfo, WithdrawAccountInfo, @@ -28,7 +29,11 @@ use { BaseStateWithExtensions, ExtensionType, }, solana_zk_sdk::{ - encryption::{auth_encryption::*, elgamal::*, pod::elgamal::PodElGamalCiphertext}, + encryption::{ + auth_encryption::*, + elgamal::*, + pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey as LegacyPodElGamalPubkey}, + }, zk_elgamal_proof_program::proof_data::*, }, }, @@ -135,7 +140,7 @@ async fn confidential_transfer_configure_token_account_with_option( let authority = Keypair::new(); let auto_approve_new_accounts = false; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -183,7 +188,7 @@ async fn confidential_transfer_configure_token_account_with_option( .await .unwrap(); - let alice_elgamal_pubkey = (*alice_meta.elgamal_keypair.pubkey()).into(); + let alice_elgamal_pubkey = PodElGamalPubkey(alice_meta.elgamal_keypair.pubkey().into()); let state = token .get_account_info(&alice_meta.token_account) @@ -250,7 +255,7 @@ async fn confidential_transfer_fail_approving_account_on_wrong_mint() { let authority = Keypair::new(); let auto_approve_new_accounts = false; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context_a = TestContext::new().await; context_a @@ -308,7 +313,7 @@ async fn confidential_transfer_enable_disable_confidential_credits() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -417,7 +422,7 @@ async fn confidential_transfer_enable_disable_non_confidential_credits() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -604,7 +609,7 @@ async fn confidential_transfer_empty_account_with_option(option: ConfidentialTra let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; @@ -641,7 +646,7 @@ async fn confidential_transfer_deposit() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -962,7 +967,7 @@ async fn confidential_transfer_withdraw_with_option(option: ConfidentialTransfer let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -1255,7 +1260,7 @@ async fn pause_confidential_deposit() { let pausable_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -1323,7 +1328,7 @@ async fn pause_confidential_withdraw() { let pausable_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -1418,7 +1423,7 @@ async fn pause_confidential_transfer() { let pausable_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -1495,7 +1500,7 @@ async fn confidential_transfer_transfer_with_option(option: ConfidentialTransfer let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -1983,12 +1988,12 @@ async fn pause_confidential_transfer_with_fee() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context @@ -2081,12 +2086,12 @@ async fn confidential_transfer_transfer_with_fee_with_option(option: Confidentia let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context @@ -2341,7 +2346,7 @@ async fn confidential_transfer_transfer_memo_with_option(option: ConfidentialTra let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -2470,12 +2475,12 @@ async fn confidential_transfer_transfer_with_fee_and_memo_option( let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context @@ -2603,7 +2608,7 @@ async fn confidential_transfer_configure_token_account_with_registry() { let authority = Keypair::new(); let auto_approve_new_accounts = false; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -2702,7 +2707,7 @@ async fn confidential_transfer_configure_token_account_with_registry() { assert!(bool::from(&extension.allow_confidential_credits)); assert_eq!( extension.elgamal_pubkey, - (*new_elgamal_keypair.pubkey()).into() + PodElGamalPubkey(new_elgamal_keypair.pubkey().into()) ); } @@ -2711,7 +2716,7 @@ async fn test_confidential_transfer_balance_decryption() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -2889,7 +2894,7 @@ async fn test_confidential_transfer_balance_decryption_with_large_values() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -3072,7 +3077,7 @@ async fn test_confidential_transfer_balance_decryption_error_handling() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -3197,7 +3202,7 @@ async fn test_confidential_transfer_pending_decryption_after_transfer() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -3286,7 +3291,7 @@ async fn confidential_transfer_apply_pending_balance_frozen_account() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -3374,7 +3379,7 @@ async fn fail_initialize_non_transferable_confidential_mint_without_mint_burn() let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; let err = context diff --git a/clients/rust-legacy/tests/confidential_transfer_fee.rs b/clients/rust-legacy/tests/confidential_transfer_fee.rs index 4b27279d2..e7cb2ef56 100644 --- a/clients/rust-legacy/tests/confidential_transfer_fee.rs +++ b/clients/rust-legacy/tests/confidential_transfer_fee.rs @@ -12,6 +12,7 @@ use { transport::TransportError, }, solana_system_interface::instruction as system_instruction, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, spl_elgamal_registry::state::ELGAMAL_REGISTRY_ACCOUNT_LEN, spl_token_2022::extension::confidential_transfer_fee::account_info::WithheldTokensInfo, spl_token_2022_interface::{ @@ -28,7 +29,9 @@ use { }, instruction, solana_zk_sdk::encryption::{ - auth_encryption::*, elgamal::*, pod::elgamal::PodElGamalCiphertext, + auth_encryption::*, + elgamal::*, + pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey as LegacyPodElGamalPubkey}, }, }, spl_token_client::{ @@ -208,12 +211,12 @@ async fn confidential_transfer_fee_config() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; @@ -317,7 +320,7 @@ async fn confidential_transfer_initialize_and_update_mint() { let authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let mut context = TestContext::new().await; context @@ -554,12 +557,12 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_mint_with_option( let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context @@ -812,12 +815,12 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_accounts_with_optio let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context @@ -944,12 +947,12 @@ async fn confidential_transfer_harvest_withheld_tokens_to_mint() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context @@ -1088,12 +1091,12 @@ async fn confidential_transfer_configure_token_account_with_fee_with_registry() let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context @@ -1185,7 +1188,7 @@ async fn confidential_transfer_configure_token_account_with_fee_with_registry() )); assert_eq!( confidential_transfer_account.elgamal_pubkey, - (*elgamal_keypair.pubkey()).into() + PodElGamalPubkey(elgamal_keypair.pubkey().into()) ); let transfer_fee = state.get_extension::().unwrap(); @@ -1208,12 +1211,12 @@ async fn test_withdraw_withheld_tokens_with_max_pending_counter() { let confidential_transfer_authority = Keypair::new(); let auto_approve_new_accounts = true; let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); + let auditor_elgamal_pubkey = PodElGamalPubkey(auditor_elgamal_keypair.pubkey().into()); let confidential_transfer_fee_authority = Keypair::new(); let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); + LegacyPodElGamalPubkey::from(*withdraw_withheld_authority_elgamal_keypair.pubkey()); let mut context = TestContext::new().await; context diff --git a/clients/rust-legacy/tests/transfer_fee.rs b/clients/rust-legacy/tests/transfer_fee.rs index 4f63ab889..9f454f29e 100644 --- a/clients/rust-legacy/tests/transfer_fee.rs +++ b/clients/rust-legacy/tests/transfer_fee.rs @@ -15,6 +15,7 @@ use { BaseStateWithExtensions, }, instruction, + pod::PodCOption, }, spl_token_client::{ client::ProgramBanksClientProcessTransaction, @@ -37,8 +38,12 @@ fn test_transfer_fee() -> TransferFee { fn test_transfer_fee_config() -> TransferFeeConfig { let transfer_fee = test_transfer_fee(); TransferFeeConfig { - transfer_fee_config_authority: COption::Some(Pubkey::new_unique()).try_into().unwrap(), - withdraw_withheld_authority: COption::Some(Pubkey::new_unique()).try_into().unwrap(), + transfer_fee_config_authority: PodCOption::from(COption::Some(Pubkey::new_unique())) + .try_into() + .unwrap(), + withdraw_withheld_authority: PodCOption::from(COption::Some(Pubkey::new_unique())) + .try_into() + .unwrap(), withheld_amount: 0.into(), older_transfer_fee: transfer_fee, newer_transfer_fee: transfer_fee, @@ -56,12 +61,16 @@ fn test_transfer_fee_config_with_keypairs() -> TransferFeeConfigWithKeypairs { let transfer_fee_config_authority = Keypair::new(); let withdraw_withheld_authority = Keypair::new(); let transfer_fee_config = TransferFeeConfig { - transfer_fee_config_authority: COption::Some(transfer_fee_config_authority.pubkey()) - .try_into() - .unwrap(), - withdraw_withheld_authority: COption::Some(withdraw_withheld_authority.pubkey()) - .try_into() - .unwrap(), + transfer_fee_config_authority: PodCOption::from(COption::Some( + transfer_fee_config_authority.pubkey(), + )) + .try_into() + .unwrap(), + withdraw_withheld_authority: PodCOption::from(COption::Some( + withdraw_withheld_authority.pubkey(), + )) + .try_into() + .unwrap(), withheld_amount: 0.into(), older_transfer_fee: transfer_fee, newer_transfer_fee: transfer_fee, diff --git a/clients/rust-legacy/tests/transfer_hook.rs b/clients/rust-legacy/tests/transfer_hook.rs index a76f54111..9cf403f0b 100644 --- a/clients/rust-legacy/tests/transfer_hook.rs +++ b/clients/rust-legacy/tests/transfer_hook.rs @@ -27,6 +27,7 @@ use { BaseStateWithExtensions, }, instruction, + pod::PodCOption, }, spl_token_client::token::{ExtensionInitializationParams, TokenError as TokenClientError}, spl_transfer_hook_interface::{ @@ -506,8 +507,12 @@ async fn success_transfer_with_fee() { maximum_fee: TEST_MAXIMUM_FEE.into(), }; let transfer_fee_config = TransferFeeConfig { - transfer_fee_config_authority: COption::Some(Pubkey::new_unique()).try_into().unwrap(), - withdraw_withheld_authority: COption::Some(Pubkey::new_unique()).try_into().unwrap(), + transfer_fee_config_authority: PodCOption::from(COption::Some(Pubkey::new_unique())) + .try_into() + .unwrap(), + withdraw_withheld_authority: PodCOption::from(COption::Some(Pubkey::new_unique())) + .try_into() + .unwrap(), withheld_amount: 0.into(), older_transfer_fee: transfer_fee, newer_transfer_fee: transfer_fee, diff --git a/confidential/proof-extraction/Cargo.toml b/confidential/proof-extraction/Cargo.toml index 819fa0387..bab28cbbb 100644 --- a/confidential/proof-extraction/Cargo.toml +++ b/confidential/proof-extraction/Cargo.toml @@ -19,5 +19,4 @@ solana-program-error = "3.0.1" solana-pubkey = "4.0.0" solana-sdk-ids = "3.1.0" solana-zk-sdk = "4.0.0" -spl-pod = "0.7.2" thiserror = "2.0.18" diff --git a/confidential/proof-extraction/src/instruction.rs b/confidential/proof-extraction/src/instruction.rs index f91aa7dd9..3f85df8d8 100644 --- a/confidential/proof-extraction/src/instruction.rs +++ b/confidential/proof-extraction/src/instruction.rs @@ -15,7 +15,6 @@ use { proof_data::{ProofType, ZkProofData}, state::ProofContextState, }, - spl_pod::bytemuck::pod_from_bytes, std::{num::NonZeroI8, slice::Iter}, }; @@ -79,7 +78,9 @@ pub fn verify_and_extract_context<'a, T: Pod + ZkProofData, U: Pod>( let context_state_account_info = next_account_info(account_info_iter)?; check_zk_elgamal_proof_program_account(context_state_account_info.owner)?; let context_state_account_data = context_state_account_info.data.borrow(); - let context_state = pod_from_bytes::>(&context_state_account_data)?; + let context_state = + bytemuck::try_from_bytes::>(&context_state_account_data) + .map_err(|_| ProgramError::InvalidArgument)?; if context_state.proof_type != T::PROOF_TYPE.into() { return Err(ProgramError::InvalidInstructionData); diff --git a/interface/Cargo.toml b/interface/Cargo.toml index cf23d3d06..ad826b42e 100644 --- a/interface/Cargo.toml +++ b/interface/Cargo.toml @@ -11,7 +11,7 @@ license = { workspace = true } edition = { workspace = true } [features] -serde = ["dep:serde", "dep:serde_with", "dep:base64", "spl-pod/serde-traits", "solana-pubkey/serde"] +serde = ["dep:serde", "dep:serde_with", "solana-nullable/serde", "solana-nullable/serde-with", "solana-pubkey/serde", "solana-zero-copy/serde", "solana-zk-sdk-pod/serde"] [dependencies] arrayref = "0.3.9" @@ -20,22 +20,24 @@ num-derive = "0.4" num-traits = "0.2" num_enum = "0.7.6" solana-account-info = "3.1.0" +solana-address = { version = "2.0.0", features = ["bytemuck", "nullable", "decode"] } solana-instruction = "3.0.0" +solana-nullable = { version = "1.1.0", features = ["bytemuck"] } solana-program-error = "3.0.1" solana-program-option = "3.1.0" solana-program-pack = "3.1.0" solana-pubkey = "4.0.0" solana-sdk-ids = "3.1.0" +solana-zero-copy = { version = "1.0.0", features = ["bytemuck"] } solana-zk-sdk = "4.0.0" +solana-zk-sdk-pod = "0.1.0" spl-token-confidential-transfer-proof-extraction = { version = "0.5.0", path = "../confidential/proof-extraction" } spl-token-group-interface = { version = "0.7.1" } spl-token-metadata-interface = { version = "0.8.0" } -spl-type-length-value = { version = "0.9.0" } -spl-pod = { version = "0.7.2" } +spl-type-length-value = { version = "0.9.1" } thiserror = "2.0" serde = { version = "1.0.219", optional = true } serde_with = { version = "3.18.0", optional = true } -base64 = { version = "0.22.1", optional = true } [target.'cfg(not(target_os = "solana"))'.dependencies] spl-token-confidential-transfer-proof-generation = { version = "0.5.0", path = "../confidential/proof-generation" } @@ -45,6 +47,7 @@ proptest = "1.11" solana-pubkey = { version = "4.0.0", features = ["curve25519"] } spl-token-interface = { version = "2.0" } spl-token-2022-interface = { path = ".", features = ["serde"] } +base64 = "0.22.1" serde_json = "1.0.149" strum = "0.28" strum_macros = "0.28" diff --git a/interface/src/extension/confidential_mint_burn/instruction.rs b/interface/src/extension/confidential_mint_burn/instruction.rs index 98a599e3a..2b5247861 100644 --- a/interface/src/extension/confidential_mint_burn/instruction.rs +++ b/interface/src/extension/confidential_mint_burn/instruction.rs @@ -36,8 +36,11 @@ use { }; /// Confidential Transfer extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive)] #[repr(u8)] pub enum ConfidentialMintBurnInstruction { @@ -195,8 +198,11 @@ pub enum ConfidentialMintBurnInstruction { } /// Data expected by `ConfidentialMintBurnInstruction::InitializeMint` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct InitializeMintData { @@ -209,8 +215,11 @@ pub struct InitializeMintData { } /// Data expected by `ConfidentialMintBurnInstruction::RotateSupplyElGamalPubkey` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct RotateSupplyElGamalPubkeyData { @@ -224,8 +233,11 @@ pub struct RotateSupplyElGamalPubkeyData { } /// Data expected by `ConfidentialMintBurnInstruction::UpdateDecryptableSupply` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct UpdateDecryptableSupplyData { @@ -235,8 +247,11 @@ pub struct UpdateDecryptableSupplyData { } /// Data expected by `ConfidentialMintBurnInstruction::ConfidentialMint` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct MintInstructionData { @@ -266,8 +281,11 @@ pub struct MintInstructionData { } /// Data expected by `ConfidentialMintBurnInstruction::ConfidentialBurn` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct BurnInstructionData { diff --git a/interface/src/extension/confidential_transfer/instruction.rs b/interface/src/extension/confidential_transfer/instruction.rs index a17edad37..1e5331925 100644 --- a/interface/src/extension/confidential_transfer/instruction.rs +++ b/interface/src/extension/confidential_transfer/instruction.rs @@ -5,6 +5,7 @@ pub use solana_zk_sdk::zk_elgamal_proof_program::{ use { crate::serialization::{aeciphertext_fromstr, elgamalciphertext_fromstr}, serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; use { crate::{ @@ -14,16 +15,21 @@ use { }, bytemuck::Zeroable, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, solana_program_error::ProgramError, solana_pubkey::Pubkey, solana_sdk_ids::{system_program, sysvar}, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, spl_token_confidential_transfer_proof_extraction::instruction::ProofLocation, }; /// Confidential Transfer extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive)] #[repr(u8)] pub enum ConfidentialTransferInstruction { @@ -491,37 +497,47 @@ pub enum ConfidentialTransferInstruction { } /// Data expected by `ConfidentialTransferInstruction::InitializeMint` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct InitializeMintData { /// Authority to modify the `ConfidentialTransferMint` configuration and to /// approve new accounts. - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// Determines if newly configured accounts must be approved by the /// `authority` before they may be used by the user. - pub auto_approve_new_accounts: PodBool, + pub auto_approve_new_accounts: Bool, /// New authority to decode any transfer amount in a confidential transfer. - pub auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey, + pub auditor_elgamal_pubkey: MaybeNull, } /// Data expected by `ConfidentialTransferInstruction::UpdateMint` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct UpdateMintData { /// Determines if newly configured accounts must be approved by the /// `authority` before they may be used by the user. - pub auto_approve_new_accounts: PodBool, + pub auto_approve_new_accounts: Bool, /// New authority to decode any transfer amount in a confidential transfer. - pub auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey, + pub auditor_elgamal_pubkey: MaybeNull, } /// Data expected by `ConfidentialTransferInstruction::ConfigureAccount` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct ConfigureAccountInstructionData { @@ -530,7 +546,7 @@ pub struct ConfigureAccountInstructionData { pub decryptable_zero_balance: DecryptableBalance, /// The maximum number of deposits and transfers that an account can receive /// before the `ApplyPendingBalance` is executed - pub maximum_pending_balance_credit_counter: PodU64, + pub maximum_pending_balance_credit_counter: U64, /// Relative location of the `ProofInstruction::ZeroCiphertextProof` /// instruction to the `ConfigureAccount` instruction in the /// transaction. If the offset is `0`, then use a context state account @@ -539,8 +555,11 @@ pub struct ConfigureAccountInstructionData { } /// Data expected by `ConfidentialTransferInstruction::EmptyAccount` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct EmptyAccountInstructionData { @@ -551,25 +570,31 @@ pub struct EmptyAccountInstructionData { } /// Data expected by `ConfidentialTransferInstruction::Deposit` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct DepositInstructionData { /// The amount of tokens to deposit - pub amount: PodU64, + pub amount: U64, /// Expected number of base 10 digits to the right of the decimal place pub decimals: u8, } /// Data expected by `ConfidentialTransferInstruction::Withdraw` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct WithdrawInstructionData { /// The amount of tokens to withdraw - pub amount: PodU64, + pub amount: U64, /// Expected number of base 10 digits to the right of the decimal place pub decimals: u8, /// The new decryptable balance if the withdrawal succeeds @@ -587,8 +612,11 @@ pub struct WithdrawInstructionData { } /// Data expected by `ConfidentialTransferInstruction::Transfer` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct TransferInstructionData { @@ -618,14 +646,17 @@ pub struct TransferInstructionData { } /// Data expected by `ConfidentialTransferInstruction::ApplyPendingBalance` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct ApplyPendingBalanceData { /// The expected number of pending balance credits since the last successful /// `ApplyPendingBalance` instruction - pub expected_pending_balance_credit_counter: PodU64, + pub expected_pending_balance_credit_counter: U64, /// The new decryptable balance if the pending balance is applied /// successfully #[cfg_attr(feature = "serde", serde(with = "aeciphertext_fromstr"))] @@ -692,9 +723,13 @@ pub fn initialize_mint( TokenInstruction::ConfidentialTransferExtension, ConfidentialTransferInstruction::InitializeMint, &InitializeMintData { - authority: authority.try_into()?, + authority: authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, auto_approve_new_accounts: auto_approve_new_accounts.into(), - auditor_elgamal_pubkey: auditor_elgamal_pubkey.try_into()?, + auditor_elgamal_pubkey: auditor_elgamal_pubkey + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } @@ -723,7 +758,9 @@ pub fn update_mint( ConfidentialTransferInstruction::UpdateMint, &UpdateMintData { auto_approve_new_accounts: auto_approve_new_accounts.into(), - auditor_elgamal_pubkey: auditor_elgamal_pubkey.try_into()?, + auditor_elgamal_pubkey: auditor_elgamal_pubkey + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } diff --git a/interface/src/extension/confidential_transfer/mod.rs b/interface/src/extension/confidential_transfer/mod.rs index 8e557ea71..9ec5cb849 100644 --- a/interface/src/extension/confidential_transfer/mod.rs +++ b/interface/src/extension/confidential_transfer/mod.rs @@ -4,15 +4,14 @@ use { extension::{Extension, ExtensionType}, }, bytemuck::{Pod, Zeroable}, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, + solana_zero_copy::unaligned::{Bool, U64}, solana_zk_sdk::encryption::pod::{ - auth_encryption::PodAeCiphertext, - elgamal::{PodElGamalCiphertext, PodElGamalPubkey}, - }, - spl_pod::{ - optional_keys::{OptionalNonZeroElGamalPubkey, OptionalNonZeroPubkey}, - primitives::{PodBool, PodU64}, + auth_encryption::PodAeCiphertext, elgamal::PodElGamalCiphertext, }, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, }; /// Maximum bit length of any deposit or transfer amount @@ -42,7 +41,7 @@ pub struct ConfidentialTransferMint { /// approve new accounts (if `auto_approve_new_accounts` is true) /// /// The legacy Token Multisig account is not supported as the authority - pub authority: OptionalNonZeroPubkey, + pub authority: MaybeNull
, /// Indicate if newly configured accounts must be approved by the /// `authority` before they may be used by the user. @@ -51,10 +50,10 @@ pub struct ConfidentialTransferMint { /// immediately /// * If `false`, the authority must approve newly configured accounts (see /// `ConfidentialTransferInstruction::ConfigureAccount`) - pub auto_approve_new_accounts: PodBool, + pub auto_approve_new_accounts: Bool, /// Authority to decode any transfer amount in a confidential transfer. - pub auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey, + pub auditor_elgamal_pubkey: MaybeNull, } impl Extension for ConfidentialTransferMint { @@ -68,7 +67,7 @@ pub struct ConfidentialTransferAccount { /// `true` if this account has been approved for use. All confidential /// transfer operations for the account will fail until approval is /// granted. - pub approved: PodBool, + pub approved: Bool, /// The public key associated with ElGamal encryption pub elgamal_pubkey: PodElGamalPubkey, @@ -87,27 +86,27 @@ pub struct ConfidentialTransferAccount { /// If `false`, the extended account rejects any incoming confidential /// transfers - pub allow_confidential_credits: PodBool, + pub allow_confidential_credits: Bool, /// If `false`, the base account rejects any incoming transfers - pub allow_non_confidential_credits: PodBool, + pub allow_non_confidential_credits: Bool, /// The total number of `Deposit` and `Transfer` instructions that have /// credited `pending_balance` - pub pending_balance_credit_counter: PodU64, + pub pending_balance_credit_counter: U64, /// The maximum number of `Deposit` and `Transfer` instructions that can /// credit `pending_balance` before the `ApplyPendingBalance` /// instruction is executed - pub maximum_pending_balance_credit_counter: PodU64, + pub maximum_pending_balance_credit_counter: U64, /// The `expected_pending_balance_credit_counter` value that was included in /// the last `ApplyPendingBalance` instruction - pub expected_pending_balance_credit_counter: PodU64, + pub expected_pending_balance_credit_counter: U64, /// The actual `pending_balance_credit_counter` when the last /// `ApplyPendingBalance` instruction was executed - pub actual_pending_balance_credit_counter: PodU64, + pub actual_pending_balance_credit_counter: U64, } impl Extension for ConfidentialTransferAccount { diff --git a/interface/src/extension/confidential_transfer_fee/instruction.rs b/interface/src/extension/confidential_transfer_fee/instruction.rs index 0d8ecbf3c..645b899db 100644 --- a/interface/src/extension/confidential_transfer_fee/instruction.rs +++ b/interface/src/extension/confidential_transfer_fee/instruction.rs @@ -2,6 +2,7 @@ use { crate::serialization::{aeciphertext_fromstr, elgamalpubkey_fromstr}, serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; use { crate::{ @@ -18,18 +19,22 @@ use { }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, solana_sdk_ids::sysvar, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_confidential_transfer_proof_extraction::instruction::ProofLocation, std::convert::TryFrom, }; /// Confidential Transfer extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive)] #[repr(u8)] pub enum ConfidentialTransferFeeInstruction { @@ -211,13 +216,17 @@ pub enum ConfidentialTransferFeeInstruction { } /// Data expected by `InitializeConfidentialTransferFeeConfig` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct InitializeConfidentialTransferFeeConfigData { /// confidential transfer fee authority - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// ElGamal public key used to encrypt withheld fees. #[cfg_attr(feature = "serde", serde(with = "elgamalpubkey_fromstr"))] @@ -226,8 +235,11 @@ pub struct InitializeConfidentialTransferFeeConfigData { /// Data expected by /// `ConfidentialTransferFeeInstruction::WithdrawWithheldTokensFromMint` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct WithdrawWithheldTokensFromMintData { @@ -243,8 +255,11 @@ pub struct WithdrawWithheldTokensFromMintData { /// Data expected by /// `ConfidentialTransferFeeInstruction::WithdrawWithheldTokensFromAccounts` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct WithdrawWithheldTokensFromAccountsData { @@ -276,7 +291,9 @@ pub fn initialize_confidential_transfer_fee_config( TokenInstruction::ConfidentialTransferFeeExtension, ConfidentialTransferFeeInstruction::InitializeConfidentialTransferFeeConfig, &InitializeConfidentialTransferFeeConfigData { - authority: authority.try_into()?, + authority: authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, withdraw_withheld_authority_elgamal_pubkey: *withdraw_withheld_authority_elgamal_pubkey, }, )) diff --git a/interface/src/extension/confidential_transfer_fee/mod.rs b/interface/src/extension/confidential_transfer_fee/mod.rs index 1c0f1fd5e..549da2f9a 100644 --- a/interface/src/extension/confidential_transfer_fee/mod.rs +++ b/interface/src/extension/confidential_transfer_fee/mod.rs @@ -4,9 +4,11 @@ use { extension::{Extension, ExtensionType}, }, bytemuck::{Pod, Zeroable}, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, + solana_zero_copy::unaligned::Bool, solana_zk_sdk::encryption::pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey}, - spl_pod::{optional_keys::OptionalNonZeroPubkey, primitives::PodBool}, spl_token_confidential_transfer_proof_extraction::encryption::PodFeeCiphertext, }; @@ -23,7 +25,7 @@ pub type EncryptedWithheldAmount = PodElGamalCiphertext; #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct ConfidentialTransferFeeConfig { /// Optional authority to set the withdraw withheld authority ElGamal key - pub authority: OptionalNonZeroPubkey, + pub authority: MaybeNull
, /// Withheld fees from accounts must be encrypted with this ElGamal key. /// @@ -34,7 +36,7 @@ pub struct ConfidentialTransferFeeConfig { pub withdraw_withheld_authority_elgamal_pubkey: PodElGamalPubkey, /// If `false`, the harvest of withheld tokens to mint is rejected. - pub harvest_to_mint_enabled: PodBool, + pub harvest_to_mint_enabled: Bool, /// Withheld confidential transfer fee tokens that have been moved to the /// mint for withdrawal. diff --git a/interface/src/extension/cpi_guard/instruction.rs b/interface/src/extension/cpi_guard/instruction.rs index 752c69258..b6dd4a51a 100644 --- a/interface/src/extension/cpi_guard/instruction.rs +++ b/interface/src/extension/cpi_guard/instruction.rs @@ -12,8 +12,11 @@ use { }; /// CPI Guard extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum CpiGuardInstruction { diff --git a/interface/src/extension/cpi_guard/mod.rs b/interface/src/extension/cpi_guard/mod.rs index 80d401a4b..585d005a2 100644 --- a/interface/src/extension/cpi_guard/mod.rs +++ b/interface/src/extension/cpi_guard/mod.rs @@ -6,7 +6,7 @@ use { state::Account, }, bytemuck::{Pod, Zeroable}, - spl_pod::primitives::PodBool, + solana_zero_copy::unaligned::Bool, }; /// CPI Guard extension instructions @@ -14,12 +14,15 @@ pub mod instruction; /// CPI Guard extension for Accounts #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct CpiGuard { /// Lock privileged token operations from happening via CPI - pub lock_cpi: PodBool, + pub lock_cpi: Bool, } impl Extension for CpiGuard { const TYPE: ExtensionType = ExtensionType::CpiGuard; diff --git a/interface/src/extension/default_account_state/instruction.rs b/interface/src/extension/default_account_state/instruction.rs index 72d061d14..da54f3aa7 100644 --- a/interface/src/extension/default_account_state/instruction.rs +++ b/interface/src/extension/default_account_state/instruction.rs @@ -13,8 +13,11 @@ use { }; /// Default Account State extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum DefaultAccountStateInstruction { diff --git a/interface/src/extension/default_account_state/mod.rs b/interface/src/extension/default_account_state/mod.rs index 9890ab14a..49f9ccae7 100644 --- a/interface/src/extension/default_account_state/mod.rs +++ b/interface/src/extension/default_account_state/mod.rs @@ -10,8 +10,11 @@ pub mod instruction; /// Default Account::state extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct DefaultAccountState { /// Default Account::state in which new Accounts should be initialized diff --git a/interface/src/extension/group_member_pointer/instruction.rs b/interface/src/extension/group_member_pointer/instruction.rs index f429c812c..8b95e66b2 100644 --- a/interface/src/extension/group_member_pointer/instruction.rs +++ b/interface/src/extension/group_member_pointer/instruction.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ check_program_account, @@ -7,16 +5,24 @@ use { }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, - std::convert::TryInto, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Group member pointer extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum GroupMemberPointerInstruction { @@ -56,25 +62,34 @@ pub enum GroupMemberPointerInstruction { } /// Data expected by `Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { /// The public key for the account that can update the group address - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// The account address that holds the member - pub member_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub member_address: MaybeNull
, } /// Data expected by `Update` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct UpdateInstructionData { /// The new account address that holds the group - pub member_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub member_address: MaybeNull
, } /// Create an `Initialize` instruction @@ -92,8 +107,12 @@ pub fn initialize( TokenInstruction::GroupMemberPointerExtension, GroupMemberPointerInstruction::Initialize, &InitializeInstructionData { - authority: authority.try_into()?, - member_address: member_address.try_into()?, + authority: authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, + member_address: member_address + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } @@ -120,7 +139,9 @@ pub fn update( TokenInstruction::GroupMemberPointerExtension, GroupMemberPointerInstruction::Update, &UpdateInstructionData { - member_address: member_address.try_into()?, + member_address: member_address + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } diff --git a/interface/src/extension/group_member_pointer/mod.rs b/interface/src/extension/group_member_pointer/mod.rs index 544369bc7..daf5b6e45 100644 --- a/interface/src/extension/group_member_pointer/mod.rs +++ b/interface/src/extension/group_member_pointer/mod.rs @@ -1,9 +1,13 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::extension::{Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, - spl_pod::optional_keys::OptionalNonZeroPubkey, + solana_address::Address, + solana_nullable::MaybeNull, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Instructions for the `GroupMemberPointer` extension @@ -11,14 +15,19 @@ pub mod instruction; /// Group member pointer extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct GroupMemberPointer { /// Authority that can set the member address - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// Account address that holds the member - pub member_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub member_address: MaybeNull
, } impl Extension for GroupMemberPointer { diff --git a/interface/src/extension/group_pointer/instruction.rs b/interface/src/extension/group_pointer/instruction.rs index c79b325e6..bc6ae78ff 100644 --- a/interface/src/extension/group_pointer/instruction.rs +++ b/interface/src/extension/group_pointer/instruction.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ check_program_account, @@ -7,16 +5,24 @@ use { }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, - std::convert::TryInto, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Group pointer extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum GroupPointerInstruction { @@ -56,25 +62,34 @@ pub enum GroupPointerInstruction { } /// Data expected by `Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { /// The public key for the account that can update the group address - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// The account address that holds the group - pub group_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub group_address: MaybeNull
, } /// Data expected by `Update` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct UpdateInstructionData { /// The new account address that holds the group configurations - pub group_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub group_address: MaybeNull
, } /// Create an `Initialize` instruction @@ -92,8 +107,12 @@ pub fn initialize( TokenInstruction::GroupPointerExtension, GroupPointerInstruction::Initialize, &InitializeInstructionData { - authority: authority.try_into()?, - group_address: group_address.try_into()?, + authority: authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, + group_address: group_address + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } @@ -120,7 +139,9 @@ pub fn update( TokenInstruction::GroupPointerExtension, GroupPointerInstruction::Update, &UpdateInstructionData { - group_address: group_address.try_into()?, + group_address: group_address + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } diff --git a/interface/src/extension/group_pointer/mod.rs b/interface/src/extension/group_pointer/mod.rs index 7f48e53f7..58d3744d1 100644 --- a/interface/src/extension/group_pointer/mod.rs +++ b/interface/src/extension/group_pointer/mod.rs @@ -1,9 +1,13 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::extension::{Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, - spl_pod::optional_keys::OptionalNonZeroPubkey, + solana_address::Address, + solana_nullable::MaybeNull, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Instructions for the `GroupPointer` extension @@ -11,14 +15,19 @@ pub mod instruction; /// Group pointer extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct GroupPointer { /// Authority that can set the group address - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// Account address that holds the group - pub group_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub group_address: MaybeNull
, } impl Extension for GroupPointer { diff --git a/interface/src/extension/interest_bearing_mint/instruction.rs b/interface/src/extension/interest_bearing_mint/instruction.rs index 7afe93339..6293294f1 100644 --- a/interface/src/extension/interest_bearing_mint/instruction.rs +++ b/interface/src/extension/interest_bearing_mint/instruction.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ check_program_account, @@ -8,16 +6,24 @@ use { }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, - std::convert::TryInto, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Interest-bearing mint extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum InterestBearingMintInstruction { @@ -57,13 +63,17 @@ pub enum InterestBearingMintInstruction { } /// Data expected by `InterestBearing::Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { /// The public key for the account that can update the rate - pub rate_authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub rate_authority: MaybeNull
, /// The initial interest rate pub rate: BasisPoints, } @@ -83,7 +93,9 @@ pub fn initialize( TokenInstruction::InterestBearingMintExtension, InterestBearingMintInstruction::Initialize, &InitializeInstructionData { - rate_authority: rate_authority.try_into()?, + rate_authority: rate_authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, rate: rate.into(), }, )) diff --git a/interface/src/extension/interest_bearing_mint/mod.rs b/interface/src/extension/interest_bearing_mint/mod.rs index 0d14031bd..92594256f 100644 --- a/interface/src/extension/interest_bearing_mint/mod.rs +++ b/interface/src/extension/interest_bearing_mint/mod.rs @@ -1,29 +1,31 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ extension::{Extension, ExtensionType}, trim_ui_amount_string, }, bytemuck::{Pod, Zeroable}, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_error::ProgramError, - spl_pod::{ - optional_keys::OptionalNonZeroPubkey, - primitives::{PodI16, PodI64}, - }, + solana_zero_copy::unaligned::{I16, I64}, std::convert::TryInto, }; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, +}; /// Interest-bearing mint extension instructions pub mod instruction; /// Annual interest rate, expressed as basis points -pub type BasisPoints = PodI16; +pub type BasisPoints = I16; const ONE_IN_BASIS_POINTS: f64 = 10_000.; const SECONDS_PER_YEAR: f64 = 60. * 60. * 24. * 365.24; /// `UnixTimestamp` expressed with an alignment-independent type -pub type UnixTimestamp = PodI64; +pub type UnixTimestamp = I64; /// Interest-bearing extension data for mints /// @@ -34,12 +36,16 @@ pub type UnixTimestamp = PodI64; /// To support changing the rate, the config also maintains state for the /// previous rate. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct InterestBearingConfig { /// Authority that can set the interest rate and authority - pub rate_authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub rate_authority: MaybeNull
, /// Timestamp of initialization, from which to base interest calculations pub initialization_timestamp: UnixTimestamp, /// Average rate from initialization until the last time it was updated @@ -171,7 +177,7 @@ mod tests { const ONE: u64 = 1_000_000_000_000_000_000; // constant 5% let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), pre_update_average_rate: 500.into(), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), @@ -201,11 +207,11 @@ mod tests { // negative let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), - pre_update_average_rate: PodI16::from(-500), + pre_update_average_rate: I16::from(-500), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), - current_rate: PodI16::from(-500), + current_rate: I16::from(-500), }; // 1 year at -5% gives a total of exp(-0.05) = 0.951229424500714 let ui_amount = config @@ -215,11 +221,11 @@ mod tests { // net out let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), - pre_update_average_rate: PodI16::from(-500), + pre_update_average_rate: I16::from(-500), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), - current_rate: PodI16::from(500), + current_rate: I16::from(500), }; // 1 year at -5% and 1 year at 5% gives a total of 1 let ui_amount = config @@ -229,11 +235,11 @@ mod tests { // huge values let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), - pre_update_average_rate: PodI16::from(500), + pre_update_average_rate: I16::from(500), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), - current_rate: PodI16::from(500), + current_rate: I16::from(500), }; let ui_amount = config .amount_to_ui_amount(u64::MAX, 0, INT_SECONDS_PER_YEAR * 2) @@ -250,7 +256,7 @@ mod tests { fn specific_ui_amount_to_amount() { // constant 5% let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), pre_update_average_rate: 500.into(), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), @@ -280,11 +286,11 @@ mod tests { // negative let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), - pre_update_average_rate: PodI16::from(-500), + pre_update_average_rate: I16::from(-500), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), - current_rate: PodI16::from(-500), + current_rate: I16::from(-500), }; // 1 year at -5% gives a total of exp(-0.05) = 0.951229424500714 let amount = config @@ -294,11 +300,11 @@ mod tests { // net out let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), - pre_update_average_rate: PodI16::from(-500), + pre_update_average_rate: I16::from(-500), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), - current_rate: PodI16::from(500), + current_rate: I16::from(500), }; // 1 year at -5% and 1 year at 5% gives a total of 1 let amount = config @@ -308,11 +314,11 @@ mod tests { // huge values let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), - pre_update_average_rate: PodI16::from(500), + pre_update_average_rate: I16::from(500), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), - current_rate: PodI16::from(500), + current_rate: I16::from(500), }; let amount = config .try_ui_amount_into_amount("20386805083448100000", 0, INT_SECONDS_PER_YEAR * 2) @@ -350,7 +356,7 @@ mod tests { #[test] fn specific_amount_to_ui_amount_no_interest() { let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), pre_update_average_rate: 0.into(), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), @@ -367,7 +373,7 @@ mod tests { #[test] fn specific_ui_amount_to_amount_no_interest() { let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: 0.into(), pre_update_average_rate: 0.into(), last_update_timestamp: INT_SECONDS_PER_YEAR.into(), @@ -423,7 +429,7 @@ mod tests { (initialization_timestamp, last_update_timestamp, current_timestamp) in low_middle_high(), ) { let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: initialization_timestamp.into(), pre_update_average_rate: pre_update_average_rate.into(), last_update_timestamp: last_update_timestamp.into(), @@ -448,7 +454,7 @@ mod tests { decimals in 0u8..20u8, ) { let config = InterestBearingConfig { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), initialization_timestamp: initialization_timestamp.into(), pre_update_average_rate: pre_update_average_rate.into(), last_update_timestamp: last_update_timestamp.into(), diff --git a/interface/src/extension/memo_transfer/instruction.rs b/interface/src/extension/memo_transfer/instruction.rs index 83cfa9bd5..6c945ba5d 100644 --- a/interface/src/extension/memo_transfer/instruction.rs +++ b/interface/src/extension/memo_transfer/instruction.rs @@ -12,8 +12,11 @@ use { }; /// Required Memo Transfers extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum RequiredMemoTransfersInstruction { diff --git a/interface/src/extension/memo_transfer/mod.rs b/interface/src/extension/memo_transfer/mod.rs index 1d0869b9a..10a39ee05 100644 --- a/interface/src/extension/memo_transfer/mod.rs +++ b/interface/src/extension/memo_transfer/mod.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use { crate::extension::{BaseState, BaseStateWithExtensions, Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, - spl_pod::primitives::PodBool, + solana_zero_copy::unaligned::Bool, }; /// Memo Transfer extension instructions @@ -11,12 +11,15 @@ pub mod instruction; /// Memo Transfer extension for Accounts #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct MemoTransfer { /// Require transfers into this account to be accompanied by a memo - pub require_incoming_transfer_memos: PodBool, + pub require_incoming_transfer_memos: Bool, } impl Extension for MemoTransfer { const TYPE: ExtensionType = ExtensionType::MemoTransfer; diff --git a/interface/src/extension/metadata_pointer/instruction.rs b/interface/src/extension/metadata_pointer/instruction.rs index b9eb96473..ff5e747b7 100644 --- a/interface/src/extension/metadata_pointer/instruction.rs +++ b/interface/src/extension/metadata_pointer/instruction.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ check_program_account, @@ -7,16 +5,24 @@ use { }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, - std::convert::TryInto, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Metadata pointer extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum MetadataPointerInstruction { @@ -56,25 +62,34 @@ pub enum MetadataPointerInstruction { } /// Data expected by `Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { /// The public key for the account that can update the metadata address - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// The account address that holds the metadata - pub metadata_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub metadata_address: MaybeNull
, } /// Data expected by `Update` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct UpdateInstructionData { /// The new account address that holds the metadata - pub metadata_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub metadata_address: MaybeNull
, } /// Create an `Initialize` instruction @@ -92,8 +107,12 @@ pub fn initialize( TokenInstruction::MetadataPointerExtension, MetadataPointerInstruction::Initialize, &InitializeInstructionData { - authority: authority.try_into()?, - metadata_address: metadata_address.try_into()?, + authority: authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, + metadata_address: metadata_address + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } @@ -120,7 +139,9 @@ pub fn update( TokenInstruction::MetadataPointerExtension, MetadataPointerInstruction::Update, &UpdateInstructionData { - metadata_address: metadata_address.try_into()?, + metadata_address: metadata_address + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } diff --git a/interface/src/extension/metadata_pointer/mod.rs b/interface/src/extension/metadata_pointer/mod.rs index 31ae02c7d..ab6722cb9 100644 --- a/interface/src/extension/metadata_pointer/mod.rs +++ b/interface/src/extension/metadata_pointer/mod.rs @@ -1,9 +1,13 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::extension::{Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, - spl_pod::optional_keys::OptionalNonZeroPubkey, + solana_address::Address, + solana_nullable::MaybeNull, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Instructions for the `MetadataPointer` extension @@ -11,14 +15,19 @@ pub mod instruction; /// Metadata pointer extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct MetadataPointer { /// Authority that can set the metadata address - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// Account address that holds the metadata - pub metadata_address: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub metadata_address: MaybeNull
, } impl Extension for MetadataPointer { diff --git a/interface/src/extension/mint_close_authority.rs b/interface/src/extension/mint_close_authority.rs index dce961437..70f510cb4 100644 --- a/interface/src/extension/mint_close_authority.rs +++ b/interface/src/extension/mint_close_authority.rs @@ -1,19 +1,27 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::extension::{Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, - spl_pod::optional_keys::OptionalNonZeroPubkey, + solana_address::Address, + solana_nullable::MaybeNull, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Close authority extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct MintCloseAuthority { /// Optional authority to close the mint - pub close_authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub close_authority: MaybeNull
, } impl Extension for MintCloseAuthority { const TYPE: ExtensionType = ExtensionType::MintCloseAuthority; diff --git a/interface/src/extension/mod.rs b/interface/src/extension/mod.rs index 78dc71421..d7ca560ad 100644 --- a/interface/src/extension/mod.rs +++ b/interface/src/extension/mod.rs @@ -36,10 +36,7 @@ use { solana_account_info::AccountInfo, solana_program_error::ProgramError, solana_program_pack::{IsInitialized, Pack}, - spl_pod::{ - bytemuck::{pod_from_bytes, pod_from_bytes_mut, pod_get_packed_len}, - primitives::PodU16, - }, + solana_zero_copy::unaligned::U16, spl_token_group_interface::state::{TokenGroup, TokenGroupMember}, spl_type_length_value::variable_len_pack::VariableLenPack, std::{ @@ -96,7 +93,7 @@ pub mod confidential_mint_burn; /// Length in TLV structure #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] #[repr(transparent)] -pub struct Length(PodU16); +pub struct Length(U16); impl From for usize { fn from(n: Length) -> Self { Self::from(u16::from(n.0)) @@ -106,7 +103,7 @@ impl TryFrom for Length { type Error = ProgramError; fn try_from(n: usize) -> Result { u16::try_from(n) - .map(|v| Self(PodU16::from(v))) + .map(|v| Self(U16::from(v))) .map_err(|_| ProgramError::AccountDataTooSmall) } } @@ -114,7 +111,7 @@ impl TryFrom for Length { /// Helper function to get the current `TlvIndices` from the current spot fn get_tlv_indices(type_start: usize) -> TlvIndices { let length_start = type_start.saturating_add(size_of::()); - let value_start = length_start.saturating_add(pod_get_packed_len::()); + let value_start = length_start.saturating_add(size_of::()); TlvIndices { type_start, length_start, @@ -137,7 +134,7 @@ const fn adjust_len_for_multisig(account_len: usize) -> usize { const fn add_type_and_length_to_len(value_len: usize) -> usize { value_len .saturating_add(size_of::()) - .saturating_add(pod_get_packed_len::()) + .saturating_add(size_of::()) } /// Helper struct for returning the indices of the type, length, and value in @@ -175,9 +172,10 @@ fn get_extension_indices( return Err(TokenError::ExtensionNotFound.into()); } } else { - let length = pod_from_bytes::( + let length = bytemuck::try_from_bytes::( &tlv_data[tlv_indices.length_start..tlv_indices.value_start], - )?; + ) + .map_err(|_| ProgramError::InvalidArgument)?; let value_end_index = tlv_indices.value_start.saturating_add(usize::from(*length)); start_index = value_end_index; } @@ -226,9 +224,10 @@ fn get_tlv_data_info(tlv_data: &[u8]) -> Result { return Err(ProgramError::InvalidAccountData); } extension_types.push(extension_type); - let length = pod_from_bytes::( + let length = bytemuck::try_from_bytes::( &tlv_data[tlv_indices.length_start..tlv_indices.value_start], - )?; + ) + .map_err(|_| ProgramError::InvalidArgument)?; let value_end_index = tlv_indices.value_start.saturating_add(usize::from(*length)); if value_end_index > tlv_data.len() { @@ -345,7 +344,8 @@ fn get_extension_bytes(tlv_data: &[u8]) -> Result<&[ } = get_extension_indices::(tlv_data, false)?; // get_extension_indices has checked that tlv_data is long enough to include // these indices - let length = pod_from_bytes::(&tlv_data[length_start..value_start])?; + let length = bytemuck::try_from_bytes::(&tlv_data[length_start..value_start]) + .map_err(|_| ProgramError::InvalidArgument)?; let value_end = value_start.saturating_add(usize::from(*length)); if tlv_data.len() < value_end { return Err(ProgramError::InvalidAccountData); @@ -366,7 +366,8 @@ fn get_extension_bytes_mut( } = get_extension_indices::(tlv_data, false)?; // get_extension_indices has checked that tlv_data is long enough to include // these indices - let length = pod_from_bytes::(&tlv_data[length_start..value_start])?; + let length = bytemuck::try_from_bytes::(&tlv_data[length_start..value_start]) + .map_err(|_| ProgramError::InvalidArgument)?; let value_end = value_start.saturating_add(usize::from(*length)); if tlv_data.len() < value_end { return Err(ProgramError::InvalidAccountData); @@ -413,7 +414,8 @@ pub trait BaseStateWithExtensions { /// Unpack a portion of the TLV data as the desired type fn get_extension(&self) -> Result<&V, ProgramError> { - pod_from_bytes::(self.get_extension_bytes::()?) + bytemuck::try_from_bytes::(self.get_extension_bytes::()?) + .map_err(|_| ProgramError::InvalidArgument) } /// Unpacks a portion of the TLV data as the desired variable-length type @@ -451,10 +453,7 @@ pub trait BaseStateWithExtensions { /// If the state already has the extension, the resulting account length /// will be unchanged. fn try_get_new_account_len(&self) -> Result { - try_get_new_account_len_for_extension_len::( - self.get_tlv_data(), - pod_get_packed_len::(), - ) + try_get_new_account_len_for_extension_len::(self.get_tlv_data(), size_of::()) } /// Calculate the new expected size if the state allocates the given @@ -552,7 +551,8 @@ impl<'data, S: BaseState + Pod> PodStateWithExtensions<'data, S> { pub fn unpack(input: &'data [u8]) -> Result { check_min_len_and_not_multisig(input, S::SIZE_OF)?; let (base_data, rest) = input.split_at(S::SIZE_OF); - let base = pod_from_bytes::(base_data)?; + let base = + bytemuck::try_from_bytes::(base_data).map_err(|_| ProgramError::InvalidArgument)?; if !base.is_initialized() { Err(ProgramError::UninitializedAccount) } else { @@ -583,7 +583,8 @@ pub trait BaseStateWithExtensionsMut: BaseStateWithExtensions { /// Unpack a portion of the TLV data as the desired type that allows /// modifying the type fn get_extension_mut(&mut self) -> Result<&mut V, ProgramError> { - pod_from_bytes_mut::(self.get_extension_bytes_mut::()?) + bytemuck::try_from_bytes_mut::(self.get_extension_bytes_mut::()?) + .map_err(|_| ProgramError::InvalidArgument) } /// Packs a variable-length extension into its appropriate data segment. @@ -607,9 +608,10 @@ pub trait BaseStateWithExtensionsMut: BaseStateWithExtensions { &mut self, overwrite: bool, ) -> Result<&mut V, ProgramError> { - let length = pod_get_packed_len::(); + let length = size_of::(); let buffer = self.alloc::(length, overwrite)?; - let extension_ref = pod_from_bytes_mut::(buffer)?; + let extension_ref = + bytemuck::try_from_bytes_mut::(buffer).map_err(|_| ProgramError::InvalidArgument)?; *extension_ref = V::default(); Ok(extension_ref) } @@ -649,7 +651,9 @@ pub trait BaseStateWithExtensionsMut: BaseStateWithExtensions { let tlv_len = get_tlv_data_info(tlv_data).map(|x| x.used_len)?; let data_len = tlv_data.len(); - let length_ref = pod_from_bytes_mut::(&mut tlv_data[length_start..value_start])?; + let length_ref = + bytemuck::try_from_bytes_mut::(&mut tlv_data[length_start..value_start]) + .map_err(|_| ProgramError::InvalidArgument)?; let old_length = usize::from(*length_ref); // Length check to avoid a panic later in `copy_within` @@ -725,7 +729,8 @@ pub trait BaseStateWithExtensionsMut: BaseStateWithExtensions { extension_type_ref.copy_from_slice(&extension_type_array); // write length let length_ref = - pod_from_bytes_mut::(&mut tlv_data[length_start..value_start])?; + bytemuck::try_from_bytes_mut::(&mut tlv_data[length_start..value_start]) + .map_err(|_| ProgramError::InvalidArgument)?; // check that the length is the same if we're doing an alloc // with overwrite, otherwise a realloc should be done @@ -904,7 +909,8 @@ impl<'data, S: BaseState + Pod> PodStateWithExtensionsMut<'data, S> { pub fn unpack(input: &'data mut [u8]) -> Result { check_min_len_and_not_multisig(input, S::SIZE_OF)?; let (base_data, rest) = input.split_at_mut(S::SIZE_OF); - let base = pod_from_bytes_mut::(base_data)?; + let base = bytemuck::try_from_bytes_mut::(base_data) + .map_err(|_| ProgramError::InvalidArgument)?; if !base.is_initialized() { Err(ProgramError::UninitializedAccount) } else { @@ -924,7 +930,8 @@ impl<'data, S: BaseState + Pod> PodStateWithExtensionsMut<'data, S> { pub fn unpack_uninitialized(input: &'data mut [u8]) -> Result { check_min_len_and_not_multisig(input, S::SIZE_OF)?; let (base_data, rest) = input.split_at_mut(S::SIZE_OF); - let base = pod_from_bytes_mut::(base_data)?; + let base = bytemuck::try_from_bytes_mut::(base_data) + .map_err(|_| ProgramError::InvalidArgument)?; if base.is_initialized() { return Err(TokenError::AlreadyInUse.into()); } @@ -1049,8 +1056,11 @@ pub enum AccountType { /// only be applied to mint accounts, and account extensions must only be /// applied to token holding accounts. #[repr(u16)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, TryFromPrimitive, IntoPrimitive)] pub enum ExtensionType { /// Used as padding if the account size would otherwise be 355, same as a @@ -1170,46 +1180,42 @@ impl ExtensionType { } Ok(match self { ExtensionType::Uninitialized => 0, - ExtensionType::TransferFeeConfig => pod_get_packed_len::(), - ExtensionType::TransferFeeAmount => pod_get_packed_len::(), - ExtensionType::MintCloseAuthority => pod_get_packed_len::(), - ExtensionType::ImmutableOwner => pod_get_packed_len::(), - ExtensionType::ConfidentialTransferMint => { - pod_get_packed_len::() - } - ExtensionType::ConfidentialTransferAccount => { - pod_get_packed_len::() - } - ExtensionType::DefaultAccountState => pod_get_packed_len::(), - ExtensionType::MemoTransfer => pod_get_packed_len::(), - ExtensionType::NonTransferable => pod_get_packed_len::(), - ExtensionType::InterestBearingConfig => pod_get_packed_len::(), - ExtensionType::CpiGuard => pod_get_packed_len::(), - ExtensionType::PermanentDelegate => pod_get_packed_len::(), - ExtensionType::NonTransferableAccount => pod_get_packed_len::(), - ExtensionType::TransferHook => pod_get_packed_len::(), - ExtensionType::TransferHookAccount => pod_get_packed_len::(), + ExtensionType::TransferFeeConfig => size_of::(), + ExtensionType::TransferFeeAmount => size_of::(), + ExtensionType::MintCloseAuthority => size_of::(), + ExtensionType::ImmutableOwner => size_of::(), + ExtensionType::ConfidentialTransferMint => size_of::(), + ExtensionType::ConfidentialTransferAccount => size_of::(), + ExtensionType::DefaultAccountState => size_of::(), + ExtensionType::MemoTransfer => size_of::(), + ExtensionType::NonTransferable => size_of::(), + ExtensionType::InterestBearingConfig => size_of::(), + ExtensionType::CpiGuard => size_of::(), + ExtensionType::PermanentDelegate => size_of::(), + ExtensionType::NonTransferableAccount => size_of::(), + ExtensionType::TransferHook => size_of::(), + ExtensionType::TransferHookAccount => size_of::(), ExtensionType::ConfidentialTransferFeeConfig => { - pod_get_packed_len::() + size_of::() } ExtensionType::ConfidentialTransferFeeAmount => { - pod_get_packed_len::() + size_of::() } - ExtensionType::MetadataPointer => pod_get_packed_len::(), + ExtensionType::MetadataPointer => size_of::(), ExtensionType::TokenMetadata => unreachable!(), - ExtensionType::GroupPointer => pod_get_packed_len::(), - ExtensionType::TokenGroup => pod_get_packed_len::(), - ExtensionType::GroupMemberPointer => pod_get_packed_len::(), - ExtensionType::TokenGroupMember => pod_get_packed_len::(), - ExtensionType::ConfidentialMintBurn => pod_get_packed_len::(), - ExtensionType::ScaledUiAmount => pod_get_packed_len::(), - ExtensionType::Pausable => pod_get_packed_len::(), - ExtensionType::PausableAccount => pod_get_packed_len::(), - ExtensionType::PermissionedBurn => pod_get_packed_len::(), + ExtensionType::GroupPointer => size_of::(), + ExtensionType::TokenGroup => size_of::(), + ExtensionType::GroupMemberPointer => size_of::(), + ExtensionType::TokenGroupMember => size_of::(), + ExtensionType::ConfidentialMintBurn => size_of::(), + ExtensionType::ScaledUiAmount => size_of::(), + ExtensionType::Pausable => size_of::(), + ExtensionType::PausableAccount => size_of::(), + ExtensionType::PermissionedBurn => size_of::(), #[cfg(test)] - ExtensionType::AccountPaddingTest => pod_get_packed_len::(), + ExtensionType::AccountPaddingTest => size_of::(), #[cfg(test)] - ExtensionType::MintPaddingTest => pod_get_packed_len::(), + ExtensionType::MintPaddingTest => size_of::(), #[cfg(test)] ExtensionType::VariableLenMintTest => unreachable!(), }) @@ -1565,12 +1571,10 @@ mod test { solana_account_info::{ Account as GetAccount, IntoAccountInfo, MAX_PERMITTED_DATA_INCREASE, }, + solana_address::Address, + solana_nullable::MaybeNull, solana_pubkey::Pubkey, - spl_pod::{ - bytemuck::pod_bytes_of, - optional_keys::OptionalNonZeroPubkey, - primitives::{PodBool, PodU64}, - }, + solana_zero_copy::unaligned::{Bool, U64}, transfer_fee::test::test_transfer_fee_config, }; @@ -1669,8 +1673,8 @@ mod test { let state = PodStateWithExtensions::::unpack(MINT_WITH_EXTENSION).unwrap(); assert_eq!(state.base, &TEST_POD_MINT); let extension = state.get_extension::().unwrap(); - let close_authority = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([1; 32]))).unwrap(); + let close_authority: MaybeNull
= + Some(Pubkey::new_from_array([1; 32])).try_into().unwrap(); assert_eq!(extension.close_authority, close_authority); assert_eq!( state.get_extension::(), @@ -1692,7 +1696,7 @@ mod test { let state = PodStateWithExtensions::::unpack(ACCOUNT_WITH_EXTENSION).unwrap(); assert_eq!(state.base, &TEST_POD_ACCOUNT); let extension = state.get_extension::().unwrap(); - let transferring = PodBool::from(true); + let transferring = Bool::from(true); assert_eq!(extension.transferring, transferring); assert_eq!( PodStateWithExtensions::::unpack(ACCOUNT_WITH_EXTENSION), @@ -1919,8 +1923,8 @@ mod test { ); // success write extension - let close_authority = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([1; 32]))).unwrap(); + let close_authority: MaybeNull
= + Some(Pubkey::new_from_array([1; 32])).try_into().unwrap(); let extension = state.init_extension::(true).unwrap(); extension.close_authority = close_authority; assert_eq!( @@ -1961,8 +1965,7 @@ mod test { expect.extend_from_slice(&[0; BASE_ACCOUNT_LENGTH - PodMint::SIZE_OF]); // padding expect.push(AccountType::Mint.into()); expect.extend_from_slice(&(ExtensionType::MintCloseAuthority as u16).to_le_bytes()); - expect - .extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); expect.extend_from_slice(&[1; 32]); // data expect.extend_from_slice(&[0; size_of::()]); expect.extend_from_slice(&[0; size_of::()]); @@ -1987,7 +1990,7 @@ mod test { assert_eq!(*unpacked_extension, MintCloseAuthority { close_authority }); // update extension - let close_authority = OptionalNonZeroPubkey::try_from(None).unwrap(); + let close_authority: MaybeNull
= None.try_into().unwrap(); unpacked_extension.close_authority = close_authority; // check updates are propagated @@ -2003,8 +2006,7 @@ mod test { expect.extend_from_slice(&[0; BASE_ACCOUNT_LENGTH - PodMint::SIZE_OF]); // padding expect.push(AccountType::Mint.into()); expect.extend_from_slice(&(ExtensionType::MintCloseAuthority as u16).to_le_bytes()); - expect - .extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); expect.extend_from_slice(&[0; 32]); expect.extend_from_slice(&[0; size_of::()]); expect.extend_from_slice(&[0; size_of::()]); @@ -2038,16 +2040,15 @@ mod test { // check raw buffer let mut expect = vec![]; - expect.extend_from_slice(pod_bytes_of(&base)); + expect.extend_from_slice(bytemuck::bytes_of(&base)); expect.extend_from_slice(&[0; BASE_ACCOUNT_LENGTH - PodMint::SIZE_OF]); // padding expect.push(AccountType::Mint.into()); expect.extend_from_slice(&(ExtensionType::MintCloseAuthority as u16).to_le_bytes()); - expect - .extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); expect.extend_from_slice(&[0; 32]); // data expect.extend_from_slice(&(ExtensionType::TransferFeeConfig as u16).to_le_bytes()); - expect.extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); - expect.extend_from_slice(pod_bytes_of(&mint_transfer_fee)); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); + expect.extend_from_slice(bytemuck::bytes_of(&mint_transfer_fee)); assert_eq!(expect, buffer); // fail to init one more extension that does not fit @@ -2070,8 +2071,8 @@ mod test { let mut state = PodStateWithExtensionsMut::::unpack_uninitialized(&mut buffer).unwrap(); // write extensions - let close_authority = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([1; 32]))).unwrap(); + let close_authority: MaybeNull
= + Some(Pubkey::new_from_array([1; 32])).try_into().unwrap(); let extension = state.init_extension::(true).unwrap(); extension.close_authority = close_authority; @@ -2114,8 +2115,8 @@ mod test { extension.older_transfer_fee = mint_transfer_fee.older_transfer_fee; extension.newer_transfer_fee = mint_transfer_fee.newer_transfer_fee; - let close_authority = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([1; 32]))).unwrap(); + let close_authority: MaybeNull
= + Some(Pubkey::new_from_array([1; 32])).try_into().unwrap(); let extension = state.init_extension::(true).unwrap(); extension.close_authority = close_authority; @@ -2179,8 +2180,8 @@ mod test { expect.extend_from_slice(&[0; BASE_ACCOUNT_LENGTH - PodMint::SIZE_OF]); // padding expect.push(AccountType::Mint.into()); expect.extend_from_slice(&(ExtensionType::MintPaddingTest as u16).to_le_bytes()); - expect.extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); - expect.extend_from_slice(&vec![1; pod_get_packed_len::()]); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); + expect.extend_from_slice(&vec![1; size_of::()]); expect.extend_from_slice(&(ExtensionType::Uninitialized as u16).to_le_bytes()); assert_eq!(expect, buffer); } @@ -2207,7 +2208,7 @@ mod test { Err(ProgramError::InvalidAccountData), ); // success write extension - let withheld_amount = PodU64::from(u64::MAX); + let withheld_amount = U64::from(u64::MAX); let extension = state.init_extension::(true).unwrap(); extension.withheld_amount = withheld_amount; @@ -2233,7 +2234,7 @@ mod test { let mut expect = TEST_ACCOUNT_SLICE.to_vec(); expect.push(AccountType::Account.into()); expect.extend_from_slice(&(ExtensionType::TransferFeeAmount as u16).to_le_bytes()); - expect.extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); expect.extend_from_slice(&u64::from(withheld_amount).to_le_bytes()); assert_eq!(expect, buffer); @@ -2254,7 +2255,7 @@ mod test { assert_eq!(*unpacked_extension, TransferFeeAmount { withheld_amount }); // update extension - let withheld_amount = PodU64::from(u32::MAX as u64); + let withheld_amount = U64::from(u32::MAX as u64); unpacked_extension.withheld_amount = withheld_amount; // check updates are propagated @@ -2266,10 +2267,10 @@ mod test { // check raw buffer let mut expect = vec![]; - expect.extend_from_slice(pod_bytes_of(&base)); + expect.extend_from_slice(bytemuck::bytes_of(&base)); expect.push(AccountType::Account.into()); expect.extend_from_slice(&(ExtensionType::TransferFeeAmount as u16).to_le_bytes()); - expect.extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); expect.extend_from_slice(&u64::from(withheld_amount).to_le_bytes()); assert_eq!(expect, buffer); @@ -2315,9 +2316,8 @@ mod test { let mut expect = TEST_ACCOUNT_SLICE.to_vec(); expect.push(AccountType::Account.into()); expect.extend_from_slice(&(ExtensionType::AccountPaddingTest as u16).to_le_bytes()); - expect - .extend_from_slice(&(pod_get_packed_len::() as u16).to_le_bytes()); - expect.extend_from_slice(&vec![2; pod_get_packed_len::()]); + expect.extend_from_slice(&(size_of::() as u16).to_le_bytes()); + expect.extend_from_slice(&vec![2; size_of::()]); expect.extend_from_slice(&(ExtensionType::Uninitialized as u16).to_le_bytes()); assert_eq!(expect, buffer); } @@ -2676,8 +2676,8 @@ mod test { state .init_variable_len_extension(&base_variable_len, false) .unwrap(); - let max_pubkey = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([255; 32]))).unwrap(); + let max_pubkey: MaybeNull
= + Some(Pubkey::new_from_array([255; 32])).try_into().unwrap(); let extension = state.init_extension::(false).unwrap(); extension.authority = max_pubkey; extension.metadata_address = max_pubkey; @@ -2842,7 +2842,7 @@ mod test { let fixed_len = FixedLenMintTest { data: [1, 2, 3, 4, 5, 6, 7, 8], }; - let value_len = pod_get_packed_len::(); + let value_len = size_of::(); let base_account_size = PodMint::SIZE_OF; let mut buffer = vec![0; base_account_size]; let state = @@ -2931,7 +2931,7 @@ mod test { let fixed_len = FixedLenMintTest { data: [1, 2, 3, 4, 5, 6, 7, 8], }; - let value_len = pod_get_packed_len::(); + let value_len = size_of::(); let account_size = ExtensionType::try_calculate_account_len::(&[ExtensionType::GroupPointer]) .unwrap() @@ -2942,8 +2942,8 @@ mod test { *state.base = TEST_POD_MINT; state.init_account_type().unwrap(); - let test_key = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([20; 32]))).unwrap(); + let test_key: MaybeNull
= + Some(Pubkey::new_from_array([20; 32])).try_into().unwrap(); let extension = state.init_extension::(false).unwrap(); extension.authority = test_key; extension.group_address = test_key; @@ -2992,8 +2992,8 @@ mod test { *state.base = TEST_POD_MINT; state.init_account_type().unwrap(); - let test_key = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([20; 32]))).unwrap(); + let test_key: MaybeNull
= + Some(Pubkey::new_from_array([20; 32])).try_into().unwrap(); let extension = state.init_extension::(false).unwrap(); extension.authority = test_key; extension.metadata_address = test_key; @@ -3065,8 +3065,8 @@ mod test { state .init_variable_len_extension(&variable_len, false) .unwrap(); - let max_pubkey = - OptionalNonZeroPubkey::try_from(Some(Pubkey::new_from_array([255; 32]))).unwrap(); + let max_pubkey: MaybeNull
= + Some(Pubkey::new_from_array([255; 32])).try_into().unwrap(); let extension = state.init_extension::(false).unwrap(); extension.authority = max_pubkey; extension.metadata_address = max_pubkey; diff --git a/interface/src/extension/pausable/instruction.rs b/interface/src/extension/pausable/instruction.rs index bbd228b6b..b470b8552 100644 --- a/interface/src/extension/pausable/instruction.rs +++ b/interface/src/extension/pausable/instruction.rs @@ -13,8 +13,11 @@ use { }; /// Pausable extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum PausableInstruction { @@ -57,8 +60,11 @@ pub enum PausableInstruction { } /// Data expected by `PausableInstruction::Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { diff --git a/interface/src/extension/pausable/mod.rs b/interface/src/extension/pausable/mod.rs index f0a5fe717..a41a331f6 100644 --- a/interface/src/extension/pausable/mod.rs +++ b/interface/src/extension/pausable/mod.rs @@ -1,29 +1,41 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::extension::{Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, - spl_pod::{optional_keys::OptionalNonZeroPubkey, primitives::PodBool}, + solana_address::Address, + solana_nullable::MaybeNull, + solana_zero_copy::unaligned::Bool, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Instruction types for the pausable extension pub mod instruction; /// Indicates that the tokens from this mint can be paused -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct PausableConfig { /// Authority that can pause or resume activity on the mint - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// Whether minting / transferring / burning tokens is paused - pub paused: PodBool, + pub paused: Bool, } /// Indicates that the tokens from this account belong to a pausable mint -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] #[repr(transparent)] pub struct PausableAccount; diff --git a/interface/src/extension/permanent_delegate.rs b/interface/src/extension/permanent_delegate.rs index dd4d99295..2b328a87c 100644 --- a/interface/src/extension/permanent_delegate.rs +++ b/interface/src/extension/permanent_delegate.rs @@ -1,20 +1,28 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::extension::{BaseState, BaseStateWithExtensions, Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, + solana_address::Address, + solana_nullable::MaybeNull, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Permanent delegate extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct PermanentDelegate { /// Optional permanent delegate for transferring or burning tokens - pub delegate: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub delegate: MaybeNull
, } impl Extension for PermanentDelegate { const TYPE: ExtensionType = ExtensionType::PermanentDelegate; @@ -28,5 +36,5 @@ pub fn get_permanent_delegate>( state .get_extension::() .ok() - .and_then(|e| Option::::from(e.delegate)) + .and_then(|e| Option::
::from(e.delegate)) } diff --git a/interface/src/extension/permissioned_burn/instruction.rs b/interface/src/extension/permissioned_burn/instruction.rs index 590b92fe3..bc161e8d9 100644 --- a/interface/src/extension/permissioned_burn/instruction.rs +++ b/interface/src/extension/permissioned_burn/instruction.rs @@ -28,12 +28,15 @@ use { solana_instruction::{AccountMeta, Instruction}, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::primitives::PodU64, + solana_zero_copy::unaligned::U64, }; /// Permissioned Burn extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum PermissionedBurnInstruction { @@ -122,8 +125,11 @@ pub enum PermissionedBurnInstruction { } /// Data expected by `PermissionedBurnInstruction::Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { @@ -132,23 +138,29 @@ pub struct InitializeInstructionData { } /// Data expected by `PermissionedBurnInstruction::Burn` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct BurnInstructionData { /// The amount of tokens to burn. - pub amount: PodU64, + pub amount: U64, } /// Data expected by `PermissionedBurnInstruction::BurnChecked` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct BurnCheckedInstructionData { /// The amount of tokens to burn. - pub amount: PodU64, + pub amount: U64, /// Expected number of base 10 digits to the right of the decimal place. pub decimals: u8, } diff --git a/interface/src/extension/permissioned_burn/mod.rs b/interface/src/extension/permissioned_burn/mod.rs index 636e38450..bf0513dd2 100644 --- a/interface/src/extension/permissioned_burn/mod.rs +++ b/interface/src/extension/permissioned_burn/mod.rs @@ -1,22 +1,30 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::extension::{Extension, ExtensionType}, bytemuck::{Pod, Zeroable}, - spl_pod::optional_keys::OptionalNonZeroPubkey, + solana_address::Address, + solana_nullable::MaybeNull, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Instruction types for the permissioned burn extension pub mod instruction; /// Indicates that the tokens from this mint require permissioned burn -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] #[repr(C)] pub struct PermissionedBurnConfig { /// Authority that is required for burning - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, } impl Extension for PermissionedBurnConfig { diff --git a/interface/src/extension/scaled_ui_amount/instruction.rs b/interface/src/extension/scaled_ui_amount/instruction.rs index 0349826a3..da53d7238 100644 --- a/interface/src/extension/scaled_ui_amount/instruction.rs +++ b/interface/src/extension/scaled_ui_amount/instruction.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ check_program_account, @@ -8,16 +6,24 @@ use { }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, - std::convert::TryInto, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Interesting-bearing mint extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum ScaledUiAmountMintInstruction { @@ -67,20 +73,27 @@ pub enum ScaledUiAmountMintInstruction { } /// Data expected by `ScaledUiAmountMint::Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { /// The public key for the account that can update the multiplier - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// The initial multiplier pub multiplier: PodF64, } /// Data expected by `ScaledUiAmountMint::UpdateMultiplier` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct UpdateMultiplierInstructionData { @@ -105,7 +118,9 @@ pub fn initialize( TokenInstruction::ScaledUiAmountExtension, ScaledUiAmountMintInstruction::Initialize, &InitializeInstructionData { - authority: authority.try_into()?, + authority: authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, multiplier: multiplier.into(), }, )) diff --git a/interface/src/extension/scaled_ui_amount/mod.rs b/interface/src/extension/scaled_ui_amount/mod.rs index ce068d666..5013274a5 100644 --- a/interface/src/extension/scaled_ui_amount/mod.rs +++ b/interface/src/extension/scaled_ui_amount/mod.rs @@ -1,20 +1,25 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ extension::{Extension, ExtensionType}, trim_ui_amount_string, }, bytemuck::{Pod, Zeroable}, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_error::ProgramError, - spl_pod::{optional_keys::OptionalNonZeroPubkey, primitives::PodI64}, + solana_zero_copy::unaligned::I64, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Scaled UI amount extension instructions pub mod instruction; /// `UnixTimestamp` expressed with an alignment-independent type -pub type UnixTimestamp = PodI64; +pub type UnixTimestamp = I64; /// `f64` type that can be used in `Pod`s #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -40,12 +45,16 @@ impl From for f64 { /// Scaled UI amount extension data for mints #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct ScaledUiAmountConfig { /// Authority that can set the scaling amount and authority - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// Amount to multiply raw amounts by, outside of the decimal pub multiplier: PodF64, /// Unix timestamp at which `new_multiplier` comes into effective diff --git a/interface/src/extension/transfer_fee/mod.rs b/interface/src/extension/transfer_fee/mod.rs index 3cf505413..b8d0a9829 100644 --- a/interface/src/extension/transfer_fee/mod.rs +++ b/interface/src/extension/transfer_fee/mod.rs @@ -1,21 +1,23 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ error::TokenError, extension::{Extension, ExtensionType}, }, bytemuck::{Pod, Zeroable}, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, - spl_pod::{ - optional_keys::OptionalNonZeroPubkey, - primitives::{PodU16, PodU64}, - }, + solana_zero_copy::unaligned::{U16, U64}, std::{ cmp, convert::{TryFrom, TryInto}, }, }; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, +}; /// Transfer fee extension instructions pub mod instruction; @@ -26,17 +28,20 @@ const ONE_IN_BASIS_POINTS: u128 = MAX_FEE_BASIS_POINTS as u128; /// Transfer fee information #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct TransferFee { /// First epoch where the transfer fee takes effect - pub epoch: PodU64, // Epoch, + pub epoch: U64, // Epoch, /// Maximum fee assessed on transfers, expressed as an amount of tokens - pub maximum_fee: PodU64, + pub maximum_fee: U64, /// Amount of transfer collected as fees, expressed as basis points of the /// transfer amount (increments of `0.01%`) - pub transfer_fee_basis_points: PodU16, + pub transfer_fee_basis_points: U16, } impl TransferFee { /// Calculate ceiling-division @@ -127,17 +132,22 @@ impl TransferFee { /// Transfer fee extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct TransferFeeConfig { /// Optional authority to set the fee - pub transfer_fee_config_authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub transfer_fee_config_authority: MaybeNull
, /// Withdraw from mint instructions must be signed by this key - pub withdraw_withheld_authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub withdraw_withheld_authority: MaybeNull
, /// Withheld transfer fee tokens that have been moved to the mint for /// withdrawal - pub withheld_amount: PodU64, + pub withheld_amount: U64, /// Older transfer fee, used if `current epoch < new_transfer_fee.epoch` pub older_transfer_fee: TransferFee, /// Newer transfer fee, used if `current epoch >= new_transfer_fee.epoch` @@ -168,12 +178,15 @@ impl Extension for TransferFeeConfig { /// Transfer fee extension data for accounts. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct TransferFeeAmount { /// Amount withheld during transfers, to be harvested to the mint - pub withheld_amount: PodU64, + pub withheld_amount: U64, } impl TransferFeeAmount { /// Check if the extension is in a closable state @@ -198,24 +211,20 @@ pub(crate) mod test { pub(crate) fn test_transfer_fee_config() -> TransferFeeConfig { TransferFeeConfig { - transfer_fee_config_authority: OptionalNonZeroPubkey::try_from(Some( - Pubkey::new_from_array([10; 32]), - )) - .unwrap(), - withdraw_withheld_authority: OptionalNonZeroPubkey::try_from(Some( - Pubkey::new_from_array([11; 32]), - )) - .unwrap(), - withheld_amount: PodU64::from(u64::MAX), + transfer_fee_config_authority: Some(Pubkey::new_from_array([10; 32])) + .try_into() + .unwrap(), + withdraw_withheld_authority: Some(Pubkey::new_from_array([11; 32])).try_into().unwrap(), + withheld_amount: U64::from(u64::MAX), older_transfer_fee: TransferFee { - epoch: PodU64::from(OLDER_EPOCH), - maximum_fee: PodU64::from(10), - transfer_fee_basis_points: PodU16::from(100), + epoch: U64::from(OLDER_EPOCH), + maximum_fee: U64::from(10), + transfer_fee_basis_points: U16::from(100), }, newer_transfer_fee: TransferFee { - epoch: PodU64::from(NEWER_EPOCH), - maximum_fee: PodU64::from(5_000), - transfer_fee_basis_points: PodU16::from(1), + epoch: U64::from(NEWER_EPOCH), + maximum_fee: U64::from(5_000), + transfer_fee_basis_points: U16::from(1), }, } } @@ -255,9 +264,9 @@ pub(crate) mod test { fn calculate_fee_max() { let one = u64::try_from(ONE_IN_BASIS_POINTS).unwrap(); let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(5_000), - transfer_fee_basis_points: PodU16::from(1), + epoch: U64::from(0), + maximum_fee: U64::from(5_000), + transfer_fee_basis_points: U16::from(1), }; let maximum_fee = u64::from(transfer_fee.maximum_fee); // hit maximum fee @@ -283,9 +292,9 @@ pub(crate) mod test { fn calculate_fee_min() { let one = u64::try_from(ONE_IN_BASIS_POINTS).unwrap(); let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(5_000), - transfer_fee_basis_points: PodU16::from(1), + epoch: U64::from(0), + maximum_fee: U64::from(5_000), + transfer_fee_basis_points: U16::from(1), }; let minimum_fee = 1; // hit minimum fee even with 1 token @@ -307,9 +316,9 @@ pub(crate) mod test { fn calculate_fee_zero() { let one = u64::try_from(ONE_IN_BASIS_POINTS).unwrap(); let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(u64::MAX), - transfer_fee_basis_points: PodU16::from(0), + epoch: U64::from(0), + maximum_fee: U64::from(u64::MAX), + transfer_fee_basis_points: U16::from(0), }; // always zero fee assert_eq!(0, transfer_fee.calculate_fee(0).unwrap()); @@ -318,9 +327,9 @@ pub(crate) mod test { assert_eq!(0, transfer_fee.calculate_fee(one).unwrap()); let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(0), - transfer_fee_basis_points: PodU16::from(MAX_FEE_BASIS_POINTS), + epoch: U64::from(0), + maximum_fee: U64::from(0), + transfer_fee_basis_points: U16::from(MAX_FEE_BASIS_POINTS), }; // always zero fee assert_eq!(0, transfer_fee.calculate_fee(0).unwrap()); @@ -333,9 +342,9 @@ pub(crate) mod test { fn calculate_fee_exact_out_max() { let one = u64::try_from(ONE_IN_BASIS_POINTS).unwrap(); let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(5_000), - transfer_fee_basis_points: PodU16::from(1), + epoch: U64::from(0), + maximum_fee: U64::from(5_000), + transfer_fee_basis_points: U16::from(1), }; let maximum_fee = u64::from(transfer_fee.maximum_fee); // hit maximum fee @@ -372,9 +381,9 @@ pub(crate) mod test { fn calculate_pre_fee_amount_edge_cases() { let maximum_fee = 5_000; let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(maximum_fee), - transfer_fee_basis_points: PodU16::from(u16::try_from(ONE_IN_BASIS_POINTS).unwrap()), + epoch: U64::from(0), + maximum_fee: U64::from(maximum_fee), + transfer_fee_basis_points: U16::from(u16::try_from(ONE_IN_BASIS_POINTS).unwrap()), }; // 0 zero out, 0 in @@ -388,9 +397,9 @@ pub(crate) mod test { // no fee same amount let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(maximum_fee), - transfer_fee_basis_points: PodU16::from(0), + epoch: U64::from(0), + maximum_fee: U64::from(maximum_fee), + transfer_fee_basis_points: U16::from(0), }; assert_eq!(1, transfer_fee.calculate_pre_fee_amount(1).unwrap()); } @@ -399,9 +408,9 @@ pub(crate) mod test { fn calculate_fee_exact_out_min() { let one = u64::try_from(ONE_IN_BASIS_POINTS).unwrap(); let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(5_000), - transfer_fee_basis_points: PodU16::from(1), + epoch: U64::from(0), + maximum_fee: U64::from(5_000), + transfer_fee_basis_points: U16::from(1), }; let minimum_fee = 1; // hit minimum fee even with 1 token @@ -430,9 +439,9 @@ pub(crate) mod test { amount_in in 0..=u64::MAX ) { let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(maximum_fee), - transfer_fee_basis_points: PodU16::from(transfer_fee_basis_points), + epoch: U64::from(0), + maximum_fee: U64::from(maximum_fee), + transfer_fee_basis_points: U16::from(transfer_fee_basis_points), }; let fee = transfer_fee.calculate_fee(amount_in).unwrap(); let amount_out = amount_in.checked_sub(fee).unwrap(); @@ -455,9 +464,9 @@ pub(crate) mod test { amount_in in 0..=u64::MAX ) { let transfer_fee = TransferFee { - epoch: PodU64::from(0), - maximum_fee: PodU64::from(maximum_fee), - transfer_fee_basis_points: PodU16::from(transfer_fee_basis_points), + epoch: U64::from(0), + maximum_fee: U64::from(maximum_fee), + transfer_fee_basis_points: U16::from(transfer_fee_basis_points), }; let fee = transfer_fee.calculate_fee(amount_in).unwrap(); let amount_out = amount_in.checked_sub(fee).unwrap(); diff --git a/interface/src/extension/transfer_hook/instruction.rs b/interface/src/extension/transfer_hook/instruction.rs index 29b8d6123..90f9f907b 100644 --- a/interface/src/extension/transfer_hook/instruction.rs +++ b/interface/src/extension/transfer_hook/instruction.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ check_program_account, @@ -7,16 +5,24 @@ use { }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, + solana_address::Address, solana_instruction::{AccountMeta, Instruction}, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, - std::convert::TryInto, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Transfer hook extension instructions -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, PartialEq, IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum TransferHookInstruction { @@ -56,25 +62,34 @@ pub enum TransferHookInstruction { } /// Data expected by `Initialize` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct InitializeInstructionData { /// The public key for the account that can update the program id - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// The program id that performs logic during transfers - pub program_id: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub program_id: MaybeNull
, } /// Data expected by `Update` -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] pub struct UpdateInstructionData { /// The program id that performs logic during transfers - pub program_id: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub program_id: MaybeNull
, } /// Create an `Initialize` instruction @@ -92,8 +107,12 @@ pub fn initialize( TokenInstruction::TransferHookExtension, TransferHookInstruction::Initialize, &InitializeInstructionData { - authority: authority.try_into()?, - program_id: transfer_hook_program_id.try_into()?, + authority: authority + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, + program_id: transfer_hook_program_id + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } @@ -120,7 +139,9 @@ pub fn update( TokenInstruction::TransferHookExtension, TransferHookInstruction::Update, &UpdateInstructionData { - program_id: transfer_hook_program_id.try_into()?, + program_id: transfer_hook_program_id + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?, }, )) } diff --git a/interface/src/extension/transfer_hook/mod.rs b/interface/src/extension/transfer_hook/mod.rs index aaa870cab..cecb590b0 100644 --- a/interface/src/extension/transfer_hook/mod.rs +++ b/interface/src/extension/transfer_hook/mod.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use { crate::{ extension::{ @@ -10,9 +8,16 @@ use { }, bytemuck::{Pod, Zeroable}, solana_account_info::AccountInfo, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_pubkey::Pubkey, - spl_pod::{optional_keys::OptionalNonZeroPubkey, primitives::PodBool}, + solana_zero_copy::unaligned::Bool, +}; +#[cfg(feature = "serde")] +use { + serde::{Deserialize, Serialize}, + serde_with::{As, DisplayFromStr}, }; /// Instructions for the `TransferHook` extension @@ -20,25 +25,33 @@ pub mod instruction; /// Transfer hook extension data for mints. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct TransferHook { /// Authority that can set the transfer hook program id - pub authority: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub authority: MaybeNull
, /// Program that authorizes the transfer - pub program_id: OptionalNonZeroPubkey, + #[cfg_attr(feature = "serde", serde(with = "As::>"))] + pub program_id: MaybeNull
, } /// Indicates that the tokens from this account belong to a mint with a transfer /// hook -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] #[repr(transparent)] pub struct TransferHookAccount { /// Flag to indicate that the account is in the middle of a transfer - pub transferring: PodBool, + pub transferring: Bool, } impl Extension for TransferHook { @@ -57,7 +70,7 @@ pub fn get_program_id>( state .get_extension::() .ok() - .and_then(|e| Option::::from(e.program_id)) + .and_then(|e| Option::
::from(e.program_id)) } /// Helper function to set the transferring flag before calling into transfer diff --git a/interface/src/instruction.rs b/interface/src/instruction.rs index e46fbd6c9..72684af54 100644 --- a/interface/src/instruction.rs +++ b/interface/src/instruction.rs @@ -21,7 +21,6 @@ use { solana_program_option::COption, solana_pubkey::{Pubkey, PUBKEY_BYTES}, solana_sdk_ids::{system_program, sysvar}, - spl_pod::bytemuck::{pod_from_bytes, pod_get_packed_len}, std::{ convert::{TryFrom, TryInto}, mem::size_of, @@ -39,9 +38,9 @@ const U64_BYTES: usize = 8; /// Instructions supported by the token program. #[repr(C)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde", + derive(Serialize, Deserialize), serde(rename_all_fields = "camelCase", rename_all = "camelCase") )] #[derive(Clone, Debug, PartialEq)] @@ -1234,8 +1233,11 @@ impl<'a> TokenInstruction<'a> { /// Specifies the authority type for `SetAuthority` instructions #[repr(u8)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] #[derive(Clone, Debug, PartialEq)] pub enum AuthorityType { /// Authority to mint new tokens @@ -2148,10 +2150,10 @@ pub fn decode_instruction_type>(input: &[u8]) -> Result(input_with_type: &[u8]) -> Result<&T, ProgramError> { - if input_with_type.len() != pod_get_packed_len::().saturating_add(1) { + if input_with_type.len() != size_of::().saturating_add(1) { Err(ProgramError::InvalidInstructionData) } else { - pod_from_bytes(&input_with_type[1..]) + bytemuck::try_from_bytes(&input_with_type[1..]).map_err(|_| ProgramError::InvalidArgument) } } diff --git a/interface/src/lib.rs b/interface/src/lib.rs index e1175c72f..f52183e9d 100644 --- a/interface/src/lib.rs +++ b/interface/src/lib.rs @@ -18,8 +18,11 @@ pub mod state; // version pub use solana_zk_sdk; use { + bytemuck::cast, solana_program_error::{ProgramError, ProgramResult}, solana_pubkey::Pubkey, + solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey as LegacyPodElGamalPubkey, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, }; solana_pubkey::declare_id!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); @@ -46,6 +49,14 @@ pub fn check_spl_token_program_account(spl_token_program_id: &Pubkey) -> Program Ok(()) } +/// Convert a legacy ZK SDK ElGamal pod pubkey into the nullable-compatible pod type. +/// This is temporary until updated solana-zk-sdk crates are published. +pub fn convert_legacy_elgamal_pubkey( + pubkey: LegacyPodElGamalPubkey, +) -> Result { + Ok(cast::(pubkey)) +} + /// Trims a string number by removing excess zeroes or unneeded decimal point fn trim_ui_amount_string(mut ui_amount: String, decimals: u8) -> String { if decimals > 0 { diff --git a/interface/src/pod.rs b/interface/src/pod.rs index 4438558f2..11b30f663 100644 --- a/interface/src/pod.rs +++ b/interface/src/pod.rs @@ -8,15 +8,13 @@ use { state::{AccountState, PackedSizeOf}, }, bytemuck::{Pod, Zeroable}, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_error::ProgramError, solana_program_option::COption, solana_program_pack::IsInitialized, solana_pubkey::Pubkey, - spl_pod::{ - bytemuck::pod_get_packed_len, - optional_keys::OptionalNonZeroPubkey, - primitives::{PodBool, PodU64}, - }, + solana_zero_copy::unaligned::{Bool, U64}, }; /// [crate::state::Mint] data stored as a Pod type @@ -29,11 +27,11 @@ pub struct PodMint { /// minted. pub mint_authority: PodCOption, /// Total supply of tokens. - pub supply: PodU64, + pub supply: U64, /// Number of base 10 digits to the right of the decimal place. pub decimals: u8, /// If `true`, this structure has been initialized - pub is_initialized: PodBool, + pub is_initialized: Bool, /// Optional authority to freeze token accounts. pub freeze_authority: PodCOption, } @@ -43,7 +41,7 @@ impl IsInitialized for PodMint { } } impl PackedSizeOf for PodMint { - const SIZE_OF: usize = pod_get_packed_len::(); + const SIZE_OF: usize = size_of::(); } #[cfg(test)] impl From for PodMint { @@ -67,7 +65,7 @@ pub struct PodAccount { /// The owner of this account. pub owner: Pubkey, /// The amount of tokens this account holds. - pub amount: PodU64, + pub amount: U64, /// If `delegate` is `Some` then `delegated_amount` represents /// the amount authorized by the delegate pub delegate: PodCOption, @@ -77,9 +75,9 @@ pub struct PodAccount { /// reserve. An Account is required to be rent-exempt, so the value is /// used by the Processor to ensure that wrapped SOL accounts do not /// drop below this threshold. - pub is_native: PodCOption, + pub is_native: PodCOption, /// The amount delegated - pub delegated_amount: PodU64, + pub delegated_amount: U64, /// Optional authority to close the account. pub close_authority: PodCOption, } @@ -105,7 +103,7 @@ impl IsInitialized for PodAccount { } } impl PackedSizeOf for PodAccount { - const SIZE_OF: usize = pod_get_packed_len::(); + const SIZE_OF: usize = size_of::(); } #[cfg(test)] impl From for PodAccount { @@ -116,7 +114,7 @@ impl From for PodAccount { amount: account.amount.into(), delegate: account.delegate.into(), state: account.state.into(), - is_native: account.is_native.map(PodU64::from_primitive).into(), + is_native: account.is_native.map(U64::from_primitive).into(), delegated_amount: account.delegated_amount.into(), close_authority: account.close_authority.into(), } @@ -132,7 +130,7 @@ pub struct PodMultisig { /// Number of valid signers pub n: u8, /// If `true`, this structure has been initialized - pub is_initialized: PodBool, + pub is_initialized: Bool, /// Signer public keys pub signers: [Pubkey; MAX_SIGNERS], } @@ -142,7 +140,7 @@ impl IsInitialized for PodMultisig { } } impl PackedSizeOf for PodMultisig { - const SIZE_OF: usize = pod_get_packed_len::(); + const SIZE_OF: usize = size_of::(); } #[cfg(test)] impl From for PodMultisig { @@ -242,7 +240,7 @@ impl From> for PodCOption { } } } -impl TryFrom> for OptionalNonZeroPubkey { +impl TryFrom> for MaybeNull
{ type Error = ProgramError; fn try_from(p: PodCOption) -> Result { match p { @@ -253,11 +251,13 @@ impl TryFrom> for OptionalNonZeroPubkey { PodCOption { option: PodCOption::::SOME, value, - } => Ok(Self(value)), + } => Some(value) + .try_into() + .map_err(|_| ProgramError::InvalidArgument), PodCOption { option: PodCOption::::NONE, value: _, - } => Ok(Self(Pubkey::default())), + } => None.try_into().map_err(|_| ProgramError::InvalidArgument), _ => unreachable!(), } } @@ -274,44 +274,43 @@ pub(crate) mod test { }, AccountState, }, - spl_pod::bytemuck::pod_from_bytes, }; pub const TEST_POD_MINT: PodMint = PodMint { mint_authority: PodCOption::some(Pubkey::new_from_array([1; 32])), - supply: PodU64::from_primitive(42), + supply: U64::from_primitive(42), decimals: 7, - is_initialized: PodBool::from_bool(true), + is_initialized: Bool::from_bool(true), freeze_authority: PodCOption::some(Pubkey::new_from_array([2; 32])), }; pub const TEST_POD_ACCOUNT: PodAccount = PodAccount { mint: Pubkey::new_from_array([1; 32]), owner: Pubkey::new_from_array([2; 32]), - amount: PodU64::from_primitive(3), + amount: U64::from_primitive(3), delegate: PodCOption::some(Pubkey::new_from_array([4; 32])), state: AccountState::Frozen as u8, - is_native: PodCOption::some(PodU64::from_primitive(5)), - delegated_amount: PodU64::from_primitive(6), + is_native: PodCOption::some(U64::from_primitive(5)), + delegated_amount: U64::from_primitive(6), close_authority: PodCOption::some(Pubkey::new_from_array([7; 32])), }; #[test] fn pod_mint_to_mint_equality() { - let pod_mint = pod_from_bytes::(TEST_MINT_SLICE).unwrap(); + let pod_mint = bytemuck::try_from_bytes::(TEST_MINT_SLICE).unwrap(); assert_eq!(*pod_mint, PodMint::from(TEST_MINT)); assert_eq!(*pod_mint, TEST_POD_MINT); } #[test] fn pod_account_to_account_equality() { - let pod_account = pod_from_bytes::(TEST_ACCOUNT_SLICE).unwrap(); + let pod_account = bytemuck::try_from_bytes::(TEST_ACCOUNT_SLICE).unwrap(); assert_eq!(*pod_account, PodAccount::from(TEST_ACCOUNT)); assert_eq!(*pod_account, TEST_POD_ACCOUNT); } #[test] fn pod_multisig_to_multisig_equality() { - let pod_multisig = pod_from_bytes::(TEST_MULTISIG_SLICE).unwrap(); + let pod_multisig = bytemuck::try_from_bytes::(TEST_MULTISIG_SLICE).unwrap(); assert_eq!(*pod_multisig, PodMultisig::from(TEST_MULTISIG)); } } diff --git a/interface/tests/serialization.rs b/interface/tests/serialization.rs index e73d6d41f..d5993e53e 100644 --- a/interface/tests/serialization.rs +++ b/interface/tests/serialization.rs @@ -2,9 +2,11 @@ use { base64::{engine::general_purpose::STANDARD, Engine}, + solana_address::Address, + solana_nullable::MaybeNull, solana_program_option::COption, solana_pubkey::Pubkey, - spl_pod::optional_keys::{OptionalNonZeroElGamalPubkey, OptionalNonZeroPubkey}, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, spl_token_2022_interface::{extension::confidential_transfer, instruction}, std::str::FromStr, }; @@ -98,19 +100,19 @@ fn serde_instruction_batch() { #[test] fn serde_instruction_optional_nonzero_pubkeys_podbool() { - // tests serde of ix containing OptionalNonZeroPubkey, PodBool and - // OptionalNonZeroElGamalPubkey + // tests serde of ix containing MaybeNull
, Bool and + // MaybeNull let authority_option: Option = Some(Pubkey::from_str("4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM").unwrap()); - let authority: OptionalNonZeroPubkey = authority_option.try_into().unwrap(); + let authority: MaybeNull
= authority_option.try_into().unwrap(); let pubkey_string = STANDARD.encode([ 162, 23, 108, 36, 130, 143, 18, 219, 196, 134, 242, 145, 179, 49, 229, 193, 74, 64, 3, 158, 68, 235, 124, 88, 247, 144, 164, 254, 228, 12, 173, 85, ]); - let elgamal_pubkey_pod_option = Some(FromStr::from_str(&pubkey_string).unwrap()); + let elgamal_pubkey_pod_option = Some(PodElGamalPubkey::from_str(&pubkey_string).unwrap()); - let auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey = + let auditor_elgamal_pubkey: MaybeNull = elgamal_pubkey_pod_option.try_into().unwrap(); let inst = confidential_transfer::instruction::InitializeMintData { @@ -131,12 +133,12 @@ fn serde_instruction_optional_nonzero_pubkeys_podbool() { #[test] fn serde_instruction_optional_nonzero_pubkeys_podbool_with_none() { - // tests serde of ix containing OptionalNonZeroPubkey, PodBool and - // OptionalNonZeroElGamalPubkey with null values - let authority: OptionalNonZeroPubkey = None.try_into().unwrap(); + // tests serde of ix containing MaybeNull
, Bool and + // MaybeNull with null values + let authority: MaybeNull
= None.try_into().unwrap(); - let auditor_elgamal_pubkey: OptionalNonZeroElGamalPubkey = - OptionalNonZeroElGamalPubkey::default(); + let auditor_elgamal_pubkey: MaybeNull = + MaybeNull::::default(); let inst = confidential_transfer::instruction::InitializeMintData { authority, @@ -193,7 +195,7 @@ fn serde_instruction_elgamal_pubkey() { let withdraw_withheld_authority_elgamal_pubkey = FromStr::from_str(&pubkey_string).unwrap(); let inst = InitializeConfidentialTransferFeeConfigData { - authority: OptionalNonZeroPubkey::default(), + authority: MaybeNull::
::default(), withdraw_withheld_authority_elgamal_pubkey, }; @@ -212,7 +214,7 @@ fn serde_instruction_basis_points() { use spl_token_2022_interface::extension::interest_bearing_mint::instruction::InitializeInstructionData; let inst = InitializeInstructionData { - rate_authority: OptionalNonZeroPubkey::default(), + rate_authority: MaybeNull::
::default(), rate: 127.into(), }; diff --git a/program/Cargo.toml b/program/Cargo.toml index 541b54be0..75f06d2ab 100644 --- a/program/Cargo.toml +++ b/program/Cargo.toml @@ -19,16 +19,18 @@ default = ["zk-ops"] zk-ops = [] [dependencies] -arrayref = "0.3.9" +base64 = { version = "0.22.1", optional = true } bytemuck = { version = "1.25.0", features = ["derive"] } -num-derive = "0.4" -num-traits = "0.2" num_enum = "0.7.6" +serde = { version = "1.0.219", optional = true } +serde_with = { version = "3.18.0", optional = true } solana-account-info = "3.1.0" +solana-address = { version = "2.0.0", features = ["bytemuck", "nullable", "decode"] } solana-clock = "3.0.0" solana-cpi = "3.1.0" solana-instruction = "3.0.0" solana-msg = "3.1.0" +solana-nullable = { version = "1.1.0", features = ["bytemuck"] } solana-program-entrypoint = "3.1.1" solana-program-error = "3.0.1" solana-program-memory = "3.1.0" @@ -40,20 +42,18 @@ solana-sdk-ids = "3.1.0" solana-security-txt = "1.1.2" solana-sysvar = { version = "3.0.0", features = ["bincode"] } solana-system-interface = { version = "3.0.0", features = ["bincode"] } +solana-zero-copy = { version = "1.0.0", features = ["bytemuck"] } solana-zk-sdk = "4.0.0" +solana-zk-sdk-pod = "0.1.0" spl-elgamal-registry-interface = { version = "0.1.0", path = "../confidential/elgamal-registry-interface" } spl-memo-interface = { version = "2.0" } +spl-pod = { version = "0.7.2" } spl-token-2022-interface = { version = "2.1.0", path = "../interface" } spl-token-confidential-transfer-ciphertext-arithmetic = { version = "0.4.1", path = "../confidential/ciphertext-arithmetic" } spl-token-confidential-transfer-proof-extraction = { version = "0.5.1", path = "../confidential/proof-extraction" } spl-token-group-interface = { version = "0.7.1" } spl-token-metadata-interface = { version = "0.8.0" } spl-transfer-hook-interface = { version = "2.1.0" } -spl-pod = { version = "0.7.2" } -thiserror = "2.0" -serde = { version = "1.0.219", optional = true } -serde_with = { version = "3.18.0", optional = true } -base64 = { version = "0.22.1", optional = true } [target.'cfg(not(target_os = "solana"))'.dependencies] spl-token-confidential-transfer-proof-generation = { version = "0.5.1", path = "../confidential/proof-generation" } @@ -64,13 +64,7 @@ mollusk-svm = "0.11" proptest = "1.11" serial_test = "3.4.0" solana-account = "3.2.0" -solana-hash = "4.2.0" -solana-keypair = "3.0.0" -solana-signer = "3.0.0" -solana-transaction = { version = "3.0.0", features = ["bincode"] } -solana-transaction-error = "3.1.0" spl-tlv-account-resolution = { version = "0.11.1" } -serde_json = "1.0.149" test-case = "3.3.1" tokio = { version = "1", features = ["macros", "rt"] } diff --git a/program/src/extension/confidential_mint_burn/processor.rs b/program/src/extension/confidential_mint_burn/processor.rs index 7a9b8ed0b..ba56f23c1 100644 --- a/program/src/extension/confidential_mint_burn/processor.rs +++ b/program/src/extension/confidential_mint_burn/processor.rs @@ -15,16 +15,14 @@ use { solana_program_error::{ProgramError, ProgramResult}, solana_pubkey::Pubkey, solana_zk_sdk::{ - encryption::pod::{ - auth_encryption::PodAeCiphertext, - elgamal::{PodElGamalCiphertext, PodElGamalPubkey}, - }, + encryption::pod::{auth_encryption::PodAeCiphertext, elgamal::PodElGamalCiphertext}, zk_elgamal_proof_program::proof_data::{ CiphertextCiphertextEqualityProofContext, CiphertextCiphertextEqualityProofData, }, }, + spl_token_2022_interface::solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey, spl_token_2022_interface::{ - check_program_account, + check_program_account, convert_legacy_elgamal_pubkey, error::TokenError, extension::{ confidential_mint_burn::{ @@ -230,11 +228,18 @@ fn process_confidential_mint( token_account.get_extension_mut::()?; confidential_transfer_account.valid_as_destination()?; - if proof_context.mint_pubkeys.destination != confidential_transfer_account.elgamal_pubkey { + if convert_legacy_elgamal_pubkey(proof_context.mint_pubkeys.destination) + .map_err(|_| TokenError::InvalidState)? + != confidential_transfer_account.elgamal_pubkey + { return Err(ProgramError::InvalidInstructionData); } - if !auditor_elgamal_pubkey.equals(&proof_context.mint_pubkeys.auditor) { + if auditor_elgamal_pubkey + != convert_legacy_elgamal_pubkey(proof_context.mint_pubkeys.auditor) + .map_err(|_| TokenError::InvalidState)? + .into() + { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } @@ -419,7 +424,10 @@ pub(crate) fn process_confidential_burn( // Check that the source encryption public key is consistent with what was // actually used to generate the zkp. - if proof_context.burn_pubkeys.source != confidential_transfer_account.elgamal_pubkey { + if convert_legacy_elgamal_pubkey(proof_context.burn_pubkeys.source) + .map_err(|_| TokenError::InvalidState)? + != confidential_transfer_account.elgamal_pubkey + { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } @@ -461,7 +469,11 @@ pub(crate) fn process_confidential_burn( return Err(TokenError::ConfidentialTransferBalanceMismatch.into()); } - if !auditor_elgamal_pubkey.equals(&proof_context.burn_pubkeys.auditor) { + if auditor_elgamal_pubkey + != convert_legacy_elgamal_pubkey(proof_context.burn_pubkeys.auditor) + .map_err(|_| TokenError::InvalidState)? + .into() + { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } diff --git a/program/src/extension/confidential_transfer/account_info.rs b/program/src/extension/confidential_transfer/account_info.rs index cd9df0358..b9df50eee 100644 --- a/program/src/extension/confidential_transfer/account_info.rs +++ b/program/src/extension/confidential_transfer/account_info.rs @@ -1,5 +1,6 @@ use { bytemuck::{Pod, Zeroable}, + solana_zero_copy::unaligned::U64, solana_zk_sdk::{ encryption::{ auth_encryption::{AeCiphertext, AeKey}, @@ -7,7 +8,6 @@ use { }, zk_elgamal_proof_program::proof_data::ZeroCiphertextProofData, }, - spl_pod::primitives::PodU64, spl_token_2022_interface::{ error::TokenError, extension::confidential_transfer::{ @@ -61,7 +61,7 @@ impl EmptyAccountAccountInfo { pub struct ApplyPendingBalanceAccountInfo { /// The total number of `Deposit` and `Transfer` instructions that have /// credited `pending_balance` - pub(crate) pending_balance_credit_counter: PodU64, + pub(crate) pending_balance_credit_counter: U64, /// The low 16 bits of the pending balance (encrypted by `elgamal_pubkey`) pub(crate) pending_balance_lo: EncryptedBalance, /// The high 32 bits of the pending balance (encrypted by `elgamal_pubkey`) diff --git a/program/src/extension/confidential_transfer/processor.rs b/program/src/extension/confidential_transfer/processor.rs index c2bce55d9..83c35721a 100644 --- a/program/src/extension/confidential_transfer/processor.rs +++ b/program/src/extension/confidential_transfer/processor.rs @@ -18,25 +18,28 @@ use { }, bytemuck::Zeroable, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_clock::Clock, solana_cpi::invoke, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::{ProgramError, ProgramResult}, solana_pubkey::Pubkey, solana_rent::Rent, solana_system_interface::instruction as system_instruction, solana_sysvar::Sysvar, + solana_zero_copy::unaligned::{Bool, U64}, solana_zk_sdk::encryption::pod::{ auth_encryption::PodAeCiphertext, elgamal::PodElGamalCiphertext, }, + solana_zk_sdk_pod::encryption::elgamal::PodElGamalPubkey, spl_elgamal_registry_interface::state::ElGamalRegistry, - spl_pod::{ - bytemuck::pod_from_bytes, - optional_keys::{OptionalNonZeroElGamalPubkey, OptionalNonZeroPubkey}, - primitives::{PodBool, PodU64}, + spl_pod::bytemuck::pod_from_bytes, + spl_token_2022_interface::solana_zk_sdk::zk_elgamal_proof_program::proof_data::{ + PubkeyValidityProofContext, ZeroCiphertextProofContext, }, spl_token_2022_interface::{ - check_program_account, + check_program_account, convert_legacy_elgamal_pubkey, error::TokenError, extension::{ confidential_transfer::{instruction::*, *}, @@ -65,9 +68,9 @@ use { /// Processes an [`InitializeMint`] instruction. fn process_initialize_mint( accounts: &[AccountInfo], - authority: &OptionalNonZeroPubkey, - auto_approve_new_account: PodBool, - auditor_encryption_pubkey: &OptionalNonZeroElGamalPubkey, + authority: &MaybeNull
, + auto_approve_new_account: Bool, + auditor_encryption_pubkey: &MaybeNull, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_info = next_account_info(account_info_iter)?; @@ -87,8 +90,8 @@ fn process_initialize_mint( /// Processes an [`UpdateMint`] instruction. fn process_update_mint( accounts: &[AccountInfo], - auto_approve_new_account: PodBool, - auditor_encryption_pubkey: &OptionalNonZeroElGamalPubkey, + auto_approve_new_account: Bool, + auditor_encryption_pubkey: &MaybeNull, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_info = next_account_info(account_info_iter)?; @@ -220,7 +223,7 @@ fn process_configure_account( program_id: &Pubkey, accounts: &[AccountInfo], decryptable_zero_balance: &DecryptableBalance, - maximum_pending_balance_credit_counter: &PodU64, + maximum_pending_balance_credit_counter: &U64, elgamal_pubkey_source: ElGamalPubkeySource, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); @@ -285,7 +288,8 @@ fn process_configure_account( token_account.init_extension::(false)?; confidential_transfer_account.approved = confidential_transfer_mint.auto_approve_new_accounts; - confidential_transfer_account.elgamal_pubkey = elgamal_pubkey; + confidential_transfer_account.elgamal_pubkey = + convert_legacy_elgamal_pubkey(elgamal_pubkey).map_err(|_| TokenError::InvalidState)?; confidential_transfer_account.maximum_pending_balance_credit_counter = *maximum_pending_balance_credit_counter; @@ -383,7 +387,10 @@ fn process_empty_account( // Check that the encryption public key and ciphertext associated with the // confidential extension account are consistent with those that were // actually used to generate the zkp. - if confidential_transfer_account.elgamal_pubkey != proof_context.pubkey { + if confidential_transfer_account.elgamal_pubkey + != convert_legacy_elgamal_pubkey(proof_context.pubkey) + .map_err(|_| TokenError::InvalidState)? + { msg!("Encryption public-key mismatch"); return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } @@ -591,7 +598,10 @@ fn process_withdraw( // Check that the encryption public key associated with the confidential // extension is consistent with the public key that was actually used to // generate the zkp. - if confidential_transfer_account.elgamal_pubkey != proof_context.source_pubkey { + if confidential_transfer_account.elgamal_pubkey + != convert_legacy_elgamal_pubkey(proof_context.source_pubkey) + .map_err(|_| TokenError::InvalidState)? + { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } @@ -680,9 +690,10 @@ fn process_transfer( // Check that the auditor encryption public key associated wth the confidential // mint is consistent with what was actually used to generate the zkp. - if !confidential_transfer_mint - .auditor_elgamal_pubkey - .equals(&proof_context.transfer_pubkeys.auditor) + if confidential_transfer_mint.auditor_elgamal_pubkey + != convert_legacy_elgamal_pubkey(proof_context.transfer_pubkeys.auditor) + .map_err(|_| TokenError::InvalidState)? + .into() { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } @@ -748,9 +759,10 @@ fn process_transfer( // Check that the encryption public keys associated with the mint confidential // transfer and confidential transfer fee extensions are consistent with // the keys that were used to generate the zkp. - if !confidential_transfer_mint - .auditor_elgamal_pubkey - .equals(&proof_context.transfer_with_fee_pubkeys.auditor) + if confidential_transfer_mint.auditor_elgamal_pubkey + != convert_legacy_elgamal_pubkey(proof_context.transfer_with_fee_pubkeys.auditor) + .map_err(|_| TokenError::InvalidState)? + .into() { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } @@ -898,7 +910,10 @@ fn process_source_for_transfer( // Check that the source encryption public key is consistent with what was // actually used to generate the zkp. - if proof_context.transfer_pubkeys.source != confidential_transfer_account.elgamal_pubkey { + if convert_legacy_elgamal_pubkey(proof_context.transfer_pubkeys.source) + .map_err(|_| TokenError::InvalidState)? + != confidential_transfer_account.elgamal_pubkey + { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } @@ -958,7 +973,8 @@ fn process_destination_for_transfer( destination_token_account.get_extension_mut::()?; destination_confidential_transfer_account.valid_as_destination()?; - if proof_context.transfer_pubkeys.destination + if convert_legacy_elgamal_pubkey(proof_context.transfer_pubkeys.destination) + .map_err(|_| TokenError::InvalidState)? != destination_confidential_transfer_account.elgamal_pubkey { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); @@ -1045,7 +1061,8 @@ fn process_source_for_transfer_with_fee( // Check that the source encryption public key is consistent with what was // actually used to generate the zkp. - if proof_context.transfer_with_fee_pubkeys.source + if convert_legacy_elgamal_pubkey(proof_context.transfer_with_fee_pubkeys.source) + .map_err(|_| TokenError::InvalidState)? != confidential_transfer_account.elgamal_pubkey { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); @@ -1108,7 +1125,8 @@ fn process_destination_for_transfer_with_fee( destination_token_account.get_extension_mut::()?; destination_confidential_transfer_account.valid_as_destination()?; - if proof_context.transfer_with_fee_pubkeys.destination + if convert_legacy_elgamal_pubkey(proof_context.transfer_with_fee_pubkeys.destination) + .map_err(|_| TokenError::InvalidState)? != destination_confidential_transfer_account.elgamal_pubkey { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); diff --git a/program/src/extension/confidential_transfer_fee/processor.rs b/program/src/extension/confidential_transfer_fee/processor.rs index fc1b6a12b..37522ae01 100644 --- a/program/src/extension/confidential_transfer_fee/processor.rs +++ b/program/src/extension/confidential_transfer_fee/processor.rs @@ -4,12 +4,14 @@ use spl_token_confidential_transfer_ciphertext_arithmetic as ciphertext_arithmet use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::{ProgramError, ProgramResult}, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, + spl_token_2022_interface::solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey, spl_token_2022_interface::{ - check_program_account, + check_program_account, convert_legacy_elgamal_pubkey, error::TokenError, extension::{ confidential_transfer::{ @@ -32,7 +34,6 @@ use { }, instruction::{decode_instruction_data, decode_instruction_type}, pod::{PodAccount, PodMint}, - solana_zk_sdk::encryption::pod::elgamal::PodElGamalPubkey, }, spl_token_confidential_transfer_proof_extraction::instruction::verify_and_extract_context, }; @@ -43,7 +44,7 @@ use bytemuck::Zeroable; /// Processes an [`InitializeConfidentialTransferFeeConfig`] instruction. fn process_initialize_confidential_transfer_fee_config( accounts: &[AccountInfo], - authority: &OptionalNonZeroPubkey, + authority: &MaybeNull
, withdraw_withheld_authority_elgamal_pubkey: &PodElGamalPubkey, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); @@ -142,7 +143,10 @@ fn process_withdraw_withheld_tokens_from_mint( } // Check that the ElGamal public key associated with the destination account is // consistent with what was actually used to generate the zkp. - if proof_context.second_pubkey != destination_confidential_transfer_account.elgamal_pubkey { + if convert_legacy_elgamal_pubkey(proof_context.second_pubkey) + .map_err(|_| TokenError::InvalidState)? + != destination_confidential_transfer_account.elgamal_pubkey + { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } // Check that the withheld amount ciphertext is consistent with the ciphertext @@ -246,7 +250,10 @@ fn process_withdraw_withheld_tokens_from_accounts( } // Checks that the ElGamal public key associated with the destination account is // consistent with what was actually used to generate the zkp. - if proof_context.second_pubkey != destination_confidential_transfer_account.elgamal_pubkey { + if convert_legacy_elgamal_pubkey(proof_context.second_pubkey) + .map_err(|_| TokenError::InvalidState)? + != destination_confidential_transfer_account.elgamal_pubkey + { return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into()); } } // free `destination_confidential_transfer_account` diff --git a/program/src/extension/group_member_pointer/processor.rs b/program/src/extension/group_member_pointer/processor.rs index 3dcfa288a..42884cdef 100644 --- a/program/src/extension/group_member_pointer/processor.rs +++ b/program/src/extension/group_member_pointer/processor.rs @@ -1,10 +1,11 @@ use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_2022_interface::{ check_program_account, error::TokenError, @@ -25,8 +26,8 @@ use { fn process_initialize( _program_id: &Pubkey, accounts: &[AccountInfo], - authority: &OptionalNonZeroPubkey, - member_address: &OptionalNonZeroPubkey, + authority: &MaybeNull
, + member_address: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; @@ -54,7 +55,7 @@ fn process_initialize( fn process_update( program_id: &Pubkey, accounts: &[AccountInfo], - new_member_address: &OptionalNonZeroPubkey, + new_member_address: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; diff --git a/program/src/extension/group_pointer/processor.rs b/program/src/extension/group_pointer/processor.rs index c9a9ecd77..482b3c609 100644 --- a/program/src/extension/group_pointer/processor.rs +++ b/program/src/extension/group_pointer/processor.rs @@ -1,10 +1,11 @@ use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_2022_interface::{ check_program_account, error::TokenError, @@ -25,8 +26,8 @@ use { fn process_initialize( _program_id: &Pubkey, accounts: &[AccountInfo], - authority: &OptionalNonZeroPubkey, - group_address: &OptionalNonZeroPubkey, + authority: &MaybeNull
, + group_address: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; @@ -54,7 +55,7 @@ fn process_initialize( fn process_update( program_id: &Pubkey, accounts: &[AccountInfo], - new_group_address: &OptionalNonZeroPubkey, + new_group_address: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; diff --git a/program/src/extension/interest_bearing_mint/processor.rs b/program/src/extension/interest_bearing_mint/processor.rs index e833aacd0..070424997 100644 --- a/program/src/extension/interest_bearing_mint/processor.rs +++ b/program/src/extension/interest_bearing_mint/processor.rs @@ -1,12 +1,13 @@ use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_clock::Clock, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, solana_pubkey::Pubkey, solana_sysvar::Sysvar, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_2022_interface::{ check_program_account, error::TokenError, @@ -25,7 +26,7 @@ use { fn process_initialize( _program_id: &Pubkey, accounts: &[AccountInfo], - rate_authority: &OptionalNonZeroPubkey, + rate_authority: &MaybeNull
, rate: &BasisPoints, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); diff --git a/program/src/extension/metadata_pointer/processor.rs b/program/src/extension/metadata_pointer/processor.rs index 1fc4b64ee..0152410ea 100644 --- a/program/src/extension/metadata_pointer/processor.rs +++ b/program/src/extension/metadata_pointer/processor.rs @@ -1,10 +1,11 @@ use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_2022_interface::{ check_program_account, error::TokenError, @@ -25,8 +26,8 @@ use { fn process_initialize( _program_id: &Pubkey, accounts: &[AccountInfo], - authority: &OptionalNonZeroPubkey, - metadata_address: &OptionalNonZeroPubkey, + authority: &MaybeNull
, + metadata_address: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; @@ -51,7 +52,7 @@ fn process_initialize( fn process_update( program_id: &Pubkey, accounts: &[AccountInfo], - new_metadata_address: &OptionalNonZeroPubkey, + new_metadata_address: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; diff --git a/program/src/extension/pausable/processor.rs b/program/src/extension/pausable/processor.rs index 15187c089..1ae6c479e 100644 --- a/program/src/extension/pausable/processor.rs +++ b/program/src/extension/pausable/processor.rs @@ -2,7 +2,7 @@ use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, solana_msg::msg, - solana_program_error::ProgramResult, + solana_program_error::{ProgramError, ProgramResult}, solana_pubkey::Pubkey, spl_token_2022_interface::{ check_program_account, @@ -32,7 +32,9 @@ fn process_initialize( let mut mint = PodStateWithExtensionsMut::::unpack_uninitialized(&mut mint_data)?; let extension = mint.init_extension::(true)?; - extension.authority = Some(*authority).try_into()?; + extension.authority = Some(*authority) + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?; Ok(()) } diff --git a/program/src/extension/permissioned_burn/processor.rs b/program/src/extension/permissioned_burn/processor.rs index 705b94124..896e85c65 100644 --- a/program/src/extension/permissioned_burn/processor.rs +++ b/program/src/extension/permissioned_burn/processor.rs @@ -10,7 +10,7 @@ use { }, solana_account_info::{next_account_info, AccountInfo}, solana_msg::msg, - solana_program_error::ProgramResult, + solana_program_error::{ProgramError, ProgramResult}, solana_pubkey::Pubkey, spl_token_2022_interface::{ check_program_account, @@ -39,7 +39,9 @@ fn process_initialize( let mut mint = PodStateWithExtensionsMut::::unpack_uninitialized(&mut mint_data)?; let extension = mint.init_extension::(true)?; - extension.authority = Some(*authority).try_into()?; + extension.authority = Some(*authority) + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?; Ok(()) } diff --git a/program/src/extension/scaled_ui_amount/processor.rs b/program/src/extension/scaled_ui_amount/processor.rs index fad68762a..becac7fb1 100644 --- a/program/src/extension/scaled_ui_amount/processor.rs +++ b/program/src/extension/scaled_ui_amount/processor.rs @@ -1,12 +1,13 @@ use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_clock::Clock, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::ProgramResult, solana_pubkey::Pubkey, solana_sysvar::Sysvar, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_2022_interface::{ check_program_account, error::TokenError, @@ -37,7 +38,7 @@ fn try_validate_multiplier(multiplier: &PodF64) -> ProgramResult { fn process_initialize( _program_id: &Pubkey, accounts: &[AccountInfo], - authority: &OptionalNonZeroPubkey, + authority: &MaybeNull
, multiplier: &PodF64, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); diff --git a/program/src/extension/transfer_fee/processor.rs b/program/src/extension/transfer_fee/processor.rs index 8995d8503..295e1f927 100644 --- a/program/src/extension/transfer_fee/processor.rs +++ b/program/src/extension/transfer_fee/processor.rs @@ -18,9 +18,8 @@ use { BaseStateWithExtensions, BaseStateWithExtensionsMut, PodStateWithExtensions, PodStateWithExtensionsMut, }, - pod::{PodAccount, PodMint}, + pod::{PodAccount, PodCOption, PodMint}, }, - std::convert::TryInto, }; fn process_initialize_transfer_fee_config( @@ -37,8 +36,10 @@ fn process_initialize_transfer_fee_config( let mut mint_data = mint_account_info.data.borrow_mut(); let mut mint = PodStateWithExtensionsMut::::unpack_uninitialized(&mut mint_data)?; let extension = mint.init_extension::(true)?; - extension.transfer_fee_config_authority = transfer_fee_config_authority.try_into()?; - extension.withdraw_withheld_authority = withdraw_withheld_authority.try_into()?; + extension.transfer_fee_config_authority = + PodCOption::from(transfer_fee_config_authority).try_into()?; + extension.withdraw_withheld_authority = + PodCOption::from(withdraw_withheld_authority).try_into()?; extension.withheld_amount = 0u64.into(); if transfer_fee_basis_points > MAX_FEE_BASIS_POINTS { diff --git a/program/src/extension/transfer_hook/processor.rs b/program/src/extension/transfer_hook/processor.rs index 4cbfb4889..c219c0597 100644 --- a/program/src/extension/transfer_hook/processor.rs +++ b/program/src/extension/transfer_hook/processor.rs @@ -1,10 +1,11 @@ use { crate::processor::Processor, solana_account_info::{next_account_info, AccountInfo}, + solana_address::Address, solana_msg::msg, + solana_nullable::MaybeNull, solana_program_error::{ProgramError, ProgramResult}, solana_pubkey::Pubkey, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_token_2022_interface::{ check_program_account, error::TokenError, @@ -25,8 +26,8 @@ use { fn process_initialize( program_id: &Pubkey, accounts: &[AccountInfo], - authority: &OptionalNonZeroPubkey, - transfer_hook_program_id: &OptionalNonZeroPubkey, + authority: &MaybeNull
, + transfer_hook_program_id: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; @@ -53,7 +54,7 @@ fn process_initialize( fn process_update( program_id: &Pubkey, accounts: &[AccountInfo], - new_program_id: &OptionalNonZeroPubkey, + new_program_id: &MaybeNull
, ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let mint_account_info = next_account_info(account_info_iter)?; diff --git a/program/src/offchain.rs b/program/src/offchain.rs index 640f9785e..2a95b0ef8 100644 --- a/program/src/offchain.rs +++ b/program/src/offchain.rs @@ -215,7 +215,6 @@ mod tests { }, solana_instruction::AccountMeta, solana_program_option::COption, - spl_pod::optional_keys::OptionalNonZeroPubkey, spl_tlv_account_resolution::{ account::ExtraAccountMeta, seeds::Seed, state::ExtraAccountMetaList, }, @@ -240,8 +239,7 @@ mod tests { let mut mint = StateWithExtensionsMut::::unpack_uninitialized(&mut data).unwrap(); let extension = mint.init_extension::(true).unwrap(); - extension.program_id = - OptionalNonZeroPubkey::try_from(Some(TRANSFER_HOOK_PROGRAM_ID)).unwrap(); + extension.program_id = Some(TRANSFER_HOOK_PROGRAM_ID).try_into().unwrap(); mint.base.mint_authority = COption::Some(Pubkey::new_unique()); mint.base.decimals = DECIMALS; diff --git a/program/src/onchain.rs b/program/src/onchain.rs index cdacce81d..f7962fdac 100644 --- a/program/src/onchain.rs +++ b/program/src/onchain.rs @@ -237,7 +237,6 @@ mod tests { solana_instruction::AccountMeta, solana_program_option::COption, solana_program_pack::Pack, - spl_pod::{optional_keys::OptionalNonZeroPubkey, primitives::PodBool}, spl_tlv_account_resolution::{account::ExtraAccountMeta, state::ExtraAccountMetaList}, spl_transfer_hook_interface::{ get_extra_account_metas_address, instruction::ExecuteInstruction, @@ -267,13 +266,13 @@ mod tests { PodStateWithExtensionsMut::::unpack_uninitialized(&mut data).unwrap(); let extension = mint.init_extension::(true).unwrap(); - extension.program_id = OptionalNonZeroPubkey(hook_program_id); + extension.program_id = Some(hook_program_id).try_into().unwrap(); mint.base.mint_authority = PodCOption::some(Pubkey::new_unique()); mint.base.decimals = 6; mint.base.supply = 100_000_000.into(); mint.base.freeze_authority = PodCOption::none(); - mint.base.is_initialized = PodBool::from_bool(true); + mint.base.is_initialized = true.into(); mint.init_account_type().unwrap(); diff --git a/program/src/processor.rs b/program/src/processor.rs index b1804f09e..8fb04b05b 100644 --- a/program/src/processor.rs +++ b/program/src/processor.rs @@ -29,7 +29,7 @@ use { solana_sysvar::{Sysvar, SysvarSerialize}, spl_pod::{ bytemuck::{pod_from_bytes, pod_from_bytes_mut}, - primitives::{PodBool, PodU64}, + primitives::PodU64, }, spl_token_2022_interface::{ check_program_account, @@ -137,7 +137,7 @@ impl Processor { mint.base.mint_authority = PodCOption::some(*mint_authority); mint.base.decimals = decimals; - mint.base.is_initialized = PodBool::from_bool(true); + mint.base.is_initialized = true.into(); mint.base.freeze_authority = freeze_authority; mint.init_account_type()?; @@ -1668,7 +1668,9 @@ impl Processor { let mut mint_data = mint_account_info.data.borrow_mut(); let mut mint = PodStateWithExtensionsMut::::unpack_uninitialized(&mut mint_data)?; let extension = mint.init_extension::(true)?; - extension.delegate = Some(*delegate).try_into()?; + extension.delegate = Some(*delegate) + .try_into() + .map_err(|_| ProgramError::InvalidArgument)?; Ok(()) }